diff --git a/.gitignore b/.gitignore index aaec950d4..6ae33d8f9 100644 --- a/.gitignore +++ b/.gitignore @@ -12,32 +12,26 @@ ebin test/ebin/*.beam .exrc plugins/*/ebin -log/ *.swp *.so .erlang.mk/ cover/ -emqx.d eunit.coverdata test/ct.cover.spec -logs ct.coverdata .idea/ -emqx.iml -_rel/ -data/ _build .rebar3 rebar3.crashdump .DS_Store -emqx.iml -bbmustache/ etc/gen.emqx.conf compile_commands.json cuttlefish -rebar.lock xrefr -erlang.mk *.coverdata etc/emqx.conf.rendered Mnesia.*/ +*.DS_Store +_checkouts +rebar.config.rendered +/rebar3 diff --git a/Makefile b/Makefile index d1cd12a60..26c04b277 100644 --- a/Makefile +++ b/Makefile @@ -1,139 +1,62 @@ -## shallow clone for speed +REBAR_VERSION = 3.13.2-emqx-3 +REBAR = ./rebar3 -REBAR_GIT_CLONE_OPTIONS += --depth 1 -export REBAR_GIT_CLONE_OPTIONS +PROFILE ?= emqx +PROFILES := emqx emqx-edge +PKG_PROFILES := emqx-pkg emqx-edge-pkg -SUITES_FILES := $(shell find test -name '*_SUITE.erl' | sort) +export REBAR_GIT_CLONE_OPTIONS=--depth=1 -CT_SUITES := $(foreach value,$(SUITES_FILES),$(shell val=$$(basename $(value) .erl); echo $${val%_*})) - -CT_NODE_NAME = emqxct@127.0.0.1 - -RUN_NODE_NAME = emqxdebug@127.0.0.1 +.PHONY: default +default: $(REBAR) $(PROFILE) .PHONY: all -all: compile +all: $(REBAR) $(PROFILES) -.PHONY: tests -tests: eunit ct +.PHONY: ensure-rebar3 +ensure-rebar3: + @./ensure-rebar3.sh $(REBAR_VERSION) -.PHONY: run -run: run_setup unlock - @rebar3 as test get-deps - @rebar3 as test auto --name $(RUN_NODE_NAME) --script scripts/run_emqx.escript - -.PHONY: run_setup -run_setup: - @erl -noshell -eval \ - "{ok, [[HOME]]} = init:get_argument(home), \ - FilePath = HOME ++ \"/.config/rebar3/rebar.config\", \ - case file:consult(FilePath) of \ - {ok, Term} -> \ - NewTerm = case lists:keyfind(plugins, 1, Term) of \ - false -> [{plugins, [rebar3_auto]} | Term]; \ - {plugins, OldPlugins} -> \ - NewPlugins0 = OldPlugins -- [rebar3_auto], \ - NewPlugins = [rebar3_auto | NewPlugins0], \ - lists:keyreplace(plugins, 1, Term, {plugins, NewPlugins}) \ - end, \ - ok = file:write_file(FilePath, [io_lib:format(\"~p.\n\", [I]) || I <- NewTerm]); \ - _Enoent -> \ - os:cmd(\"mkdir -p ~/.config/rebar3/ \"), \ - NewTerm=[{plugins, [rebar3_auto]}], \ - ok = file:write_file(FilePath, [io_lib:format(\"~p.\n\", [I]) || I <- NewTerm]) \ - end, \ - halt(0)." - -.PHONY: shell -shell: - @rebar3 as test auto - -compile: unlock - @rebar3 compile - -unlock: - @rebar3 unlock - -clean: distclean - -## Cuttlefish escript is built by default when cuttlefish app (as dependency) was built -CUTTLEFISH_SCRIPT := _build/default/lib/cuttlefish/cuttlefish - -.PHONY: cover -cover: - @rebar3 cover - -.PHONY: coveralls -coveralls: - @rebar3 as test coveralls send - -.PHONY: xref -xref: - @rebar3 xref - -.PHONY: dialyzer -dialyzer: - @rebar3 dialyzer - -.PHONY: proper -proper: - @rebar3 proper -d test/props -c - -.PHONY: deps -deps: - @rebar3 get-deps - -.PHONY: eunit -eunit: - @rebar3 eunit -v - -.PHONY: ct_setup -ct_setup: - rebar3 as test compile - @mkdir -p data - @if [ ! -f data/loaded_plugins ]; then touch data/loaded_plugins; fi - @ln -s -f '../../../../etc' _build/test/lib/emqx/ - @ln -s -f '../../../../data' _build/test/lib/emqx/ - -.PHONY: ct -ct: ct_setup - @rebar3 ct -v --name $(CT_NODE_NAME) --suite=$(shell echo $(foreach var,$(CT_SUITES),test/$(var)_SUITE) | tr ' ' ',') - -## Run one single CT with rebar3 -## e.g. make ct-one-suite suite=emqx_bridge -.PHONY: $(SUITES:%=ct-%) -$(CT_SUITES:%=ct-%): ct_setup - @rebar3 ct -v --readable=false --name $(CT_NODE_NAME) --suite=$(@:ct-%=%)_SUITE --cover - -.PHONY: app.config -app.config: $(CUTTLEFISH_SCRIPT) etc/gen.emqx.conf - $(CUTTLEFISH_SCRIPT) -l info -e etc/ -c etc/gen.emqx.conf -i priv/emqx.schema -d data/ - -$(CUTTLEFISH_SCRIPT): - @rebar3 get-deps - @if [ ! -f cuttlefish ]; then make -C _build/default/lib/cuttlefish; fi - -bbmustache: - @git clone https://github.com/soranoba/bbmustache.git && cd bbmustache && ./rebar3 compile && cd .. - -# This hack is to generate a conf file for testing -# relx overlay is used for release -etc/gen.emqx.conf: bbmustache etc/emqx.conf - @erl -noshell -pa bbmustache/_build/default/lib/bbmustache/ebin -eval \ - "{ok, Temp} = file:read_file('etc/emqx.conf'), \ - {ok, Vars0} = file:consult('vars'), \ - Vars = [{atom_to_list(N), list_to_binary(V)} || {N, V} <- Vars0], \ - Targ = bbmustache:render(Temp, Vars), \ - ok = file:write_file('etc/gen.emqx.conf', Targ), \ - halt(0)." - -.PHONY: gen-clean -gen-clean: - @rm -rf bbmustache - @rm -f etc/gen.emqx.conf etc/emqx.conf.rendered +$(REBAR): ensure-rebar3 .PHONY: distclean -distclean: gen-clean - @rm -rf Mnesia.* - @rm -rf _build cover deps logs log data - @rm -f rebar.lock compile_commands.json cuttlefish erl_crash.dump +distclean: + @rm -rf _build + +.PHONY: $(PROFILES) +$(PROFILES:%=%): $(REBAR) +ifneq ($(shell echo $(@) |grep edge),) + export EMQX_DESC="EMQ X Edge" +else + export EMQX_DESC="EMQ X Broker" +endif + $(REBAR) as $(@) release + +.PHONY: $(PROFILES:%=build-%) +$(PROFILES:%=build-%): $(REBAR) + $(REBAR) as $(@:build-%=%) compile + +# rebar clean +.PHONY: clean $(PROFILES:%=clean-%) +clean: $(PROFILES:%=clean-%) clean-stamps +$(PROFILES:%=clean-%): $(REBAR) + $(REBAR) as $(@:clean-%=%) clean + +.PHONY: clean-stamps +clean-stamps: + find -L _build -name '.stamp' -type f | xargs rm -f + +.PHONY: deps-all +deps-all: $(REBAR) $(PROFILES:%=deps-%) $(PKG_PROFILES:%=deps-%) + +.PHONY: $(PROFILES:%=deps-%) $(PKG_PROFILES:%=deps-%) +$(PROFILES:%=deps-%) $(PKG_PROFILES:%=deps-%): $(REBAR) +ifneq ($(shell echo $(@) |grep edge),) + export EMQX_DESC="EMQ X Edge" +else + export EMQX_DESC="EMQ X Broker" +endif + $(REBAR) as $(@:deps-%=%) get-deps + +include packages.mk +include docker.mk diff --git a/priv/emqx.schema b/apps/emqx/priv/emqx.schema similarity index 100% rename from priv/emqx.schema rename to apps/emqx/priv/emqx.schema diff --git a/apps/emqx/rebar.config b/apps/emqx/rebar.config new file mode 100644 index 000000000..7b1f06cca --- /dev/null +++ b/apps/emqx/rebar.config @@ -0,0 +1 @@ +{deps, []}. \ No newline at end of file diff --git a/src/emqx.app.src b/apps/emqx/src/emqx.app.src similarity index 71% rename from src/emqx.app.src rename to apps/emqx/src/emqx.app.src index ac5c50d7c..b26b7dcd7 100644 --- a/src/emqx.app.src +++ b/apps/emqx/src/emqx.app.src @@ -1,11 +1,10 @@ {application, emqx, [{description, "EMQ X Broker"}, {id, "emqx"}, - {vsn, "git"}, + {vsn, "5.0.0"}, % strict semver, bump manually! {modules, []}, {registered, []}, - {applications, [kernel,stdlib,gproc,gen_rpc,esockd,cowboy, - sasl,os_mon]}, + {applications, [kernel,stdlib,gproc,gen_rpc,esockd,cowboy,sasl,os_mon,emqx_libs]}, {mod, {emqx_app,[]}}, {env, []}, {licenses, ["Apache-2.0"]}, diff --git a/src/emqx.appup.src b/apps/emqx/src/emqx.appup.src similarity index 100% rename from src/emqx.appup.src rename to apps/emqx/src/emqx.appup.src diff --git a/src/emqx.erl b/apps/emqx/src/emqx.erl similarity index 98% rename from src/emqx.erl rename to apps/emqx/src/emqx.erl index 2c6d444e7..4f4f4964f 100644 --- a/src/emqx.erl +++ b/apps/emqx/src/emqx.erl @@ -16,9 +16,9 @@ -module(emqx). --include("emqx.hrl"). --include("logger.hrl"). --include("types.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). +-include_lib("emqx_libs/include/types.hrl"). -logger_header("[EMQ X]"). diff --git a/src/emqx_access_control.erl b/apps/emqx/src/emqx_access_control.erl similarity index 98% rename from src/emqx_access_control.erl rename to apps/emqx/src/emqx_access_control.erl index 32383b3f0..2495d3579 100644 --- a/src/emqx_access_control.erl +++ b/apps/emqx/src/emqx_access_control.erl @@ -16,7 +16,7 @@ -module(emqx_access_control). --include("emqx.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). -export([authenticate/1]). diff --git a/src/emqx_access_rule.erl b/apps/emqx/src/emqx_access_rule.erl similarity index 99% rename from src/emqx_access_rule.erl rename to apps/emqx/src/emqx_access_rule.erl index 89943cdbd..a5bc2aad9 100644 --- a/src/emqx_access_rule.erl +++ b/apps/emqx/src/emqx_access_rule.erl @@ -16,7 +16,7 @@ -module(emqx_access_rule). --include("emqx.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). %% APIs -export([ match/3 diff --git a/src/emqx_acl_cache.erl b/apps/emqx/src/emqx_acl_cache.erl similarity index 99% rename from src/emqx_acl_cache.erl rename to apps/emqx/src/emqx_acl_cache.erl index ef549d8d3..0f8693d72 100644 --- a/src/emqx_acl_cache.erl +++ b/apps/emqx/src/emqx_acl_cache.erl @@ -16,7 +16,7 @@ -module(emqx_acl_cache). --include("emqx.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). -export([ list_acl_cache/0 , get_acl_cache/2 diff --git a/src/emqx_alarm.erl b/apps/emqx/src/emqx_alarm.erl similarity index 99% rename from src/emqx_alarm.erl rename to apps/emqx/src/emqx_alarm.erl index 37d6fe1e8..f3f696adb 100644 --- a/src/emqx_alarm.erl +++ b/apps/emqx/src/emqx_alarm.erl @@ -18,8 +18,8 @@ -behaviour(gen_server). --include("emqx.hrl"). --include("logger.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). -logger_header("[Alarm Handler]"). diff --git a/src/emqx_alarm_handler.erl b/apps/emqx/src/emqx_alarm_handler.erl similarity index 96% rename from src/emqx_alarm_handler.erl rename to apps/emqx/src/emqx_alarm_handler.erl index 7f66f6eb1..8c73b5605 100644 --- a/src/emqx_alarm_handler.erl +++ b/apps/emqx/src/emqx_alarm_handler.erl @@ -18,8 +18,8 @@ -behaviour(gen_event). --include("emqx.hrl"). --include("logger.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). -logger_header("[Alarm Handler]"). diff --git a/src/emqx_app.erl b/apps/emqx/src/emqx_app.erl similarity index 100% rename from src/emqx_app.erl rename to apps/emqx/src/emqx_app.erl diff --git a/src/emqx_banned.erl b/apps/emqx/src/emqx_banned.erl similarity index 97% rename from src/emqx_banned.erl rename to apps/emqx/src/emqx_banned.erl index 80f93be70..f4c5d728f 100644 --- a/src/emqx_banned.erl +++ b/apps/emqx/src/emqx_banned.erl @@ -18,9 +18,9 @@ -behaviour(gen_server). --include("emqx.hrl"). --include("logger.hrl"). --include("types.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). +-include_lib("emqx_libs/include/types.hrl"). -logger_header("[Banned]"). diff --git a/src/emqx_base62.erl b/apps/emqx/src/emqx_base62.erl similarity index 100% rename from src/emqx_base62.erl rename to apps/emqx/src/emqx_base62.erl diff --git a/src/emqx_batch.erl b/apps/emqx/src/emqx_batch.erl similarity index 100% rename from src/emqx_batch.erl rename to apps/emqx/src/emqx_batch.erl diff --git a/src/emqx_boot.erl b/apps/emqx/src/emqx_boot.erl similarity index 100% rename from src/emqx_boot.erl rename to apps/emqx/src/emqx_boot.erl diff --git a/src/emqx_broker.erl b/apps/emqx/src/emqx_broker.erl similarity index 98% rename from src/emqx_broker.erl rename to apps/emqx/src/emqx_broker.erl index 85c6ad070..5a1c1d9d3 100644 --- a/src/emqx_broker.erl +++ b/apps/emqx/src/emqx_broker.erl @@ -18,10 +18,10 @@ -behaviour(gen_server). --include("emqx.hrl"). --include("logger.hrl"). --include("types.hrl"). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). +-include_lib("emqx_libs/include/types.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -logger_header("[Broker]"). diff --git a/src/emqx_broker_helper.erl b/apps/emqx/src/emqx_broker_helper.erl similarity index 98% rename from src/emqx_broker_helper.erl rename to apps/emqx/src/emqx_broker_helper.erl index 18ebbccf2..535d81a35 100644 --- a/src/emqx_broker_helper.erl +++ b/apps/emqx/src/emqx_broker_helper.erl @@ -18,8 +18,8 @@ -behaviour(gen_server). --include("logger.hrl"). --include("types.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). +-include_lib("emqx_libs/include/types.hrl"). -logger_header("[Broker Helper]"). diff --git a/src/emqx_broker_sup.erl b/apps/emqx/src/emqx_broker_sup.erl similarity index 100% rename from src/emqx_broker_sup.erl rename to apps/emqx/src/emqx_broker_sup.erl diff --git a/src/emqx_channel.erl b/apps/emqx/src/emqx_channel.erl similarity index 99% rename from src/emqx_channel.erl rename to apps/emqx/src/emqx_channel.erl index 71b89f153..312fe60c9 100644 --- a/src/emqx_channel.erl +++ b/apps/emqx/src/emqx_channel.erl @@ -17,10 +17,10 @@ %% MQTT Channel -module(emqx_channel). --include("emqx.hrl"). --include("emqx_mqtt.hrl"). --include("logger.hrl"). --include("types.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). +-include_lib("emqx_libs/include/types.hrl"). -logger_header("[Channel]"). diff --git a/src/emqx_cm.erl b/apps/emqx/src/emqx_cm.erl similarity index 99% rename from src/emqx_cm.erl rename to apps/emqx/src/emqx_cm.erl index 200a5f08e..1654f4b4e 100644 --- a/src/emqx_cm.erl +++ b/apps/emqx/src/emqx_cm.erl @@ -19,9 +19,9 @@ -behaviour(gen_server). --include("emqx.hrl"). --include("logger.hrl"). --include("types.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). +-include_lib("emqx_libs/include/types.hrl"). -logger_header("[CM]"). diff --git a/src/emqx_cm_locker.erl b/apps/emqx/src/emqx_cm_locker.erl similarity index 96% rename from src/emqx_cm_locker.erl rename to apps/emqx/src/emqx_cm_locker.erl index b5979c706..84e24a568 100644 --- a/src/emqx_cm_locker.erl +++ b/apps/emqx/src/emqx_cm_locker.erl @@ -16,8 +16,8 @@ -module(emqx_cm_locker). --include("emqx.hrl"). --include("types.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/types.hrl"). -export([start_link/0]). diff --git a/src/emqx_cm_registry.erl b/apps/emqx/src/emqx_cm_registry.erl similarity index 97% rename from src/emqx_cm_registry.erl rename to apps/emqx/src/emqx_cm_registry.erl index 6609d70f4..fb53d571d 100644 --- a/src/emqx_cm_registry.erl +++ b/apps/emqx/src/emqx_cm_registry.erl @@ -19,9 +19,9 @@ -behaviour(gen_server). --include("emqx.hrl"). --include("logger.hrl"). --include("types.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). +-include_lib("emqx_libs/include/types.hrl"). -logger_header("[Registry]"). diff --git a/src/emqx_cm_sup.erl b/apps/emqx/src/emqx_cm_sup.erl similarity index 100% rename from src/emqx_cm_sup.erl rename to apps/emqx/src/emqx_cm_sup.erl diff --git a/src/emqx_connection.erl b/apps/emqx/src/emqx_connection.erl similarity index 99% rename from src/emqx_connection.erl rename to apps/emqx/src/emqx_connection.erl index 2ab7f6c1e..632357f83 100644 --- a/src/emqx_connection.erl +++ b/apps/emqx/src/emqx_connection.erl @@ -17,10 +17,10 @@ %% MQTT/TCP|TLS Connection -module(emqx_connection). --include("emqx.hrl"). --include("emqx_mqtt.hrl"). --include("logger.hrl"). --include("types.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). +-include_lib("emqx_libs/include/types.hrl"). -logger_header("[MQTT]"). diff --git a/src/emqx_ctl.erl b/apps/emqx/src/emqx_ctl.erl similarity index 98% rename from src/emqx_ctl.erl rename to apps/emqx/src/emqx_ctl.erl index 45cf34543..ffe3537b5 100644 --- a/src/emqx_ctl.erl +++ b/apps/emqx/src/emqx_ctl.erl @@ -18,8 +18,8 @@ -behaviour(gen_server). --include("types.hrl"). --include("logger.hrl"). +-include_lib("emqx_libs/include/types.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). -logger_header("[Ctl]"). diff --git a/src/emqx_flapping.erl b/apps/emqx/src/emqx_flapping.erl similarity index 97% rename from src/emqx_flapping.erl rename to apps/emqx/src/emqx_flapping.erl index 0c1b60ddd..7a0602647 100644 --- a/src/emqx_flapping.erl +++ b/apps/emqx/src/emqx_flapping.erl @@ -18,9 +18,9 @@ -behaviour(gen_server). --include("emqx.hrl"). --include("types.hrl"). --include("logger.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/types.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). -logger_header("[Flapping]"). diff --git a/src/emqx_frame.erl b/apps/emqx/src/emqx_frame.erl similarity index 99% rename from src/emqx_frame.erl rename to apps/emqx/src/emqx_frame.erl index 1c27548f7..5fb893e57 100644 --- a/src/emqx_frame.erl +++ b/apps/emqx/src/emqx_frame.erl @@ -16,8 +16,8 @@ -module(emqx_frame). --include("emqx.hrl"). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -export([ initial_parse_state/0 , initial_parse_state/1 diff --git a/src/emqx_gc.erl b/apps/emqx/src/emqx_gc.erl similarity index 98% rename from src/emqx_gc.erl rename to apps/emqx/src/emqx_gc.erl index 3bf826f73..908ab50b6 100644 --- a/src/emqx_gc.erl +++ b/apps/emqx/src/emqx_gc.erl @@ -26,7 +26,7 @@ -module(emqx_gc). --include("types.hrl"). +-include_lib("emqx_libs/include/types.hrl"). -export([ init/1 , run/2 diff --git a/src/emqx_gen_mod.erl b/apps/emqx/src/emqx_gen_mod.erl similarity index 100% rename from src/emqx_gen_mod.erl rename to apps/emqx/src/emqx_gen_mod.erl diff --git a/src/emqx_global_gc.erl b/apps/emqx/src/emqx_global_gc.erl similarity index 98% rename from src/emqx_global_gc.erl rename to apps/emqx/src/emqx_global_gc.erl index da953e347..7c7fdc461 100644 --- a/src/emqx_global_gc.erl +++ b/apps/emqx/src/emqx_global_gc.erl @@ -18,7 +18,7 @@ -behaviour(gen_server). --include("types.hrl"). +-include_lib("emqx_libs/include/types.hrl"). -export([start_link/0, stop/0]). diff --git a/src/emqx_guid.erl b/apps/emqx/src/emqx_guid.erl similarity index 100% rename from src/emqx_guid.erl rename to apps/emqx/src/emqx_guid.erl diff --git a/src/emqx_hooks.erl b/apps/emqx/src/emqx_hooks.erl similarity index 98% rename from src/emqx_hooks.erl rename to apps/emqx/src/emqx_hooks.erl index 273071d75..3325ca87c 100644 --- a/src/emqx_hooks.erl +++ b/apps/emqx/src/emqx_hooks.erl @@ -18,8 +18,8 @@ -behaviour(gen_server). --include("logger.hrl"). --include("types.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). +-include_lib("emqx_libs/include/types.hrl"). -logger_header("[Hooks]"). diff --git a/src/emqx_inflight.erl b/apps/emqx/src/emqx_inflight.erl similarity index 100% rename from src/emqx_inflight.erl rename to apps/emqx/src/emqx_inflight.erl diff --git a/src/emqx_json.erl b/apps/emqx/src/emqx_json.erl similarity index 100% rename from src/emqx_json.erl rename to apps/emqx/src/emqx_json.erl diff --git a/src/emqx_keepalive.erl b/apps/emqx/src/emqx_keepalive.erl similarity index 100% rename from src/emqx_keepalive.erl rename to apps/emqx/src/emqx_keepalive.erl diff --git a/src/emqx_kernel_sup.erl b/apps/emqx/src/emqx_kernel_sup.erl similarity index 100% rename from src/emqx_kernel_sup.erl rename to apps/emqx/src/emqx_kernel_sup.erl diff --git a/src/emqx_limiter.erl b/apps/emqx/src/emqx_limiter.erl similarity index 99% rename from src/emqx_limiter.erl rename to apps/emqx/src/emqx_limiter.erl index e3ff7512f..ddcff03f4 100644 --- a/src/emqx_limiter.erl +++ b/apps/emqx/src/emqx_limiter.erl @@ -17,7 +17,7 @@ %% Ratelimit or Quota checker -module(emqx_limiter). --include("types.hrl"). +-include_lib("emqx_libs/include/types.hrl"). -export([ init/2 , init/4 %% XXX: Compatible with before 4.2 version diff --git a/src/emqx_listeners.erl b/apps/emqx/src/emqx_listeners.erl similarity index 99% rename from src/emqx_listeners.erl rename to apps/emqx/src/emqx_listeners.erl index ce256d147..456c06f6e 100644 --- a/src/emqx_listeners.erl +++ b/apps/emqx/src/emqx_listeners.erl @@ -17,7 +17,7 @@ %% @doc Start/Stop MQTT listeners. -module(emqx_listeners). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). %% APIs -export([ start/0 diff --git a/src/emqx_logger_formatter.erl b/apps/emqx/src/emqx_logger_formatter.erl similarity index 100% rename from src/emqx_logger_formatter.erl rename to apps/emqx/src/emqx_logger_formatter.erl diff --git a/src/emqx_message.erl b/apps/emqx/src/emqx_message.erl similarity index 98% rename from src/emqx_message.erl rename to apps/emqx/src/emqx_message.erl index decbb0c18..db85c5f79 100644 --- a/src/emqx_message.erl +++ b/apps/emqx/src/emqx_message.erl @@ -18,9 +18,9 @@ -compile(inline). --include("emqx.hrl"). --include("emqx_mqtt.hrl"). --include("types.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/types.hrl"). %% Create -export([ make/2 diff --git a/src/emqx_metrics.erl b/apps/emqx/src/emqx_metrics.erl similarity index 99% rename from src/emqx_metrics.erl rename to apps/emqx/src/emqx_metrics.erl index 4bd529a2e..8ce8e084e 100644 --- a/src/emqx_metrics.erl +++ b/apps/emqx/src/emqx_metrics.erl @@ -18,10 +18,10 @@ -behavior(gen_server). --include("logger.hrl"). --include("types.hrl"). --include("emqx_mqtt.hrl"). --include("emqx.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). +-include_lib("emqx_libs/include/types.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -logger_header("[Metrics]"). diff --git a/src/emqx_misc.erl b/apps/emqx/src/emqx_misc.erl similarity index 98% rename from src/emqx_misc.erl rename to apps/emqx/src/emqx_misc.erl index 88e3c91a6..dc2aac0a5 100644 --- a/src/emqx_misc.erl +++ b/apps/emqx/src/emqx_misc.erl @@ -18,8 +18,8 @@ -compile(inline). --include("types.hrl"). --include("logger.hrl"). +-include_lib("emqx_libs/include/types.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). -export([ merge_opts/2 , maybe_apply/2 diff --git a/src/emqx_mod_acl_internal.erl b/apps/emqx/src/emqx_mod_acl_internal.erl similarity index 97% rename from src/emqx_mod_acl_internal.erl rename to apps/emqx/src/emqx_mod_acl_internal.erl index 7d5dd82c6..e7b498463 100644 --- a/src/emqx_mod_acl_internal.erl +++ b/apps/emqx/src/emqx_mod_acl_internal.erl @@ -18,8 +18,8 @@ -behaviour(emqx_gen_mod). --include("emqx.hrl"). --include("logger.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). -logger_header("[ACL_INTERNAL]"). diff --git a/src/emqx_mod_delayed.erl b/apps/emqx/src/emqx_mod_delayed.erl similarity index 98% rename from src/emqx_mod_delayed.erl rename to apps/emqx/src/emqx_mod_delayed.erl index 208da68ca..524d9015a 100644 --- a/src/emqx_mod_delayed.erl +++ b/apps/emqx/src/emqx_mod_delayed.erl @@ -19,8 +19,8 @@ -behaviour(gen_server). -behaviour(emqx_gen_mod). --include_lib("emqx/include/emqx.hrl"). --include_lib("emqx/include/logger.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). %% Mnesia bootstrap -export([mnesia/1]). diff --git a/src/emqx_mod_presence.erl b/apps/emqx/src/emqx_mod_presence.erl similarity index 98% rename from src/emqx_mod_presence.erl rename to apps/emqx/src/emqx_mod_presence.erl index f5aa2279e..08e1be9d1 100644 --- a/src/emqx_mod_presence.erl +++ b/apps/emqx/src/emqx_mod_presence.erl @@ -18,8 +18,8 @@ -behaviour(emqx_gen_mod). --include("emqx.hrl"). --include("logger.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). -logger_header("[Presence]"). diff --git a/src/emqx_mod_rewrite.erl b/apps/emqx/src/emqx_mod_rewrite.erl similarity index 97% rename from src/emqx_mod_rewrite.erl rename to apps/emqx/src/emqx_mod_rewrite.erl index f5e343eed..007f8fde4 100644 --- a/src/emqx_mod_rewrite.erl +++ b/apps/emqx/src/emqx_mod_rewrite.erl @@ -18,8 +18,8 @@ -behaviour(emqx_gen_mod). --include_lib("emqx.hrl"). --include_lib("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -ifdef(TEST). -export([ compile/1 diff --git a/src/emqx_mod_subscription.erl b/apps/emqx/src/emqx_mod_subscription.erl similarity index 96% rename from src/emqx_mod_subscription.erl rename to apps/emqx/src/emqx_mod_subscription.erl index b6d04528b..7fcac81cc 100644 --- a/src/emqx_mod_subscription.erl +++ b/apps/emqx/src/emqx_mod_subscription.erl @@ -18,8 +18,8 @@ -behaviour(emqx_gen_mod). --include_lib("emqx.hrl"). --include_lib("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). %% emqx_gen_mod callbacks -export([ load/1 diff --git a/src/emqx_mod_sup.erl b/apps/emqx/src/emqx_mod_sup.erl similarity index 97% rename from src/emqx_mod_sup.erl rename to apps/emqx/src/emqx_mod_sup.erl index b5512013c..dfae8125d 100644 --- a/src/emqx_mod_sup.erl +++ b/apps/emqx/src/emqx_mod_sup.erl @@ -18,7 +18,7 @@ -behaviour(supervisor). --include("types.hrl"). +-include_lib("emqx_libs/include/types.hrl"). -export([ start_link/0 , start_child/1 diff --git a/src/emqx_mod_topic_metrics.erl b/apps/emqx/src/emqx_mod_topic_metrics.erl similarity index 86% rename from src/emqx_mod_topic_metrics.erl rename to apps/emqx/src/emqx_mod_topic_metrics.erl index f0e638f4d..9e7abd3a6 100644 --- a/src/emqx_mod_topic_metrics.erl +++ b/apps/emqx/src/emqx_mod_topic_metrics.erl @@ -19,9 +19,9 @@ -behaviour(gen_server). -behaviour(emqx_gen_mod). --include("emqx.hrl"). --include("logger.hrl"). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -logger_header("[TOPIC_METRICS]"). @@ -52,6 +52,9 @@ , all_registered_topics/0 ]). +%% stats. +-export([ rates/2 ]). + %% gen_server callbacks -export([ init/1 , handle_call/3 @@ -78,13 +81,15 @@ ]). -define(TICKING_INTERVAL, 1). +-define(SPEED_AVERAGE_WINDOW_SIZE, 5). +-define(SPEED_MEDIUM_WINDOW_SIZE, 60). +-define(SPEED_LONG_WINDOW_SIZE, 300). -record(speed, { last = 0 :: number(), - tick = 1 :: number(), last_v = 0 :: number(), - acc = 0 :: number(), - samples = [] :: list() + last_medium = 0 :: number(), + last_long = 0 :: number() }). -record(state, { @@ -180,7 +185,15 @@ val(Topic, Metric) -> end. rate(Topic, Metric) -> - gen_server:call(?MODULE, {get_rate, Topic, Metric}). + case rates(Topic, Metric) of + #{short := Last} -> + Last; + {error, Reason} -> + {error, Reason} + end. + +rates(Topic, Metric) -> + gen_server:call(?MODULE, {get_rates, Topic, Metric}). metrics(Topic) -> case ets:lookup(?TAB, Topic) of @@ -253,7 +266,7 @@ handle_call({unregister, Topic}, _From, State = #state{speeds = Speeds}) -> {reply, ok, State#state{speeds = NSpeeds}} end; -handle_call({get_rate, Topic, Metric}, _From, State = #state{speeds = Speeds}) -> +handle_call({get_rates, Topic, Metric}, _From, State = #state{speeds = Speeds}) -> case is_registered(Topic) of false -> {reply, {error, topic_not_found}, State}; @@ -261,8 +274,8 @@ handle_call({get_rate, Topic, Metric}, _From, State = #state{speeds = Speeds}) - case maps:get({Topic, Metric}, Speeds, undefined) of undefined -> {reply, {error, invalid_metric}, State}; - #speed{last = Last} -> - {reply, Last, State} + #speed{last = Short, last_medium = Medium, last_long = Long} -> + {reply, #{ short => Short, medium => Medium, long => Long }, State} end end. @@ -358,25 +371,29 @@ counters_size() -> number_of_registered_topics() -> proplists:get_value(size, ets:info(?TAB)). -calculate_speed(CurVal, #speed{last_v = LastVal, tick = Tick, acc = Acc, samples = Samples}) -> +calculate_speed(CurVal, #speed{last = Last, + last_v = LastVal, + last_medium = LastMedium, + last_long = LastLong +}) -> %% calculate the current speed based on the last value of the counter CurSpeed = (CurVal - LastVal) / ?TICKING_INTERVAL, + #speed{ + last_v = CurVal, + last = short_mma(Last, CurSpeed), + last_medium = medium_mma(LastMedium, CurSpeed), + last_long = long_mma(LastLong, CurSpeed) + }. - %% calculate the average speed in last 5 seconds - case Tick < 5 of - true -> - Acc1 = Acc + CurSpeed, - #speed{last = Acc1 / Tick, - last_v = CurVal, - acc = Acc1, - samples = Samples ++ [CurSpeed], - tick = Tick + 1}; - false -> - [FirstSpeed | Speeds] = Samples, - Acc1 = Acc + CurSpeed - FirstSpeed, - #speed{last = Acc1 / Tick, - last_v = CurVal, - acc = Acc1, - samples = Speeds ++ [CurSpeed], - tick = Tick} - end. +%% Modified Moving Average ref: https://en.wikipedia.org/wiki/Moving_average +mma(WindowSize, LastSpeed, CurSpeed) -> + (LastSpeed * (WindowSize - 1) + CurSpeed) / WindowSize. + +short_mma(LastSpeed, CurSpeed) -> + mma(?SPEED_AVERAGE_WINDOW_SIZE, LastSpeed, CurSpeed). + +medium_mma(LastSpeed, CurSpeed) -> + mma(?SPEED_MEDIUM_WINDOW_SIZE, LastSpeed, CurSpeed). + +long_mma(LastSpeed, CurSpeed) -> + mma(?SPEED_LONG_WINDOW_SIZE, LastSpeed, CurSpeed). diff --git a/src/emqx_modules.erl b/apps/emqx/src/emqx_modules.erl similarity index 99% rename from src/emqx_modules.erl rename to apps/emqx/src/emqx_modules.erl index 55fb44001..58621f28a 100644 --- a/src/emqx_modules.erl +++ b/apps/emqx/src/emqx_modules.erl @@ -16,7 +16,7 @@ -module(emqx_modules). --include("logger.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). -logger_header("[Modules]"). diff --git a/src/emqx_mountpoint.erl b/apps/emqx/src/emqx_mountpoint.erl similarity index 96% rename from src/emqx_mountpoint.erl rename to apps/emqx/src/emqx_mountpoint.erl index 8dfc23b30..83367655f 100644 --- a/src/emqx_mountpoint.erl +++ b/apps/emqx/src/emqx_mountpoint.erl @@ -16,8 +16,8 @@ -module(emqx_mountpoint). --include("emqx.hrl"). --include("types.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/types.hrl"). -export([ mount/2 , unmount/2 diff --git a/src/emqx_mqtt_caps.erl b/apps/emqx/src/emqx_mqtt_caps.erl similarity index 98% rename from src/emqx_mqtt_caps.erl rename to apps/emqx/src/emqx_mqtt_caps.erl index f29d59915..7f4896ebd 100644 --- a/src/emqx_mqtt_caps.erl +++ b/apps/emqx/src/emqx_mqtt_caps.erl @@ -17,8 +17,8 @@ %% @doc MQTTv5 Capabilities -module(emqx_mqtt_caps). --include("emqx_mqtt.hrl"). --include("types.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/types.hrl"). -export([ check_pub/2 , check_sub/3 diff --git a/src/emqx_mqtt_props.erl b/apps/emqx/src/emqx_mqtt_props.erl similarity index 99% rename from src/emqx_mqtt_props.erl rename to apps/emqx/src/emqx_mqtt_props.erl index 7acea6761..643b8cc76 100644 --- a/src/emqx_mqtt_props.erl +++ b/apps/emqx/src/emqx_mqtt_props.erl @@ -17,7 +17,7 @@ %% @doc MQTT5 Properties -module(emqx_mqtt_props). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -export([ id/1 , name/1 diff --git a/src/emqx_mqueue.erl b/apps/emqx/src/emqx_mqueue.erl similarity index 98% rename from src/emqx_mqueue.erl rename to apps/emqx/src/emqx_mqueue.erl index f77a1d98f..5286dfe10 100644 --- a/src/emqx_mqueue.erl +++ b/apps/emqx/src/emqx_mqueue.erl @@ -49,9 +49,9 @@ -module(emqx_mqueue). --include("emqx.hrl"). --include("types.hrl"). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/types.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -export([ init/1 , info/1 diff --git a/src/emqx_os_mon.erl b/apps/emqx/src/emqx_os_mon.erl similarity index 98% rename from src/emqx_os_mon.erl rename to apps/emqx/src/emqx_os_mon.erl index 49517d8a6..0e2dbbd15 100644 --- a/src/emqx_os_mon.erl +++ b/apps/emqx/src/emqx_os_mon.erl @@ -18,7 +18,7 @@ -behaviour(gen_server). --include("logger.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). -logger_header("[OS_MON]"). @@ -47,7 +47,7 @@ , code_change/3 ]). --include("emqx.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). -define(OS_MON, ?MODULE). diff --git a/src/emqx_packet.erl b/apps/emqx/src/emqx_packet.erl similarity index 99% rename from src/emqx_packet.erl rename to apps/emqx/src/emqx_packet.erl index 015f95e0d..25b9d9996 100644 --- a/src/emqx_packet.erl +++ b/apps/emqx/src/emqx_packet.erl @@ -16,8 +16,8 @@ -module(emqx_packet). --include("emqx.hrl"). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). %% Header APIs -export([ type/1 diff --git a/src/emqx_pd.erl b/apps/emqx/src/emqx_pd.erl similarity index 97% rename from src/emqx_pd.erl rename to apps/emqx/src/emqx_pd.erl index 8754ac090..c62f761b3 100644 --- a/src/emqx_pd.erl +++ b/apps/emqx/src/emqx_pd.erl @@ -17,7 +17,7 @@ %% @doc The utility functions for erlang process dictionary. -module(emqx_pd). --include("types.hrl"). +-include_lib("emqx_libs/include/types.hrl"). -export([ get_counters/1 , get_counter/1 diff --git a/src/emqx_plugins.erl b/apps/emqx/src/emqx_plugins.erl similarity index 98% rename from src/emqx_plugins.erl rename to apps/emqx/src/emqx_plugins.erl index faa6abae3..5eb9267c7 100644 --- a/src/emqx_plugins.erl +++ b/apps/emqx/src/emqx_plugins.erl @@ -16,8 +16,8 @@ -module(emqx_plugins). --include("emqx.hrl"). --include("logger.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). -logger_header("[Plugins]"). @@ -234,7 +234,7 @@ generate_configs(App) -> Conf = cuttlefish_conf:file(ConfFile), cuttlefish_generator:map(Schema, Conf); {false, false} -> - error(no_avaliable_configuration) + error({config_not_found, {ConfigFile, ConfFile, SchemaFile}}) end. apply_configs([]) -> diff --git a/src/emqx_pmon.erl b/apps/emqx/src/emqx_pmon.erl similarity index 100% rename from src/emqx_pmon.erl rename to apps/emqx/src/emqx_pmon.erl diff --git a/src/emqx_pool.erl b/apps/emqx/src/emqx_pool.erl similarity index 97% rename from src/emqx_pool.erl rename to apps/emqx/src/emqx_pool.erl index 49a7c2cac..00fdb4c8b 100644 --- a/src/emqx_pool.erl +++ b/apps/emqx/src/emqx_pool.erl @@ -18,8 +18,8 @@ -behaviour(gen_server). --include("logger.hrl"). --include("types.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). +-include_lib("emqx_libs/include/types.hrl"). -logger_header("[Pool]"). diff --git a/src/emqx_pool_sup.erl b/apps/emqx/src/emqx_pool_sup.erl similarity index 98% rename from src/emqx_pool_sup.erl rename to apps/emqx/src/emqx_pool_sup.erl index 080cd842b..7c2d6639d 100644 --- a/src/emqx_pool_sup.erl +++ b/apps/emqx/src/emqx_pool_sup.erl @@ -18,7 +18,7 @@ -behaviour(supervisor). --include("types.hrl"). +-include_lib("emqx_libs/include/types.hrl"). -export([spec/1, spec/2]). diff --git a/src/emqx_pqueue.erl b/apps/emqx/src/emqx_pqueue.erl similarity index 100% rename from src/emqx_pqueue.erl rename to apps/emqx/src/emqx_pqueue.erl diff --git a/src/emqx_psk.erl b/apps/emqx/src/emqx_psk.erl similarity index 97% rename from src/emqx_psk.erl rename to apps/emqx/src/emqx_psk.erl index f1170d2d9..057dc3e84 100644 --- a/src/emqx_psk.erl +++ b/apps/emqx/src/emqx_psk.erl @@ -16,7 +16,7 @@ -module(emqx_psk). --include("logger.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). -logger_header("[PSK]"). diff --git a/src/emqx_reason_codes.erl b/apps/emqx/src/emqx_reason_codes.erl similarity index 99% rename from src/emqx_reason_codes.erl rename to apps/emqx/src/emqx_reason_codes.erl index 8e96df165..c9ada26a4 100644 --- a/src/emqx_reason_codes.erl +++ b/apps/emqx/src/emqx_reason_codes.erl @@ -17,7 +17,7 @@ %% @doc MQTT5 reason codes -module(emqx_reason_codes). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -export([ name/1 , name/2 diff --git a/src/emqx_router.erl b/apps/emqx/src/emqx_router.erl similarity index 98% rename from src/emqx_router.erl rename to apps/emqx/src/emqx_router.erl index cc358758f..00fb934f6 100644 --- a/src/emqx_router.erl +++ b/apps/emqx/src/emqx_router.erl @@ -18,9 +18,9 @@ -behaviour(gen_server). --include("emqx.hrl"). --include("logger.hrl"). --include("types.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). +-include_lib("emqx_libs/include/types.hrl"). -include_lib("ekka/include/ekka.hrl"). -logger_header("[Router]"). diff --git a/src/emqx_router_helper.erl b/apps/emqx/src/emqx_router_helper.erl similarity index 97% rename from src/emqx_router_helper.erl rename to apps/emqx/src/emqx_router_helper.erl index ba5cc5543..33761c027 100644 --- a/src/emqx_router_helper.erl +++ b/apps/emqx/src/emqx_router_helper.erl @@ -18,9 +18,9 @@ -behaviour(gen_server). --include("emqx.hrl"). --include("logger.hrl"). --include("types.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). +-include_lib("emqx_libs/include/types.hrl"). -logger_header("[Router Helper]"). diff --git a/src/emqx_router_sup.erl b/apps/emqx/src/emqx_router_sup.erl similarity index 100% rename from src/emqx_router_sup.erl rename to apps/emqx/src/emqx_router_sup.erl diff --git a/src/emqx_rpc.erl b/apps/emqx/src/emqx_rpc.erl similarity index 100% rename from src/emqx_rpc.erl rename to apps/emqx/src/emqx_rpc.erl diff --git a/src/emqx_sequence.erl b/apps/emqx/src/emqx_sequence.erl similarity index 100% rename from src/emqx_sequence.erl rename to apps/emqx/src/emqx_sequence.erl diff --git a/src/emqx_session.erl b/apps/emqx/src/emqx_session.erl similarity index 99% rename from src/emqx_session.erl rename to apps/emqx/src/emqx_session.erl index e89943f2a..9961e5a75 100644 --- a/src/emqx_session.erl +++ b/apps/emqx/src/emqx_session.erl @@ -43,10 +43,10 @@ %% MQTT Session -module(emqx_session). --include("emqx.hrl"). --include("emqx_mqtt.hrl"). --include("logger.hrl"). --include("types.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). +-include_lib("emqx_libs/include/types.hrl"). -logger_header("[Session]"). diff --git a/src/emqx_shared_sub.erl b/apps/emqx/src/emqx_shared_sub.erl similarity index 98% rename from src/emqx_shared_sub.erl rename to apps/emqx/src/emqx_shared_sub.erl index 71372cd90..863b57868 100644 --- a/src/emqx_shared_sub.erl +++ b/apps/emqx/src/emqx_shared_sub.erl @@ -18,10 +18,10 @@ -behaviour(gen_server). --include("emqx.hrl"). --include("emqx_mqtt.hrl"). --include("logger.hrl"). --include("types.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). +-include_lib("emqx_libs/include/types.hrl"). -logger_header("[Shared Sub]"). diff --git a/src/emqx_stats.erl b/apps/emqx/src/emqx_stats.erl similarity index 98% rename from src/emqx_stats.erl rename to apps/emqx/src/emqx_stats.erl index a6d53cfeb..6a120b55d 100644 --- a/src/emqx_stats.erl +++ b/apps/emqx/src/emqx_stats.erl @@ -18,9 +18,9 @@ -behaviour(gen_server). --include("emqx.hrl"). --include("logger.hrl"). --include("types.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). +-include_lib("emqx_libs/include/types.hrl"). -logger_header("[Stats]"). diff --git a/src/emqx_sup.erl b/apps/emqx/src/emqx_sup.erl similarity index 98% rename from src/emqx_sup.erl rename to apps/emqx/src/emqx_sup.erl index c0aa3a2a8..f841f57d1 100644 --- a/src/emqx_sup.erl +++ b/apps/emqx/src/emqx_sup.erl @@ -18,7 +18,7 @@ -behaviour(supervisor). --include("types.hrl"). +-include_lib("emqx_libs/include/types.hrl"). -export([ start_link/0 , start_child/1 diff --git a/src/emqx_sys.erl b/apps/emqx/src/emqx_sys.erl similarity index 98% rename from src/emqx_sys.erl rename to apps/emqx/src/emqx_sys.erl index 38387b3ce..64da255f9 100644 --- a/src/emqx_sys.erl +++ b/apps/emqx/src/emqx_sys.erl @@ -18,9 +18,9 @@ -behaviour(gen_server). --include("emqx.hrl"). --include("types.hrl"). --include("logger.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/types.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). -logger_header("[SYS]"). diff --git a/src/emqx_sys_mon.erl b/apps/emqx/src/emqx_sys_mon.erl similarity index 98% rename from src/emqx_sys_mon.erl rename to apps/emqx/src/emqx_sys_mon.erl index 5ee22c563..514b5f7d2 100644 --- a/src/emqx_sys_mon.erl +++ b/apps/emqx/src/emqx_sys_mon.erl @@ -18,8 +18,8 @@ -behavior(gen_server). --include("types.hrl"). --include("logger.hrl"). +-include_lib("emqx_libs/include/types.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). -logger_header("[SYSMON]"). diff --git a/src/emqx_sys_sup.erl b/apps/emqx/src/emqx_sys_sup.erl similarity index 100% rename from src/emqx_sys_sup.erl rename to apps/emqx/src/emqx_sys_sup.erl diff --git a/src/emqx_tables.erl b/apps/emqx/src/emqx_tables.erl similarity index 100% rename from src/emqx_tables.erl rename to apps/emqx/src/emqx_tables.erl diff --git a/src/emqx_topic.erl b/apps/emqx/src/emqx_topic.erl similarity index 100% rename from src/emqx_topic.erl rename to apps/emqx/src/emqx_topic.erl diff --git a/src/emqx_tracer.erl b/apps/emqx/src/emqx_tracer.erl similarity index 98% rename from src/emqx_tracer.erl rename to apps/emqx/src/emqx_tracer.erl index a01dcb27f..32b74ec54 100644 --- a/src/emqx_tracer.erl +++ b/apps/emqx/src/emqx_tracer.erl @@ -16,8 +16,8 @@ -module(emqx_tracer). --include("emqx.hrl"). --include("logger.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). -logger_header("[Tracer]"). diff --git a/src/emqx_trie.erl b/apps/emqx/src/emqx_trie.erl similarity index 99% rename from src/emqx_trie.erl rename to apps/emqx/src/emqx_trie.erl index 4189c0270..051cc1d84 100644 --- a/src/emqx_trie.erl +++ b/apps/emqx/src/emqx_trie.erl @@ -16,7 +16,7 @@ -module(emqx_trie). --include("emqx.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). %% Mnesia bootstrap -export([mnesia/1]). diff --git a/src/emqx_types.erl b/apps/emqx/src/emqx_types.erl similarity index 98% rename from src/emqx_types.erl rename to apps/emqx/src/emqx_types.erl index 291e35538..2794b8834 100644 --- a/src/emqx_types.erl +++ b/apps/emqx/src/emqx_types.erl @@ -16,9 +16,9 @@ -module(emqx_types). --include("emqx.hrl"). --include("emqx_mqtt.hrl"). --include("types.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/types.hrl"). -export_type([ ver/0 , qos/0 diff --git a/src/emqx_vm.erl b/apps/emqx/src/emqx_vm.erl similarity index 100% rename from src/emqx_vm.erl rename to apps/emqx/src/emqx_vm.erl diff --git a/src/emqx_vm_mon.erl b/apps/emqx/src/emqx_vm_mon.erl similarity index 99% rename from src/emqx_vm_mon.erl rename to apps/emqx/src/emqx_vm_mon.erl index 791e700d1..98d4fccb3 100644 --- a/src/emqx_vm_mon.erl +++ b/apps/emqx/src/emqx_vm_mon.erl @@ -18,7 +18,7 @@ -behaviour(gen_server). --include("logger.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). %% APIs -export([start_link/1]). diff --git a/src/emqx_ws_connection.erl b/apps/emqx/src/emqx_ws_connection.erl similarity index 99% rename from src/emqx_ws_connection.erl rename to apps/emqx/src/emqx_ws_connection.erl index 33b882768..a6610796c 100644 --- a/src/emqx_ws_connection.erl +++ b/apps/emqx/src/emqx_ws_connection.erl @@ -17,10 +17,10 @@ %% MQTT/WS|WSS Connection -module(emqx_ws_connection). --include("emqx.hrl"). --include("emqx_mqtt.hrl"). --include("logger.hrl"). --include("types.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). +-include_lib("emqx_libs/include/types.hrl"). -logger_header("[MQTT/WS]"). diff --git a/src/emqx_zone.erl b/apps/emqx/src/emqx_zone.erl similarity index 97% rename from src/emqx_zone.erl rename to apps/emqx/src/emqx_zone.erl index 6cec6c1ee..19a64ba21 100644 --- a/src/emqx_zone.erl +++ b/apps/emqx/src/emqx_zone.erl @@ -18,10 +18,10 @@ -behaviour(gen_server). --include("emqx.hrl"). --include("emqx_mqtt.hrl"). --include("logger.hrl"). --include("types.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). +-include_lib("emqx_libs/include/types.hrl"). -logger_header("[Zone]"). diff --git a/test/emqx_SUITE.erl b/apps/emqx/test/emqx_SUITE.erl similarity index 99% rename from test/emqx_SUITE.erl rename to apps/emqx/test/emqx_SUITE.erl index 48c2177e1..37e2d21c3 100644 --- a/test/emqx_SUITE.erl +++ b/apps/emqx/test/emqx_SUITE.erl @@ -19,7 +19,7 @@ -compile(export_all). -compile(nowarn_export_all). --include("emqx.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("common_test/include/ct.hrl"). diff --git a/test/emqx_SUITE_data/acl.conf b/apps/emqx/test/emqx_SUITE_data/acl.conf similarity index 100% rename from test/emqx_SUITE_data/acl.conf rename to apps/emqx/test/emqx_SUITE_data/acl.conf diff --git a/test/emqx_SUITE_data/loaded_modules b/apps/emqx/test/emqx_SUITE_data/loaded_modules similarity index 100% rename from test/emqx_SUITE_data/loaded_modules rename to apps/emqx/test/emqx_SUITE_data/loaded_modules diff --git a/test/emqx_SUITE_data/loaded_plugins b/apps/emqx/test/emqx_SUITE_data/loaded_plugins similarity index 100% rename from test/emqx_SUITE_data/loaded_plugins rename to apps/emqx/test/emqx_SUITE_data/loaded_plugins diff --git a/test/emqx_access_SUITE_data/acl.conf b/apps/emqx/test/emqx_access_SUITE_data/acl.conf similarity index 100% rename from test/emqx_access_SUITE_data/acl.conf rename to apps/emqx/test/emqx_access_SUITE_data/acl.conf diff --git a/test/emqx_access_SUITE_data/acl_deny_action.conf b/apps/emqx/test/emqx_access_SUITE_data/acl_deny_action.conf similarity index 100% rename from test/emqx_access_SUITE_data/acl_deny_action.conf rename to apps/emqx/test/emqx_access_SUITE_data/acl_deny_action.conf diff --git a/test/emqx_access_control_SUITE.erl b/apps/emqx/test/emqx_access_control_SUITE.erl similarity index 98% rename from test/emqx_access_control_SUITE.erl rename to apps/emqx/test/emqx_access_control_SUITE.erl index a327eea6d..7da7a28cb 100644 --- a/test/emqx_access_control_SUITE.erl +++ b/apps/emqx/test/emqx_access_control_SUITE.erl @@ -19,7 +19,7 @@ -compile(export_all). -compile(nowarn_export_all). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -include_lib("eunit/include/eunit.hrl"). all() -> emqx_ct:all(?MODULE). diff --git a/test/emqx_access_rule_SUITE.erl b/apps/emqx/test/emqx_access_rule_SUITE.erl similarity index 100% rename from test/emqx_access_rule_SUITE.erl rename to apps/emqx/test/emqx_access_rule_SUITE.erl diff --git a/test/emqx_acl_cache_SUITE.erl b/apps/emqx/test/emqx_acl_cache_SUITE.erl similarity index 100% rename from test/emqx_acl_cache_SUITE.erl rename to apps/emqx/test/emqx_acl_cache_SUITE.erl diff --git a/test/emqx_acl_test_mod.erl b/apps/emqx/test/emqx_acl_test_mod.erl similarity index 100% rename from test/emqx_acl_test_mod.erl rename to apps/emqx/test/emqx_acl_test_mod.erl diff --git a/test/emqx_alarm_SUITE.erl b/apps/emqx/test/emqx_alarm_SUITE.erl similarity index 97% rename from test/emqx_alarm_SUITE.erl rename to apps/emqx/test/emqx_alarm_SUITE.erl index 863806ff6..c575ec375 100644 --- a/test/emqx_alarm_SUITE.erl +++ b/apps/emqx/test/emqx_alarm_SUITE.erl @@ -19,8 +19,8 @@ -compile(export_all). -compile(nowarn_export_all). --include("emqx.hrl"). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -include_lib("eunit/include/eunit.hrl"). all() -> emqx_ct:all(?MODULE). diff --git a/test/emqx_banned_SUITE.erl b/apps/emqx/test/emqx_banned_SUITE.erl similarity index 98% rename from test/emqx_banned_SUITE.erl rename to apps/emqx/test/emqx_banned_SUITE.erl index d99530e12..885bff9e4 100644 --- a/test/emqx_banned_SUITE.erl +++ b/apps/emqx/test/emqx_banned_SUITE.erl @@ -19,7 +19,7 @@ -compile(export_all). -compile(nowarn_export_all). --include("emqx.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). -include_lib("eunit/include/eunit.hrl"). all() -> emqx_ct:all(?MODULE). diff --git a/test/emqx_batch_SUITE.erl b/apps/emqx/test/emqx_batch_SUITE.erl similarity index 100% rename from test/emqx_batch_SUITE.erl rename to apps/emqx/test/emqx_batch_SUITE.erl diff --git a/test/emqx_boot_SUITE.erl b/apps/emqx/test/emqx_boot_SUITE.erl similarity index 100% rename from test/emqx_boot_SUITE.erl rename to apps/emqx/test/emqx_boot_SUITE.erl diff --git a/test/emqx_broker_SUITE.erl b/apps/emqx/test/emqx_broker_SUITE.erl similarity index 98% rename from test/emqx_broker_SUITE.erl rename to apps/emqx/test/emqx_broker_SUITE.erl index d52132497..7bc4f5e84 100644 --- a/test/emqx_broker_SUITE.erl +++ b/apps/emqx/test/emqx_broker_SUITE.erl @@ -24,8 +24,8 @@ -include_lib("eunit/include/eunit.hrl"). -include_lib("common_test/include/ct.hrl"). --include("emqx.hrl"). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). all() -> emqx_ct:all(?MODULE). diff --git a/test/emqx_broker_helper_SUITE.erl b/apps/emqx/test/emqx_broker_helper_SUITE.erl similarity index 100% rename from test/emqx_broker_helper_SUITE.erl rename to apps/emqx/test/emqx_broker_helper_SUITE.erl diff --git a/test/emqx_channel_SUITE.erl b/apps/emqx/test/emqx_channel_SUITE.erl similarity index 99% rename from test/emqx_channel_SUITE.erl rename to apps/emqx/test/emqx_channel_SUITE.erl index 613da40ac..71bfe6e8b 100644 --- a/test/emqx_channel_SUITE.erl +++ b/apps/emqx/test/emqx_channel_SUITE.erl @@ -19,8 +19,8 @@ -compile(export_all). -compile(nowarn_export_all). --include("emqx.hrl"). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -include_lib("eunit/include/eunit.hrl"). diff --git a/test/emqx_client_SUITE.erl b/apps/emqx/test/emqx_client_SUITE.erl similarity index 99% rename from test/emqx_client_SUITE.erl rename to apps/emqx/test/emqx_client_SUITE.erl index e231e40ab..eb552ae90 100644 --- a/test/emqx_client_SUITE.erl +++ b/apps/emqx/test/emqx_client_SUITE.erl @@ -21,7 +21,7 @@ -import(lists, [nth/2]). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("common_test/include/ct.hrl"). diff --git a/test/emqx_cm_SUITE.erl b/apps/emqx/test/emqx_cm_SUITE.erl similarity index 99% rename from test/emqx_cm_SUITE.erl rename to apps/emqx/test/emqx_cm_SUITE.erl index 6a4b84d01..7ba4f56c3 100644 --- a/test/emqx_cm_SUITE.erl +++ b/apps/emqx/test/emqx_cm_SUITE.erl @@ -19,7 +19,7 @@ -compile(export_all). -compile(nowarn_export_all). --include("emqx.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). -include_lib("eunit/include/eunit.hrl"). -define(CM, emqx_cm). diff --git a/test/emqx_cm_locker_SUITE.erl b/apps/emqx/test/emqx_cm_locker_SUITE.erl similarity index 100% rename from test/emqx_cm_locker_SUITE.erl rename to apps/emqx/test/emqx_cm_locker_SUITE.erl diff --git a/test/emqx_cm_registry_SUITE.erl b/apps/emqx/test/emqx_cm_registry_SUITE.erl similarity index 100% rename from test/emqx_cm_registry_SUITE.erl rename to apps/emqx/test/emqx_cm_registry_SUITE.erl diff --git a/test/emqx_connection_SUITE.erl b/apps/emqx/test/emqx_connection_SUITE.erl similarity index 99% rename from test/emqx_connection_SUITE.erl rename to apps/emqx/test/emqx_connection_SUITE.erl index b908fe4ab..0c3706787 100644 --- a/test/emqx_connection_SUITE.erl +++ b/apps/emqx/test/emqx_connection_SUITE.erl @@ -19,7 +19,7 @@ -compile(export_all). -compile(nowarn_export_all). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -include_lib("eunit/include/eunit.hrl"). all() -> emqx_ct:all(?MODULE). diff --git a/test/emqx_ctl_SUITE.erl b/apps/emqx/test/emqx_ctl_SUITE.erl similarity index 100% rename from test/emqx_ctl_SUITE.erl rename to apps/emqx/test/emqx_ctl_SUITE.erl diff --git a/test/emqx_flapping_SUITE.erl b/apps/emqx/test/emqx_flapping_SUITE.erl similarity index 100% rename from test/emqx_flapping_SUITE.erl rename to apps/emqx/test/emqx_flapping_SUITE.erl diff --git a/test/emqx_frame_SUITE.erl b/apps/emqx/test/emqx_frame_SUITE.erl similarity index 99% rename from test/emqx_frame_SUITE.erl rename to apps/emqx/test/emqx_frame_SUITE.erl index 5d4e146db..8471cd1f2 100644 --- a/test/emqx_frame_SUITE.erl +++ b/apps/emqx/test/emqx_frame_SUITE.erl @@ -19,7 +19,7 @@ -compile(export_all). -compile(nowarn_export_all). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("common_test/include/ct.hrl"). -include_lib("emqx_ct_helpers/include/emqx_ct.hrl"). diff --git a/test/emqx_gc_SUITE.erl b/apps/emqx/test/emqx_gc_SUITE.erl similarity index 100% rename from test/emqx_gc_SUITE.erl rename to apps/emqx/test/emqx_gc_SUITE.erl diff --git a/test/emqx_global_gc_SUITE.erl b/apps/emqx/test/emqx_global_gc_SUITE.erl similarity index 100% rename from test/emqx_global_gc_SUITE.erl rename to apps/emqx/test/emqx_global_gc_SUITE.erl diff --git a/test/emqx_guid_SUITE.erl b/apps/emqx/test/emqx_guid_SUITE.erl similarity index 100% rename from test/emqx_guid_SUITE.erl rename to apps/emqx/test/emqx_guid_SUITE.erl diff --git a/test/emqx_hooks_SUITE.erl b/apps/emqx/test/emqx_hooks_SUITE.erl similarity index 100% rename from test/emqx_hooks_SUITE.erl rename to apps/emqx/test/emqx_hooks_SUITE.erl diff --git a/test/emqx_inflight_SUITE.erl b/apps/emqx/test/emqx_inflight_SUITE.erl similarity index 100% rename from test/emqx_inflight_SUITE.erl rename to apps/emqx/test/emqx_inflight_SUITE.erl diff --git a/test/emqx_json_SUITE.erl b/apps/emqx/test/emqx_json_SUITE.erl similarity index 100% rename from test/emqx_json_SUITE.erl rename to apps/emqx/test/emqx_json_SUITE.erl diff --git a/test/emqx_keepalive_SUITE.erl b/apps/emqx/test/emqx_keepalive_SUITE.erl similarity index 100% rename from test/emqx_keepalive_SUITE.erl rename to apps/emqx/test/emqx_keepalive_SUITE.erl diff --git a/test/emqx_limiter_SUITE.erl b/apps/emqx/test/emqx_limiter_SUITE.erl similarity index 100% rename from test/emqx_limiter_SUITE.erl rename to apps/emqx/test/emqx_limiter_SUITE.erl diff --git a/test/emqx_listeners_SUITE.erl b/apps/emqx/test/emqx_listeners_SUITE.erl similarity index 97% rename from test/emqx_listeners_SUITE.erl rename to apps/emqx/test/emqx_listeners_SUITE.erl index 1472cc072..d7960bd57 100644 --- a/test/emqx_listeners_SUITE.erl +++ b/apps/emqx/test/emqx_listeners_SUITE.erl @@ -19,8 +19,8 @@ -compile(export_all). -compile(nowarn_export_all). --include("emqx.hrl"). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -include_lib("eunit/include/eunit.hrl"). all() -> emqx_ct:all(?MODULE). diff --git a/test/emqx_logger_SUITE.erl b/apps/emqx/test/emqx_logger_SUITE.erl similarity index 100% rename from test/emqx_logger_SUITE.erl rename to apps/emqx/test/emqx_logger_SUITE.erl diff --git a/test/emqx_logger_formatter_SUITE.erl b/apps/emqx/test/emqx_logger_formatter_SUITE.erl similarity index 100% rename from test/emqx_logger_formatter_SUITE.erl rename to apps/emqx/test/emqx_logger_formatter_SUITE.erl diff --git a/test/emqx_message_SUITE.erl b/apps/emqx/test/emqx_message_SUITE.erl similarity index 99% rename from test/emqx_message_SUITE.erl rename to apps/emqx/test/emqx_message_SUITE.erl index 2eebdc1dc..fc52feb24 100644 --- a/test/emqx_message_SUITE.erl +++ b/apps/emqx/test/emqx_message_SUITE.erl @@ -19,8 +19,8 @@ -compile(export_all). -compile(nowarn_export_all). --include("emqx.hrl"). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -include_lib("eunit/include/eunit.hrl"). all() -> emqx_ct:all(?MODULE). diff --git a/test/emqx_metrics_SUITE.erl b/apps/emqx/test/emqx_metrics_SUITE.erl similarity index 99% rename from test/emqx_metrics_SUITE.erl rename to apps/emqx/test/emqx_metrics_SUITE.erl index 33f297e7d..9f107bffd 100644 --- a/test/emqx_metrics_SUITE.erl +++ b/apps/emqx/test/emqx_metrics_SUITE.erl @@ -19,7 +19,7 @@ -compile(export_all). -compile(nowarn_export_all). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -include_lib("eunit/include/eunit.hrl"). all() -> emqx_ct:all(?MODULE). diff --git a/test/emqx_misc_SUITE.erl b/apps/emqx/test/emqx_misc_SUITE.erl similarity index 100% rename from test/emqx_misc_SUITE.erl rename to apps/emqx/test/emqx_misc_SUITE.erl diff --git a/test/emqx_mod_acl_internal_SUITE.erl b/apps/emqx/test/emqx_mod_acl_internal_SUITE.erl similarity index 98% rename from test/emqx_mod_acl_internal_SUITE.erl rename to apps/emqx/test/emqx_mod_acl_internal_SUITE.erl index bd9a0bf5a..8734e5f55 100644 --- a/test/emqx_mod_acl_internal_SUITE.erl +++ b/apps/emqx/test/emqx_mod_acl_internal_SUITE.erl @@ -19,7 +19,7 @@ -compile(export_all). -compile(nowarn_export_all). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -include_lib("eunit/include/eunit.hrl"). all() -> emqx_ct:all(?MODULE). diff --git a/test/emqx_mod_delayed_SUITE.erl b/apps/emqx/test/emqx_mod_delayed_SUITE.erl similarity index 98% rename from test/emqx_mod_delayed_SUITE.erl rename to apps/emqx/test/emqx_mod_delayed_SUITE.erl index 3759e8c4d..2badb9867 100644 --- a/test/emqx_mod_delayed_SUITE.erl +++ b/apps/emqx/test/emqx_mod_delayed_SUITE.erl @@ -25,7 +25,7 @@ -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). --include_lib("emqx/include/emqx.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). %%-------------------------------------------------------------------- %% Setups diff --git a/test/emqx_mod_presence_SUITE.erl b/apps/emqx/test/emqx_mod_presence_SUITE.erl similarity index 98% rename from test/emqx_mod_presence_SUITE.erl rename to apps/emqx/test/emqx_mod_presence_SUITE.erl index 49d5d206b..955526558 100644 --- a/test/emqx_mod_presence_SUITE.erl +++ b/apps/emqx/test/emqx_mod_presence_SUITE.erl @@ -19,7 +19,7 @@ -compile(export_all). -compile(nowarn_export_all). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -include_lib("eunit/include/eunit.hrl"). all() -> emqx_ct:all(?MODULE). diff --git a/test/emqx_mod_rewrite_SUITE.erl b/apps/emqx/test/emqx_mod_rewrite_SUITE.erl similarity index 98% rename from test/emqx_mod_rewrite_SUITE.erl rename to apps/emqx/test/emqx_mod_rewrite_SUITE.erl index e3c19200e..1dcfb87b2 100644 --- a/test/emqx_mod_rewrite_SUITE.erl +++ b/apps/emqx/test/emqx_mod_rewrite_SUITE.erl @@ -19,7 +19,7 @@ -compile(export_all). -compile(nowarn_export_all). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -include_lib("eunit/include/eunit.hrl"). -define(RULES, [{rewrite, pub, <<"x/#">>,<<"^x/y/(.+)$">>,<<"z/y/$1">>}, diff --git a/test/emqx_mod_subscription_SUITE.erl b/apps/emqx/test/emqx_mod_subscription_SUITE.erl similarity index 98% rename from test/emqx_mod_subscription_SUITE.erl rename to apps/emqx/test/emqx_mod_subscription_SUITE.erl index 06cd17cea..57fbf3b66 100644 --- a/test/emqx_mod_subscription_SUITE.erl +++ b/apps/emqx/test/emqx_mod_subscription_SUITE.erl @@ -19,7 +19,7 @@ -compile(export_all). -compile(nowarn_export_all). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -include_lib("eunit/include/eunit.hrl"). all() -> emqx_ct:all(?MODULE). diff --git a/test/emqx_mod_sup_SUITE.erl b/apps/emqx/test/emqx_mod_sup_SUITE.erl similarity index 100% rename from test/emqx_mod_sup_SUITE.erl rename to apps/emqx/test/emqx_mod_sup_SUITE.erl diff --git a/test/emqx_mod_topic_metrics_SUITE.erl b/apps/emqx/test/emqx_mod_topic_metrics_SUITE.erl similarity index 92% rename from test/emqx_mod_topic_metrics_SUITE.erl rename to apps/emqx/test/emqx_mod_topic_metrics_SUITE.erl index 4ac1b00eb..188b5881b 100644 --- a/test/emqx_mod_topic_metrics_SUITE.erl +++ b/apps/emqx/test/emqx_mod_topic_metrics_SUITE.erl @@ -36,11 +36,13 @@ t_nonexistent_topic_metrics(_) -> ?assertEqual({error, topic_not_found}, emqx_mod_topic_metrics:val(<<"a/b/c">>, 'messages.in')), ?assertEqual({error, topic_not_found}, emqx_mod_topic_metrics:inc(<<"a/b/c">>, 'messages.in')), ?assertEqual({error, topic_not_found}, emqx_mod_topic_metrics:rate(<<"a/b/c">>, 'messages.in')), + ?assertEqual({error, topic_not_found}, emqx_mod_topic_metrics:rates(<<"a/b/c">>, 'messages.in')), emqx_mod_topic_metrics:register(<<"a/b/c">>), ?assertEqual(0, emqx_mod_topic_metrics:val(<<"a/b/c">>, 'messages.in')), ?assertEqual({error, invalid_metric}, emqx_mod_topic_metrics:val(<<"a/b/c">>, 'invalid.metrics')), ?assertEqual({error, invalid_metric}, emqx_mod_topic_metrics:inc(<<"a/b/c">>, 'invalid.metrics')), ?assertEqual({error, invalid_metric}, emqx_mod_topic_metrics:rate(<<"a/b/c">>, 'invalid.metrics')), + ?assertEqual({error, invalid_metric}, emqx_mod_topic_metrics:rates(<<"a/b/c">>, 'invalid.metrics')), emqx_mod_topic_metrics:unregister(<<"a/b/c">>), emqx_mod_topic_metrics:unload([]). @@ -57,6 +59,7 @@ t_topic_metrics(_) -> ?assertEqual(ok, emqx_mod_topic_metrics:inc(<<"a/b/c">>, 'messages.in')), ?assertEqual(1, emqx_mod_topic_metrics:val(<<"a/b/c">>, 'messages.in')), ?assert(emqx_mod_topic_metrics:rate(<<"a/b/c">>, 'messages.in') =:= 0), + ?assert(emqx_mod_topic_metrics:rates(<<"a/b/c">>, 'messages.in') =:= #{long => 0,medium => 0,short => 0}), emqx_mod_topic_metrics:unregister(<<"a/b/c">>), emqx_mod_topic_metrics:unload([]). @@ -89,4 +92,4 @@ t_hook(_) -> ?assertEqual(1, emqx_mod_topic_metrics:val(<<"a/b/c">>, 'messages.qos0.out')), ?assertEqual(1, emqx_mod_topic_metrics:val(<<"a/b/c">>, 'messages.dropped')), emqx_mod_topic_metrics:unregister(<<"a/b/c">>), - emqx_mod_topic_metrics:unload([]). \ No newline at end of file + emqx_mod_topic_metrics:unload([]). diff --git a/test/emqx_modules_SUITE.erl b/apps/emqx/test/emqx_modules_SUITE.erl similarity index 100% rename from test/emqx_modules_SUITE.erl rename to apps/emqx/test/emqx_modules_SUITE.erl diff --git a/test/emqx_mountpoint_SUITE.erl b/apps/emqx/test/emqx_mountpoint_SUITE.erl similarity index 98% rename from test/emqx_mountpoint_SUITE.erl rename to apps/emqx/test/emqx_mountpoint_SUITE.erl index 26d717cd8..56b000f40 100644 --- a/test/emqx_mountpoint_SUITE.erl +++ b/apps/emqx/test/emqx_mountpoint_SUITE.erl @@ -25,7 +25,7 @@ , replvar/2 ]). --include("emqx.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). -include_lib("eunit/include/eunit.hrl"). all() -> emqx_ct:all(?MODULE). diff --git a/test/emqx_mqtt_SUITE.erl b/apps/emqx/test/emqx_mqtt_SUITE.erl similarity index 99% rename from test/emqx_mqtt_SUITE.erl rename to apps/emqx/test/emqx_mqtt_SUITE.erl index 27bd46a7f..371f07ee8 100644 --- a/test/emqx_mqtt_SUITE.erl +++ b/apps/emqx/test/emqx_mqtt_SUITE.erl @@ -19,7 +19,7 @@ -compile(export_all). -compile(nowarn_export_all). --include("emqx.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("common_test/include/ct.hrl"). diff --git a/test/emqx_mqtt_caps_SUITE.erl b/apps/emqx/test/emqx_mqtt_caps_SUITE.erl similarity index 98% rename from test/emqx_mqtt_caps_SUITE.erl rename to apps/emqx/test/emqx_mqtt_caps_SUITE.erl index 695d69642..c65647608 100644 --- a/test/emqx_mqtt_caps_SUITE.erl +++ b/apps/emqx/test/emqx_mqtt_caps_SUITE.erl @@ -19,7 +19,7 @@ -compile(export_all). -compile(nowarn_export_all). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -include_lib("eunit/include/eunit.hrl"). all() -> emqx_ct:all(?MODULE). diff --git a/test/emqx_mqtt_props_SUITE.erl b/apps/emqx/test/emqx_mqtt_props_SUITE.erl similarity index 98% rename from test/emqx_mqtt_props_SUITE.erl rename to apps/emqx/test/emqx_mqtt_props_SUITE.erl index f440b386d..f35d7f433 100644 --- a/test/emqx_mqtt_props_SUITE.erl +++ b/apps/emqx/test/emqx_mqtt_props_SUITE.erl @@ -19,7 +19,7 @@ -compile(export_all). -compile(nowarn_export_all). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("emqx_ct_helpers/include/emqx_ct.hrl"). diff --git a/test/emqx_mqueue_SUITE.erl b/apps/emqx/test/emqx_mqueue_SUITE.erl similarity index 98% rename from test/emqx_mqueue_SUITE.erl rename to apps/emqx/test/emqx_mqueue_SUITE.erl index 3be1344a2..d950decb6 100644 --- a/test/emqx_mqueue_SUITE.erl +++ b/apps/emqx/test/emqx_mqueue_SUITE.erl @@ -19,8 +19,8 @@ -compile(export_all). -compile(nowarn_export_all). --include("emqx.hrl"). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -include_lib("eunit/include/eunit.hrl"). diff --git a/test/emqx_os_mon_SUITE.erl b/apps/emqx/test/emqx_os_mon_SUITE.erl similarity index 100% rename from test/emqx_os_mon_SUITE.erl rename to apps/emqx/test/emqx_os_mon_SUITE.erl diff --git a/test/emqx_packet_SUITE.erl b/apps/emqx/test/emqx_packet_SUITE.erl similarity index 99% rename from test/emqx_packet_SUITE.erl rename to apps/emqx/test/emqx_packet_SUITE.erl index 00ab6e0c5..0b95dbd24 100644 --- a/test/emqx_packet_SUITE.erl +++ b/apps/emqx/test/emqx_packet_SUITE.erl @@ -19,8 +19,8 @@ -compile(export_all). -compile(nowarn_export_all). --include("emqx.hrl"). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -include_lib("eunit/include/eunit.hrl"). diff --git a/test/emqx_pd_SUITE.erl b/apps/emqx/test/emqx_pd_SUITE.erl similarity index 100% rename from test/emqx_pd_SUITE.erl rename to apps/emqx/test/emqx_pd_SUITE.erl diff --git a/test/emqx_plugins_SUITE.erl b/apps/emqx/test/emqx_plugins_SUITE.erl similarity index 99% rename from test/emqx_plugins_SUITE.erl rename to apps/emqx/test/emqx_plugins_SUITE.erl index ad99209e6..9b7e22289 100644 --- a/test/emqx_plugins_SUITE.erl +++ b/apps/emqx/test/emqx_plugins_SUITE.erl @@ -19,7 +19,7 @@ -compile(export_all). -compile(nowarn_export_all). --include("emqx.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). -include_lib("eunit/include/eunit.hrl"). all() -> emqx_ct:all(?MODULE). diff --git a/test/emqx_plugins_SUITE_data/emqx_mini_plugin/Makefile b/apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/Makefile similarity index 100% rename from test/emqx_plugins_SUITE_data/emqx_mini_plugin/Makefile rename to apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/Makefile diff --git a/test/emqx_plugins_SUITE_data/emqx_mini_plugin/etc/emqx_mini_plugin.conf b/apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/etc/emqx_mini_plugin.conf similarity index 100% rename from test/emqx_plugins_SUITE_data/emqx_mini_plugin/etc/emqx_mini_plugin.conf rename to apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/etc/emqx_mini_plugin.conf diff --git a/test/emqx_plugins_SUITE_data/emqx_mini_plugin/priv/emqx_mini_plugin.schema b/apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/priv/emqx_mini_plugin.schema similarity index 100% rename from test/emqx_plugins_SUITE_data/emqx_mini_plugin/priv/emqx_mini_plugin.schema rename to apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/priv/emqx_mini_plugin.schema diff --git a/test/emqx_plugins_SUITE_data/emqx_mini_plugin/rebar.config b/apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/rebar.config similarity index 100% rename from test/emqx_plugins_SUITE_data/emqx_mini_plugin/rebar.config rename to apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/rebar.config diff --git a/test/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin.app.src b/apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin.app.src similarity index 94% rename from test/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin.app.src rename to apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin.app.src index 20e17efda..413b4e1fd 100644 --- a/test/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin.app.src +++ b/apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin.app.src @@ -1,6 +1,6 @@ {application, emqx_mini_plugin, [{description, "An EMQ X plugin for testcase"}, - {vsn, "git"}, + {vsn, "0.1"}, {modules, []}, {registered, []}, {mod, {emqx_mini_plugin_app, []}}, diff --git a/test/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin_app.erl b/apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin_app.erl similarity index 100% rename from test/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin_app.erl rename to apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin_app.erl diff --git a/test/emqx_pmon_SUITE.erl b/apps/emqx/test/emqx_pmon_SUITE.erl similarity index 100% rename from test/emqx_pmon_SUITE.erl rename to apps/emqx/test/emqx_pmon_SUITE.erl diff --git a/test/emqx_pool_SUITE.erl b/apps/emqx/test/emqx_pool_SUITE.erl similarity index 100% rename from test/emqx_pool_SUITE.erl rename to apps/emqx/test/emqx_pool_SUITE.erl diff --git a/test/emqx_pqueue_SUITE.erl b/apps/emqx/test/emqx_pqueue_SUITE.erl similarity index 100% rename from test/emqx_pqueue_SUITE.erl rename to apps/emqx/test/emqx_pqueue_SUITE.erl diff --git a/test/emqx_reason_codes_SUITE.erl b/apps/emqx/test/emqx_reason_codes_SUITE.erl similarity index 96% rename from test/emqx_reason_codes_SUITE.erl rename to apps/emqx/test/emqx_reason_codes_SUITE.erl index 027d6d85f..5ed810f24 100644 --- a/test/emqx_reason_codes_SUITE.erl +++ b/apps/emqx/test/emqx_reason_codes_SUITE.erl @@ -19,7 +19,7 @@ -compile(export_all). -compile(nowarn_export_all). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -include_lib("eunit/include/eunit.hrl"). all() -> emqx_ct:all(?MODULE). diff --git a/test/emqx_request_handler.erl b/apps/emqx/test/emqx_request_handler.erl similarity index 98% rename from test/emqx_request_handler.erl rename to apps/emqx/test/emqx_request_handler.erl index 690d45d34..c76e093c8 100644 --- a/test/emqx_request_handler.erl +++ b/apps/emqx/test/emqx_request_handler.erl @@ -18,7 +18,7 @@ -export([start_link/4, stop/1]). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -type qos() :: emqx_mqtt_types:qos_name() | emqx_mqtt_types:qos(). -type topic() :: emqx_topic:topic(). diff --git a/test/emqx_request_responser_SUITE.erl b/apps/emqx/test/emqx_request_responser_SUITE.erl similarity index 98% rename from test/emqx_request_responser_SUITE.erl rename to apps/emqx/test/emqx_request_responser_SUITE.erl index 7d66c7760..67187ed3f 100644 --- a/test/emqx_request_responser_SUITE.erl +++ b/apps/emqx/test/emqx_request_responser_SUITE.erl @@ -17,7 +17,7 @@ -compile(export_all). -compile(nowarn_export_all). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("common_test/include/ct.hrl"). diff --git a/test/emqx_request_sender.erl b/apps/emqx/test/emqx_request_sender.erl similarity index 98% rename from test/emqx_request_sender.erl rename to apps/emqx/test/emqx_request_sender.erl index aed845a42..b07622bb9 100644 --- a/test/emqx_request_sender.erl +++ b/apps/emqx/test/emqx_request_sender.erl @@ -18,7 +18,7 @@ -export([start_link/3, stop/1, send/6]). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). start_link(ResponseTopic, QoS, Options0) -> Parent = self(), diff --git a/test/emqx_router_SUITE.erl b/apps/emqx/test/emqx_router_SUITE.erl similarity index 98% rename from test/emqx_router_SUITE.erl rename to apps/emqx/test/emqx_router_SUITE.erl index fb2d34ea7..06d310072 100644 --- a/test/emqx_router_SUITE.erl +++ b/apps/emqx/test/emqx_router_SUITE.erl @@ -19,7 +19,7 @@ -compile(export_all). -compile(nowarn_export_all). --include("emqx.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). -include_lib("eunit/include/eunit.hrl"). -define(R, emqx_router). diff --git a/test/emqx_router_helper_SUITE.erl b/apps/emqx/test/emqx_router_helper_SUITE.erl similarity index 100% rename from test/emqx_router_helper_SUITE.erl rename to apps/emqx/test/emqx_router_helper_SUITE.erl diff --git a/test/emqx_sequence_SUITE.erl b/apps/emqx/test/emqx_sequence_SUITE.erl similarity index 100% rename from test/emqx_sequence_SUITE.erl rename to apps/emqx/test/emqx_sequence_SUITE.erl diff --git a/test/emqx_session_SUITE.erl b/apps/emqx/test/emqx_session_SUITE.erl similarity index 99% rename from test/emqx_session_SUITE.erl rename to apps/emqx/test/emqx_session_SUITE.erl index dd9611b71..452e1d622 100644 --- a/test/emqx_session_SUITE.erl +++ b/apps/emqx/test/emqx_session_SUITE.erl @@ -19,7 +19,7 @@ -compile(export_all). -compile(nowarn_export_all). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -include_lib("eunit/include/eunit.hrl"). all() -> emqx_ct:all(?MODULE). diff --git a/test/emqx_shared_sub_SUITE.erl b/apps/emqx/test/emqx_shared_sub_SUITE.erl similarity index 99% rename from test/emqx_shared_sub_SUITE.erl rename to apps/emqx/test/emqx_shared_sub_SUITE.erl index 218e8a073..c827a8fc2 100644 --- a/test/emqx_shared_sub_SUITE.erl +++ b/apps/emqx/test/emqx_shared_sub_SUITE.erl @@ -19,7 +19,7 @@ -compile(export_all). -compile(nowarn_export_all). --include("emqx.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("common_test/include/ct.hrl"). diff --git a/test/emqx_stats_SUITE.erl b/apps/emqx/test/emqx_stats_SUITE.erl similarity index 100% rename from test/emqx_stats_SUITE.erl rename to apps/emqx/test/emqx_stats_SUITE.erl diff --git a/test/emqx_sup_SUITE.erl b/apps/emqx/test/emqx_sup_SUITE.erl similarity index 100% rename from test/emqx_sup_SUITE.erl rename to apps/emqx/test/emqx_sup_SUITE.erl diff --git a/test/emqx_sys_SUITE.erl b/apps/emqx/test/emqx_sys_SUITE.erl similarity index 100% rename from test/emqx_sys_SUITE.erl rename to apps/emqx/test/emqx_sys_SUITE.erl diff --git a/test/emqx_sys_mon_SUITE.erl b/apps/emqx/test/emqx_sys_mon_SUITE.erl similarity index 99% rename from test/emqx_sys_mon_SUITE.erl rename to apps/emqx/test/emqx_sys_mon_SUITE.erl index ef0e31957..520c45e54 100644 --- a/test/emqx_sys_mon_SUITE.erl +++ b/apps/emqx/test/emqx_sys_mon_SUITE.erl @@ -19,7 +19,7 @@ -compile(export_all). -compile(nowarn_export_all). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -include_lib("eunit/include/eunit.hrl"). -define(SYSMON, emqx_sys_mon). diff --git a/test/emqx_tables_SUITE.erl b/apps/emqx/test/emqx_tables_SUITE.erl similarity index 100% rename from test/emqx_tables_SUITE.erl rename to apps/emqx/test/emqx_tables_SUITE.erl diff --git a/test/emqx_takeover_SUITE.erl b/apps/emqx/test/emqx_takeover_SUITE.erl similarity index 99% rename from test/emqx_takeover_SUITE.erl rename to apps/emqx/test/emqx_takeover_SUITE.erl index ca5ebb084..98f258440 100644 --- a/test/emqx_takeover_SUITE.erl +++ b/apps/emqx/test/emqx_takeover_SUITE.erl @@ -19,7 +19,7 @@ -compile(export_all). -compile(nowarn_export_all). --include("emqx.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("common_test/include/ct.hrl"). diff --git a/test/emqx_topic_SUITE.erl b/apps/emqx/test/emqx_topic_SUITE.erl similarity index 100% rename from test/emqx_topic_SUITE.erl rename to apps/emqx/test/emqx_topic_SUITE.erl diff --git a/test/emqx_tracer_SUITE.erl b/apps/emqx/test/emqx_tracer_SUITE.erl similarity index 100% rename from test/emqx_tracer_SUITE.erl rename to apps/emqx/test/emqx_tracer_SUITE.erl diff --git a/test/emqx_trie_SUITE.erl b/apps/emqx/test/emqx_trie_SUITE.erl similarity index 99% rename from test/emqx_trie_SUITE.erl rename to apps/emqx/test/emqx_trie_SUITE.erl index f1db3813c..b3d7549f7 100644 --- a/test/emqx_trie_SUITE.erl +++ b/apps/emqx/test/emqx_trie_SUITE.erl @@ -19,7 +19,7 @@ -compile(export_all). -compile(nowarn_export_all). --include("emqx.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). -include_lib("eunit/include/eunit.hrl"). -define(TRIE, emqx_trie). diff --git a/test/emqx_vm_SUITE.erl b/apps/emqx/test/emqx_vm_SUITE.erl similarity index 100% rename from test/emqx_vm_SUITE.erl rename to apps/emqx/test/emqx_vm_SUITE.erl diff --git a/test/emqx_vm_mon_SUITE.erl b/apps/emqx/test/emqx_vm_mon_SUITE.erl similarity index 100% rename from test/emqx_vm_mon_SUITE.erl rename to apps/emqx/test/emqx_vm_mon_SUITE.erl diff --git a/test/emqx_ws_connection_SUITE.erl b/apps/emqx/test/emqx_ws_connection_SUITE.erl similarity index 99% rename from test/emqx_ws_connection_SUITE.erl rename to apps/emqx/test/emqx_ws_connection_SUITE.erl index 125b14a74..83fbcb195 100644 --- a/test/emqx_ws_connection_SUITE.erl +++ b/apps/emqx/test/emqx_ws_connection_SUITE.erl @@ -16,8 +16,8 @@ -module(emqx_ws_connection_SUITE). --include("emqx.hrl"). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -include_lib("eunit/include/eunit.hrl"). -compile(export_all). diff --git a/test/emqx_zone_SUITE.erl b/apps/emqx/test/emqx_zone_SUITE.erl similarity index 100% rename from test/emqx_zone_SUITE.erl rename to apps/emqx/test/emqx_zone_SUITE.erl diff --git a/test/mqtt_protocol_v5_SUITE.erl b/apps/emqx/test/mqtt_protocol_v5_SUITE.erl similarity index 99% rename from test/mqtt_protocol_v5_SUITE.erl rename to apps/emqx/test/mqtt_protocol_v5_SUITE.erl index 50fc9c04d..f171d0f67 100644 --- a/test/mqtt_protocol_v5_SUITE.erl +++ b/apps/emqx/test/mqtt_protocol_v5_SUITE.erl @@ -19,8 +19,8 @@ -compile(export_all). -compile(nowarn_export_all). --include("emqx.hrl"). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -include_lib("eunit/include/eunit.hrl"). -import(lists, [nth/2]). diff --git a/test/props/prop_emqx_base62.erl b/apps/emqx/test/props/prop_emqx_base62.erl similarity index 100% rename from test/props/prop_emqx_base62.erl rename to apps/emqx/test/props/prop_emqx_base62.erl diff --git a/test/props/prop_emqx_frame.erl b/apps/emqx/test/props/prop_emqx_frame.erl similarity index 98% rename from test/props/prop_emqx_frame.erl rename to apps/emqx/test/props/prop_emqx_frame.erl index 731e4ba1e..da763f8f5 100644 --- a/test/props/prop_emqx_frame.erl +++ b/apps/emqx/test/props/prop_emqx_frame.erl @@ -16,7 +16,7 @@ -module(prop_emqx_frame). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -include_lib("proper/include/proper.hrl"). %%-------------------------------------------------------------------- diff --git a/test/props/prop_emqx_json.erl b/apps/emqx/test/props/prop_emqx_json.erl similarity index 100% rename from test/props/prop_emqx_json.erl rename to apps/emqx/test/props/prop_emqx_json.erl diff --git a/test/props/prop_emqx_psk.erl b/apps/emqx/test/props/prop_emqx_psk.erl similarity index 100% rename from test/props/prop_emqx_psk.erl rename to apps/emqx/test/props/prop_emqx_psk.erl diff --git a/test/props/prop_emqx_reason_codes.erl b/apps/emqx/test/props/prop_emqx_reason_codes.erl similarity index 98% rename from test/props/prop_emqx_reason_codes.erl rename to apps/emqx/test/props/prop_emqx_reason_codes.erl index f6f5e81b0..2b90d2e43 100644 --- a/test/props/prop_emqx_reason_codes.erl +++ b/apps/emqx/test/props/prop_emqx_reason_codes.erl @@ -16,7 +16,7 @@ -module(prop_emqx_reason_codes). --include("emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). -include_lib("proper/include/proper.hrl"). %%-------------------------------------------------------------------- diff --git a/test/props/prop_emqx_rpc.erl b/apps/emqx/test/props/prop_emqx_rpc.erl similarity index 100% rename from test/props/prop_emqx_rpc.erl rename to apps/emqx/test/props/prop_emqx_rpc.erl diff --git a/test/props/prop_emqx_sys.erl b/apps/emqx/test/props/prop_emqx_sys.erl similarity index 100% rename from test/props/prop_emqx_sys.erl rename to apps/emqx/test/props/prop_emqx_sys.erl diff --git a/apps/emqx_auth_clientid/README.md b/apps/emqx_auth_clientid/README.md new file mode 100644 index 000000000..991e74cb1 --- /dev/null +++ b/apps/emqx_auth_clientid/README.md @@ -0,0 +1,117 @@ +emqx_auth_clientid +================== + +Authentication with ClientId and Password + +Build +----- + +``` +make && make tests +``` + +Configuration +------------- + +etc/emqx_auth_clientid.conf: + +``` +## Password hash. +## +## Value: plain | md5 | sha | sha256 +auth.client.password_hash = sha256 +``` + +[REST API](https://developer.emqx.io/docs/emq/v3/en/rest.html) +------------ + +List all clientids: + +``` +# Request +GET api/v4/auth_clientid + +# Response +{ + "code": 0, + "data": ["clientid1"] +} +``` + +Add clientid: + +``` +# Request +POST api/v4/auth_clientid +{ + "clientid": "a_client_id", + "password": "password" +} + +# Response +{ + "code": 0 +} +``` + +Update password for a clientid: + +``` +# Request +PUT api/v4/auth_clientid/$CLIENTID + +{ + "password": "password" +} + +# Response +{ + "code": 0 +} +``` + +Lookup a clientid info: + +``` +# Request +GET api/v4/auth_clientid/$CLIENTID + +# Response +{ + "code": 0, + "data": { + "clientid": "a_client_id", + "password": "hash_password" + } +} +``` + +Delete a clientid: + +``` +# Request +DELETE api/v4/auth_clientid/$CLIENTID + +# Response +{ + "code": 0 +} +``` + +Load the Plugin +--------------- + +``` +./bin/emqx_ctl plugins load emqx_auth_clientid +``` + +License +------- + +Apache License Version 2.0 + +Author +------ + +EMQ X Team. + diff --git a/apps/emqx_auth_clientid/TODO b/apps/emqx_auth_clientid/TODO new file mode 100644 index 000000000..a6e013c83 --- /dev/null +++ b/apps/emqx_auth_clientid/TODO @@ -0,0 +1,3 @@ +1. Hash password +2. Add Test cases +3. Hot Reloader diff --git a/apps/emqx_auth_clientid/include/emqx_auth_clientid.hrl b/apps/emqx_auth_clientid/include/emqx_auth_clientid.hrl new file mode 100644 index 000000000..328a46bcd --- /dev/null +++ b/apps/emqx_auth_clientid/include/emqx_auth_clientid.hrl @@ -0,0 +1,13 @@ +-define(APP, emqx_auth_clientid). + +-record(auth_metrics, { + success = 'client.auth.success', + failure = 'client.auth.failure', + ignore = 'client.auth.ignore' + }). + +-define(METRICS(Type), tl(tuple_to_list(#Type{}))). +-define(METRICS(Type, K), #Type{}#Type.K). + +-define(AUTH_METRICS, ?METRICS(auth_metrics)). +-define(AUTH_METRICS(K), ?METRICS(auth_metrics, K)). \ No newline at end of file diff --git a/apps/emqx_auth_clientid/priv/emqx_auth_clientid.schema b/apps/emqx_auth_clientid/priv/emqx_auth_clientid.schema new file mode 100644 index 000000000..db21d8e3e --- /dev/null +++ b/apps/emqx_auth_clientid/priv/emqx_auth_clientid.schema @@ -0,0 +1,26 @@ +%%-*- mode: erlang -*- +%% emqx_auth_clientid config mapping + +{mapping, "auth.client.password_hash", "emqx_auth_clientid.password_hash", [ + {default, sha256}, + {datatype, {enum, [plain, md5, sha, sha256]}} +]}. + +{mapping, "auth.client.$id.clientid", "emqx_auth_clientid.client_list", [ + {datatype, string} +]}. + +{mapping, "auth.client.$id.password", "emqx_auth_clientid.client_list", [ + {datatype, string} +]}. + +{translation, "emqx_auth_clientid.client_list", fun(Conf) -> + ClientList = cuttlefish_variable:filter_by_prefix("auth.client", Conf), + lists:foldl( + fun({["auth", "client", Id, "clientid"], ClientId}, AccIn) -> + [{ClientId, cuttlefish:conf_get("auth.client." ++ Id ++ ".password", Conf)} | AccIn]; + (_, AccIn) -> + AccIn + end, [], ClientList) +end}. + diff --git a/apps/emqx_auth_clientid/rebar.config b/apps/emqx_auth_clientid/rebar.config new file mode 100644 index 000000000..7b1f06cca --- /dev/null +++ b/apps/emqx_auth_clientid/rebar.config @@ -0,0 +1 @@ +{deps, []}. \ No newline at end of file diff --git a/apps/emqx_auth_clientid/src/emqx_auth_clientid.app.src b/apps/emqx_auth_clientid/src/emqx_auth_clientid.app.src new file mode 100644 index 000000000..cf96e6eca --- /dev/null +++ b/apps/emqx_auth_clientid/src/emqx_auth_clientid.app.src @@ -0,0 +1,14 @@ +{application, emqx_auth_clientid, + [{description, "EMQ X Authentication with ClientId/Password"}, + {vsn, "5.0.0"}, % strict semver, bump manually! + {modules, []}, + {registered, [emqx_auth_clientid_sup]}, + {applications, [kernel,stdlib,minirest,emqx_passwd,emqx_libs]}, + {mod, {emqx_auth_clientid_app, []}}, + {env, []}, + {licenses, ["Apache-2.0"]}, + {maintainers, ["EMQ X Team "]}, + {links, [{"Homepage", "https://emqx.io/"}, + {"Github", "https://github.com/emqx/emqx-auth-clientid"} + ]} + ]}. diff --git a/apps/emqx_auth_clientid/src/emqx_auth_clientid.erl b/apps/emqx_auth_clientid/src/emqx_auth_clientid.erl new file mode 100644 index 000000000..6643971ed --- /dev/null +++ b/apps/emqx_auth_clientid/src/emqx_auth_clientid.erl @@ -0,0 +1,170 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_clientid). + +-include("emqx_auth_clientid.hrl"). + +-include_lib("emqx_libs/include/emqx.hrl"). + +%% CLI callbacks +-export([cli/1]). + +%% APIs +-export([ add_clientid/2 + , update_password/2 + , lookup_clientid/1 + , remove_clientid/1 + , all_clientids/0 + ]). + +-export([unwrap_salt/1]). + +%% Auth callbacks +-export([ init/1 + , register_metrics/0 + , check/3 + , description/0 + ]). + +-define(TAB, ?MODULE). + +-record(?TAB, {clientid, password}). + +%%-------------------------------------------------------------------- +%% CLI +%%-------------------------------------------------------------------- + +cli(["list"]) -> + ClientIds = mnesia:dirty_all_keys(?TAB), + [emqx_ctl:print("~s~n", [ClientId]) || ClientId <- ClientIds]; + +cli(["add", ClientId, Password]) -> + Ok = add_clientid(iolist_to_binary(ClientId), iolist_to_binary(Password)), + emqx_ctl:print("~p~n", [Ok]); + +cli(["update", ClientId, NewPassword]) -> + Ok = update_password(iolist_to_binary(ClientId), iolist_to_binary(NewPassword)), + emqx_ctl:print("~p~n", [Ok]); + +cli(["del", ClientId]) -> + emqx_ctl:print("~p~n", [remove_clientid(iolist_to_binary(ClientId))]); + +cli(_) -> + emqx_ctl:usage([{"clientid list", "List ClientId"}, + {"clientid add ", "Add ClientId"}, + {"clientid update ", "Update Clientid"}, + {"clientid del ", "Delete ClientId"}]). + +%%-------------------------------------------------------------------- +%% API +%%-------------------------------------------------------------------- +%% @doc Add clientid with password +-spec(add_clientid(binary(), binary()) -> {atomic, ok} | {aborted, any()}). +add_clientid(ClientId, Password) -> + Client = #?TAB{clientid = ClientId, password = encrypted_data(Password)}, + ret(mnesia:transaction(fun do_add_clientid/1, [Client])). + +do_add_clientid(Client = #?TAB{clientid = ClientId}) -> + case mnesia:read(?TAB, ClientId) of + [] -> mnesia:write(Client); + [_|_] -> mnesia:abort(exitsted) + end. + +%% @doc Update clientid with newpassword +-spec(update_password(binary(), binary()) -> {atomic, ok} | {aborted, any()}). +update_password(ClientId, NewPassword) -> + Client = #?TAB{clientid = ClientId, password = encrypted_data(NewPassword)}, + ret(mnesia:transaction(fun do_update_password/1, [Client])). + +do_update_password(Client = #?TAB{clientid = ClientId}) -> + case mnesia:read(?TAB, ClientId) of + [_|_] -> mnesia:write(Client); + [] -> mnesia:abort(noexitsted) + end. + +%% @doc Lookup clientid +-spec(lookup_clientid(binary()) -> list(#?TAB{})). +lookup_clientid(ClientId) -> + mnesia:dirty_read(?TAB, ClientId). + +%% @doc Lookup all clientids +-spec(all_clientids() -> list(binary())). +all_clientids() -> + mnesia:dirty_all_keys(?TAB). + +%% @doc Remove clientid +-spec(remove_clientid(binary()) -> {atomic, ok} | {aborted, term()}). +remove_clientid(ClientId) -> + ret(mnesia:transaction(fun mnesia:delete/1, [{?TAB, ClientId}])). + +unwrap_salt(<<_Salt:4/binary, HashPasswd/binary>>) -> + HashPasswd. + +%% @private +ret({atomic, ok}) -> ok; +ret({aborted, Error}) -> {error, Error}. + +%%-------------------------------------------------------------------- +%% Auth callbacks +%%-------------------------------------------------------------------- + +init(DefaultIds) -> + ok = ekka_mnesia:create_table(?TAB, [ + {disc_copies, [node()]}, + {attributes, record_info(fields, ?TAB)}, + {storage_properties, [{ets, [{read_concurrency, true}]}]}]), + lists:foreach(fun add_default_clientid/1, DefaultIds), + ok = ekka_mnesia:copy_table(?TAB, disc_copies). + +%% @private +add_default_clientid({ClientId, Password}) -> + add_clientid(iolist_to_binary(ClientId), iolist_to_binary(Password)). + +register_metrics() -> + [emqx_metrics:ensure(MetricName) || MetricName <- ?AUTH_METRICS]. + +check(#{clientid := ClientId, password := Password}, AuthResult, #{hash_type := HashType}) -> + case mnesia:dirty_read(?TAB, ClientId) of + [] -> emqx_metrics:inc(?AUTH_METRICS(ignore)); + [#?TAB{password = <>}] -> + case Hash =:= hash(Password, Salt, HashType) of + true -> + emqx_metrics:inc(?AUTH_METRICS(success)), + {stop, AuthResult#{auth_result => success, anonymous => false}}; + false -> + emqx_metrics:inc(?AUTH_METRICS(failure)), + {stop, AuthResult#{auth_result => not_authorized, anonymous => false}} + end + end. + +description() -> + "ClientId Authentication Module". + +encrypted_data(Password) -> + HashType = application:get_env(emqx_auth_clientid, password_hash, sha256), + SaltBin = salt(), + <>. + +hash(undefined, SaltBin, HashType) -> + hash(<<>>, SaltBin, HashType); +hash(Password, SaltBin, HashType) -> + emqx_passwd:hash(HashType, <>). + +salt() -> + rand:seed(exsplus, erlang:timestamp()), + Salt = rand:uniform(16#ffffffff), <>. + diff --git a/apps/emqx_auth_clientid/src/emqx_auth_clientid_api.erl b/apps/emqx_auth_clientid/src/emqx_auth_clientid_api.erl new file mode 100644 index 000000000..6da5b14e8 --- /dev/null +++ b/apps/emqx_auth_clientid/src/emqx_auth_clientid_api.erl @@ -0,0 +1,127 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_clientid_api). + +-include("emqx_auth_clientid.hrl"). + +-export([ list/2 + , lookup/2 + , add/2 + , update/2 + , delete/2 + ]). + +-import(proplists, [get_value/2]). +-import(minirest, [return/0, return/1]). + +-rest_api(#{name => list_clientid, + method => 'GET', + path => "/auth_clientid", + func => list, + descr => "List available clientid in the cluster" + }). + +-rest_api(#{name => lookup_clientid, + method => 'GET', + path => "/auth_clientid/:bin:clientid", + func => lookup, + descr => "Lookup clientid in the cluster" + }). + +-rest_api(#{name => add_clientid, + method => 'POST', + path => "/auth_clientid", + func => add, + descr => "Add clientid in the cluster" + }). + +-rest_api(#{name => update_clientid, + method => 'PUT', + path => "/auth_clientid/:bin:clientid", + func => update, + descr => "Update clientid in the cluster" + }). + +-rest_api(#{name => delete_clientid, + method => 'DELETE', + path => "/auth_clientid/:bin:clientid", + func => delete, + descr => "Delete clientid in the cluster" + }). + +list(_Bindings, _Params) -> + return({ok, emqx_auth_clientid:all_clientids()}). + +lookup(#{clientid := ClientId}, _Params) -> + case emqx_auth_clientid:lookup_clientid(ClientId) of + [] -> return({error, not_found}); + Auth -> return({ok, format(Auth)}) + end. + +add(_Bindings, Params) -> + ClientId = get_value(<<"clientid">>, Params), + Password = get_value(<<"password">>, Params), + case validate([clientid, password], [ClientId, Password]) of + ok -> + case emqx_auth_clientid:add_clientid(ClientId, Password) of + ok -> return(); + Error -> return(Error) + end; + Error -> return(Error) + end. + +update(#{clientid := ClientId}, Params) -> + Password = get_value(<<"password">>, Params), + case validate([password], [Password]) of + ok -> + case emqx_auth_clientid:update_password(ClientId, Password) of + ok -> return(); + Error -> return(Error) + end; + Error -> return(Error) + end. + +delete(#{clientid := ClientId}, _) -> + case emqx_auth_clientid:remove_clientid(ClientId) of + ok -> return(); + Error -> return(Error) + end. + +%%------------------------------------------------------------------------------ +%% Interval Funcs +%%------------------------------------------------------------------------------ + +format([{?APP, ClientId, Password}]) -> + #{clientid => ClientId, + password => emqx_auth_clientid:unwrap_salt(Password)}. + +validate([], []) -> + ok; +validate([K|Keys], [V|Values]) -> + case validation(K, V) of + false -> {error, K}; + true -> validate(Keys, Values) + end. + +validation(clientid, V) when is_binary(V) + andalso byte_size(V) > 0 -> + true; +validation(password, V) when is_binary(V) + andalso byte_size(V) > 0 -> + true; +validation(_, _) -> + false. diff --git a/apps/emqx_auth_clientid/src/emqx_auth_clientid_app.erl b/apps/emqx_auth_clientid/src/emqx_auth_clientid_app.erl new file mode 100644 index 000000000..4c7b242b4 --- /dev/null +++ b/apps/emqx_auth_clientid/src/emqx_auth_clientid_app.erl @@ -0,0 +1,53 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_clientid_app). + +-include("emqx_auth_clientid.hrl"). + +-behaviour(application). + +-emqx_plugin(auth). + +-export([ start/2 + , stop/1 + ]). + +-behaviour(supervisor). + +-export([init/1]). + +start(_Type, _Args) -> + emqx_ctl:register_command(clientid, {?APP, cli}, []), + emqx_auth_clientid:register_metrics(), + HashType = application:get_env(?APP, password_hash, sha256), + Params = #{hash_type => HashType}, + emqx:hook('client.authenticate', fun emqx_auth_clientid:check/3, [Params]), + DefaultIds = application:get_env(?APP, client_list, []), + ok = emqx_auth_clientid:init(DefaultIds), + supervisor:start_link({local, ?MODULE}, ?MODULE, []). + +stop(_State) -> + emqx:unhook('client.authenticate', fun emqx_auth_clientid:check/3), + emqx_ctl:unregister_command(clientid). + +%%-------------------------------------------------------------------- +%% Dummy supervisor +%%-------------------------------------------------------------------- + +init([]) -> + {ok, { {one_for_all, 1, 10}, []} }. + diff --git a/apps/emqx_auth_clientid/test/emqx_auth_clientid_SUITE.erl b/apps/emqx_auth_clientid/test/emqx_auth_clientid_SUITE.erl new file mode 100644 index 000000000..24ab0f7ce --- /dev/null +++ b/apps/emqx_auth_clientid/test/emqx_auth_clientid_SUITE.erl @@ -0,0 +1,191 @@ +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. + +-module(emqx_auth_clientid_SUITE). + +-compile(nowarn_export_all). +-compile(export_all). + +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("eunit/include/eunit.hrl"). +-include_lib("common_test/include/ct.hrl"). + +-import(emqx_ct_http, [ request_api/3 + , request_api/5 + , get_http_data/1 + , create_default_app/0 + , default_auth_header/0 + ]). + +-define(HOST, "http://127.0.0.1:8081/"). +-define(API_VERSION, "v4"). +-define(BASE_PATH, "api"). + +-define(CLIENTID, <<"client_id_for_ct">>). +-define(PASSWORD, <<"password">>). +-define(NPASSWORD, <<"password1">>). +-define(USER, #{clientid => ?CLIENTID, zone => external}). + +all() -> + emqx_ct:all(?MODULE). + +init_per_suite(Config) -> + emqx_ct_helpers:start_apps([emqx_auth_clientid, emqx_management], fun set_special_configs/1), + create_default_app(), + Config. + +end_per_suite(_Config) -> + emqx_ct_helpers:stop_apps([emqx_auth_clientid, emqx_management]). + +set_special_configs(emqx) -> + application:set_env(emqx, allow_anonymous, true), + application:set_env(emqx, enable_acl_cache, false), + LoadedPluginPath = filename:join(["test", "emqx_SUITE_data", "loaded_plugins"]), + application:set_env(emqx, plugins_loaded_file, + emqx_ct_helpers:deps_path(emqx, LoadedPluginPath)); + +set_special_configs(_App) -> + ok. + +%%------------------------------------------------------------------------------ +%% Testcases +%%------------------------------------------------------------------------------ + +t_managing(_) -> + clean_all_clientids(), + + ok = emqx_auth_clientid:add_clientid(?CLIENTID, ?PASSWORD), + ?assertNotEqual(emqx_auth_clientid:lookup_clientid(?CLIENTID), []), + + {ok, #{auth_result := success, + anonymous := false}} = emqx_access_control:authenticate(?USER#{password => ?PASSWORD}), + + {error, _} = emqx_access_control:authenticate(?USER#{password => ?NPASSWORD}), + + emqx_auth_clientid:update_password(?CLIENTID, ?NPASSWORD), + {ok, #{auth_result := success, + anonymous := false}} = emqx_access_control:authenticate(?USER#{password => ?NPASSWORD}), + + ok = emqx_auth_clientid:remove_clientid(?CLIENTID), + {ok, #{auth_result := success, + anonymous := true}} = emqx_access_control:authenticate(?USER#{password => ?PASSWORD}). + +t_cli(_) -> + clean_all_clientids(), + + HashType = application:get_env(emqx_auth_clientid, password_hash, sha256), + + emqx_auth_clientid:cli(["add", ?CLIENTID, ?PASSWORD]), + [{_, ?CLIENTID, <>}] = emqx_auth_clientid:lookup_clientid(?CLIENTID), + ?assertEqual(Hash, emqx_passwd:hash(HashType, <>)), + + emqx_auth_clientid:cli(["update", ?CLIENTID, ?NPASSWORD]), + [{_, ?CLIENTID, <>}] = emqx_auth_clientid:lookup_clientid(?CLIENTID), + ?assertEqual(Hash1, emqx_passwd:hash(HashType, <>)), + + emqx_auth_clientid:cli(["del", ?CLIENTID]), + ?assertEqual([], emqx_auth_clientid:lookup_clientid(?CLIENTID)), + + emqx_auth_clientid:cli(["add", "user1", "pass1"]), + emqx_auth_clientid:cli(["add", "user2", "pass2"]), + ?assertEqual(2, length(emqx_auth_clientid:cli(["list"]))), + + emqx_auth_clientid:cli(usage). + +t_rest_api(_Config) -> + clean_all_clientids(), + + HashType = application:get_env(emqx_auth_clientid, password_hash, sha256), + + {ok, Result} = request_http_rest_list(), + [] = get_http_data(Result), + + {ok, _} = request_http_rest_add(?CLIENTID, ?PASSWORD), + {ok, Result1} = request_http_rest_lookup(?CLIENTID), + #{<<"password">> := Hash} = get_http_data(Result1), + [{_, ?CLIENTID, <>}] = emqx_auth_clientid:lookup_clientid(?CLIENTID), + ?assertEqual(Hash, emqx_passwd:hash(HashType, <>)), + + {ok, _} = request_http_rest_update(?CLIENTID, ?NPASSWORD), + [{_, ?CLIENTID, <>}] = emqx_auth_clientid:lookup_clientid(?CLIENTID), + ?assertEqual(Hash1, emqx_passwd:hash(HashType, <>)), + + {ok, _} = request_http_rest_delete(?CLIENTID), + ?assertEqual([], emqx_auth_clientid:lookup_clientid(?CLIENTID)). + +t_conf_not_override_existed(_) -> + clean_all_clientids(), + + application:stop(emqx_auth_clientid), + application:set_env(emqx_auth_clientid, client_list, [{?CLIENTID, ?PASSWORD}]), + application:ensure_all_started(emqx_auth_clientid), + + {ok, _} = emqx_access_control:authenticate(?USER#{password => ?PASSWORD}), + emqx_auth_clientid:cli(["update", ?CLIENTID, ?NPASSWORD]), + + {error, _} = emqx_access_control:authenticate(?USER#{password => ?PASSWORD}), + {ok, _} = emqx_access_control:authenticate(?USER#{password => ?NPASSWORD}), + + application:stop(emqx_auth_clientid), + application:ensure_all_started(emqx_auth_clientid), + {ok, _} = emqx_access_control:authenticate(?USER#{password => ?NPASSWORD}), + + ct:pal("~p", [ets:tab2list(emqx_auth_clientid)]), + {ok, _} = request_http_rest_update(?CLIENTID, ?PASSWORD), + application:stop(emqx_auth_clientid), + application:ensure_all_started(emqx_auth_clientid), + ct:pal("~p", [ets:tab2list(emqx_auth_clientid)]), + {ok, _} = emqx_access_control:authenticate(?USER#{password => ?PASSWORD}). + +%%-------------------------------------------------------------------- +%% Helpers +%%-------------------------------------------------------------------- + +clean_all_clientids() -> + [mnesia:dirty_delete({emqx_auth_clientid, Id}) + || Id <- mnesia:dirty_all_keys(emqx_auth_clientid)]. + +%%-------------------------------------------------------------------- +%% REST API Requests + +request_http_rest_list() -> + request_api(get, uri(), default_auth_header()). + +request_http_rest_lookup(ClientId) -> + request_api(get, uri([ClientId]), default_auth_header()). + +request_http_rest_add(ClientId, Password) -> + Params = #{<<"clientid">> => ClientId, <<"password">> => Password}, + request_api(post, uri(), [], default_auth_header(), Params). + +request_http_rest_update(ClientId, Password) -> + Params = #{<<"password">> => Password}, + request_api(put, uri([ClientId]), [], default_auth_header(), Params). + +request_http_rest_delete(ClientId) -> + request_api(delete, uri([ClientId]), default_auth_header()). + +%% @private +uri() -> uri([]). +uri(Parts) when is_list(Parts) -> + NParts = [b2l(E) || E <- Parts], + %% http://127.0.0.1:8080/api/v4/auth_clientid/// + ?HOST ++ filename:join([?BASE_PATH, ?API_VERSION, "auth_clientid"| NParts]). + +%% @private +b2l(B) when is_binary(B) -> + binary_to_list(B); +b2l(L) when is_list(L) -> + L. + diff --git a/apps/emqx_auth_http/README.md b/apps/emqx_auth_http/README.md new file mode 100644 index 000000000..ed743334a --- /dev/null +++ b/apps/emqx_auth_http/README.md @@ -0,0 +1,100 @@ +emqx_auth_http +============== + +EMQ X HTTP Auth/ACL Plugin + +Build +----- + +``` +make && make tests +``` + +Configure the Plugin +-------------------- + +File: etc/emqx_auth_http.conf + +``` +##-------------------------------------------------------------------- +## Authentication request. +## +## Variables: +## - %u: username +## - %c: clientid +## - %a: ipaddress +## - %r: protocol +## - %P: password +## - %C: common name of client TLS cert +## - %d: subject of client TLS cert +## +## Value: URL +auth.http.auth_req = http://127.0.0.1:8080/mqtt/auth +## Value: post | get | put +auth.http.auth_req.method = post +## Value: Params +auth.http.auth_req.params = clientid=%c,username=%u,password=%P + +##-------------------------------------------------------------------- +## Superuser request. +## +## Variables: +## - %u: username +## - %c: clientid +## - %a: ipaddress +## - %r: protocol +## - %P: password +## - %C: common name of client TLS cert +## - %d: subject of client TLS cert +## +## Value: URL +auth.http.super_req = http://127.0.0.1:8080/mqtt/superuser +## Value: post | get | put +auth.http.super_req.method = post +## Value: Params +auth.http.super_req.params = clientid=%c,username=%u + +##-------------------------------------------------------------------- +## ACL request. +## +## Variables: +## - %A: 1 | 2, 1 = sub, 2 = pub +## - %u: username +## - %c: clientid +## - %a: ipaddress +## - %r: protocol +## - %m: mountpoint +## - %t: topic +## +## Value: URL +auth.http.acl_req = http://127.0.0.1:8080/mqtt/acl +## Value: post | get | put +auth.http.acl_req.method = get +## Value: Params +auth.http.acl_req.params = access=%A,username=%u,clientid=%c,ipaddr=%a,topic=%t +``` + +Load the Plugin +--------------- + +``` +./bin/emqx_ctl plugins load emqx_auth_http +``` + +HTTP API +-------- + +200 if ok + +4xx if unauthorized + +License +------- + +Apache License Version 2.0 + +Author +------ + +EMQ X Team. + diff --git a/apps/emqx_auth_http/include/emqx_auth_http.hrl b/apps/emqx_auth_http/include/emqx_auth_http.hrl new file mode 100644 index 000000000..09e58e324 --- /dev/null +++ b/apps/emqx_auth_http/include/emqx_auth_http.hrl @@ -0,0 +1,25 @@ + +-define(APP, emqx_auth_http). + +-record(http_request, {method = post, content_type, url, params, options = []}). + +-record(auth_metrics, { + success = 'client.auth.success', + failure = 'client.auth.failure', + ignore = 'client.auth.ignore' + }). + +-record(acl_metrics, { + allow = 'client.acl.allow', + deny = 'client.acl.deny', + ignore = 'client.acl.ignore' + }). + +-define(METRICS(Type), tl(tuple_to_list(#Type{}))). +-define(METRICS(Type, K), #Type{}#Type.K). + +-define(AUTH_METRICS, ?METRICS(auth_metrics)). +-define(AUTH_METRICS(K), ?METRICS(auth_metrics, K)). + +-define(ACL_METRICS, ?METRICS(acl_metrics)). +-define(ACL_METRICS(K), ?METRICS(acl_metrics, K)). diff --git a/apps/emqx_auth_http/priv/emqx_auth_http.schema b/apps/emqx_auth_http/priv/emqx_auth_http.schema new file mode 100644 index 000000000..e6a986344 --- /dev/null +++ b/apps/emqx_auth_http/priv/emqx_auth_http.schema @@ -0,0 +1,165 @@ +%%-*- mode: erlang -*- +%% emqx_auth_http config mapping +{mapping, "auth.http.auth_req", "emqx_auth_http.auth_req", [ + {datatype, string} +]}. + +{mapping, "auth.http.auth_req.method", "emqx_auth_http.auth_req", [ + {default, post}, + {datatype, {enum, [post, get]}} +]}. + +{mapping, "auth.http.auth_req.content_type", "emqx_auth_http.auth_req", [ + {default, 'x-www-form-urlencoded'}, + {datatype, {enum, [json, 'x-www-form-urlencoded']}} +]}. + +{mapping, "auth.http.auth_req.params", "emqx_auth_http.auth_req", [ + {datatype, string} +]}. + +{translation, "emqx_auth_http.auth_req", fun(Conf) -> + case cuttlefish:conf_get("auth.http.auth_req", Conf) of + undefined -> cuttlefish:unset(); + Url -> + Params = cuttlefish:conf_get("auth.http.auth_req.params", Conf), + [{url, Url}, + {method, cuttlefish:conf_get("auth.http.auth_req.method", Conf)}, + {content_type, cuttlefish:conf_get("auth.http.auth_req.content_type", Conf)}, + {params, [list_to_tuple(string:tokens(S, "=")) || S <- string:tokens(Params, ",")]}] + end +end}. + +{mapping, "auth.http.super_req", "emqx_auth_http.super_req", [ + {datatype, string} +]}. + +{mapping, "auth.http.super_req.method", "emqx_auth_http.super_req", [ + {default, post}, + {datatype, {enum, [post, get]}} +]}. + +{mapping, "auth.http.super_req.content_type", "emqx_auth_http.super_req", [ + {default, 'x-www-form-urlencoded'}, + {datatype, {enum, [json, 'x-www-form-urlencoded']}} +]}. + +{mapping, "auth.http.super_req.params", "emqx_auth_http.super_req", [ + {datatype, string} +]}. + +{translation, "emqx_auth_http.super_req", fun(Conf) -> + case cuttlefish:conf_get("auth.http.super_req", Conf, undefined) of + undefined -> cuttlefish:unset(); + Url -> Params = cuttlefish:conf_get("auth.http.super_req.params", Conf), + [{url, Url}, {method, cuttlefish:conf_get("auth.http.super_req.method", Conf)}, + {content_type, cuttlefish:conf_get("auth.http.super_req.content_type", Conf)}, + {params, [list_to_tuple(string:tokens(S, "=")) || S <- string:tokens(Params, ",")]}] + end +end}. + +{mapping, "auth.http.acl_req", "emqx_auth_http.acl_req", [ + {default, undefined}, + {datatype, string} +]}. + +{mapping, "auth.http.acl_req.method", "emqx_auth_http.acl_req", [ + {default, post}, + {datatype, {enum, [post, get]}} +]}. + +{mapping, "auth.http.acl_req.content_type", "emqx_auth_http.acl_req", [ + {default, 'x-www-form-urlencoded'}, + {datatype, {enum, [json, 'x-www-form-urlencoded']}} +]}. + +{mapping, "auth.http.acl_req.params", "emqx_auth_http.acl_req", [ + {datatype, string} +]}. + +{translation, "emqx_auth_http.acl_req", fun(Conf) -> + case cuttlefish:conf_get("auth.http.acl_req", Conf, undefined) of + undefined -> cuttlefish:unset(); + Url -> Params = cuttlefish:conf_get("auth.http.acl_req.params", Conf), + [{url, Url}, {method, cuttlefish:conf_get("auth.http.acl_req.method", Conf)}, + {content_type, cuttlefish:conf_get("auth.http.acl_req.content_type", Conf)}, + {params, [list_to_tuple(string:tokens(S, "=")) || S <- string:tokens(Params, ",")]}] + end +end}. + +{mapping, "auth.http.request.timeout", "emqx_auth_http.http_opts", [ + {default, 0}, + {datatype, [integer, {duration, ms}]} +]}. + +{mapping, "auth.http.request.connect_timeout", "emqx_auth_http.http_opts", [ + {datatype, [integer, {duration, ms}]} +]}. + +{mapping, "auth.http.ssl.cacertfile", "emqx_auth_http.http_opts", [ + {datatype, string} +]}. + +{mapping, "auth.http.ssl.certfile", "emqx_auth_http.http_opts", [ + {datatype, string} +]}. + +{mapping, "auth.http.ssl.keyfile", "emqx_auth_http.http_opts", [ + {datatype, string} +]}. + +{translation, "emqx_auth_http.http_opts", fun(Conf) -> + Filter = fun(L) -> [{K, V} || {K, V} <- L, V =/= undefined] end, + InfinityFun = fun(0) -> infinity; + (Duration) -> Duration + end, + SslOpts = Filter([{cacertfile, cuttlefish:conf_get("auth.http.ssl.cacertfile", Conf, undefined)}, + {certfile, cuttlefish:conf_get("auth.http.ssl.certfile", Conf, undefined)}, + {keyfile, cuttlefish:conf_get("auth.http.ssl.keyfile", Conf, undefined)}]), + Opts = [{timeout, InfinityFun(cuttlefish:conf_get("auth.http.request.timeout", Conf))}, + {connect_timeout, InfinityFun(cuttlefish:conf_get("auth.http.request.connect_timeout", Conf, undefined))}], + case SslOpts of + [] -> Filter(Opts); + _ -> + TlsVers = ['tlsv1.2','tlsv1.1',tlsv1], + DefaultOpts = [{versions, TlsVers}, + {ciphers, lists:foldl( + fun(TlsVer, Ciphers) -> + Ciphers ++ ssl:cipher_suites(all, TlsVer) + end, [], TlsVers)}], + Filter([{ssl, DefaultOpts ++ SslOpts} | Opts]) + end +end}. + +{mapping, "auth.http.request.retry_times", "emqx_auth_http.retry_opts", [ + {default, 3}, + {datatype, integer} +]}. + +{mapping, "auth.http.request.retry_interval", "emqx_auth_http.retry_opts", [ + {default, "1s"}, + {datatype, {duration, ms}} +]}. + +{mapping, "auth.http.request.retry_backoff", "emqx_auth_http.retry_opts", [ + {default, 2.0}, + {datatype, float} +]}. + +{translation, "emqx_auth_http.retry_opts", fun(Conf) -> + [{times, cuttlefish:conf_get("auth.http.request.retry_times", Conf)}, + {interval, cuttlefish:conf_get("auth.http.request.retry_interval", Conf)}, + {backoff, cuttlefish:conf_get("auth.http.request.retry_backoff", Conf)}] +end}. + +{mapping, "auth.http.header.$field", "emqx_auth_http.headers", [ + {datatype, string} +]}. + +{translation, "emqx_auth_http.headers", fun(Conf) -> + lists:map( + fun({["auth", "http", "header", Field], Value}) -> + {Field, Value} + end, + cuttlefish_variable:filter_by_prefix("auth.http.header", Conf)) +end}. \ No newline at end of file diff --git a/apps/emqx_auth_http/rebar.config b/apps/emqx_auth_http/rebar.config new file mode 100644 index 000000000..7b1f06cca --- /dev/null +++ b/apps/emqx_auth_http/rebar.config @@ -0,0 +1 @@ +{deps, []}. \ No newline at end of file diff --git a/apps/emqx_auth_http/src/emqx_acl_http.erl b/apps/emqx_auth_http/src/emqx_acl_http.erl new file mode 100644 index 000000000..621b20b0d --- /dev/null +++ b/apps/emqx_auth_http/src/emqx_acl_http.erl @@ -0,0 +1,92 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_acl_http). + +-include("emqx_auth_http.hrl"). + +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). + +-logger_header("[ACL http]"). + +-import(emqx_auth_http_cli, + [ request/8 + , feedvar/2 + ]). + +%% ACL callbacks +-export([ register_metrics/0 + , check_acl/5 + , description/0 + ]). + +-spec(register_metrics() -> ok). +register_metrics() -> + lists:foreach(fun emqx_metrics:ensure/1, ?ACL_METRICS). + +%%-------------------------------------------------------------------- +%% ACL callbacks +%%-------------------------------------------------------------------- + +check_acl(ClientInfo, PubSub, Topic, AclResult, State) -> + return_with(fun inc_metrics/1, + do_check_acl(ClientInfo, PubSub, Topic, AclResult, State)). + +do_check_acl(#{username := <<$$, _/binary>>}, _PubSub, _Topic, _AclResult, _Config) -> + ok; +do_check_acl(ClientInfo, PubSub, Topic, _AclResult, #{acl_req := AclReq, + http_opts := HttpOpts, + retry_opts := RetryOpts, + headers := Headers}) -> + ClientInfo1 = ClientInfo#{access => access(PubSub), topic => Topic}, + case check_acl_request(AclReq, ClientInfo1, Headers, HttpOpts, RetryOpts) of + {ok, 200, "ignore"} -> ok; + {ok, 200, _Body} -> {stop, allow}; + {ok, _Code, _Body} -> {stop, deny}; + {error, Error} -> + ?LOG(error, "Request ACL url ~s, error: ~p", + [AclReq#http_request.url, Error]), + ok + end. + +description() -> "ACL with HTTP API". + +%%-------------------------------------------------------------------- +%% Internal functions +%%-------------------------------------------------------------------- + +inc_metrics(ok) -> + emqx_metrics:inc(?ACL_METRICS(ignore)); +inc_metrics({stop, allow}) -> + emqx_metrics:inc(?ACL_METRICS(allow)); +inc_metrics({stop, deny}) -> + emqx_metrics:inc(?ACL_METRICS(deny)). + +return_with(Fun, Result) -> + Fun(Result), Result. + +check_acl_request(#http_request{url = Url, + method = Method, + content_type = ContentType, + params = Params, + options = Options}, + ClientInfo, Headers, HttpOpts, RetryOpts) -> + request(Method, ContentType, Url, feedvar(Params, ClientInfo), Headers, HttpOpts, Options, RetryOpts). + +access(subscribe) -> 1; +access(publish) -> 2. + diff --git a/apps/emqx_auth_http/src/emqx_auth_http.app.src b/apps/emqx_auth_http/src/emqx_auth_http.app.src new file mode 100644 index 000000000..1a74b33ac --- /dev/null +++ b/apps/emqx_auth_http/src/emqx_auth_http.app.src @@ -0,0 +1,14 @@ +{application, emqx_auth_http, + [{description, "EMQ X Authentication/ACL with HTTP API"}, + {vsn, "5.0.0"}, % strict semver, bump manually! + {modules, []}, + {registered, [emqx_auth_http_sup]}, + {applications, [kernel,stdlib,emqx_libs]}, + {mod, {emqx_auth_http_app, []}}, + {env, []}, + {licenses, ["Apache-2.0"]}, + {maintainers, ["EMQ X Team "]}, + {links, [{"Homepage", "https://emqx.io/"}, + {"Github", "https://github.com/emqx/emqx-auth-http"} + ]} + ]}. diff --git a/apps/emqx_auth_http/src/emqx_auth_http.erl b/apps/emqx_auth_http/src/emqx_auth_http.erl new file mode 100644 index 000000000..02afa7f2c --- /dev/null +++ b/apps/emqx_auth_http/src/emqx_auth_http.erl @@ -0,0 +1,116 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_http). + +-include("emqx_auth_http.hrl"). + +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). +-include_lib("emqx_libs/include/types.hrl"). + +-logger_header("[Auth http]"). + +-import(emqx_auth_http_cli, + [ request/8 + , feedvar/2 + ]). + +%% Callbacks +-export([ register_metrics/0 + , check/3 + , description/0 + ]). + +-spec(register_metrics() -> ok). +register_metrics() -> + lists:foreach(fun emqx_metrics:ensure/1, ?AUTH_METRICS). + +check(ClientInfo, AuthResult, #{auth_req := AuthReq, + super_req := SuperReq, + http_opts := HttpOpts, + retry_opts := RetryOpts, + headers := Headers}) -> + case authenticate(AuthReq, ClientInfo, Headers, HttpOpts, RetryOpts) of + {ok, 200, "ignore"} -> + emqx_metrics:inc(?AUTH_METRICS(ignore)), ok; + {ok, 200, Body} -> + emqx_metrics:inc(?AUTH_METRICS(success)), + IsSuperuser = is_superuser(SuperReq, ClientInfo, Headers, HttpOpts, RetryOpts), + {stop, AuthResult#{is_superuser => IsSuperuser, + auth_result => success, + anonymous => false, + mountpoint => mountpoint(Body, ClientInfo)}}; + {ok, Code, _Body} -> + ?LOG(error, "Deny connection from url: ~s, response http code: ~p", + [AuthReq#http_request.url, Code]), + emqx_metrics:inc(?AUTH_METRICS(failure)), + {stop, AuthResult#{auth_result => http_to_connack_error(Code), + anonymous => false}}; + {error, Error} -> + ?LOG(error, "Request auth url: ~s, error: ~p", + [AuthReq#http_request.url, Error]), + emqx_metrics:inc(?AUTH_METRICS(failure)), + %%FIXME later: server_unavailable is not right. + {stop, AuthResult#{auth_result => server_unavailable, + anonymous => false}} + end. + +description() -> "Authentication by HTTP API". + +%%-------------------------------------------------------------------- +%% Requests +%%-------------------------------------------------------------------- + +authenticate(#http_request{url = Url, + method = Method, + content_type = ContentType, + params = Params, + options = Options}, + ClientInfo, HttpHeaders, HttpOpts, RetryOpts) -> + request(Method, ContentType, Url, feedvar(Params, ClientInfo), HttpHeaders, HttpOpts, Options, RetryOpts). + +-spec(is_superuser(maybe(#http_request{}), emqx_types:client(), list(), list(), list()) -> boolean()). +is_superuser(undefined, _ClientInfo, _HttpHeaders, _HttpOpts, _RetryOpts) -> + false; +is_superuser(#http_request{url = Url, + method = Method, + content_type = ContentType, + params = Params, + options = Options}, + ClientInfo, HttpHeaders, HttpOpts, RetryOpts) -> + case request(Method, ContentType, Url, feedvar(Params, ClientInfo), HttpHeaders, HttpOpts, Options, RetryOpts) of + {ok, 200, _Body} -> true; + {ok, _Code, _Body} -> false; + {error, Error} -> ?LOG(error, "Request superuser url ~s, error: ~p", [Url, Error]), + false + end. + +mountpoint(Body, #{mountpoint := Mountpoint}) -> + case emqx_json:safe_decode(iolist_to_binary(Body), [return_maps]) of + {error, _} -> Mountpoint; + {ok, Json} when is_map(Json) -> + maps:get(<<"mountpoint">>, Json, Mountpoint); + {ok, _NotMap} -> Mountpoint + end. + +http_to_connack_error(400) -> bad_username_or_password; +http_to_connack_error(401) -> bad_username_or_password; +http_to_connack_error(403) -> not_authorized; +http_to_connack_error(429) -> banned; +http_to_connack_error(503) -> server_unavailable; +http_to_connack_error(504) -> server_busy; +http_to_connack_error(_) -> server_unavailable. diff --git a/apps/emqx_auth_http/src/emqx_auth_http_app.erl b/apps/emqx_auth_http/src/emqx_auth_http_app.erl new file mode 100644 index 000000000..51f6762ee --- /dev/null +++ b/apps/emqx_auth_http/src/emqx_auth_http_app.erl @@ -0,0 +1,103 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_http_app). + +-behaviour(application). +-behaviour(supervisor). + +-emqx_plugin(auth). + +-include("emqx_auth_http.hrl"). + +-export([ start/2 + , stop/1 + ]). +-export([init/1]). + +%%-------------------------------------------------------------------- +%% Application Callbacks +%%-------------------------------------------------------------------- + +start(_StartType, _StartArgs) -> + with_env(auth_req, fun load_auth_hook/1), + with_env(acl_req, fun load_acl_hook/1), + supervisor:start_link({local, ?MODULE}, ?MODULE, []). + +load_auth_hook(AuthReq) -> + ok = emqx_auth_http:register_metrics(), + SuperReq = r(application:get_env(?APP, super_req, undefined)), + HttpOpts = application:get_env(?APP, http_opts, []), + RetryOpts = application:get_env(?APP, retry_opts, []), + Headers = application:get_env(?APP, headers, []), + Params = #{auth_req => AuthReq, + super_req => SuperReq, + http_opts => HttpOpts, + retry_opts => maps:from_list(RetryOpts), + headers => Headers}, + emqx:hook('client.authenticate', {emqx_auth_http, check, [Params]}). + +load_acl_hook(AclReq) -> + ok = emqx_acl_http:register_metrics(), + HttpOpts = application:get_env(?APP, http_opts, []), + RetryOpts = application:get_env(?APP, retry_opts, []), + Headers = application:get_env(?APP, headers, []), + Params = #{acl_req => AclReq, + http_opts => HttpOpts, + retry_opts => maps:from_list(RetryOpts), + headers => Headers}, + emqx:hook('client.check_acl', {emqx_acl_http, check_acl, [Params]}). + +stop(_State) -> + emqx:unhook('client.authenticate', {emqx_auth_http, check}), + emqx:unhook('client.check_acl', {emqx_acl_http, check_acl}). + +%%-------------------------------------------------------------------- +%% Dummy supervisor +%%-------------------------------------------------------------------- + +init([]) -> + {ok, { {one_for_all, 10, 100}, []} }. + +%%-------------------------------------------------------------------- +%% Internel functions +%%-------------------------------------------------------------------- + +with_env(Par, Fun) -> + case application:get_env(?APP, Par) of + undefined -> ok; + {ok, Req} -> Fun(r(Req)) + end. + +r(undefined) -> + undefined; +r(Config) -> + Method = proplists:get_value(method, Config, post), + ContentType = proplists:get_value(content_type, Config, 'x-www-form-urlencoded'), + Url = proplists:get_value(url, Config), + Params = proplists:get_value(params, Config), + #http_request{method = Method, content_type = ContentType, url = Url, params = Params, options = inet(Url)}. + +inet(Url) -> + case uri_string:parse(Url) of + #{host := Host} -> + case inet:parse_address(Host) of + {ok, Ip} when tuple_size(Ip) =:= 8 -> + [{ipv6_host_with_brackets, true}, {socket_opts, [{ipfamily, inet6}]}]; + _ -> [] + end; + _ -> [] + end. diff --git a/apps/emqx_auth_http/src/emqx_auth_http_cli.erl b/apps/emqx_auth_http/src/emqx_auth_http_cli.erl new file mode 100644 index 000000000..35a20d0f0 --- /dev/null +++ b/apps/emqx_auth_http/src/emqx_auth_http_cli.erl @@ -0,0 +1,101 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_http_cli). + +-export([ request/8 + , feedvar/2 + , feedvar/3 + ]). + +%%-------------------------------------------------------------------- +%% HTTP Request +%%-------------------------------------------------------------------- + +request(get, _ContentType, Url, Params, HttpHeaders, HttpOpts, Options, RetryOpts) -> + Req = {Url ++ "?" ++ cow_qs:qs(bin_kw(Params)), HttpHeaders}, + reply(request_(get, Req, [{autoredirect, true} | HttpOpts], Options, RetryOpts)); + +request(post, 'x-www-form-urlencoded', Url, Params, HttpHeaders, HttpOpts, Options, RetryOpts) -> + Req = {Url, HttpHeaders, "application/x-www-form-urlencoded", cow_qs:qs(bin_kw(Params))}, + reply(request_(post, Req, [{autoredirect, true} | HttpOpts], Options, RetryOpts)); + +request(post, json, Url, Params, HttpHeaders, HttpOpts, Options, RetryOpts) -> + Req = {Url, HttpHeaders, "application/json", emqx_json:encode(bin_kw(Params))}, + reply(request_(post, Req, [{autoredirect, true} | HttpOpts], Options, RetryOpts)). + +request_(Method, Req, HTTPOpts, Opts, RetryOpts = #{times := Times, + interval := Interval, + backoff := BackOff}) -> + case httpc:request(Method, Req, HTTPOpts, Opts) of + {error, _Reason} when Times > 0 -> + timer:sleep(trunc(Interval)), + RetryOpts1 = RetryOpts#{times := Times - 1, + interval := Interval * BackOff}, + request_(Method, Req, HTTPOpts, Opts, RetryOpts1); + Other -> Other + end. + +reply({ok, {{_, Code, _}, _Headers, Body}}) -> + {ok, Code, Body}; +reply({ok, Code, Body}) -> + {ok, Code, Body}; +reply({error, Error}) -> + {error, Error}. + +%% TODO: move this conversion to cuttlefish config and schema +bin_kw(KeywordList) when is_list(KeywordList) -> + [{bin(K), bin(V)} || {K, V} <- KeywordList]. + +bin(Atom) when is_atom(Atom) -> + list_to_binary(atom_to_list(Atom)); +bin(Int) when is_integer(Int) -> + integer_to_binary(Int); +bin(Float) when is_float(Float) -> + float_to_binary(Float, [{decimals, 12}, compact]); +bin(List) when is_list(List)-> + list_to_binary(List); +bin(Binary) when is_binary(Binary) -> + Binary. + +%%-------------------------------------------------------------------- +%% Feed Variables +%%-------------------------------------------------------------------- + +feedvar(Params, ClientInfo = #{clientid := ClientId, + protocol := Protocol, + peerhost := Peerhost}) -> + lists:map(fun({Param, "%u"}) -> {Param, maps:get(username, ClientInfo, null)}; + ({Param, "%c"}) -> {Param, ClientId}; + ({Param, "%r"}) -> {Param, Protocol}; + ({Param, "%a"}) -> {Param, inet:ntoa(Peerhost)}; + ({Param, "%P"}) -> {Param, maps:get(password, ClientInfo, null)}; + ({Param, "%p"}) -> {Param, maps:get(sockport, ClientInfo, null)}; + ({Param, "%C"}) -> {Param, maps:get(cn, ClientInfo, null)}; + ({Param, "%d"}) -> {Param, maps:get(dn, ClientInfo, null)}; + ({Param, "%A"}) -> {Param, maps:get(access, ClientInfo, null)}; + ({Param, "%t"}) -> {Param, maps:get(topic, ClientInfo, null)}; + ({Param, "%m"}) -> {Param, maps:get(mountpoint, ClientInfo, null)}; + ({Param, Var}) -> {Param, Var} + end, Params). + +feedvar(Params, Var, Val) -> + lists:map(fun({Param, Var0}) when Var0 == Var -> + {Param, Val}; + ({Param, Var0}) -> + {Param, Var0} + end, Params). + diff --git a/apps/emqx_auth_http/test/emqx_auth_http_SUITE.erl b/apps/emqx_auth_http/test/emqx_auth_http_SUITE.erl new file mode 100644 index 000000000..e0984b134 --- /dev/null +++ b/apps/emqx_auth_http/test/emqx_auth_http_SUITE.erl @@ -0,0 +1,167 @@ +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. + +-module(emqx_auth_http_SUITE). + +-compile(export_all). +-compile(nowarn_export_all). + +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("common_test/include/ct.hrl"). +-include_lib("eunit/include/eunit.hrl"). + +-define(APP, emqx_auth_http). + +-define(USER(ClientId, Username, Protocol, Peerhost, Zone), + #{clientid => ClientId, username => Username, protocol => Protocol, + peerhost => Peerhost, zone => Zone}). + +-define(USER(ClientId, Username, Protocol, Peerhost, Zone, Mountpoint), + #{clientid => ClientId, username => Username, protocol => Protocol, + peerhost => Peerhost, zone => Zone, mountpoint => Mountpoint}). + +%%-------------------------------------------------------------------- +%% Setups +%%-------------------------------------------------------------------- + +all() -> + [{group, http_inet}, + {group, http_inet6}, + {group, https_inet}, + {group, https_inet6}]. + +groups() -> + Cases = emqx_ct:all(?MODULE), + [{Name, Cases} || Name <- [http_inet, http_inet6, https_inet, https_inet6]]. + +init_per_group(GrpName, Cfg) -> + [Schema, Inet] = [list_to_atom(X) || X <- string:tokens(atom_to_list(GrpName), "_")], + http_auth_server:start(Schema, Inet), + Fun = fun(App) -> set_special_configs(App, Schema, Inet) end, + emqx_ct_helpers:start_apps([emqx_auth_http], Fun), + Cfg. + +end_per_group(_GrpName, _Cfg) -> + http_auth_server:stop(), + emqx_ct_helpers:stop_apps([emqx_auth_http, emqx]). + +set_special_configs(emqx, _Schmea, _Inet) -> + application:set_env(emqx, allow_anonymous, true), + application:set_env(emqx, enable_acl_cache, false), + LoadedPluginPath = filename:join(["test", "emqx_SUITE_data", "loaded_plugins"]), + application:set_env(emqx, plugins_loaded_file, + emqx_ct_helpers:deps_path(emqx, LoadedPluginPath)); + +set_special_configs(emqx_auth_http, Schema, Inet) -> + AuthReq = maps:from_list(application:get_env(emqx_auth_http, auth_req, [])), + SuprReq = maps:from_list(application:get_env(emqx_auth_http, super_req, [])), + AclReq = maps:from_list(application:get_env(emqx_auth_http, acl_req, [])), + SvrAddr = http_server_host(Schema, Inet), + + AuthReq1 = AuthReq#{method := get, url := SvrAddr ++ "/mqtt/auth"}, + SuprReq1 = SuprReq#{method := post, content_type := 'x-www-form-urlencoded', url := SvrAddr ++ "/mqtt/superuser"}, + AclReq1 = AclReq #{method := post, content_type := json, url := SvrAddr ++ "/mqtt/acl"}, + + Schema =:= https andalso set_https_client_opts(), + + application:set_env(emqx_auth_http, auth_req, maps:to_list(AuthReq1)), + application:set_env(emqx_auth_http, super_req, maps:to_list(SuprReq1)), + application:set_env(emqx_auth_http, acl_req, maps:to_list(AclReq1)). + +%% @private +set_https_client_opts() -> + HttpOpts = maps:from_list(application:get_env(emqx_auth_http, http_opts, [])), + HttpOpts1 = HttpOpts#{ssl => emqx_ct_helpers:client_ssl_twoway()}, + application:set_env(emqx_auth_http, http_opts, maps:to_list(HttpOpts1)). + +%% @private +http_server_host(http, inet) -> "http://127.0.0.1:8991"; +http_server_host(http, inet6) -> "http://[::1]:8991"; +http_server_host(https, inet) -> "https://127.0.0.1:8991"; +http_server_host(https, inet6) -> "https://[::1]:8991". + +%%------------------------------------------------------------------------------ +%% Testcases +%%------------------------------------------------------------------------------ + +t_check_acl(_) -> + SuperUser = ?USER(<<"superclient">>, <<"superuser">>, mqtt, {127,0,0,1}, external), + deny = emqx_access_control:check_acl(SuperUser, subscribe, <<"users/testuser/1">>), + deny = emqx_access_control:check_acl(SuperUser, publish, <<"anytopic">>), + + User1 = ?USER(<<"client1">>, <<"testuser">>, mqtt, {127,0,0,1}, external), + UnIpUser1 = ?USER(<<"client1">>, <<"testuser">>, mqtt, {192,168,0,4}, external), + UnClientIdUser1 = ?USER(<<"unkonwc">>, <<"testuser">>, mqtt, {127,0,0,1}, external), + UnnameUser1= ?USER(<<"client1">>, <<"unuser">>, mqtt, {127,0,0,1}, external), + allow = emqx_access_control:check_acl(User1, subscribe, <<"users/testuser/1">>), + deny = emqx_access_control:check_acl(User1, publish, <<"users/testuser/1">>), + deny = emqx_access_control:check_acl(UnIpUser1, subscribe, <<"users/testuser/1">>), + deny = emqx_access_control:check_acl(UnClientIdUser1, subscribe, <<"users/testuser/1">>), + deny = emqx_access_control:check_acl(UnnameUser1, subscribe, <<"$SYS/testuser/1">>), + + User2 = ?USER(<<"client2">>, <<"xyz">>, mqtt, {127,0,0,1}, external), + UserC = ?USER(<<"client2">>, <<"xyz">>, mqtt, {192,168,1,3}, external), + allow = emqx_access_control:check_acl(UserC, publish, <<"a/b/c">>), + deny = emqx_access_control:check_acl(User2, publish, <<"a/b/c">>), + deny = emqx_access_control:check_acl(User2, subscribe, <<"$SYS/testuser/1">>). + +t_check_auth(_) -> + User1 = ?USER(<<"client1">>, <<"testuser1">>, mqtt, {127,0,0,1}, external, undefined), + User2 = ?USER(<<"client2">>, <<"testuser2">>, mqtt, {127,0,0,1}, exteneral, undefined), + User3 = ?USER(<<"client3">>, undefined, mqtt, {127,0,0,1}, exteneral, undefined), + + {ok, #{auth_result := success, + anonymous := false, + is_superuser := false}} = emqx_access_control:authenticate(User1#{password => <<"pass1">>}), + {error, bad_username_or_password} = emqx_access_control:authenticate(User1#{password => <<"pass">>}), + {error, bad_username_or_password} = emqx_access_control:authenticate(User1#{password => <<>>}), + + {ok, #{is_superuser := false}} = emqx_access_control:authenticate(User2#{password => <<"pass2">>}), + {error, bad_username_or_password} = emqx_access_control:authenticate(User2#{password => <<>>}), + {error, bad_username_or_password} = emqx_access_control:authenticate(User2#{password => <<"errorpwd">>}), + + {error, bad_username_or_password} = emqx_access_control:authenticate(User3#{password => <<"pwd">>}). + +t_sub_pub(_) -> + ct:pal("start client"), + {ok, T1} = emqtt:start_link([{host, "localhost"}, + {clientid, <<"client1">>}, + {username, <<"testuser1">>}, + {password, <<"pass1">>}]), + {ok, _} = emqtt:connect(T1), + emqtt:publish(T1, <<"topic">>, <<"body">>, [{qos, 0}, {retain, true}]), + timer:sleep(1000), + {ok, T2} = emqtt:start_link([{host, "localhost"}, + {clientid, <<"client2">>}, + {username, <<"testuser2">>}, + {password, <<"pass2">>}]), + {ok, _} = emqtt:connect(T2), + emqtt:subscribe(T2, <<"topic">>), + receive + {publish, _Topic, Payload} -> + ?assertEqual(<<"body">>, Payload) + after 1000 -> false end, + emqtt:disconnect(T1), + emqtt:disconnect(T2). + +t_comment_config(_) -> + AuthCount = length(emqx_hooks:lookup('client.authenticate')), + AclCount = length(emqx_hooks:lookup('client.check_acl')), + application:stop(?APP), + [application:unset_env(?APP, Par) || Par <- [acl_req, auth_req]], + application:start(?APP), + ?assertEqual([], emqx_hooks:lookup('client.authenticate')), + ?assertEqual(AuthCount - 1, length(emqx_hooks:lookup('client.authenticate'))), + ?assertEqual(AclCount - 1, length(emqx_hooks:lookup('client.check_acl'))). + diff --git a/apps/emqx_auth_http/test/http_auth_server.erl b/apps/emqx_auth_http/test/http_auth_server.erl new file mode 100644 index 000000000..54c4d38b3 --- /dev/null +++ b/apps/emqx_auth_http/test/http_auth_server.erl @@ -0,0 +1,152 @@ +-module(http_auth_server). + +-export([ start/2 + , stop/0 + ]). + +-define(SUPERUSER, [[{"username", "superuser"}, {"clientid", "superclient"}]]). + +-define(ACL, [[{<<"username">>, <<"testuser">>}, + {<<"clientid">>, <<"client1">>}, + {<<"access">>, <<"1">>}, + {<<"topic">>, <<"users/testuser/1">>}, + {<<"ipaddr">>, <<"127.0.0.1">>}, + {<<"mountpoint">>, <<"null">>}], + [{<<"username">>, <<"xyz">>}, + {<<"clientid">>, <<"client2">>}, + {<<"access">>, <<"2">>}, + {<<"topic">>, <<"a/b/c">>}, + {<<"ipaddr">>, <<"192.168.1.3">>}, + {<<"mountpoint">>, <<"null">>}], + [{<<"username">>, <<"testuser1">>}, + {<<"clientid">>, <<"client1">>}, + {<<"access">>, <<"2">>}, + {<<"topic">>, <<"topic">>}, + {<<"ipaddr">>, <<"127.0.0.1">>}, + {<<"mountpoint">>, <<"null">>}], + [{<<"username">>, <<"testuser2">>}, + {<<"clientid">>, <<"client2">>}, + {<<"access">>, <<"1">>}, + {<<"topic">>, <<"topic">>}, + {<<"ipaddr">>, <<"127.0.0.1">>}, + {<<"mountpoint">>, <<"null">>}]]). + +-define(AUTH, [[{<<"clientid">>, <<"client1">>}, + {<<"username">>, <<"testuser1">>}, + {<<"password">>, <<"pass1">>}], + [{<<"clientid">>, <<"client2">>}, + {<<"username">>, <<"testuser2">>}, + {<<"password">>, <<"pass2">>}]]). + +%%------------------------------------------------------------------------------ +%% REST Interface +%%------------------------------------------------------------------------------ + +-rest_api(#{ name => auth + , method => 'GET' + , path => "/mqtt/auth" + , func => authenticate + , descr => "Authenticate user access permission" + }). + +-rest_api(#{ name => is_superuser + , method => 'GET' + , path => "/mqtt/superuser" + , func => is_superuser + , descr => "Is super user" + }). + +-rest_api(#{ name => acl + , method => 'GET' + , path => "/mqtt/acl" + , func => check_acl + , descr => "Check acl" + }). + +-rest_api(#{ name => auth + , method => 'POST' + , path => "/mqtt/auth" + , func => authenticate + , descr => "Authenticate user access permission" + }). + +-rest_api(#{ name => is_superuser + , method => 'POST' + , path => "/mqtt/superuser" + , func => is_superuser + , descr => "Is super user" + }). + +-rest_api(#{ name => acl + , method => 'POST' + , path => "/mqtt/acl" + , func => check_acl + , descr => "Check acl" + }). + +-export([ authenticate/2 + , is_superuser/2 + , check_acl/2 + ]). + +authenticate(_Binding, Params) -> + return(check(Params, ?AUTH)). + +is_superuser(_Binding, Params) -> + return(check(Params, ?SUPERUSER)). + +check_acl(_Binding, Params) -> + return(check(Params, ?ACL)). + +return(allow) -> {200, <<"allow">>}; +return(deny) -> {400, <<"deny">>}. + +start(http, Inet) -> + application:ensure_all_started(minirest), + Handlers = [{"/", minirest:handler(#{modules => [?MODULE]})}], + Dispatch = [{"/[...]", minirest, Handlers}], + minirest:start_http(http_auth_server, #{socket_opts => [Inet, {port, 8991}]}, Dispatch); + +start(https, Inet) -> + application:ensure_all_started(minirest), + Handlers = [{"/", minirest:handler(#{modules => [?MODULE]})}], + Dispatch = [{"/[...]", minirest, Handlers}], + minirest:start_https(http_auth_server, #{socket_opts => [Inet, {port, 8991} | certopts()]}, Dispatch). + +%% @private +certopts() -> + Certfile = filename:join(["etc", "certs", "cert.pem"]), + Keyfile = filename:join(["etc", "certs", "key.pem"]), + CaCert = filename:join(["etc", "certs", "cacert.pem"]), + [{verify, verify_peer}, + {certfile, emqx_ct_helpers:deps_path(emqx, Certfile)}, + {keyfile, emqx_ct_helpers:deps_path(emqx, Keyfile)}, + {cacertfile, emqx_ct_helpers:deps_path(emqx, CaCert)}] ++ emqx_ct_helpers:client_ssl(). + +stop() -> + minirest:stop_http(http_auth_server). + +-spec check(HttpReqParams :: list(), DefinedConf :: list()) -> allow | deny. +check(_Params, []) -> + %ct:pal("check auth_result: deny~n"), + deny; +check(Params, [ConfRecord|T]) -> + % ct:pal("Params: ~p, ConfRecord:~p ~n", [Params, ConfRecord]), + case match_config(Params, ConfRecord) of + not_match -> + check(Params, T); + matched -> allow + end. + +match_config([], _ConfigColumn) -> + %ct:pal("match_config auth_result: matched~n"), + matched; + +match_config([Param|T], ConfigColumn) -> + %ct:pal("Param: ~p, ConfigColumn:~p ~n", [Param, ConfigColumn]), + case lists:member(Param, ConfigColumn) of + true -> + match_config(T, ConfigColumn); + false -> + not_match + end. diff --git a/apps/emqx_auth_jwt/README.md b/apps/emqx_auth_jwt/README.md new file mode 100644 index 000000000..9675ae87c --- /dev/null +++ b/apps/emqx_auth_jwt/README.md @@ -0,0 +1,90 @@ + +# emqx-auth-jwt + +EMQ X JWT Authentication Plugin + +Build +----- + +``` +make && make tests +``` + +Configure the Plugin +-------------------- + +File: etc/plugins/emqx_auth_jwt.conf + +``` +## HMAC Hash Secret. +## +## Value: String +auth.jwt.secret = emqxsecret + +## From where the JWT string can be got +## +## Value: username | password +## Default: password +auth.jwt.from = password + +## RSA or ECDSA public key file. +## +## Value: File +## auth.jwt.pubkey = etc/certs/jwt_public_key.pem + +## Enable to verify claims fields +## +## Value: on | off +auth.jwt.verify_claims = off + +## The checklist of claims to validate +## +## Value: String +## auth.jwt.verify_claims.$name = expected +## +## Variables: +## - %u: username +## - %c: clientid +# auth.jwt.verify_claims.username = %u +``` + +Load the Plugin +--------------- + +``` +./bin/emqx_ctl plugins load emqx_auth_jwt +``` + +Example +------- + +``` +mosquitto_pub -t 'pub' -m 'hello' -i test -u test -P eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiYm9iIiwiYWdlIjoyOX0.bIV_ZQ8D5nQi0LT8AVkpM4Pd6wmlbpR9S8nOLJAsA8o +``` + +Algorithms +---------- + +The JWT spec supports several algorithms for cryptographic signing. This plugin currently supports: + +* HS256 - HMAC using SHA-256 hash algorithm +* HS384 - HMAC using SHA-384 hash algorithm +* HS512 - HMAC using SHA-512 hash algorithm + +* RS256 - RSA with the SHA-256 hash algorithm +* RS384 - RSA with the SHA-384 hash algorithm +* RS512 - RSA with the SHA-512 hash algorithm + +* ES256 - ECDSA using the P-256 curve +* ES384 - ECDSA using the P-384 curve +* ES512 - ECDSA using the P-512 curve + +License +------- + +Apache License Version 2.0 + +Author +------ + +EMQ X Team. diff --git a/apps/emqx_auth_jwt/TODO.md b/apps/emqx_auth_jwt/TODO.md new file mode 100644 index 000000000..dfd730e0a --- /dev/null +++ b/apps/emqx_auth_jwt/TODO.md @@ -0,0 +1,2 @@ +1. Notice for the [Critical vulnerabilities in JSON Web Token](https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/) + diff --git a/apps/emqx_auth_jwt/doc/hmac-vs-ecdsa-for-jwt.txt b/apps/emqx_auth_jwt/doc/hmac-vs-ecdsa-for-jwt.txt new file mode 100644 index 000000000..88fa5ebde --- /dev/null +++ b/apps/emqx_auth_jwt/doc/hmac-vs-ecdsa-for-jwt.txt @@ -0,0 +1,3 @@ + +https://crypto.stackexchange.com/questions/30657/hmac-vs-ecdsa-for-jwt + diff --git a/apps/emqx_auth_jwt/priv/emqx_auth_jwt.schema b/apps/emqx_auth_jwt/priv/emqx_auth_jwt.schema new file mode 100644 index 000000000..e8210a8cd --- /dev/null +++ b/apps/emqx_auth_jwt/priv/emqx_auth_jwt.schema @@ -0,0 +1,48 @@ +%%-*- mode: erlang -*- + +{mapping, "auth.jwt.secret", "emqx_auth_jwt.secret", [ + {datatype, string} +]}. + +{mapping, "auth.jwt.from", "emqx_auth_jwt.from", [ + {default, password}, + {datatype, atom} +]}. + +{mapping, "auth.jwt.pubkey", "emqx_auth_jwt.pubkey", [ + {datatype, string} +]}. + +{mapping, "auth.jwt.verify_claims", "emqx_auth_jwt.verify_claims", [ + {default, off}, + {datatype, flag} +]}. + +{mapping, "auth.jwt.verify_claims.$name", "emqx_auth_jwt.verify_claims", [ + {datatype, string} +]}. + +{translation, "emqx_auth_jwt.verify_claims", fun(Conf) -> + case cuttlefish:conf_get("auth.jwt.verify_claims", Conf) of + false -> cuttlefish:unset(); + true -> + lists:foldr( + fun({["auth","jwt","verify_claims", Name], Value}, Acc) -> + [{list_to_atom(Name), list_to_binary(Value)} | Acc]; + ({["auth","jwt","verify_claims"], _Value}, Acc) -> + Acc + end, [], cuttlefish_variable:filter_by_prefix("auth.jwt.verify_claims", Conf)) + end +end}. + +{mapping, "auth.jwt.signature_format", "emqx_auth_jwt.jwerl_opts", [ + {default, "der"}, + {datatype, {enum, [raw, der]}} +]}. + +{translation, "emqx_auth_jwt.jwerl_opts", fun(Conf) -> + Filter = fun(L) -> [I || I <- L, I /= undefined] end, + maps:from_list(Filter( + [{raw, cuttlefish:conf_get("auth.jwt.signature_format", Conf) == raw}] + )) +end}. diff --git a/apps/emqx_auth_jwt/rebar.config b/apps/emqx_auth_jwt/rebar.config new file mode 100644 index 000000000..0728a0b95 --- /dev/null +++ b/apps/emqx_auth_jwt/rebar.config @@ -0,0 +1,3 @@ +{deps, + [{jwerl, {git, "https://github.com/emqx/jwerl.git", {branch, "1.1.1"}}} + ]}. diff --git a/apps/emqx_auth_jwt/src/emqx_auth_jwt.app.src b/apps/emqx_auth_jwt/src/emqx_auth_jwt.app.src new file mode 100644 index 000000000..e89ac458d --- /dev/null +++ b/apps/emqx_auth_jwt/src/emqx_auth_jwt.app.src @@ -0,0 +1,14 @@ +{application, emqx_auth_jwt, + [{description, "EMQ X Authentication with JWT"}, + {vsn, "5.0.0"}, % strict semver, bump manually! + {modules, []}, + {registered, [emqx_auth_jwt_sup]}, + {applications, [kernel,stdlib,jwerl,emqx_libs]}, + {mod, {emqx_auth_jwt_app, []}}, + {env, []}, + {licenses, ["Apache-2.0"]}, + {maintainers, ["EMQ X Team "]}, + {links, [{"Homepage", "https://emqx.io/"}, + {"Github", "https://github.com/emqx/emqx-auth-jwt"} + ]} + ]}. diff --git a/apps/emqx_auth_jwt/src/emqx_auth_jwt.erl b/apps/emqx_auth_jwt/src/emqx_auth_jwt.erl new file mode 100644 index 000000000..551f5c6b4 --- /dev/null +++ b/apps/emqx_auth_jwt/src/emqx_auth_jwt.erl @@ -0,0 +1,146 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_jwt). + +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). + +-logger_header("[JWT]"). + +-export([ register_metrics/0 + , check/3 + , description/0 + ]). + +-record(auth_metrics, { + success = 'client.auth.success', + failure = 'client.auth.failure', + ignore = 'client.auth.ignore' + }). + +-define(METRICS(Type), tl(tuple_to_list(#Type{}))). +-define(METRICS(Type, K), #Type{}#Type.K). + +-define(AUTH_METRICS, ?METRICS(auth_metrics)). +-define(AUTH_METRICS(K), ?METRICS(auth_metrics, K)). + +-spec(register_metrics() -> ok). +register_metrics() -> + lists:foreach(fun emqx_metrics:ensure/1, ?AUTH_METRICS). + +%%-------------------------------------------------------------------- +%% Authentication callbacks +%%-------------------------------------------------------------------- + +check(ClientInfo, AuthResult, Env = #{from := From, checklists := Checklists}) -> + case maps:find(From, ClientInfo) of + error -> + ok = emqx_metrics:inc(?AUTH_METRICS(ignore)), + {ok, AuthResult#{auth_result => token_undefined, anonymous => false}}; + {ok, Token} -> + try jwerl:header(Token) of + Headers -> + case verify_token(Headers, Token, Env) of + {ok, Claims} -> + {stop, maps:merge(AuthResult, verify_claims(Checklists, Claims, ClientInfo))}; + {error, Reason} -> + ok = emqx_metrics:inc(?AUTH_METRICS(failure)), + {stop, AuthResult#{auth_result => Reason, anonymous => false}} + end + catch + _Error:Reason -> + ?LOG(error, "Check token error: ~p", [Reason]), + emqx_metrics:inc(?AUTH_METRICS(ignore)) + end + end. + +description() -> "Authentication with JWT". + +%%-------------------------------------------------------------------- +%% Verify Token +%%-------------------------------------------------------------------- + +verify_token(#{alg := <<"HS", _/binary>>}, _Token, #{secret := undefined}) -> + {error, hmac_secret_undefined}; +verify_token(#{alg := Alg = <<"HS", _/binary>>}, Token, #{secret := Secret, opts := Opts}) -> + verify_token2(Alg, Token, Secret, Opts); + +verify_token(#{alg := <<"RS", _/binary>>}, _Token, #{pubkey := undefined}) -> + {error, rsa_pubkey_undefined}; +verify_token(#{alg := Alg = <<"RS", _/binary>>}, Token, #{pubkey := PubKey, opts := Opts}) -> + verify_token2(Alg, Token, PubKey, Opts); + +verify_token(#{alg := <<"ES", _/binary>>}, _Token, #{pubkey := undefined}) -> + {error, ecdsa_pubkey_undefined}; +verify_token(#{alg := Alg = <<"ES", _/binary>>}, Token, #{pubkey := PubKey, opts := Opts}) -> + verify_token2(Alg, Token, PubKey, Opts); + +verify_token(Header, _Token, _Env) -> + ?LOG(error, "Unsupported token algorithm: ~p", [Header]), + {error, token_unsupported}. + +verify_token2(Alg, Token, SecretOrKey, Opts) -> + try jwerl:verify(Token, decode_algo(Alg), SecretOrKey, #{}, Opts) of + {ok, Claims} -> + {ok, Claims}; + {error, Reason} -> + {error, Reason} + catch + _Error:Reason -> + {error, Reason} + end. + +decode_algo(<<"HS256">>) -> hs256; +decode_algo(<<"HS384">>) -> hs384; +decode_algo(<<"HS512">>) -> hs512; +decode_algo(<<"RS256">>) -> rs256; +decode_algo(<<"RS384">>) -> rs384; +decode_algo(<<"RS512">>) -> rs512; +decode_algo(<<"ES256">>) -> es256; +decode_algo(<<"ES384">>) -> es384; +decode_algo(<<"ES512">>) -> es512; +decode_algo(<<"none">>) -> none; +decode_algo(Alg) -> throw({error, {unsupported_algorithm, Alg}}). + +%%-------------------------------------------------------------------- +%% Verify Claims +%%-------------------------------------------------------------------- + +verify_claims(Checklists, Claims, ClientInfo) -> + case do_verify_claims(feedvar(Checklists, ClientInfo), Claims) of + {error, Reason} -> + ok = emqx_metrics:inc(?AUTH_METRICS(failure)), + #{auth_result => Reason, anonymous => false}; + ok -> + ok = emqx_metrics:inc(?AUTH_METRICS(success)), + #{auth_result => success, anonymous => false, jwt_claims => Claims} + end. + +do_verify_claims([], _Claims) -> + ok; +do_verify_claims([{Key, Expected} | L], Claims) -> + case maps:get(Key, Claims, undefined) =:= Expected of + true -> do_verify_claims(L, Claims); + false -> {error, {verify_claim_failed, Key}} + end. + +feedvar(Checklists, #{username := Username, clientid := ClientId}) -> + lists:map(fun({K, <<"%u">>}) -> {K, Username}; + ({K, <<"%c">>}) -> {K, ClientId}; + ({K, Expected}) -> {K, Expected} + end, Checklists). + diff --git a/apps/emqx_auth_jwt/src/emqx_auth_jwt_app.erl b/apps/emqx_auth_jwt/src/emqx_auth_jwt_app.erl new file mode 100644 index 000000000..511f6e826 --- /dev/null +++ b/apps/emqx_auth_jwt/src/emqx_auth_jwt_app.erl @@ -0,0 +1,69 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_jwt_app). + +-behaviour(application). + +-behaviour(supervisor). + +-emqx_plugin(auth). + +-export([start/2, stop/1]). + +-export([init/1]). + +-define(APP, emqx_auth_jwt). + +-define(JWT_ACTION, {emqx_auth_jwt, check, [auth_env()]}). + +start(_Type, _Args) -> + ok = emqx_auth_jwt:register_metrics(), + emqx:hook('client.authenticate', ?JWT_ACTION), + supervisor:start_link({local, ?MODULE}, ?MODULE, []). + +stop(_State) -> + emqx:unhook('client.authenticate', ?JWT_ACTION). + +%%-------------------------------------------------------------------- +%% Dummy supervisor +%%-------------------------------------------------------------------- + +init([]) -> + {ok, { {one_for_all, 1, 10}, []} }. + +%%-------------------------------------------------------------------- +%% Internal functions +%%-------------------------------------------------------------------- + +auth_env() -> + #{secret => env(secret, undefined), + from => env(from, password), + pubkey => read_pubkey(), + checklists => env(verify_claims, []), + opts => env(jwerl_opts, #{}) + }. + +read_pubkey() -> + case env(pubkey, undefined) of + undefined -> undefined; + Path -> + {ok, PubKey} = file:read_file(Path), PubKey + end. + +env(Key, Default) -> + application:get_env(?APP, Key, Default). + diff --git a/apps/emqx_auth_jwt/test/emqx_auth_jwt_SUITE.erl b/apps/emqx_auth_jwt/test/emqx_auth_jwt_SUITE.erl new file mode 100644 index 000000000..dcb1f2758 --- /dev/null +++ b/apps/emqx_auth_jwt/test/emqx_auth_jwt_SUITE.erl @@ -0,0 +1,137 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_jwt_SUITE). + +-compile(nowarn_export_all). +-compile(export_all). + +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("eunit/include/eunit.hrl"). +-include_lib("common_test/include/ct.hrl"). + +-define(APP, emqx_auth_jwt). + +all() -> + [{group, emqx_auth_jwt}]. + +groups() -> + [{emqx_auth_jwt, [sequence], [ t_check_auth + , t_check_claims + , t_check_claims_clientid + , t_check_claims_username + ]} + ]. + +init_per_suite(Config) -> + emqx_ct_helpers:start_apps([emqx, emqx_auth_jwt], fun set_special_configs/1), + Config. + +end_per_suite(_Config) -> + emqx_ct_helpers:stop_apps([emqx_auth_jwt, emqx]). + +set_special_configs(emqx) -> + application:set_env(emqx, allow_anonymous, false), + application:set_env(emqx, acl_nomatch, deny), + application:set_env(emqx, enable_acl_cache, false), + LoadedPluginPath = filename:join(["test", "emqx_SUITE_data", "loaded_plugins"]), + AclFilePath = filename:join(["test", "emqx_SUITE_data", "acl.conf"]), + application:set_env(emqx, plugins_loaded_file, + emqx_ct_helpers:deps_path(emqx, LoadedPluginPath)), + application:set_env(emqx, acl_file, + emqx_ct_helpers:deps_path(emqx, AclFilePath)); + +set_special_configs(emqx_auth_jwt) -> + application:set_env(emqx_auth_jwt, secret, "emqxsecret"), + application:set_env(emqx_auth_jwt, from, password); + +set_special_configs(_) -> + ok. + +%%------------------------------------------------------------------------------ +%% Testcases +%%------------------------------------------------------------------------------ + +t_check_auth(_) -> + Plain = #{clientid => <<"client1">>, username => <<"plain">>, zone => external}, + Jwt = jwerl:sign([{clientid, <<"client1">>}, + {username, <<"plain">>}, + {exp, os:system_time(seconds) + 3}], hs256, <<"emqxsecret">>), + ct:pal("Jwt: ~p~n", [Jwt]), + + Result0 = emqx_access_control:authenticate(Plain#{password => Jwt}), + ct:pal("Auth result: ~p~n", [Result0]), + ?assertMatch({ok, #{auth_result := success, jwt_claims := #{clientid := <<"client1">>}}}, Result0), + + ct:sleep(3100), + Result1 = emqx_access_control:authenticate(Plain#{password => Jwt}), + ct:pal("Auth result after 1000ms: ~p~n", [Result1]), + ?assertMatch({error, _}, Result1), + + Jwt_Error = jwerl:sign([{clientid, <<"client1">>}, + {username, <<"plain">>}], hs256, <<"secret">>), + ct:pal("invalid jwt: ~p~n", [Jwt_Error]), + Result2 = emqx_access_control:authenticate(Plain#{password => Jwt_Error}), + ct:pal("Auth result for the invalid jwt: ~p~n", [Result2]), + ?assertEqual({error, invalid_signature}, Result2), + ?assertMatch({error, _}, emqx_access_control:authenticate(Plain#{password => <<"asd">>})). + +t_check_claims(_) -> + application:set_env(emqx_auth_jwt, verify_claims, [{sub, <<"value">>}]), + Plain = #{clientid => <<"client1">>, username => <<"plain">>, zone => external}, + Jwt = jwerl:sign([{clientid, <<"client1">>}, + {username, <<"plain">>}, + {sub, value}, + {exp, os:system_time(seconds) + 3}], hs256, <<"emqxsecret">>), + Result0 = emqx_access_control:authenticate(Plain#{password => Jwt}), + ct:pal("Auth result: ~p~n", [Result0]), + ?assertMatch({ok, #{auth_result := success, jwt_claims := _}}, Result0), + Jwt_Error = jwerl:sign([{clientid, <<"client1">>}, + {username, <<"plain">>}], hs256, <<"secret">>), + Result2 = emqx_access_control:authenticate(Plain#{password => Jwt_Error}), + ct:pal("Auth result for the invalid jwt: ~p~n", [Result2]), + ?assertEqual({error, invalid_signature}, Result2). + +t_check_claims_clientid(_) -> + application:set_env(emqx_auth_jwt, verify_claims, [{clientid, <<"%c">>}]), + Plain = #{clientid => <<"client23">>, username => <<"plain">>, zone => external}, + Jwt = jwerl:sign([{clientid, <<"client23">>}, + {username, <<"plain">>}, + {exp, os:system_time(seconds) + 3}], hs256, <<"emqxsecret">>), + Result0 = emqx_access_control:authenticate(Plain#{password => Jwt}), + ct:pal("Auth result: ~p~n", [Result0]), + ?assertMatch({ok, #{auth_result := success, jwt_claims := _}}, Result0), + Jwt_Error = jwerl:sign([{clientid, <<"client1">>}, + {username, <<"plain">>}], hs256, <<"secret">>), + Result2 = emqx_access_control:authenticate(Plain#{password => Jwt_Error}), + ct:pal("Auth result for the invalid jwt: ~p~n", [Result2]), + ?assertEqual({error, invalid_signature}, Result2). + +t_check_claims_username(_) -> + application:set_env(emqx_auth_jwt, verify_claims, [{username, <<"%u">>}]), + Plain = #{clientid => <<"client23">>, username => <<"plain">>, zone => external}, + Jwt = jwerl:sign([{clientid, <<"client23">>}, + {username, <<"plain">>}, + {exp, os:system_time(seconds) + 3}], hs256, <<"emqxsecret">>), + Result0 = emqx_access_control:authenticate(Plain#{password => Jwt}), + ct:pal("Auth result: ~p~n", [Result0]), + ?assertMatch({ok, #{auth_result := success, jwt_claims := _}}, Result0), + Jwt_Error = jwerl:sign([{clientid, <<"client1">>}, + {username, <<"plain">>}], hs256, <<"secret">>), + Result3 = emqx_access_control:authenticate(Plain#{password => Jwt_Error}), + ct:pal("Auth result for the invalid jwt: ~p~n", [Result3]), + ?assertEqual({error, invalid_signature}, Result3). + diff --git a/apps/emqx_auth_ldap/.ci/docker-compose.yml b/apps/emqx_auth_ldap/.ci/docker-compose.yml new file mode 100644 index 000000000..bba9b711f --- /dev/null +++ b/apps/emqx_auth_ldap/.ci/docker-compose.yml @@ -0,0 +1,26 @@ +version: '3' + +services: + erlang: + image: erlang:22.1 + volumes: + - ../:/emqx_auth_ldap + networks: + - emqx_bridge + depends_on: + - ldap_server + tty: true + + ldap_server: + build: ./emqx-ldap + image: emqx-ldap:1.0 + restart: always + ports: + - 389:389 + - 636:636 + networks: + - emqx_bridge + +networks: + emqx_bridge: + driver: bridge diff --git a/apps/emqx_auth_ldap/.ci/emqx-ldap/Dockerfile b/apps/emqx_auth_ldap/.ci/emqx-ldap/Dockerfile new file mode 100644 index 000000000..0a01572c4 --- /dev/null +++ b/apps/emqx_auth_ldap/.ci/emqx-ldap/Dockerfile @@ -0,0 +1,26 @@ +FROM buildpack-deps:stretch + +ENV VERSION=2.4.50 + +RUN apt-get update && apt-get install -y groff groff-base +RUN wget ftp://ftp.openldap.org/pub/OpenLDAP/openldap-release/openldap-${VERSION}.tgz \ + && gunzip -c openldap-${VERSION}.tgz | tar xvfB - \ + && cd openldap-${VERSION} \ + && ./configure && make depend && make && make install \ + && cd .. && rm -rf openldap-${VERSION} + +COPY ./slapd.conf /usr/local/etc/openldap/slapd.conf +COPY ./emqx.io.ldif /usr/local/etc/openldap/schema/emqx.io.ldif +COPY ./emqx.schema /usr/local/etc/openldap/schema/emqx.schema +COPY ./*.pem /usr/local/etc/openldap/ + +RUN mkdir -p /usr/local/etc/openldap/data \ + && slapadd -l /usr/local/etc/openldap/schema/emqx.io.ldif -f /usr/local/etc/openldap/slapd.conf + +WORKDIR /usr/local/etc/openldap + +EXPOSE 389 636 + +ENTRYPOINT ["/usr/local/libexec/slapd", "-h", "ldap:/// ldaps:///", "-d", "3", "-f", "/usr/local/etc/openldap/slapd.conf"] + +CMD [] diff --git a/apps/emqx_auth_ldap/.ci/emqx-ldap/slapd.conf b/apps/emqx_auth_ldap/.ci/emqx-ldap/slapd.conf new file mode 100644 index 000000000..d6ba20caa --- /dev/null +++ b/apps/emqx_auth_ldap/.ci/emqx-ldap/slapd.conf @@ -0,0 +1,16 @@ +include /usr/local/etc/openldap/schema/core.schema +include /usr/local/etc/openldap/schema/cosine.schema +include /usr/local/etc/openldap/schema/inetorgperson.schema +include /usr/local/etc/openldap/schema/ppolicy.schema +include /usr/local/etc/openldap/schema/emqx.schema + +TLSCACertificateFile /usr/local/etc/openldap/cacert.pem +TLSCertificateFile /usr/local/etc/openldap/cert.pem +TLSCertificateKeyFile /usr/local/etc/openldap/key.pem + +database bdb +suffix "dc=emqx,dc=io" +rootdn "cn=root,dc=emqx,dc=io" +rootpw {SSHA}eoF7NhNrejVYYyGHqnt+MdKNBh4r1w3W + +directory /usr/local/etc/openldap/data diff --git a/apps/emqx_auth_ldap/README.md b/apps/emqx_auth_ldap/README.md new file mode 100644 index 000000000..c4d56c839 --- /dev/null +++ b/apps/emqx_auth_ldap/README.md @@ -0,0 +1,96 @@ +emqx_auth_ldap +============== + +EMQ X LDAP Authentication Plugin + +Build +----- + +``` +make +``` + +Load the Plugin +--------------- + +``` +# ./bin/emqx_ctl plugins load emqx_auth_ldap +``` + +Generate Password +--------------- + +``` +slappasswd -h '{ssha}' -s public +``` + +Configuration Open LDAP +----------------------- + +vim /etc/openldap/slapd.conf + +``` +include /etc/openldap/schema/core.schema +include /etc/openldap/schema/cosine.schema +include /etc/openldap/schema/inetorgperson.schema +include /etc/openldap/schema/ppolicy.schema +include /etc/openldap/schema/emqx.schema + +database bdb +suffix "dc=emqx,dc=io" +rootdn "cn=root,dc=emqx,dc=io" +rootpw {SSHA}eoF7NhNrejVYYyGHqnt+MdKNBh4r1w3W + +directory /etc/openldap/data +``` + +If the ldap launched with error below: +``` +Unrecognized database type (bdb) +5c4a72b9 slapd.conf: line 7: failed init (bdb) +slapadd: bad configuration file! +``` + +Insert lines to the slapd.conf +``` +modulepath /usr/lib/ldap +moduleload back_bdb.la +``` + +Import EMQX User Data +---------------------- + +Use ldapadd +``` +# ldapadd -x -D "cn=root,dc=emqx,dc=io" -w public -f emqx.com.ldif +``` + +Use slapadd +``` +# sudo slapadd -l schema/emqx.io.ldif -f slapd.conf +``` + +Launch slapd +``` +# sudo slapd -d 3 +``` + +Test +----- +After configure slapd correctly and launch slapd successfully. +You could execute + +``` bash +# make tests +``` + +License +------- + +Apache License Version 2.0 + +Author +------ + +EMQ X Team. + diff --git a/apps/emqx_auth_ldap/emqx.io.ldif b/apps/emqx_auth_ldap/emqx.io.ldif new file mode 100644 index 000000000..f9833cd88 --- /dev/null +++ b/apps/emqx_auth_ldap/emqx.io.ldif @@ -0,0 +1,135 @@ +## create emqx.io + +dn:dc=emqx,dc=io +objectclass: top +objectclass: dcobject +objectclass: organization +dc:emqx +o:emqx,Inc. + +# create testdevice.emqx.io +dn:ou=testdevice,dc=emqx,dc=io +objectClass: top +objectclass:organizationalUnit +ou:testdevice + +# create user admin +dn:uid=admin,ou=testdevice,dc=emqx,dc=io +objectClass: top +objectClass: simpleSecurityObject +objectClass: account +userPassword:: e1NIQX1XNnBoNU1tNVB6OEdnaVVMYlBnekczN21qOWc9 +uid: admin + +## create user=mqttuser0001, +# password=mqttuser0001, +# passhash={SHA}mlb3fat40MKBTXUVZwCKmL73R/0= +# base64passhash=e1NIQX1tbGIzZmF0NDBNS0JUWFVWWndDS21MNzNSLzA9 +dn:uid=mqttuser0001,ou=testdevice,dc=emqx,dc=io +objectClass: top +objectClass: mqttUser +objectClass: mqttDevice +objectClass: mqttSecurity +uid: mqttuser0001 +isEnabled: TRUE +mqttAccountName: user1 +mqttPublishTopic: mqttuser0001/pub/1 +mqttPublishTopic: mqttuser0001/pub/+ +mqttPublishTopic: mqttuser0001/pub/# +mqttSubscriptionTopic: mqttuser0001/sub/1 +mqttSubscriptionTopic: mqttuser0001/sub/+ +mqttSubscriptionTopic: mqttuser0001/sub/# +mqttPubSubTopic: mqttuser0001/pubsub/1 +mqttPubSubTopic: mqttuser0001/pubsub/+ +mqttPubSubTopic: mqttuser0001/pubsub/# +userPassword:: e1NIQX1tbGIzZmF0NDBNS0JUWFVWWndDS21MNzNSLzA9 + +## create user=mqttuser0002 +# password=mqttuser0002, +# passhash={SSHA}n9XdtoG4Q/TQ3TQF4Y+khJbMBH4qXj4M +# base64passhash=e1NTSEF9bjlYZHRvRzRRL1RRM1RRRjRZK2toSmJNQkg0cVhqNE0= +dn:uid=mqttuser0002,ou=testdevice,dc=emqx,dc=io +objectClass: top +objectClass: mqttUser +objectClass: mqttDevice +objectClass: mqttSecurity +uid: mqttuser0002 +isEnabled: TRUE +mqttAccountName: user2 +mqttPublishTopic: mqttuser0002/pub/1 +mqttPublishTopic: mqttuser0002/pub/+ +mqttPublishTopic: mqttuser0002/pub/# +mqttSubscriptionTopic: mqttuser0002/sub/1 +mqttSubscriptionTopic: mqttuser0002/sub/+ +mqttSubscriptionTopic: mqttuser0002/sub/# +mqttPubSubTopic: mqttuser0002/pubsub/1 +mqttPubSubTopic: mqttuser0002/pubsub/+ +mqttPubSubTopic: mqttuser0002/pubsub/# +userPassword:: e1NTSEF9bjlYZHRvRzRRL1RRM1RRRjRZK2toSmJNQkg0cVhqNE0= + +## create user mqttuser0003 +# password=mqttuser0003, +# passhash={MD5}ybsPGoaK3nDyiQvveiCOIw== +# base64passhash=e01ENX15YnNQR29hSzNuRHlpUXZ2ZWlDT0l3PT0= +dn:uid=mqttuser0003,ou=testdevice,dc=emqx,dc=io +objectClass: top +objectClass: mqttUser +objectClass: mqttDevice +objectClass: mqttSecurity +uid: mqttuser0003 +isEnabled: TRUE +mqttPublishTopic: mqttuser0003/pub/1 +mqttPublishTopic: mqttuser0003/pub/+ +mqttPublishTopic: mqttuser0003/pub/# +mqttSubscriptionTopic: mqttuser0003/sub/1 +mqttSubscriptionTopic: mqttuser0003/sub/+ +mqttSubscriptionTopic: mqttuser0003/sub/# +mqttPubSubTopic: mqttuser0003/pubsub/1 +mqttPubSubTopic: mqttuser0003/pubsub/+ +mqttPubSubTopic: mqttuser0003/pubsub/# +userPassword:: e01ENX15YnNQR29hSzNuRHlpUXZ2ZWlDT0l3PT0= + +## create user mqttuser0004 +# password=mqttuser0004, +# passhash={MD5}2Br6pPDSEDIEvUlu9+s+MA== +# base64passhash=e01ENX0yQnI2cFBEU0VESUV2VWx1OStzK01BPT0= +dn:uid=mqttuser0004,ou=testdevice,dc=emqx,dc=io +objectClass: top +objectClass: mqttUser +objectClass: mqttDevice +objectClass: mqttSecurity +uid: mqttuser0004 +isEnabled: TRUE +mqttPublishTopic: mqttuser0004/pub/1 +mqttPublishTopic: mqttuser0004/pub/+ +mqttPublishTopic: mqttuser0004/pub/# +mqttSubscriptionTopic: mqttuser0004/sub/1 +mqttSubscriptionTopic: mqttuser0004/sub/+ +mqttSubscriptionTopic: mqttuser0004/sub/# +mqttPubSubTopic: mqttuser0004/pubsub/1 +mqttPubSubTopic: mqttuser0004/pubsub/+ +mqttPubSubTopic: mqttuser0004/pubsub/# +userPassword: {MD5}2Br6pPDSEDIEvUlu9+s+MA== + +## create user mqttuser0005 +# password=mqttuser0005, +# passhash={SHA}jKnxeEDGR14kE8AR7yuVFOelhz4= +# base64passhash=e1NIQX1qS254ZUVER1IxNGtFOEFSN3l1VkZPZWxoejQ9 +objectClass: top +dn:uid=mqttuser0005,ou=testdevice,dc=emqx,dc=io +objectClass: mqttUser +objectClass: mqttDevice +objectClass: mqttSecurity +uid: mqttuser0005 +isEnabled: TRUE +mqttPublishTopic: mqttuser0005/pub/1 +mqttPublishTopic: mqttuser0005/pub/+ +mqttPublishTopic: mqttuser0005/pub/# +mqttSubscriptionTopic: mqttuser0005/sub/1 +mqttSubscriptionTopic: mqttuser0005/sub/+ +mqttSubscriptionTopic: mqttuser0005/sub/# +mqttPubSubTopic: mqttuser0005/pubsub/1 +mqttPubSubTopic: mqttuser0005/pubsub/+ +mqttPubSubTopic: mqttuser0005/pubsub/# +userPassword: {SHA}jKnxeEDGR14kE8AR7yuVFOelhz4= + diff --git a/apps/emqx_auth_ldap/emqx.schema b/apps/emqx_auth_ldap/emqx.schema new file mode 100644 index 000000000..55f92269b --- /dev/null +++ b/apps/emqx_auth_ldap/emqx.schema @@ -0,0 +1,46 @@ +# +# Preliminary Apple OS X Native LDAP Schema +# This file is subject to change. +# +attributetype ( 1.3.6.1.4.1.11.2.53.2.2.3.1.2.3.1.3 NAME 'isEnabled' + EQUALITY booleanMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 + SINGLE-VALUE + USAGE userApplications ) + +attributetype ( 1.3.6.1.4.1.11.2.53.2.2.3.1.2.3.4.1 NAME ( 'mqttPublishTopic' 'mpt' ) + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + USAGE userApplications ) +attributetype ( 1.3.6.1.4.1.11.2.53.2.2.3.1.2.3.4.2 NAME ( 'mqttSubscriptionTopic' 'mst' ) + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + USAGE userApplications ) +attributetype ( 1.3.6.1.4.1.11.2.53.2.2.3.1.2.3.4.3 NAME ( 'mqttPubSubTopic' 'mpst' ) + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + USAGE userApplications ) +attributetype ( 1.3.6.1.4.1.11.2.53.2.2.3.1.2.3.4.4 NAME ( 'mqttAccountName' 'man' ) + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + USAGE userApplications ) + + +objectclass ( 1.3.6.1.4.1.11.2.53.2.2.3.1.2.3.4 NAME 'mqttUser' + AUXILIARY + MAY ( mqttPublishTopic $ mqttSubscriptionTopic $ mqttPubSubTopic $ mqttAccountName) ) + +objectclass ( 1.3.6.1.4.1.11.2.53.2.2.3.1.2.3.2 NAME 'mqttDevice' + SUP top + STRUCTURAL + MUST ( uid ) + MAY ( isEnabled ) ) + +objectclass ( 1.3.6.1.4.1.11.2.53.2.2.3.1.2.3.3 NAME 'mqttSecurity' + SUP top + AUXILIARY + MAY ( userPassword $ userPKCS12 $ pwdAttribute $ pwdLockout ) ) diff --git a/apps/emqx_auth_ldap/include/emqx_auth_ldap.hrl b/apps/emqx_auth_ldap/include/emqx_auth_ldap.hrl new file mode 100644 index 000000000..8950c0ec8 --- /dev/null +++ b/apps/emqx_auth_ldap/include/emqx_auth_ldap.hrl @@ -0,0 +1,23 @@ + +-define(APP, emqx_auth_ldap). + +-record(auth_metrics, { + success = 'client.auth.success', + failure = 'client.auth.failure', + ignore = 'client.auth.ignore' + }). + +-record(acl_metrics, { + allow = 'client.acl.allow', + deny = 'client.acl.deny', + ignore = 'client.acl.ignore' + }). + +-define(METRICS(Type), tl(tuple_to_list(#Type{}))). +-define(METRICS(Type, K), #Type{}#Type.K). + +-define(AUTH_METRICS, ?METRICS(auth_metrics)). +-define(AUTH_METRICS(K), ?METRICS(auth_metrics, K)). + +-define(ACL_METRICS, ?METRICS(acl_metrics)). +-define(ACL_METRICS(K), ?METRICS(acl_metrics, K)). diff --git a/apps/emqx_auth_ldap/priv/emqx_auth_ldap.schema b/apps/emqx_auth_ldap/priv/emqx_auth_ldap.schema new file mode 100644 index 000000000..554752a0b --- /dev/null +++ b/apps/emqx_auth_ldap/priv/emqx_auth_ldap.schema @@ -0,0 +1,176 @@ +%%-*- mode: erlang -*- +%% emqx_auth_ldap config mapping + +{mapping, "auth.ldap.servers", "emqx_auth_ldap.ldap", [ + {default, "127.0.0.1"}, + {datatype, string} +]}. + +{mapping, "auth.ldap.port", "emqx_auth_ldap.ldap", [ + {default, 389}, + {datatype, integer} +]}. + +{mapping, "auth.ldap.pool", "emqx_auth_ldap.ldap", [ + {default, 8}, + {datatype, integer} +]}. + +{mapping, "auth.ldap.bind_dn", "emqx_auth_ldap.ldap", [ + {datatype, string}, + {default, "cn=root,dc=emqx,dc=io"} +]}. + +{mapping, "auth.ldap.bind_password", "emqx_auth_ldap.ldap", [ + {datatype, string}, + {default, "public"} +]}. + +{mapping, "auth.ldap.timeout", "emqx_auth_ldap.ldap", [ + {default, "30s"}, + {datatype, {duration, ms}} +]}. + +{mapping, "auth.ldap.ssl", "emqx_auth_ldap.ldap", [ + {default, false}, + {datatype, {enum, [true, false]}} +]}. + +{mapping, "auth.ldap.ssl.certfile", "emqx_auth_ldap.ldap", [ + {datatype, string} +]}. + +{mapping, "auth.ldap.ssl.keyfile", "emqx_auth_ldap.ldap", [ + {datatype, string} +]}. + +{mapping, "auth.ldap.ssl.cacertfile", "emqx_auth_ldap.ldap", [ + {datatype, string} +]}. + +{mapping, "auth.ldap.ssl.verify", "emqx_auth_ldap.ldap", [ + {default, verify_none}, + {datatype, {enum, [verify_none, verify_peer]}} +]}. + +{mapping, "auth.ldap.ssl.fail_if_no_peer_cert", "emqx_auth_ldap.ldap", [ + {datatype, {enum, [true, false]}} +]}. + +{mapping, "auth.ldap.ssl.server_name_indication", "emqx_auth_ldap.ldap", [ + {datatype, string} +]}. + +{translation, "emqx_auth_ldap.ldap", fun(Conf) -> + A2N = fun(A) -> case inet:parse_address(A) of {ok, N} -> N; _ -> A end end, + Servers = [A2N(A) || A <- string:tokens(cuttlefish:conf_get("auth.ldap.servers", Conf), ",")], + Port = cuttlefish:conf_get("auth.ldap.port", Conf), + Pool = cuttlefish:conf_get("auth.ldap.pool", Conf), + BindDN = cuttlefish:conf_get("auth.ldap.bind_dn", Conf), + BindPassword = cuttlefish:conf_get("auth.ldap.bind_password", Conf), + Timeout = cuttlefish:conf_get("auth.ldap.timeout", Conf), + Filter = fun(Ls) -> [E || E = {_, V} <- Ls, V /= undefined]end, + SslOpts = fun() -> + [{certfile, cuttlefish:conf_get("auth.ldap.ssl.certfile", Conf)}, + {keyfile, cuttlefish:conf_get("auth.ldap.ssl.keyfile", Conf)}, + {cacertfile, cuttlefish:conf_get("auth.ldap.ssl.cacertfile", Conf, undefined)}, + {verify, cuttlefish:conf_get("auth.ldap.ssl.verify", Conf, undefined)}, + {server_name_indication, cuttlefish:conf_get("auth.ldap.ssl.server_name_indication", Conf, disable)}, + {fail_if_no_peer_cert, cuttlefish:conf_get("auth.ldap.ssl.fail_if_no_peer_cert", Conf, undefined)}] + end, + Opts = [{servers, Servers}, + {port, Port}, + {timeout, Timeout}, + {bind_dn, BindDN}, + {bind_password, BindPassword}, + {pool, Pool}, + {auto_reconnect, 2}], + case cuttlefish:conf_get("auth.ldap.ssl", Conf) of + true -> [{ssl, true}, {sslopts, Filter(SslOpts())}|Opts]; + false -> [{ssl, false}|Opts] + end +end}. + +{mapping, "auth.ldap.device_dn", "emqx_auth_ldap.device_dn", [ + {default, "ou=device,dc=emqx,dc=io"}, + {datatype, string} +]}. + +{mapping, "auth.ldap.match_objectclass", "emqx_auth_ldap.match_objectclass", [ + {default, "mqttUser"}, + {datatype, string} +]}. + +{mapping, "auth.ldap.custom_base_dn", "emqx_auth_ldap.custom_base_dn", [ + {default, "${username_attr}=${user},${device_dn}"}, + {datatype, string} +]}. + +%% auth.ldap.filters.1.key = "objectClass" +%% auth.ldap.filters.1.value = "mqttUser" +%% auth.ldap.filters.1.op = "and" +%% auth.ldap.filters.2.key = "uiAttr" +%% auth.ldap.filters.2.value "someAttr" +%% auth.ldap.filters.2.op = "or" +%% auth.ldap.filters.3.key = "someKey" +%% auth.ldap.filters.3.value = "someValue" +%% The configuratation structure sent to the application: +%% [{"objectClass","mqttUser"},"and",{"uiAttr","someAttr"},"or",{"someKey","someAttr"}] +%% The resulting LDAP filter would look like this: +%% ==> "|(&(objectClass=Class)(uiAttr=someAttr)(someKey=someValue))" +{translation, "emqx_auth_ldap.filters", +fun(Conf) -> + Settings = cuttlefish_variable:filter_by_prefix("auth.ldap.filters", Conf), + Keys = [{Num, {key, V}} || {["auth","ldap","filters", Num, "key"], V} <- Settings], + Values = [{Num, {value, V}} || {["auth","ldap","filters", Num, "value"], V} <- Settings], + Ops = [{Num, {op, V}} || {["auth","ldap","filters", Num, "op"], V} <- Settings], + RawFilters = Keys ++ Values ++ Ops, + Filters = + lists:foldl( + fun({Num,{T,V}}, Acc)-> + maps:update_with(Num, + fun(F)-> + maps:put(T,V,F) + end, + #{T=>V}, Acc) + end, #{}, RawFilters), + Order=lists:usort(maps:keys(Filters)), + lists:reverse( + lists:foldl( + fun(F,Acc)-> + case F of + #{key:=K, op:=Op, value:=V} -> [Op,{K,V}|Acc]; + #{key:=K, value:=V} -> [{K,V}|Acc] + end + end, + [], + lists:map(fun(K) -> maps:get(K, Filters) end, Order))) +end}. + +{mapping, "auth.ldap.filters.$num.key", "emqx_auth_ldap.filters", [ + {datatype, string} +]}. + +{mapping, "auth.ldap.filters.$num.value", "emqx_auth_ldap.filters", [ + {datatype, string} +]}. + +{mapping, "auth.ldap.filters.$num.op", "emqx_auth_ldap.filters", [ + {datatype, {enum, [ "or", "and" ] } } +]}. + + +{mapping, "auth.ldap.bind_as_user", "emqx_auth_ldap.bind_as_user", [ + {default, false}, + {datatype, {enum, [true, false]}} +]}. + +{mapping, "auth.ldap.username.attributetype", "emqx_auth_ldap.username_attr", [ + {default, "uid"}, + {datatype, string} +]}. + +{mapping, "auth.ldap.password.attributetype", "emqx_auth_ldap.password_attr", [ + {default, "userPassword"}, + {datatype, string} +]}. diff --git a/apps/emqx_auth_ldap/rebar.config b/apps/emqx_auth_ldap/rebar.config new file mode 100644 index 000000000..8fe128ac5 --- /dev/null +++ b/apps/emqx_auth_ldap/rebar.config @@ -0,0 +1,3 @@ +{deps, + [{eldap2, {git, "https://github.com/emqx/eldap2", {tag, "v0.2.2"}}} + ]}. diff --git a/apps/emqx_auth_ldap/src/emqx_acl_ldap.erl b/apps/emqx_auth_ldap/src/emqx_acl_ldap.erl new file mode 100644 index 000000000..e117940b1 --- /dev/null +++ b/apps/emqx_auth_ldap/src/emqx_acl_ldap.erl @@ -0,0 +1,98 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_acl_ldap). + +-include("emqx_auth_ldap.hrl"). + +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("eldap/include/eldap.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). + +-export([ register_metrics/0 + , check_acl/5 + , description/0 + ]). + +-import(proplists, [get_value/2]). + +-import(emqx_auth_ldap_cli, [search/4]). + +-spec(register_metrics() -> ok). +register_metrics() -> + lists:foreach(fun emqx_metrics:ensure/1, ?ACL_METRICS). + +check_acl(ClientInfo, PubSub, Topic, NoMatchAction, State) -> + case do_check_acl(ClientInfo, PubSub, Topic, NoMatchAction, State) of + ok -> emqx_metrics:inc(?ACL_METRICS(ignore)), ok; + {stop, allow} -> emqx_metrics:inc(?ACL_METRICS(allow)), {stop, allow}; + {stop, deny} -> emqx_metrics:inc(?ACL_METRICS(deny)), {stop, deny} + end. + +do_check_acl(#{username := <<$$, _/binary>>}, _PubSub, _Topic, _NoMatchAction, _State) -> + ok; + +do_check_acl(#{username := Username}, PubSub, Topic, _NoMatchAction, + #{device_dn := DeviceDn, + match_objectclass := ObjectClass, + username_attr := UidAttr, + custom_base_dn := CustomBaseDN, + pool := Pool} = Config) -> + + Filters = maps:get(filters, Config, []), + + ReplaceRules = [{"${username_attr}", UidAttr}, + {"${user}", binary_to_list(Username)}, + {"${device_dn}", DeviceDn}], + + Filter = emqx_auth_ldap:prepare_filter(Filters, UidAttr, ObjectClass, ReplaceRules), + + Attribute = case PubSub of + publish -> "mqttPublishTopic"; + subscribe -> "mqttSubscriptionTopic" + end, + Attribute1 = "mqttPubSubTopic", + ?LOG(debug, "[LDAP] search dn:~p filter:~p, attribute:~p", + [DeviceDn, Filter, Attribute]), + + BaseDN = emqx_auth_ldap:replace_vars(CustomBaseDN, ReplaceRules), + + case search(Pool, BaseDN, Filter, [Attribute, Attribute1]) of + {error, noSuchObject} -> + ok; + {ok, #eldap_search_result{entries = []}} -> + ok; + {ok, #eldap_search_result{entries = [Entry]}} -> + Topics = get_value(Attribute, Entry#eldap_entry.attributes) + ++ get_value(Attribute1, Entry#eldap_entry.attributes), + match(Topic, Topics); + Error -> + ?LOG(error, "[LDAP] search error:~p", [Error]), + {stop, deny} + end. + +match(_Topic, []) -> + ok; + +match(Topic, [Filter | Topics]) -> + case emqx_topic:match(Topic, list_to_binary(Filter)) of + true -> {stop, allow}; + false -> match(Topic, Topics) + end. + +description() -> + "ACL with LDAP". + diff --git a/apps/emqx_auth_ldap/src/emqx_auth_ldap.app.src b/apps/emqx_auth_ldap/src/emqx_auth_ldap.app.src new file mode 100644 index 000000000..802920c3e --- /dev/null +++ b/apps/emqx_auth_ldap/src/emqx_auth_ldap.app.src @@ -0,0 +1,14 @@ +{application, emqx_auth_ldap, + [{description, "EMQ X Authentication/ACL with LDAP"}, + {vsn, "5.0.0"}, % strict semver, bump manually! + {modules, []}, + {registered, [emqx_auth_ldap_sup,emqx_libs]}, + {applications, [kernel,stdlib,eldap2,ecpool,emqx_passwd,emqx_libs]}, + {mod, {emqx_auth_ldap_app,[]}}, + {env, []}, + {licenses, ["Apache-2.0"]}, + {maintainers, ["EMQ X Team "]}, + {links, [{"Homepage", "https://emqx.io/"}, + {"Github", "https://github.com/emqx/emqx-auth-ldap"} + ]} + ]}. diff --git a/apps/emqx_auth_ldap/src/emqx_auth_ldap.erl b/apps/emqx_auth_ldap/src/emqx_auth_ldap.erl new file mode 100644 index 000000000..b3d6251fb --- /dev/null +++ b/apps/emqx_auth_ldap/src/emqx_auth_ldap.erl @@ -0,0 +1,210 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_ldap). + +-include("emqx_auth_ldap.hrl"). + +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("eldap/include/eldap.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). + +-import(proplists, [get_value/2]). + +-import(emqx_auth_ldap_cli, [search/3]). + +-export([ register_metrics/0 + , check/3 + , description/0 + , prepare_filter/4 + , replace_vars/2 + ]). + +-spec(register_metrics() -> ok). +register_metrics() -> + lists:foreach(fun emqx_metrics:ensure/1, ?AUTH_METRICS). + +check(ClientInfo = #{username := Username, password := Password}, AuthResult, + State = #{password_attr := PasswdAttr, bind_as_user := BindAsUserRequired, pool := Pool}) -> + CheckResult = + case lookup_user(Username, State) of + undefined -> {error, not_found}; + {error, Error} -> {error, Error}; + Entry -> + PasswordString = binary_to_list(Password), + ObjectName = Entry#eldap_entry.object_name, + Attributes = Entry#eldap_entry.attributes, + case BindAsUserRequired of + true -> + emqx_auth_ldap_cli:post_bind(Pool, ObjectName, PasswordString); + false -> + case get_value(PasswdAttr, Attributes) of + undefined -> + logger:error("LDAP Search State: ~p, uid: ~p, result:~p", + [State, Username, Attributes]), + {error, not_found}; + [Passhash1] -> + format_password(Passhash1, Password, ClientInfo) + end + end + end, + case CheckResult of + ok -> + ok = emqx_metrics:inc(?AUTH_METRICS(success)), + {stop, AuthResult#{auth_result => success, anonymous => false}}; + {error, not_found} -> + emqx_metrics:inc(?AUTH_METRICS(ignore)); + {error, ResultCode} -> + ok = emqx_metrics:inc(?AUTH_METRICS(failure)), + ?LOG(error, "[LDAP] Auth from ldap failed: ~p", [ResultCode]), + {stop, AuthResult#{auth_result => ResultCode, anonymous => false}} + end. + +lookup_user(Username, #{username_attr := UidAttr, + match_objectclass := ObjectClass, + device_dn := DeviceDn, + custom_base_dn := CustomBaseDN, pool := Pool} = Config) -> + + Filters = maps:get(filters, Config, []), + + ReplaceRules = [{"${username_attr}", UidAttr}, + {"${user}", binary_to_list(Username)}, + {"${device_dn}", DeviceDn}], + + Filter = prepare_filter(Filters, UidAttr, ObjectClass, ReplaceRules), + + %% auth.ldap.custom_base_dn = "${username_attr}=${user},${device_dn}" + BaseDN = replace_vars(CustomBaseDN, ReplaceRules), + + case search(Pool, BaseDN, Filter) of + %% This clause seems to be impossible to match. `eldap2:search/2` does + %% not validates the result, so if it returns "successfully" from the + %% LDAP server, it always returns `{ok, #eldap_search_result{}}`. + {error, noSuchObject} -> + undefined; + %% In case no user was found by the search, but the search was completed + %% without error we get an empty `entries` list. + {ok, #eldap_search_result{entries = []}} -> + undefined; + {ok, #eldap_search_result{entries = [Entry]}} -> + Attributes = Entry#eldap_entry.attributes, + case get_value("isEnabled", Attributes) of + undefined -> + Entry; + [Val] -> + case list_to_atom(string:to_lower(Val)) of + true -> Entry; + false -> {error, username_disabled} + end + end; + {error, Error} -> + ?LOG(error, "[LDAP] Search dn: ~p, filter: ~p, fail:~p", [DeviceDn, Filter, Error]), + {error, username_or_password_error} + end. + +check_pass(Password, Password, _ClientInfo) -> ok; +check_pass(_, _, _) -> {error, bad_username_or_password}. + +format_password(Passhash, Password, ClientInfo) -> + case do_format_password(Passhash, Password) of + {error, Error2} -> + {error, Error2}; + {Passhash1, Password1} -> + check_pass(Passhash1, Password1, ClientInfo) + end. + +do_format_password(Passhash, Password) -> + Base64PasshashHandler = + handle_passhash(fun(HashType, Passhash1, Password1) -> + Passhash2 = binary_to_list(base64:decode(Passhash1)), + resolve_passhash(HashType, Passhash2, Password1) + end, + fun(_Passhash, _Password) -> + {error, password_error} + end), + PasshashHandler = handle_passhash(fun resolve_passhash/3, Base64PasshashHandler), + PasshashHandler(Passhash, Password). + +resolve_passhash(HashType, Passhash, Password) -> + [_, Passhash1] = string:tokens(Passhash, "}"), + do_resolve(HashType, Passhash1, Password). + +handle_passhash(HandleMatch, HandleNoMatch) -> + fun(Passhash, Password) -> + case re:run(Passhash, "(?<={)[^{}]+(?=})", [{capture, all, list}, global]) of + {match, [[HashType]]} -> + HandleMatch(list_to_atom(string:to_lower(HashType)), Passhash, Password); + _ -> + HandleNoMatch(Passhash, Password) + end + end. + +do_resolve(ssha, Passhash, Password) -> + D64 = base64:decode(Passhash), + {HashedData, Salt} = lists:split(20, binary_to_list(D64)), + NewHash = crypto:hash(sha, <>), + {list_to_binary(HashedData), NewHash}; +do_resolve(HashType, Passhash, Password) -> + Password1 = base64:encode(crypto:hash(HashType, Password)), + {list_to_binary(Passhash), Password1}. + +description() -> "LDAP Authentication Plugin". + +prepare_filter(Filters, _UidAttr, ObjectClass, ReplaceRules) -> + SubFilters = + lists:map(fun({K, V}) -> + {replace_vars(K, ReplaceRules), replace_vars(V, ReplaceRules)}; + (Op) -> + Op + end, Filters), + case SubFilters of + [] -> eldap2:equalityMatch("objectClass", ObjectClass); + _List -> compile_filters(SubFilters, []) + end. + + +compile_filters([{Key, Value}], []) -> + compile_equal(Key, Value); +compile_filters([{K1, V1}, "and", {K2, V2} | Rest], []) -> + compile_filters( + Rest, + eldap2:'and'([compile_equal(K1, V1), + compile_equal(K2, V2)])); +compile_filters([{K1, V1}, "or", {K2, V2} | Rest], []) -> + compile_filters( + Rest, + eldap2:'or'([compile_equal(K1, V1), + compile_equal(K2, V2)])); +compile_filters(["and", {K, V} | Rest], PartialFilter) -> + compile_filters( + Rest, + eldap2:'and'([PartialFilter, + compile_equal(K, V)])); +compile_filters(["or", {K, V} | Rest], PartialFilter) -> + compile_filters( + Rest, + eldap2:'or'([PartialFilter, + compile_equal(K, V)])); +compile_filters([], Filter) -> + Filter. + +compile_equal(Key, Value) -> + eldap2:equalityMatch(Key, Value). + +replace_vars(CustomBaseDN, ReplaceRules) -> + lists:foldl(fun({Pattern, Substitute}, DN) -> + lists:flatten(string:replace(DN, Pattern, Substitute)) + end, CustomBaseDN, ReplaceRules). diff --git a/apps/emqx_auth_ldap/src/emqx_auth_ldap_app.erl b/apps/emqx_auth_ldap/src/emqx_auth_ldap_app.erl new file mode 100644 index 000000000..5922950f0 --- /dev/null +++ b/apps/emqx_auth_ldap/src/emqx_auth_ldap_app.erl @@ -0,0 +1,78 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_ldap_app). + +-behaviour(application). + +-emqx_plugin(auth). + +-include("emqx_auth_ldap.hrl"). + +%% Application callbacks +-export([ start/2 + , prep_stop/1 + , stop/1 + ]). + +start(_StartType, _StartArgs) -> + {ok, Sup} = emqx_auth_ldap_sup:start_link(), + if_enabled([device_dn, match_objectclass, + username_attr, password_attr, + filters, custom_base_dn, bind_as_user], + fun load_auth_hook/1), + if_enabled([device_dn, match_objectclass, + username_attr, password_attr, + filters, custom_base_dn, bind_as_user], + fun load_acl_hook/1), + {ok, Sup}. + +prep_stop(State) -> + emqx:unhook('client.authenticate', fun emqx_auth_ldap:check/3), + emqx:unhook('client.check_acl', fun emqx_acl_ldap:check_acl/5), + State. + +stop(_State) -> + ok. + +load_auth_hook(DeviceDn) -> + ok = emqx_auth_ldap:register_metrics(), + Params = maps:from_list(DeviceDn), + emqx:hook('client.authenticate', fun emqx_auth_ldap:check/3, [Params#{pool => ?APP}]). + +load_acl_hook(DeviceDn) -> + ok = emqx_acl_ldap:register_metrics(), + Params = maps:from_list(DeviceDn), + emqx:hook('client.check_acl', fun emqx_acl_ldap:check_acl/5 , [Params#{pool => ?APP}]). + +if_enabled(Cfgs, Fun) -> + case get_env(Cfgs) of + {ok, InitArgs} -> Fun(InitArgs); + [] -> ok + end. + +get_env(Cfgs) -> + get_env(Cfgs, []). + +get_env([Cfg | LeftCfgs], ENVS) -> + case application:get_env(?APP, Cfg) of + {ok, ENV} -> + get_env(LeftCfgs, [{Cfg, ENV} | ENVS]); + undefined -> + get_env(LeftCfgs, ENVS) + end; +get_env([], ENVS) -> + {ok, ENVS}. diff --git a/apps/emqx_auth_ldap/src/emqx_auth_ldap_cli.erl b/apps/emqx_auth_ldap/src/emqx_auth_ldap_cli.erl new file mode 100644 index 000000000..8ec22848e --- /dev/null +++ b/apps/emqx_auth_ldap/src/emqx_auth_ldap_cli.erl @@ -0,0 +1,150 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_ldap_cli). + +-behaviour(ecpool_worker). + +-include("emqx_auth_ldap.hrl"). + +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). + +%% ecpool callback +-export([connect/1]). + +-export([ search/3 + , search/4 + , post_bind/3 + , init_args/1 + ]). + +-import(proplists, + [ get_value/2 + , get_value/3 + ]). + +%%-------------------------------------------------------------------- +%% LDAP Connect/Search +%%-------------------------------------------------------------------- + +connect(Opts) -> + Servers = get_value(servers, Opts, ["localhost"]), + Port = get_value(port, Opts, 389), + Timeout = get_value(timeout, Opts, 30), + BindDn = get_value(bind_dn, Opts), + BindPassword = get_value(bind_password, Opts), + LdapOpts = case get_value(ssl, Opts, false)of + true -> + SslOpts = get_value(sslopts, Opts), + [{port, Port}, {timeout, Timeout}, {sslopts, SslOpts}]; + false -> + [{port, Port}, {timeout, Timeout}] + end, + ?LOG(debug, "[LDAP] Connecting to OpenLDAP server: ~p, Opts:~p ...", [Servers, LdapOpts]), + + case eldap2:open(Servers, LdapOpts) of + {ok, LDAP} -> + try eldap2:simple_bind(LDAP, BindDn, BindPassword) of + ok -> {ok, LDAP}; + {error, Error} -> + ?LOG(error, "[LDAP] Can't authenticated to OpenLDAP server: ~p", [Error]), + {error, Error} + catch + error:Reason -> + ?LOG(error, "[LDAP] Can't authenticated to OpenLDAP server: ~p", [Reason]), + {error, Reason} + end; + {error, Reason} -> + ?LOG(error, "[LDAP] Can't connect to OpenLDAP server: ~p", [Reason]), + {error, Reason} + end. + +search(Pool, Base, Filter) -> + ecpool:with_client(Pool, + fun(C) -> + case application:get_env(?APP, bind_as_user) of + {ok, true} -> + {ok, Opts} = application:get_env(?APP, ldap), + BindDn = get_value(bind_dn, Opts), + BindPassword = get_value(bind_password, Opts), + try eldap2:simple_bind(C, BindDn, BindPassword) of + ok -> + eldap2:search(C, [{base, Base}, + {filter, Filter}, + {deref, eldap2:derefFindingBaseObj()}]); + {error, Error} -> + {error, Error} + catch + error:Reason -> {error, Reason} + end; + {ok, false} -> + eldap2:search(C, [{base, Base}, + {filter, Filter}, + {deref, eldap2:derefFindingBaseObj()}]) + end + end). + +search(Pool, Base, Filter, Attributes) -> + ecpool:with_client(Pool, + fun(C) -> + case application:get_env(?APP, bind_as_user) of + {ok, true} -> + {ok, Opts} = application:get_env(?APP, ldap), + BindDn = get_value(bind_dn, Opts), + BindPassword = get_value(bind_password, Opts), + try eldap2:simple_bind(C, BindDn, BindPassword) of + ok -> + eldap2:search(C, [{base, Base}, + {filter, Filter}, + {attributes, Attributes}, + {deref, eldap2:derefFindingBaseObj()}]); + {error, Error} -> + {error, Error} + catch + error:Reason -> {error, Reason} + end; + {ok, false} -> + eldap2:search(C, [{base, Base}, + {filter, Filter}, + {attributes, Attributes}, + {deref, eldap2:derefFindingBaseObj()}]) + end + end). + +post_bind(Pool, BindDn, BindPassword) -> + ecpool:with_client(Pool, + fun(C) -> + try eldap2:simple_bind(C, BindDn, BindPassword) of + ok -> ok; + {error, Error} -> + {error, Error} + catch + error:Reason -> {error, Reason} + end + end). + + +init_args(ENVS) -> + DeviceDn = get_value(device_dn, ENVS), + ObjectClass = get_value(match_objectclass, ENVS), + UidAttr = get_value(username_attr, ENVS), + PasswdAttr = get_value(password_attr, ENVS), + {ok, #{device_dn => DeviceDn, + match_objectclass => ObjectClass, + username_attr => UidAttr, + password_attr => PasswdAttr}}. + diff --git a/apps/emqx_auth_ldap/src/emqx_auth_ldap_sup.erl b/apps/emqx_auth_ldap/src/emqx_auth_ldap_sup.erl new file mode 100644 index 000000000..ca4440f1a --- /dev/null +++ b/apps/emqx_auth_ldap/src/emqx_auth_ldap_sup.erl @@ -0,0 +1,35 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_ldap_sup). + +-behaviour(supervisor). + +-include("emqx_auth_ldap.hrl"). + +-export([start_link/0]). + +-export([init/1]). + +start_link() -> + supervisor:start_link({local, ?MODULE}, ?MODULE, []). + +init([]) -> + %% LDAP Connection Pool. + {ok, Server} = application:get_env(?APP, ldap), + PoolSpec = ecpool:pool_spec(?APP, ?APP, emqx_auth_ldap_cli, Server), + {ok, {{one_for_one, 10, 100}, [PoolSpec]}}. + diff --git a/apps/emqx_auth_ldap/test/certs/cacert.pem b/apps/emqx_auth_ldap/test/certs/cacert.pem new file mode 100644 index 000000000..604fd2362 --- /dev/null +++ b/apps/emqx_auth_ldap/test/certs/cacert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDUTCCAjmgAwIBAgIJAPPYCjTmxdt/MA0GCSqGSIb3DQEBCwUAMD8xCzAJBgNV +BAYTAkNOMREwDwYDVQQIDAhoYW5nemhvdTEMMAoGA1UECgwDRU1RMQ8wDQYDVQQD +DAZSb290Q0EwHhcNMjAwNTA4MDgwNjUyWhcNMzAwNTA2MDgwNjUyWjA/MQswCQYD +VQQGEwJDTjERMA8GA1UECAwIaGFuZ3pob3UxDDAKBgNVBAoMA0VNUTEPMA0GA1UE +AwwGUm9vdENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzcgVLex1 +EZ9ON64EX8v+wcSjzOZpiEOsAOuSXOEN3wb8FKUxCdsGrsJYB7a5VM/Jot25Mod2 +juS3OBMg6r85k2TWjdxUoUs+HiUB/pP/ARaaW6VntpAEokpij/przWMPgJnBF3Ur +MjtbLayH9hGmpQrI5c2vmHQ2reRZnSFbY+2b8SXZ+3lZZgz9+BaQYWdQWfaUWEHZ +uDaNiViVO0OT8DRjCuiDp3yYDj3iLWbTA/gDL6Tf5XuHuEwcOQUrd+h0hyIphO8D +tsrsHZ14j4AWYLk1CPA6pq1HIUvEl2rANx2lVUNv+nt64K/Mr3RnVQd9s8bK+TXQ +KGHd2Lv/PALYuwIDAQABo1AwTjAdBgNVHQ4EFgQUGBmW+iDzxctWAWxmhgdlE8Pj +EbQwHwYDVR0jBBgwFoAUGBmW+iDzxctWAWxmhgdlE8PjEbQwDAYDVR0TBAUwAwEB +/zANBgkqhkiG9w0BAQsFAAOCAQEAGbhRUjpIred4cFAFJ7bbYD9hKu/yzWPWkMRa +ErlCKHmuYsYk+5d16JQhJaFy6MGXfLgo3KV2itl0d+OWNH0U9ULXcglTxy6+njo5 +CFqdUBPwN1jxhzo9yteDMKF4+AHIxbvCAJa17qcwUKR5MKNvv09C6pvQDJLzid7y +E2dkgSuggik3oa0427KvctFf8uhOV94RvEDyqvT5+pgNYZ2Yfga9pD/jjpoHEUlo +88IGU8/wJCx3Ds2yc8+oBg/ynxG8f/HmCC1ET6EHHoe2jlo8FpU/SgGtghS1YL30 +IWxNsPrUP+XsZpBJy/mvOhE5QXo6Y35zDqqj8tI7AGmAWu22jg== +-----END CERTIFICATE----- diff --git a/apps/emqx_auth_ldap/test/certs/cert.pem b/apps/emqx_auth_ldap/test/certs/cert.pem new file mode 100644 index 000000000..092390b1d --- /dev/null +++ b/apps/emqx_auth_ldap/test/certs/cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDEzCCAfugAwIBAgIBAjANBgkqhkiG9w0BAQsFADA/MQswCQYDVQQGEwJDTjER +MA8GA1UECAwIaGFuZ3pob3UxDDAKBgNVBAoMA0VNUTEPMA0GA1UEAwwGUm9vdENB +MB4XDTIwMDUwODA4MDcwNVoXDTMwMDUwNjA4MDcwNVowPzELMAkGA1UEBhMCQ04x +ETAPBgNVBAgMCGhhbmd6aG91MQwwCgYDVQQKDANFTVExDzANBgNVBAMMBlNlcnZl +cjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALNeWT3pE+QFfiRJzKmn +AMUrWo3K2j/Tm3+Xnl6WLz67/0rcYrJbbKvS3uyRP/stXyXEKw9CepyQ1ViBVFkW +Aoy8qQEOWFDsZc/5UzhXUnb6LXr3qTkFEjNmhj+7uzv/lbBxlUG1NlYzSeOB6/RT +8zH/lhOeKhLnWYPXdXKsa1FL6ij4X8DeDO1kY7fvAGmBn/THh1uTpDizM4YmeI+7 +4dmayA5xXvARte5h4Vu5SIze7iC057N+vymToMk2Jgk+ZZFpyXrnq+yo6RaD3ANc +lrc4FbeUQZ5a5s5Sxgs9a0Y3WMG+7c5VnVXcbjBRz/aq2NtOnQQjikKKQA8GF080 +BQkCAwEAAaMaMBgwCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwDQYJKoZIhvcNAQEL +BQADggEBAJefnMZpaRDHQSNUIEL3iwGXE9c6PmIsQVE2ustr+CakBp3TZ4l0enLt +iGMfEVFju69cO4oyokWv+hl5eCMkHBf14Kv51vj448jowYnF1zmzn7SEzm5Uzlsa +sqjtAprnLyof69WtLU1j5rYWBuFX86yOTwRAFNjm9fvhAcrEONBsQtqipBWkMROp +iUYMkRqbKcQMdwxov+lHBYKq9zbWRoqLROAn54SRqgQk6c15JdEfgOOjShbsOkIH +UhqcwRkQic7n1zwHVGVDgNIZVgmJ2IdIWBlPEC7oLrRrBD/X1iEEXtKab6p5o22n +KB5mN+iQaE+Oe2cpGKZJiJRdM+IqDDQ= +-----END CERTIFICATE----- diff --git a/apps/emqx_auth_ldap/test/certs/client-cert.pem b/apps/emqx_auth_ldap/test/certs/client-cert.pem new file mode 100644 index 000000000..09d855221 --- /dev/null +++ b/apps/emqx_auth_ldap/test/certs/client-cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDEzCCAfugAwIBAgIBATANBgkqhkiG9w0BAQsFADA/MQswCQYDVQQGEwJDTjER +MA8GA1UECAwIaGFuZ3pob3UxDDAKBgNVBAoMA0VNUTEPMA0GA1UEAwwGUm9vdENB +MB4XDTIwMDUwODA4MDY1N1oXDTMwMDUwNjA4MDY1N1owPzELMAkGA1UEBhMCQ04x +ETAPBgNVBAgMCGhhbmd6aG91MQwwCgYDVQQKDANFTVExDzANBgNVBAMMBkNsaWVu +dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMy4hoksKcZBDbY680u6 +TS25U51nuB1FBcGMlF9B/t057wPOlxF/OcmbxY5MwepS41JDGPgulE1V7fpsXkiW +1LUimYV/tsqBfymIe0mlY7oORahKji7zKQ2UBIVFhdlvQxunlIDnw6F9popUgyHt +dMhtlgZK8oqRwHxO5dbfoukYd6J/r+etS5q26sgVkf3C6dt0Td7B25H9qW+f7oLV +PbcHYCa+i73u9670nrpXsC+Qc7Mygwa2Kq/jwU+ftyLQnOeW07DuzOwsziC/fQZa +nbxR+8U9FNftgRcC3uP/JMKYUqsiRAuaDokARZxVTV5hUElfpO6z6/NItSDvvh3i +eikCAwEAAaMaMBgwCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwDQYJKoZIhvcNAQEL +BQADggEBABchYxKo0YMma7g1qDswJXsR5s56Czx/I+B41YcpMBMTrRqpUC0nHtLk +M7/tZp592u/tT8gzEnQjZLKBAhFeZaR3aaKyknLqwiPqJIgg0pgsBGITrAK3Pv4z +5/YvAJJKgTe5UdeTz6U4lvNEux/4juZ4pmqH4qSFJTOzQS7LmgSmNIdd072rwXBd +UzcSHzsJgEMb88u/LDLjj1pQ7AtZ4Tta8JZTvcgBFmjB0QUi6fgkHY6oGat/W4kR +jSRUBlMUbM/drr2PVzRc2dwbFIl3X+ZE6n5Sl3ZwRAC/s92JU6CPMRW02muVu6xl +goraNgPISnrbpR6KjxLZkVembXzjNNc= +-----END CERTIFICATE----- diff --git a/apps/emqx_auth_ldap/test/certs/client-key.pem b/apps/emqx_auth_ldap/test/certs/client-key.pem new file mode 100644 index 000000000..2b3f30cf6 --- /dev/null +++ b/apps/emqx_auth_ldap/test/certs/client-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAzLiGiSwpxkENtjrzS7pNLblTnWe4HUUFwYyUX0H+3TnvA86X +EX85yZvFjkzB6lLjUkMY+C6UTVXt+mxeSJbUtSKZhX+2yoF/KYh7SaVjug5FqEqO +LvMpDZQEhUWF2W9DG6eUgOfDoX2milSDIe10yG2WBkryipHAfE7l1t+i6Rh3on+v +561LmrbqyBWR/cLp23RN3sHbkf2pb5/ugtU9twdgJr6Lve73rvSeulewL5BzszKD +BrYqr+PBT5+3ItCc55bTsO7M7CzOIL99BlqdvFH7xT0U1+2BFwLe4/8kwphSqyJE +C5oOiQBFnFVNXmFQSV+k7rPr80i1IO++HeJ6KQIDAQABAoIBAGWgvPjfuaU3qizq +uti/FY07USz0zkuJdkANH6LiSjlchzDmn8wJ0pApCjuIE0PV/g9aS8z4opp5q/gD +UBLM/a8mC/xf2EhTXOMrY7i9p/I3H5FZ4ZehEqIw9sWKK9YzC6dw26HabB2BGOnW +5nozPSQ6cp2RGzJ7BIkxSZwPzPnVTgy3OAuPOiJytvK+hGLhsNaT+Y9bNDvplVT2 +ZwYTV8GlHZC+4b2wNROILm0O86v96O+Qd8nn3fXjGHbMsAnONBq10bZS16L4fvkH +5G+W/1PeSXmtZFppdRRDxIW+DWcXK0D48WRliuxcV4eOOxI+a9N2ZJZZiNLQZGwg +w3A8+mECgYEA8HuJFrlRvdoBe2U/EwUtG74dcyy30L4yEBnN5QscXmEEikhaQCfX +Wm6EieMcIB/5I5TQmSw0cmBMeZjSXYoFdoI16/X6yMMuATdxpvhOZGdUGXxhAH+x +xoTUavWZnEqW3fkUU71kT5E2f2i+0zoatFESXHeslJyz85aAYpP92H0CgYEA2e5A +Yozt5eaA1Gyhd8SeptkEU4xPirNUnVQHStpMWUb1kzTNXrPmNWccQ7JpfpG6DcYl +zUF6p6mlzY+zkMiyPQjwEJlhiHM2NlL1QS7td0R8ewgsFoyn8WsBI4RejWrEG9td +EDniuIw+pBFkcWthnTLHwECHdzgquToyTMjrBB0CgYEA28tdGbrZXhcyAZEhHAZA +Gzog+pKlkpEzeonLKIuGKzCrEKRecIK5jrqyQsCjhS0T7ZRnL4g6i0s+umiV5M5w +fcc292pEA1h45L3DD6OlKplSQVTv55/OYS4oY3YEJtf5mfm8vWi9lQeY8sxOlQpn +O+VZTdBHmTC8PGeTAgZXHZUCgYA6Tyv88lYowB7SN2qQgBQu8jvdGtqhcs/99GCr +H3N0I69LPsKAR0QeH8OJPXBKhDUywESXAaEOwS5yrLNP1tMRz5Vj65YUCzeDG3kx +gpvY4IMp7ArX0bSRvJ6mYSFnVxy3k174G3TVCfksrtagHioVBGQ7xUg5ltafjrms +n8l55QKBgQDVzU8tQvBVqY8/1lnw11Vj4fkE/drZHJ5UkdC1eenOfSWhlSLfUJ8j +ds7vEWpRPPoVuPZYeR1y78cyxKe1GBx6Wa2lF5c7xjmiu0xbRnrxYeLolce9/ntp +asClqpnHT8/VJYTD7Kqj0fouTTZf0zkig/y+2XERppd8k+pSKjUCPQ== +-----END RSA PRIVATE KEY----- diff --git a/apps/emqx_auth_ldap/test/certs/key.pem b/apps/emqx_auth_ldap/test/certs/key.pem new file mode 100644 index 000000000..6c338216e --- /dev/null +++ b/apps/emqx_auth_ldap/test/certs/key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAs15ZPekT5AV+JEnMqacAxStajcraP9Obf5eeXpYvPrv/Stxi +sltsq9Le7JE/+y1fJcQrD0J6nJDVWIFUWRYCjLypAQ5YUOxlz/lTOFdSdvotevep +OQUSM2aGP7u7O/+VsHGVQbU2VjNJ44Hr9FPzMf+WE54qEudZg9d1cqxrUUvqKPhf +wN4M7WRjt+8AaYGf9MeHW5OkOLMzhiZ4j7vh2ZrIDnFe8BG17mHhW7lIjN7uILTn +s36/KZOgyTYmCT5lkWnJeuer7KjpFoPcA1yWtzgVt5RBnlrmzlLGCz1rRjdYwb7t +zlWdVdxuMFHP9qrY206dBCOKQopADwYXTzQFCQIDAQABAoIBAQCuvCbr7Pd3lvI/ +n7VFQG+7pHRe1VKwAxDkx2t8cYos7y/QWcm8Ptwqtw58HzPZGWYrgGMCRpzzkRSF +V9g3wP1S5Scu5C6dBu5YIGc157tqNGXB+SpdZddJQ4Nc6yGHXYERllT04ffBGc3N +WG/oYS/1cSteiSIrsDy/91FvGRCi7FPxH3wIgHssY/tw69s1Cfvaq5lr2NTFzxIG +xCvpJKEdSfVfS9I7LYiymVjst3IOR/w76/ZFY9cRa8ZtmQSWWsm0TUpRC1jdcbkm +ZoJptYWlP+gSwx/fpMYftrkJFGOJhHJHQhwxT5X/ajAISeqjjwkWSEJLwnHQd11C +Zy2+29lBAoGBANlEAIK4VxCqyPXNKfoOOi5dS64NfvyH4A1v2+KaHWc7lqaqPN49 +ezfN2n3X+KWx4cviDD914Yc2JQ1vVJjSaHci7yivocDo2OfZDmjBqzaMp/y+rX1R +/f3MmiTqMa468rjaxI9RRZu7vDgpTR+za1+OBCgMzjvAng8dJuN/5gjlAoGBANNY +uYPKtearBmkqdrSV7eTUe49Nhr0XotLaVBH37TCW0Xv9wjO2xmbm5Ga/DCtPIsBb +yPeYwX9FjoasuadUD7hRvbFu6dBa0HGLmkXRJZTcD7MEX2Lhu4BuC72yDLLFd0r+ +Ep9WP7F5iJyagYqIZtz+4uf7gBvUDdmvXz3sGr1VAoGAdXTD6eeKeiI6PlhKBztF +zOb3EQOO0SsLv3fnodu7ZaHbUgLaoTMPuB17r2jgrYM7FKQCBxTNdfGZmmfDjlLB +0xZ5wL8ibU30ZXL8zTlWPElST9sto4B+FYVVF/vcG9sWeUUb2ncPcJ/Po3UAktDG +jYQTTyuNGtSJHpad/YOZctkCgYBtWRaC7bq3of0rJGFOhdQT9SwItN/lrfj8hyHA +OjpqTV4NfPmhsAtu6j96OZaeQc+FHvgXwt06cE6Rt4RG4uNPRluTFgO7XYFDfitP +vCppnoIw6S5BBvHwPP+uIhUX2bsi/dm8vu8tb+gSvo4PkwtFhEr6I9HglBKmcmog +q6waEQKBgHyecFBeM6Ls11Cd64vborwJPAuxIW7HBAFj/BS99oeG4TjBx4Sz2dFd +rzUibJt4ndnHIvCN8JQkjNG14i9hJln+H3mRss8fbZ9vQdqG+2vOWADYSzzsNI55 +RFY7JjluKcVkp/zCDeUxTU3O6sS+v6/3VE11Cob6OYQx3lN5wrZ3 +-----END RSA PRIVATE KEY----- diff --git a/apps/emqx_auth_ldap/test/emqx_auth_ldap_SUITE.erl b/apps/emqx_auth_ldap/test/emqx_auth_ldap_SUITE.erl new file mode 100644 index 000000000..4d92b9b80 --- /dev/null +++ b/apps/emqx_auth_ldap/test/emqx_auth_ldap_SUITE.erl @@ -0,0 +1,153 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_ldap_SUITE). + +-compile(export_all). +-compile(nowarn_export_all). + +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("eunit/include/eunit.hrl"). +-include_lib("common_test/include/ct.hrl"). + +-define(PID, emqx_auth_ldap). + +-define(APP, emqx_auth_ldap). + +-define(DeviceDN, "ou=test_device,dc=emqx,dc=io"). + +-define(AuthDN, "ou=test_auth,dc=emqx,dc=io"). + +%%-------------------------------------------------------------------- +%% Setups +%%-------------------------------------------------------------------- + +all() -> + [{group, nossl}, {group, ssl}]. + +groups() -> + Cases = emqx_ct:all(?MODULE), + [{nossl, Cases}, {ssl, Cases}]. + +init_per_group(GrpName, Cfg) -> + Fun = fun(App) -> set_special_configs(GrpName, App) end, + emqx_ct_helpers:start_apps([emqx_auth_ldap], Fun), + emqx_mod_acl_internal:unload([]), + Cfg. + +end_per_group(_GrpName, _Cfg) -> + emqx_ct_helpers:stop_apps([emqx_auth_ldap]). + +%%-------------------------------------------------------------------- +%% Cases +%%-------------------------------------------------------------------- + +t_check_auth(_) -> + MqttUser1 = #{clientid => <<"mqttuser1">>, + username => <<"mqttuser0001">>, + password => <<"mqttuser0001">>, + zone => external}, + MqttUser2 = #{clientid => <<"mqttuser2">>, + username => <<"mqttuser0002">>, + password => <<"mqttuser0002">>, + zone => external}, + MqttUser3 = #{clientid => <<"mqttuser3">>, + username => <<"mqttuser0003">>, + password => <<"mqttuser0003">>, + zone => external}, + MqttUser4 = #{clientid => <<"mqttuser4">>, + username => <<"mqttuser0004">>, + password => <<"mqttuser0004">>, + zone => external}, + MqttUser5 = #{clientid => <<"mqttuser5">>, + username => <<"mqttuser0005">>, + password => <<"mqttuser0005">>, + zone => external}, + NonExistUser1 = #{clientid => <<"mqttuser6">>, + username => <<"mqttuser0006">>, + password => <<"mqttuser0006">>, + zone => external}, + NonExistUser2 = #{clientid => <<"mqttuser7">>, + username => <<"mqttuser0005">>, + password => <<"mqttuser0006">>, + zone => external}, + ct:log("MqttUser: ~p", [emqx_access_control:authenticate(MqttUser1)]), + ?assertMatch({ok, #{auth_result := success}}, emqx_access_control:authenticate(MqttUser1)), + ?assertMatch({ok, #{auth_result := success}}, emqx_access_control:authenticate(MqttUser2)), + ?assertMatch({ok, #{auth_result := success}}, emqx_access_control:authenticate(MqttUser3)), + ?assertMatch({ok, #{auth_result := success}}, emqx_access_control:authenticate(MqttUser4)), + ?assertMatch({ok, #{auth_result := success}}, emqx_access_control:authenticate(MqttUser5)), + ?assertEqual({error, not_authorized}, emqx_access_control:authenticate(NonExistUser1)), + ?assertEqual({error, bad_username_or_password}, emqx_access_control:authenticate(NonExistUser2)). + +t_check_acl(_) -> + MqttUser = #{clientid => <<"mqttuser1">>, username => <<"mqttuser0001">>, zone => external}, + NoMqttUser = #{clientid => <<"mqttuser2">>, username => <<"mqttuser0007">>, zone => external}, + allow = emqx_access_control:check_acl(MqttUser, publish, <<"mqttuser0001/pub/1">>), + allow = emqx_access_control:check_acl(MqttUser, publish, <<"mqttuser0001/pub/+">>), + allow = emqx_access_control:check_acl(MqttUser, publish, <<"mqttuser0001/pub/#">>), + + allow = emqx_access_control:check_acl(MqttUser, subscribe, <<"mqttuser0001/sub/1">>), + allow = emqx_access_control:check_acl(MqttUser, subscribe, <<"mqttuser0001/sub/+">>), + allow = emqx_access_control:check_acl(MqttUser, subscribe, <<"mqttuser0001/sub/#">>), + + allow = emqx_access_control:check_acl(MqttUser, publish, <<"mqttuser0001/pubsub/1">>), + allow = emqx_access_control:check_acl(MqttUser, publish, <<"mqttuser0001/pubsub/+">>), + allow = emqx_access_control:check_acl(MqttUser, publish, <<"mqttuser0001/pubsub/#">>), + allow = emqx_access_control:check_acl(MqttUser, subscribe, <<"mqttuser0001/pubsub/1">>), + allow = emqx_access_control:check_acl(MqttUser, subscribe, <<"mqttuser0001/pubsub/+">>), + allow = emqx_access_control:check_acl(MqttUser, subscribe, <<"mqttuser0001/pubsub/#">>), + + deny = emqx_access_control:check_acl(NoMqttUser, publish, <<"mqttuser0001/req/mqttuser0001/+">>), + deny = emqx_access_control:check_acl(MqttUser, publish, <<"mqttuser0001/req/mqttuser0002/+">>), + deny = emqx_access_control:check_acl(MqttUser, subscribe, <<"mqttuser0001/req/+/mqttuser0002">>), + ok. + +%%-------------------------------------------------------------------- +%% Helpers +%%-------------------------------------------------------------------- + +set_special_configs(_, emqx) -> + application:set_env(emqx, allow_anonymous, false), + application:set_env(emqx, enable_acl_cache, false), + application:set_env(emqx, acl_nomatch, deny), + AclFilePath = filename:join(["test", "emqx_SUITE_data", "acl.conf"]), + application:set_env(emqx, acl_file, + emqx_ct_helpers:deps_path(emqx, AclFilePath)), + LoadedPluginPath = filename:join(["test", "emqx_SUITE_data", "loaded_plugins"]), + application:set_env(emqx, plugins_loaded_file, + emqx_ct_helpers:deps_path(emqx, LoadedPluginPath)); + +set_special_configs(Ssl, emqx_auth_ldap) -> + case Ssl == ssl of + true -> + LdapOpts = application:get_env(emqx_auth_ldap, ldap, []), + Path = emqx_ct_helpers:deps_path(emqx_auth_ldap, "test/certs/"), + SslOpts = [{verify, verify_peer}, + {fail_if_no_peer_cert, true}, + {server_name_indication, disable}, + {keyfile, Path ++ "/client-key.pem"}, + {certfile, Path ++ "/client-cert.pem"}, + {cacertfile, Path ++ "/cacert.pem"}], + LdapOpts1 = lists:keystore(ssl, 1, LdapOpts, {ssl, true}), + LdapOpts2 = lists:keystore(sslopts, 1, LdapOpts1, {sslopts, SslOpts}), + LdapOpts3 = lists:keystore(port, 1, LdapOpts2, {port, 636}), + application:set_env(emqx_auth_ldap, ldap, LdapOpts3); + _ -> + ok + end, + application:set_env(emqx_auth_ldap, device_dn, "ou=testdevice, dc=emqx, dc=io"). + diff --git a/apps/emqx_auth_ldap/test/emqx_auth_ldap_bind_as_user_SUITE.erl b/apps/emqx_auth_ldap/test/emqx_auth_ldap_bind_as_user_SUITE.erl new file mode 100644 index 000000000..a9afbae45 --- /dev/null +++ b/apps/emqx_auth_ldap/test/emqx_auth_ldap_bind_as_user_SUITE.erl @@ -0,0 +1,114 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_ldap_bind_as_user_SUITE). + +-compile(export_all). +-compile(no_warning_export). + +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("eunit/include/eunit.hrl"). +-include_lib("common_test/include/ct.hrl"). + +-define(PID, emqx_auth_ldap). + +-define(APP, emqx_auth_ldap). + +-define(DeviceDN, "ou=test_device,dc=emqx,dc=io"). + +-define(AuthDN, "ou=test_auth,dc=emqx,dc=io"). + +all() -> + [check_auth, + check_acl]. + +init_per_suite(Config) -> + emqx_ct_helpers:start_apps([emqx, emqx_auth_ldap], fun set_special_configs/1), + emqx_mod_acl_internal:unload([]), + Config. + +end_per_suite(_Config) -> + emqx_ct_helpers:stop_apps([emqx_auth_ldap, emqx]). + +check_auth(_) -> + MqttUser1 = #{clientid => <<"mqttuser1">>, + username => <<"user1">>, + password => <<"mqttuser0001">>, + zone => external}, + MqttUser2 = #{clientid => <<"mqttuser2">>, + username => <<"user2">>, + password => <<"mqttuser0002">>, + zone => external}, + NonExistUser1 = #{clientid => <<"mqttuser3">>, + username => <<"user3">>, + password => <<"mqttuser0003">>, + zone => external}, + ct:log("MqttUser: ~p", [emqx_access_control:authenticate(MqttUser1)]), + ?assertMatch({ok, #{auth_result := success}}, emqx_access_control:authenticate(MqttUser1)), + ?assertMatch({ok, #{auth_result := success}}, emqx_access_control:authenticate(MqttUser2)), + ?assertEqual({error, not_authorized}, emqx_access_control:authenticate(NonExistUser1)). + +check_acl(_) -> + % emqx_modules:load_module(emqx_mod_acl_internal, false), + MqttUser = #{clientid => <<"mqttuser1">>, username => <<"user1">>, zone => external}, + NoMqttUser = #{clientid => <<"mqttuser2">>, username => <<"user7">>, zone => external}, + allow = emqx_access_control:check_acl(MqttUser, publish, <<"mqttuser0001/pub/1">>), + allow = emqx_access_control:check_acl(MqttUser, publish, <<"mqttuser0001/pub/+">>), + allow = emqx_access_control:check_acl(MqttUser, publish, <<"mqttuser0001/pub/#">>), + + allow = emqx_access_control:check_acl(MqttUser, subscribe, <<"mqttuser0001/sub/1">>), + allow = emqx_access_control:check_acl(MqttUser, subscribe, <<"mqttuser0001/sub/+">>), + allow = emqx_access_control:check_acl(MqttUser, subscribe, <<"mqttuser0001/sub/#">>), + + allow = emqx_access_control:check_acl(MqttUser, publish, <<"mqttuser0001/pubsub/1">>), + allow = emqx_access_control:check_acl(MqttUser, publish, <<"mqttuser0001/pubsub/+">>), + allow = emqx_access_control:check_acl(MqttUser, publish, <<"mqttuser0001/pubsub/#">>), + allow = emqx_access_control:check_acl(MqttUser, subscribe, <<"mqttuser0001/pubsub/1">>), + allow = emqx_access_control:check_acl(MqttUser, subscribe, <<"mqttuser0001/pubsub/+">>), + allow = emqx_access_control:check_acl(MqttUser, subscribe, <<"mqttuser0001/pubsub/#">>), + + deny = emqx_access_control:check_acl(NoMqttUser, publish, <<"mqttuser0001/req/mqttuser0001/+">>), + deny = emqx_access_control:check_acl(MqttUser, publish, <<"mqttuser0001/req/mqttuser0002/+">>), + deny = emqx_access_control:check_acl(MqttUser, subscribe, <<"mqttuser0001/req/+/mqttuser0002">>), + ok. + +set_special_configs(emqx) -> + application:set_env(emqx, allow_anonymous, false), + application:set_env(emqx, enable_acl_cache, false), + application:set_env(emqx, acl_nomatch, deny), + AclFilePath = filename:join(["test", "emqx_SUITE_data", "acl.conf"]), + application:set_env(emqx, acl_file, + emqx_ct_helpers:deps_path(emqx, AclFilePath)), + LoadedPluginPath = filename:join(["test", "emqx_SUITE_data", "loaded_plugins"]), + application:set_env(emqx, plugins_loaded_file, + emqx_ct_helpers:deps_path(emqx, LoadedPluginPath)); + +set_special_configs(emqx_auth_ldap) -> + application:set_env(emqx_auth_ldap, bind_as_user, true), + application:set_env(emqx_auth_ldap, device_dn, "ou=testdevice, dc=emqx, dc=io"), + application:set_env(emqx_auth_ldap, custom_base_dn, "${device_dn}"), + %% auth.ldap.filters.1.key = mqttAccountName + %% auth.ldap.filters.1.value = ${user} + %% auth.ldap.filters.1.op = and + %% auth.ldap.filters.2.key = objectClass + %% auth.ldap.filters.1.value = mqttUser + application:set_env(emqx_auth_ldap, filters, [{"mqttAccountName", "${user}"}, + "and", + {"objectClass", "mqttUser"}]); + +set_special_configs(_App) -> + ok. + diff --git a/apps/emqx_auth_mnesia/README.md b/apps/emqx_auth_mnesia/README.md new file mode 100644 index 000000000..8b4c145a8 --- /dev/null +++ b/apps/emqx_auth_mnesia/README.md @@ -0,0 +1,2 @@ +emqx_auth_mnesia +=============== diff --git a/apps/emqx_auth_mnesia/include/emqx_auth_mnesia.hrl b/apps/emqx_auth_mnesia/include/emqx_auth_mnesia.hrl new file mode 100644 index 000000000..31557ea63 --- /dev/null +++ b/apps/emqx_auth_mnesia/include/emqx_auth_mnesia.hrl @@ -0,0 +1,35 @@ +-define(APP, emqx_auth_mnesia). + +-record(emqx_user, { + login, + password, + is_superuser + }). + +-record(emqx_acl, { + login, + topic, + action, + allow + }). + +-record(auth_metrics, { + success = 'client.auth.success', + failure = 'client.auth.failure', + ignore = 'client.auth.ignore' + }). + +-record(acl_metrics, { + allow = 'client.acl.allow', + deny = 'client.acl.deny', + ignore = 'client.acl.ignore' + }). + +-define(METRICS(Type), tl(tuple_to_list(#Type{}))). +-define(METRICS(Type, K), #Type{}#Type.K). + +-define(AUTH_METRICS, ?METRICS(auth_metrics)). +-define(AUTH_METRICS(K), ?METRICS(auth_metrics, K)). + +-define(ACL_METRICS, ?METRICS(acl_metrics)). +-define(ACL_METRICS(K), ?METRICS(acl_metrics, K)). \ No newline at end of file diff --git a/apps/emqx_auth_mnesia/priv/emqx_auth_mnesia.schema b/apps/emqx_auth_mnesia/priv/emqx_auth_mnesia.schema new file mode 100644 index 000000000..34333b145 --- /dev/null +++ b/apps/emqx_auth_mnesia/priv/emqx_auth_mnesia.schema @@ -0,0 +1,35 @@ +%%-*- mode: erlang -*- +%% emqx_auth_mnesia config mapping + +{mapping, "auth.mnesia.as", "emqx_auth_mnesia.as", [ + {default, username}, + {datatype, {enum, [username, clientid]}} +]}. + +{mapping, "auth.mnesia.password_hash", "emqx_auth_mnesia.password_hash", [ + {default, sha256}, + {datatype, {enum, [plain, md5, sha, sha256]}} +]}. + +{mapping, "auth.mnesia.$id.login", "emqx_auth_mnesia.userlist", [ + {datatype, string} +]}. + +{mapping, "auth.mnesia.$id.password", "emqx_auth_mnesia.userlist", [ + {datatype, string} +]}. + +{mapping, "auth.mnesia.$id.is_superuser", "emqx_auth_mnesia.userlist", [ + {default, false}, + {datatype, {enum, [false, true]}} +]}. + +{translation, "emqx_auth_mnesia.userlist", fun(Conf) -> + Userlist = cuttlefish_variable:filter_by_prefix("auth.mnesia", Conf), + lists:foldl( + fun({["auth", "mnesia", Id, "login"], Username}, AccIn) -> + [{Username, cuttlefish:conf_get("auth.mnesia." ++ Id ++ ".password", Conf), cuttlefish:conf_get("auth.mnesia." ++ Id ++ ".is_superuser", Conf)} | AccIn]; + (_, AccIn) -> + AccIn + end, [], Userlist) +end}. diff --git a/apps/emqx_auth_mnesia/rebar.config b/apps/emqx_auth_mnesia/rebar.config new file mode 100644 index 000000000..7b1f06cca --- /dev/null +++ b/apps/emqx_auth_mnesia/rebar.config @@ -0,0 +1 @@ +{deps, []}. \ No newline at end of file diff --git a/apps/emqx_auth_mnesia/src/emqx_acl_mnesia.erl b/apps/emqx_auth_mnesia/src/emqx_acl_mnesia.erl new file mode 100644 index 000000000..63a357979 --- /dev/null +++ b/apps/emqx_auth_mnesia/src/emqx_acl_mnesia.erl @@ -0,0 +1,83 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_acl_mnesia). + +-include("emqx_auth_mnesia.hrl"). + +%% ACL Callbacks +-export([ init/0 + , register_metrics/0 + , check_acl/5 + , description/0 + ]). + +init() -> + ok = ekka_mnesia:create_table(emqx_acl, [ + {type, bag}, + {disc_copies, [node()]}, + {attributes, record_info(fields, emqx_acl)}, + {storage_properties, [{ets, [{read_concurrency, true}]}]}]), + ok = ekka_mnesia:copy_table(emqx_user, disc_copies). + +-spec(register_metrics() -> ok). +register_metrics() -> + lists:foreach(fun emqx_metrics:ensure/1, ?ACL_METRICS). + +check_acl(ClientInfo, PubSub, Topic, NoMatchAction, #{key_as := As}) -> + Login = maps:get(As, ClientInfo), + case do_check_acl(Login, PubSub, Topic, NoMatchAction) of + ok -> emqx_metrics:inc(?ACL_METRICS(ignore)), ok; + {stop, allow} -> emqx_metrics:inc(?ACL_METRICS(allow)), {stop, allow}; + {stop, deny} -> emqx_metrics:inc(?ACL_METRICS(deny)), {stop, deny} + end. + +description() -> "Acl with Mnesia". + +%%-------------------------------------------------------------------- +%% Internal functions +%%------------------------------------------------------------------- + +do_check_acl(Login, PubSub, Topic, _NoMatchAction) -> + case match(PubSub, Topic, emqx_auth_mnesia_cli:lookup_acl(Login)) of + allow -> {stop, allow}; + deny -> {stop, deny}; + _ -> + case match(PubSub, Topic, emqx_auth_mnesia_cli:lookup_acl(<<"$all">>)) of + allow -> {stop, allow}; + deny -> {stop, deny}; + _ -> ok + end + end. + +match(_PubSub, _Topic, []) -> + nomatch; +match(PubSub, Topic, [ #emqx_acl{topic = ACLTopic, action = Action, allow = Allow} | UserAcl]) -> + case match_actions(PubSub, Action) andalso match_topic(Topic, ACLTopic) of + true -> case Allow of + true -> allow; + _ -> deny + end; + false -> match(PubSub, Topic, UserAcl) + end. + +match_topic(Topic, ACLTopic) when is_binary(Topic) -> + emqx_topic:match(Topic, ACLTopic). + +match_actions(_, <<"pubsub">>) -> true; +match_actions(subscribe, <<"sub">>) -> true; +match_actions(publish, <<"pub">>) -> true; +match_actions(_, _) -> false. diff --git a/apps/emqx_auth_mnesia/src/emqx_acl_mnesia_api.erl b/apps/emqx_auth_mnesia/src/emqx_acl_mnesia_api.erl new file mode 100644 index 000000000..3891b7ffd --- /dev/null +++ b/apps/emqx_auth_mnesia/src/emqx_acl_mnesia_api.erl @@ -0,0 +1,148 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_acl_mnesia_api). + +-include("emqx_auth_mnesia.hrl"). + +-import(proplists, [get_value/2]). + +-import(minirest, [return/1]). + +-rest_api(#{name => list_emqx_acl, + method => 'GET', + path => "/mqtt_acl", + func => list, + descr => "List available mnesia in the cluster" + }). + +-rest_api(#{name => lookup_emqx_acl, + method => 'GET', + path => "/mqtt_acl/:bin:login", + func => lookup, + descr => "Lookup mnesia in the cluster" + }). + +-rest_api(#{name => add_emqx_acl, + method => 'POST', + path => "/mqtt_acl", + func => add, + descr => "Add mnesia in the cluster" + }). + +-rest_api(#{name => delete_emqx_acl, + method => 'DELETE', + path => "/mqtt_acl/:bin:login/:bin:topic", + func => delete, + descr => "Delete mnesia in the cluster" + }). + +-export([ list/2 + , lookup/2 + , add/2 + , delete/2 + ]). + +list(_Bindings, Params) -> + return({ok, emqx_auth_mnesia_api:paginate(emqx_acl, Params, fun format/1)}). + +lookup(#{login := Login}, _Params) -> + return({ok, format(emqx_auth_mnesia_cli:lookup_acl(urldecode(Login)))}). + +add(_Bindings, Params) -> + [ P | _] = Params, + case is_list(P) of + true -> return(add_acl(Params, [])); + false -> return(add_acl([Params], [])) + end. + +add_acl([ Params | ParamsN ], ReList ) -> + Login = urldecode(get_value(<<"login">>, Params)), + Topic = urldecode(get_value(<<"topic">>, Params)), + Action = urldecode(get_value(<<"action">>, Params)), + Allow = get_value(<<"allow">>, Params), + Re = case validate([login, topic, action, allow], [Login, Topic, Action, Allow]) of + ok -> + emqx_auth_mnesia_cli:add_acl(Login, Topic, Action, Allow); + Err -> Err + end, + add_acl(ParamsN, [{Login, format_msg(Re)} | ReList]); + +add_acl([], ReList) -> + {ok, ReList}. + +delete(#{login := Login, topic := Topic}, _) -> + return(emqx_auth_mnesia_cli:remove_acl(urldecode(Login), urldecode(Topic))). + +%%------------------------------------------------------------------------------ +%% Interval Funcs +%%------------------------------------------------------------------------------ + +format(#emqx_acl{login = Login, topic = Topic, action = Action, allow = Allow}) -> + #{login => Login, topic => Topic, action => Action, allow => Allow }; + +format([]) -> + #{}; + +format([#emqx_acl{login = Login, topic = Topic, action = Action, allow = Allow}]) -> + format(#emqx_acl{login = Login, topic = Topic, action = Action, allow = Allow}); + +format([ #emqx_acl{login = _Key, topic = _Topic, action = _Action, allow = _Allow}| _] = List) -> + format(List, []). + +format([#emqx_acl{login = Login, topic = Topic, action = Action, allow = Allow} | List], ReList) -> + format(List, [ format(#emqx_acl{login = Login, topic = Topic, action = Action, allow = Allow}) | ReList]); +format([], ReList) -> ReList. + +validate([], []) -> + ok; +validate([K|Keys], [V|Values]) -> + case do_validation(K, V) of + false -> {error, K}; + true -> validate(Keys, Values) + end. + +do_validation(login, V) when is_binary(V) + andalso byte_size(V) > 0 -> + true; +do_validation(topic, V) when is_binary(V) + andalso byte_size(V) > 0 -> + true; +do_validation(action, V) when is_binary(V) -> + case V =:= <<"pub">> orelse V =:= <<"sub">> orelse V =:= <<"pubsub">> of + true -> true; + false -> false + end; +do_validation(allow, V) when is_boolean(V) -> + true; +do_validation(_, _) -> + false. + +format_msg(Message) + when is_atom(Message); + is_binary(Message) -> Message; + +format_msg(Message) when is_tuple(Message) -> + iolist_to_binary(io_lib:format("~p", [Message])). + +-if(?OTP_RELEASE >= 23). +urldecode(S) -> + [{R, _}] = uri_string:dissect_query(S), R. +-else. +urldecode(S) -> + http_uri:decode(S). +-endif. + diff --git a/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.app.src b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.app.src new file mode 100644 index 000000000..c1e4aec18 --- /dev/null +++ b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.app.src @@ -0,0 +1,14 @@ +{application, emqx_auth_mnesia, + [{description, "EMQ X Authentication with Mnesia"}, + {vsn, "5.0.0"}, % strict semver, bump manually! + {modules, []}, + {registered, []}, + {applications, [kernel,stdlib,mnesia,emqx_libs]}, + {mod, {emqx_auth_mnesia_app,[]}}, + {env, []}, + {licenses, ["Apache-2.0"]}, + {maintainers, ["EMQ X Team "]}, + {links, [{"Homepage", "https://emqx.io/"}, + {"Github", "https://github.com/emqx/emqx-auth-mnesia"} + ]} + ]}. diff --git a/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.erl b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.erl new file mode 100644 index 000000000..8b47c8b32 --- /dev/null +++ b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.erl @@ -0,0 +1,76 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_mnesia). + +-include("emqx_auth_mnesia.hrl"). + +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). +-include_lib("emqx_libs/include/types.hrl"). + +%% Auth callbacks +-export([ init/1 + , register_metrics/0 + , check/3 + , description/0 + ]). + +init(DefaultUsers) -> + ok = ekka_mnesia:create_table(emqx_user, [ + {disc_copies, [node()]}, + {attributes, record_info(fields, emqx_user)}, + {storage_properties, [{ets, [{read_concurrency, true}]}]}]), + ok = lists:foreach(fun add_default_user/1, DefaultUsers), + ok = ekka_mnesia:copy_table(emqx_user, disc_copies). + +%% @private +add_default_user({Login, Password, IsSuperuser}) -> + emqx_auth_mnesia_cli:add_user(iolist_to_binary(Login), iolist_to_binary(Password), IsSuperuser). + +-spec(register_metrics() -> ok). +register_metrics() -> + lists:foreach(fun emqx_metrics:ensure/1, ?AUTH_METRICS). + +check(ClientInfo = #{password := Password}, AuthResult, #{hash_type := HashType, key_as := As}) -> + Login = maps:get(As, ClientInfo), + case emqx_auth_mnesia_cli:lookup_user(Login) of + [] -> + emqx_metrics:inc(?AUTH_METRICS(ignore)), + ok; + [User] -> + case emqx_passwd:check_pass({User#emqx_user.password, Password}, HashType) of + ok -> + emqx_metrics:inc(?AUTH_METRICS(success)), + {stop, AuthResult#{is_superuser => is_superuser(User), + anonymous => false, + auth_result => success}}; + {error, Reason} -> + ?LOG(error, "[Mnesia] Auth from mnesia failed: ~p", [Reason]), + emqx_metrics:inc(?AUTH_METRICS(failure)), + {stop, AuthResult#{auth_result => password_error, anonymous => false}} + end + end. + +description() -> "Authentication with Mnesia". + +%%-------------------------------------------------------------------- +%% Internal functions +%%-------------------------------------------------------------------- +is_superuser(#emqx_user{is_superuser = true}) -> + true; +is_superuser(_) -> + false. diff --git a/apps/emqx_auth_mnesia/src/emqx_auth_mnesia_api.erl b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia_api.erl new file mode 100644 index 000000000..7c527b0fd --- /dev/null +++ b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia_api.erl @@ -0,0 +1,201 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_mnesia_api). + +-include_lib("stdlib/include/qlc.hrl"). + +-import(proplists, [get_value/2]). + +-import(minirest, [return/1]). + +-rest_api(#{name => list_emqx_user, + method => 'GET', + path => "/mqtt_user", + func => list, + descr => "List available mnesia in the cluster" + }). + +-rest_api(#{name => lookup_emqx_user, + method => 'GET', + path => "/mqtt_user/:bin:login", + func => lookup, + descr => "Lookup mnesia in the cluster" + }). + +-rest_api(#{name => add_emqx_user, + method => 'POST', + path => "/mqtt_user", + func => add, + descr => "Add mnesia in the cluster" + }). + +-rest_api(#{name => update_emqx_user, + method => 'PUT', + path => "/mqtt_user/:bin:login", + func => update, + descr => "Update mnesia in the cluster" + }). + +-rest_api(#{name => delete_emqx_user, + method => 'DELETE', + path => "/mqtt_user/:bin:login", + func => delete, + descr => "Delete mnesia in the cluster" + }). + +-export([ list/2 + , lookup/2 + , add/2 + , update/2 + , delete/2 + ]). + +-export([paginate/3]). + +list(_Bindings, Params) -> + return({ok, paginate(emqx_user, Params, fun format/1)}). + +lookup(#{login := Login}, _Params) -> + return({ok, format(emqx_auth_mnesia_cli:lookup_user(urldecode(Login)))}). + +add(_Bindings, Params) -> + [ P | _] = Params, + case is_list(P) of + true -> return(add_user(Params, [])); + false -> return(add_user([Params], [])) + end. + +add_user([ Params | ParamsN ], ReList ) -> + Login = urldecode(get_value(<<"login">>, Params)), + Password = urldecode(get_value(<<"password">>, Params)), + IsSuperuser = get_value(<<"is_superuser">>, Params), + Re = case validate([login, password, is_superuser], [Login, Password, IsSuperuser]) of + ok -> + emqx_auth_mnesia_cli:add_user(Login, Password, IsSuperuser); + Err -> Err + end, + add_user(ParamsN, [{Login, format_msg(Re)} | ReList]); + +add_user([], ReList) -> + {ok, ReList}. + +update(#{login := Login}, Params) -> + Password = get_value(<<"password">>, Params), + IsSuperuser = get_value(<<"is_superuser">>, Params), + case validate([password, is_superuser], [Password, IsSuperuser]) of + ok -> return(emqx_auth_mnesia_cli:update_user(urldecode(Login), urldecode(Password), IsSuperuser)); + Err -> return(Err) + end. + +delete(#{login := Login}, _) -> + return(emqx_auth_mnesia_cli:remove_user(urldecode(Login))). + +%%------------------------------------------------------------------------------ +%% Paging Query +%%------------------------------------------------------------------------------ + +paginate(Tables, Params, RowFun) -> + Qh = query_handle(Tables), + Count = count(Tables), + Page = page(Params), + Limit = limit(Params), + Cursor = qlc:cursor(Qh), + case Page > 1 of + true -> qlc:next_answers(Cursor, (Page - 1) * Limit); + false -> ok + end, + Rows = qlc:next_answers(Cursor, Limit), + qlc:delete_cursor(Cursor), + #{meta => #{page => Page, limit => Limit, count => Count}, + data => [RowFun(Row) || Row <- Rows]}. + +query_handle(Table) when is_atom(Table) -> + qlc:q([R|| R <- ets:table(Table)]); +query_handle([Table]) when is_atom(Table) -> + qlc:q([R|| R <- ets:table(Table)]); +query_handle(Tables) -> + qlc:append([qlc:q([E || E <- ets:table(T)]) || T <- Tables]). + +count(Table) when is_atom(Table) -> + ets:info(Table, size); +count([Table]) when is_atom(Table) -> + ets:info(Table, size); +count(Tables) -> + lists:sum([count(T) || T <- Tables]). + +page(Params) -> + binary_to_integer(proplists:get_value(<<"_page">>, Params, <<"1">>)). + +limit(Params) -> + case proplists:get_value(<<"_limit">>, Params) of + undefined -> 10; + Size -> binary_to_integer(Size) + end. + + + +%%------------------------------------------------------------------------------ +%% Interval Funcs +%%------------------------------------------------------------------------------ + +format({emqx_user, Login, Password, IsSuperuser}) -> + #{login => Login, + password => Password, + is_superuser => IsSuperuser}; + +format([]) -> + #{}; + +format([{emqx_user, Login, Password, IsSuperuser}]) -> + #{login => Login, + password => Password, + is_superuser => IsSuperuser}. + +validate([], []) -> + ok; +validate([K|Keys], [V|Values]) -> + case do_validation(K, V) of + false -> {error, K}; + true -> validate(Keys, Values) + end. + +do_validation(login, V) when is_binary(V) + andalso byte_size(V) > 0 -> + true; +do_validation(password, V) when is_binary(V) + andalso byte_size(V) > 0 -> + true; +do_validation(is_superuser, V) when is_boolean(V) -> + true; +do_validation(_, _) -> + false. + +format_msg(Message) + when is_atom(Message); + is_binary(Message) -> Message; + +format_msg(Message) when is_tuple(Message) -> + iolist_to_binary(io_lib:format("~p", [Message])). + +-if(?OTP_RELEASE >= 23). +urldecode(S) -> + [{R, _}] = uri_string:dissect_query(S), R. +-else. +urldecode(S) -> + http_uri:decode(S). +-endif. + diff --git a/apps/emqx_auth_mnesia/src/emqx_auth_mnesia_app.erl b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia_app.erl new file mode 100644 index 000000000..094eba0ea --- /dev/null +++ b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia_app.erl @@ -0,0 +1,70 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_mnesia_app). + +-behaviour(application). + +-emqx_plugin(auth). + +-include("emqx_auth_mnesia.hrl"). + +%% Application callbacks +-export([ start/2 + , prep_stop/1 + , stop/1 + ]). + +%%-------------------------------------------------------------------- +%% Application callbacks +%%-------------------------------------------------------------------- + +start(_StartType, _StartArgs) -> + {ok, Sup} = emqx_auth_mnesia_sup:start_link(), + emqx_ctl:register_command('mqtt-user', {emqx_auth_mnesia_cli, auth_cli}, []), + emqx_ctl:register_command('mqtt-acl', {emqx_auth_mnesia_cli, acl_cli}, []), + load_auth_hook(), + load_acl_hook(), + {ok, Sup}. + +prep_stop(State) -> + emqx:unhook('client.authenticate', fun emqx_auth_mnesia:check/3), + emqx:unhook('client.check_acl', fun emqx_acl_mnesia:check_acl/5), + emqx_ctl:unregister_command('mqtt-user'), + emqx_ctl:unregister_command('mqtt-acl'), + State. + +stop(_State) -> + ok. + +load_auth_hook() -> + DefaultUsers = application:get_env(?APP, userlist, []), + ok = emqx_auth_mnesia:init(DefaultUsers), + ok = emqx_auth_mnesia:register_metrics(), + Params = #{ + hash_type => application:get_env(emqx_auth_mnesia, hash_type, sha256), + key_as => application:get_env(emqx_auth_mnesia, as, username) + }, + emqx:hook('client.authenticate', fun emqx_auth_mnesia:check/3, [Params]). + +load_acl_hook() -> + ok = emqx_acl_mnesia:init(), + ok = emqx_acl_mnesia:register_metrics(), + Params = #{ + key_as => application:get_env(emqx_auth_mnesia, as, username) + }, + emqx:hook('client.check_acl', fun emqx_acl_mnesia:check_acl/5, [Params]). + diff --git a/apps/emqx_auth_mnesia/src/emqx_auth_mnesia_cli.erl b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia_cli.erl new file mode 100644 index 000000000..fb14bed53 --- /dev/null +++ b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia_cli.erl @@ -0,0 +1,193 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_mnesia_cli). + +-include("emqx_auth_mnesia.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). +-define(TABLE, emqx_user). +%% Auth APIs +-export([ add_user/3 + , update_user/3 + , remove_user/1 + , lookup_user/1 + , all_users/0 + ]). +%% Acl APIs +-export([ add_acl/4 + , remove_acl/2 + , lookup_acl/1 + , all_acls/0 + ]). +%% Cli +-export([ auth_cli/1 + , acl_cli/1]). +%%-------------------------------------------------------------------- +%% Auth APIs +%%-------------------------------------------------------------------- + +%% @doc Add User +-spec(add_user(binary(), binary(), atom()) -> ok | {error, any()}). +add_user(Login, Password, IsSuperuser) -> + User = #emqx_user{login = Login, password = encrypted_data(Password), is_superuser = IsSuperuser}, + ret(mnesia:transaction(fun insert_user/1, [User])). + +insert_user(User = #emqx_user{login = Login}) -> + case mnesia:read(?TABLE, Login) of + [] -> mnesia:write(User); + [_|_] -> mnesia:abort(existed) + end. + +%% @doc Update User +-spec(update_user(binary(), binary(), atom()) -> ok | {error, any()}). +update_user(Login, NewPassword, IsSuperuser) -> + User = #emqx_user{login = Login, password = encrypted_data(NewPassword), is_superuser = IsSuperuser}, + ret(mnesia:transaction(fun do_update_user/1, [User])). + +do_update_user(User = #emqx_user{login = Login}) -> + case mnesia:read(?TABLE, Login) of + [_|_] -> mnesia:write(User); + [] -> mnesia:abort(noexisted) + end. + +%% @doc Lookup user by login +-spec(lookup_user(binary()) -> list()). +lookup_user(undefined) -> []; +lookup_user(Login) -> + case mnesia:dirty_read(?TABLE, Login) of + {error, Reason} -> + ?LOG(error, "[Mnesia] do_check_user error: ~p~n", [Reason]), + []; + Re -> Re + end. + +%% @doc Remove user +-spec(remove_user(binary()) -> ok | {error, any()}). +remove_user(Login) -> + ret(mnesia:transaction(fun mnesia:delete/1, [{?TABLE, Login}])). + +%% @doc All logins +-spec(all_users() -> list()). +all_users() -> mnesia:dirty_all_keys(?TABLE). + +%%-------------------------------------------------------------------- +%% Acl API +%%-------------------------------------------------------------------- + +%% @doc Add Acls +-spec(add_acl(binary(), binary(), binary(), atom()) -> ok | {error, any()}). +add_acl(Login, Topic, Action, Allow) -> + Acls = #emqx_acl{login = Login, topic = Topic, action = Action, allow = Allow}, + ret(mnesia:transaction(fun mnesia:write/1, [Acls])). + +%% @doc Lookup acl by login +-spec(lookup_acl(binary()) -> list()). +lookup_acl(undefined) -> []; +lookup_acl(Login) -> + case mnesia:dirty_read(emqx_acl, Login) of + {error, Reason} -> + ?LOG(error, "[Mnesia] do_check_acl error: ~p~n", [Reason]), + []; + Re -> Re + end. + +%% @doc Remove acl +-spec(remove_acl(binary(), binary()) -> ok | {error, any()}). +remove_acl(Login, Topic) -> + [ ok = mnesia:dirty_delete_object(emqx_acl, #emqx_acl{login = Login, topic = Topic, action = Action, allow = Allow}) || [Action, Allow] <- ets:select(emqx_acl, [{{emqx_acl, Login, Topic,'$1','$2'}, [], ['$$']}])], + ok. + + +%% @doc All logins +-spec(all_acls() -> list()). +all_acls() -> mnesia:dirty_all_keys(emqx_acl). + + +%%-------------------------------------------------------------------- +%% Internal functions +%%-------------------------------------------------------------------- + +ret({atomic, ok}) -> ok; +ret({aborted, Error}) -> {error, Error}. + +encrypted_data(Password) -> + HashType = application:get_env(emqx_auth_mnesia, hash_type, sha256), + emqx_passwd:hash(HashType, Password). + +%%-------------------------------------------------------------------- +%% Auth APIs +%%-------------------------------------------------------------------- + +%% User +auth_cli(["add", Login, Password, IsSuperuser]) -> + case add_user(iolist_to_binary(Login), iolist_to_binary(Password), IsSuperuser) of + ok -> emqx_ctl:print("ok~n"); + {error, Reason} -> emqx_ctl:print("Error: ~p~n", [Reason]) + end; + +auth_cli(["update", Login, NewPassword, IsSuperuser]) -> + case update_user(iolist_to_binary(Login), iolist_to_binary(NewPassword), IsSuperuser) of + ok -> emqx_ctl:print("ok~n"); + {error, Reason} -> emqx_ctl:print("Error: ~p~n", [Reason]) + end; + +auth_cli(["del", Login]) -> + case remove_user(iolist_to_binary(Login)) of + ok -> emqx_ctl:print("ok~n"); + {error, Reason} -> emqx_ctl:print("Error: ~p~n", [Reason]) + end; + +auth_cli(["show", P]) -> + [emqx_ctl:print("User(login = ~p is_super = ~p)~n", [Login, IsSuperuser]) + || {_, Login, _Password, IsSuperuser} <- lookup_user(iolist_to_binary(P))]; + +auth_cli(["list"]) -> + [emqx_ctl:print("User(login = ~p)~n",[E]) + || E <- all_users()]; + +auth_cli(_) -> + emqx_ctl:usage([{"mqtt-user add ", "Add user"}, + {"mqtt-user update ", "Update user"}, + {"mqtt-user delete ", "Delete user"}, + {"mqtt-user show ", "Lookup user detail"}, + {"mqtt-user list", "List all users"}]). + +%% Acl +acl_cli(["add", Login, Topic, Action, Allow]) -> + case add_acl(iolist_to_binary(Login), iolist_to_binary(Topic), iolist_to_binary(Action), Allow) of + ok -> emqx_ctl:print("ok~n"); + {error, Reason} -> emqx_ctl:print("Error: ~p~n", [Reason]) + end; + +acl_cli(["del", Login, Topic])-> + case remove_acl(iolist_to_binary(Login), iolist_to_binary(Topic)) of + ok -> emqx_ctl:print("ok~n"); + {error, Reason} -> emqx_ctl:print("Error: ~p~n", [Reason]) + end; + +acl_cli(["show", P]) -> + [emqx_ctl:print("Acl(login = ~p topic = ~p action = ~p allow = ~p)~n",[Login, Topic, Action, Allow]) + || {_, Login, Topic, Action, Allow} <- lookup_acl(iolist_to_binary(P)) ]; + +acl_cli(["list"]) -> + [emqx_ctl:print("Acl(login = ~p)~n",[E]) + || E <- all_acls() ]; + +acl_cli(_) -> + emqx_ctl:usage([{"mqtt-acl add ", "Add acl"}, + {"mqtt-acl show ", "Lookup acl detail"}, + {"mqtt-acl del ", "Delete acl"}, + {"mqtt-acl list","List all acls"}]). diff --git a/apps/emqx_auth_mnesia/src/emqx_auth_mnesia_sup.erl b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia_sup.erl new file mode 100644 index 000000000..ed32b31e7 --- /dev/null +++ b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia_sup.erl @@ -0,0 +1,36 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_mnesia_sup). + +-behaviour(supervisor). + +-include("emqx_auth_mnesia.hrl"). + +-export([start_link/0]). + +%% Supervisor callbacks +-export([init/1]). + +start_link() -> + supervisor:start_link({local, ?MODULE}, ?MODULE, []). + +%%-------------------------------------------------------------------- +%% Supervisor callbacks +%%-------------------------------------------------------------------- + +init([]) -> + {ok, {{one_for_one, 10, 100}, []}}. \ No newline at end of file diff --git a/apps/emqx_auth_mnesia/test/emqx_acl_mnesia_SUITE.erl b/apps/emqx_auth_mnesia/test/emqx_acl_mnesia_SUITE.erl new file mode 100644 index 000000000..11cfca521 --- /dev/null +++ b/apps/emqx_auth_mnesia/test/emqx_acl_mnesia_SUITE.erl @@ -0,0 +1,279 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_acl_mnesia_SUITE). + +-compile(export_all). + +-include("emqx_auth_mnesia.hrl"). +-include_lib("eunit/include/eunit.hrl"). +-include_lib("common_test/include/ct.hrl"). + +-import(emqx_ct_http, [ request_api/3 + , request_api/5 + , get_http_data/1 + , create_default_app/0 + , default_auth_header/0 + ]). + +-define(HOST, "http://127.0.0.1:8081/"). +-define(API_VERSION, "v4"). +-define(BASE_PATH, "api"). + +all() -> + emqx_ct:all(?MODULE). + +groups() -> + []. + +init_per_suite(Config) -> + emqx_ct_helpers:start_apps([emqx_management, emqx_auth_mnesia], fun set_special_configs/1), + create_default_app(), + Config. + +end_per_suite(_Config) -> + emqx_ct_helpers:stop_apps([emqx_management, emqx_auth_mnesia]). + +init_per_testcase(t_check_acl_as_clientid, Config) -> + emqx:hook('client.check_acl', fun emqx_acl_mnesia:check_acl/5, [#{key_as => clientid}]), + Config; + +init_per_testcase(_, Config) -> + emqx:hook('client.check_acl', fun emqx_acl_mnesia:check_acl/5, [#{key_as => username}]), + Config. + +end_per_testcase(_, Config) -> + emqx:unhook('client.check_acl', fun emqx_acl_mnesia:check_acl/5), + Config. + +set_special_configs(emqx) -> + application:set_env(emqx, allow_anonymous, true), + application:set_env(emqx, enable_acl_cache, false), + LoadedPluginPath = filename:join(["test", "emqx_SUITE_data", "loaded_plugins"]), + application:set_env(emqx, plugins_loaded_file, + emqx_ct_helpers:deps_path(emqx, LoadedPluginPath)); + +set_special_configs(_App) -> + ok. + +%%------------------------------------------------------------------------------ +%% Testcases +%%------------------------------------------------------------------------------ + +t_management(_Config) -> + clean_all_acls(), + ?assertEqual("Acl with Mnesia", emqx_acl_mnesia:description()), + ?assertEqual([], emqx_auth_mnesia_cli:all_acls()), + + ok = emqx_auth_mnesia_cli:add_acl(<<"test_username">>, <<"Topic/A">>, <<"sub">>, true), + ok = emqx_auth_mnesia_cli:add_acl(<<"test_username">>, <<"Topic/B">>, <<"pub">>, true), + ok = emqx_auth_mnesia_cli:add_acl(<<"test_username">>, <<"Topic/C">>, <<"pubsub">>, true), + + ?assertEqual([{emqx_acl,<<"test_username">>,<<"Topic/A">>,<<"sub">>, true}, + {emqx_acl,<<"test_username">>,<<"Topic/B">>,<<"pub">>, true}, + {emqx_acl,<<"test_username">>,<<"Topic/C">>,<<"pubsub">>, true}],emqx_auth_mnesia_cli:lookup_acl(<<"test_username">>)), + ok = emqx_auth_mnesia_cli:remove_acl(<<"test_username">>, <<"Topic/A">>), + ?assertEqual([{emqx_acl,<<"test_username">>,<<"Topic/B">>,<<"pub">>, true}, + {emqx_acl,<<"test_username">>,<<"Topic/C">>,<<"pubsub">>, true}], emqx_auth_mnesia_cli:lookup_acl(<<"test_username">>)), + + + ok = emqx_auth_mnesia_cli:add_acl(<<"$all">>, <<"Topic/A">>, <<"sub">>, true), + ok = emqx_auth_mnesia_cli:add_acl(<<"$all">>, <<"Topic/B">>, <<"pub">>, true), + ok = emqx_auth_mnesia_cli:add_acl(<<"$all">>, <<"Topic/C">>, <<"pubsub">>, true), + + ?assertEqual([{emqx_acl,<<"$all">>,<<"Topic/A">>,<<"sub">>, true}, + {emqx_acl,<<"$all">>,<<"Topic/B">>,<<"pub">>, true}, + {emqx_acl,<<"$all">>,<<"Topic/C">>,<<"pubsub">>, true}],emqx_auth_mnesia_cli:lookup_acl(<<"$all">>)), + ok = emqx_auth_mnesia_cli:remove_acl(<<"$all">>, <<"Topic/A">>), + ?assertEqual([{emqx_acl,<<"$all">>,<<"Topic/B">>,<<"pub">>, true}, + {emqx_acl,<<"$all">>,<<"Topic/C">>,<<"pubsub">>, true}], emqx_auth_mnesia_cli:lookup_acl(<<"$all">>)). + +t_check_acl_as_clientid(_) -> + clean_all_acls(), + emqx_modules:load_module(emqx_mod_acl_internal, false), + + User1 = #{zone => external, clientid => <<"test_clientid">>}, + User2 = #{zone => external, clientid => <<"no_exist">>}, + + ok = emqx_auth_mnesia_cli:add_acl(<<"test_clientid">>, <<"#">>, <<"sub">>, false), + ok = emqx_auth_mnesia_cli:add_acl(<<"test_clientid">>, <<"+/A">>, <<"pub">>, false), + ok = emqx_auth_mnesia_cli:add_acl(<<"test_clientid">>, <<"Topic/A/B">>, <<"pubsub">>, true), + + deny = emqx_access_control:check_acl(User1, subscribe, <<"Any">>), + deny = emqx_access_control:check_acl(User1, publish, <<"Any/A">>), + allow = emqx_access_control:check_acl(User1, publish, <<"Any/C">>), + allow = emqx_access_control:check_acl(User1, publish, <<"Topic/A/B">>), + + allow = emqx_access_control:check_acl(User2, subscribe, <<"Topic/C">>), + allow = emqx_access_control:check_acl(User2, publish, <<"Topic/D">>). + +t_check_acl_as_username(_Config) -> + clean_all_acls(), + emqx_modules:load_module(emqx_mod_acl_internal, false), + + User1 = #{zone => external, username => <<"test_username">>}, + User2 = #{zone => external, username => <<"no_exist">>}, + + ok = emqx_auth_mnesia_cli:add_acl(<<"test_username">>, <<"Topic/A">>, <<"sub">>, true), + ok = emqx_auth_mnesia_cli:add_acl(<<"test_username">>, <<"Topic/B">>, <<"pub">>, true), + ok = emqx_auth_mnesia_cli:add_acl(<<"test_username">>, <<"Topic/A/B">>, <<"pubsub">>, false), + allow = emqx_access_control:check_acl(User1, subscribe, <<"Topic/A">>), + allow = emqx_access_control:check_acl(User1, subscribe, <<"Topic/B">>), + deny = emqx_access_control:check_acl(User1, subscribe, <<"Topic/A/B">>), + allow = emqx_access_control:check_acl(User1, publish, <<"Topic/A">>), + allow = emqx_access_control:check_acl(User1, publish, <<"Topic/B">>), + deny = emqx_access_control:check_acl(User1, publish, <<"Topic/A/B">>), + + allow = emqx_access_control:check_acl(User2, subscribe, <<"Topic/C">>), + allow = emqx_access_control:check_acl(User2, publish, <<"Topic/D">>). + +t_check_acl_as_all(_) -> + clean_all_acls(), + emqx_modules:load_module(emqx_mod_acl_internal, false), + + ok = emqx_auth_mnesia_cli:add_acl(<<"$all">>, <<"Topic/A">>, <<"sub">>, false), + ok = emqx_auth_mnesia_cli:add_acl(<<"$all">>, <<"Topic/B">>, <<"pub">>, false), + ok = emqx_auth_mnesia_cli:add_acl(<<"$all">>, <<"Topic/A/B">>, <<"pubsub">>, true), + + User1 = #{zone => external, username => <<"test_username">>}, + User2 = #{zone => external, username => <<"no_exist">>}, + + ok = emqx_auth_mnesia_cli:add_acl(<<"test_username">>, <<"Topic/A">>, <<"sub">>, true), + ok = emqx_auth_mnesia_cli:add_acl(<<"test_username">>, <<"Topic/B">>, <<"pub">>, true), + ok = emqx_auth_mnesia_cli:add_acl(<<"test_username">>, <<"Topic/A/B">>, <<"pubsub">>, false), + + allow = emqx_access_control:check_acl(User1, subscribe, <<"Topic/A">>), + allow = emqx_access_control:check_acl(User1, subscribe, <<"Topic/B">>), + deny = emqx_access_control:check_acl(User1, subscribe, <<"Topic/A/B">>), + allow = emqx_access_control:check_acl(User1, publish, <<"Topic/A">>), + allow = emqx_access_control:check_acl(User1, publish, <<"Topic/B">>), + deny = emqx_access_control:check_acl(User1, publish, <<"Topic/A/B">>), + + deny = emqx_access_control:check_acl(User2, subscribe, <<"Topic/A">>), + deny = emqx_access_control:check_acl(User2, publish, <<"Topic/B">>), + allow = emqx_access_control:check_acl(User2, subscribe, <<"Topic/A/B">>), + allow = emqx_access_control:check_acl(User2, publish, <<"Topic/A/B">>), + allow = emqx_access_control:check_acl(User2, subscribe, <<"Topic/C">>), + allow = emqx_access_control:check_acl(User2, publish, <<"Topic/D">>). + +t_rest_api(_Config) -> + clean_all_acls(), + + {ok, Result} = request_http_rest_list(), + [] = get_http_data(Result), + + Params = #{<<"login">> => <<"test_username">>, <<"topic">> => <<"Topic/A">>, <<"action">> => <<"pubsub">>, <<"allow">> => true}, + {ok, _} = request_http_rest_add(Params), + {ok, Result1} = request_http_rest_lookup(<<"test_username">>), + #{<<"login">> := <<"test_username">>, <<"topic">> := <<"Topic/A">>, <<"action">> := <<"pubsub">>, <<"allow">> := true} = get_http_data(Result1), + + Params1 = [ + #{<<"login">> => <<"$all">>, <<"topic">> => <<"+/A">>, <<"action">> => <<"pub">>, <<"allow">> => true}, + #{<<"login">> => <<"test_username">>, <<"topic">> => <<"+/A">>, <<"action">> => <<"pub">>, <<"allow">> => true}, + #{<<"login">> => <<"test_username/1">>, <<"topic">> => <<"#">>, <<"action">> => <<"sub">>, <<"allow">> => true}, + #{<<"login">> => <<"test_username/2">>, <<"topic">> => <<"+/A">>, <<"action">> => <<"error_format">>, <<"allow">> => true} + ], + {ok, Result2} = request_http_rest_add(Params1), + #{ + <<"$all">> := <<"ok">>, + <<"test_username">> := <<"ok">>, + <<"test_username/1">> := <<"ok">>, + <<"test_username/2">> := <<"{error,action}">> + } = get_http_data(Result2), + + {ok, Result3} = request_http_rest_lookup(<<"test_username">>), + [#{<<"login">> := <<"test_username">>, <<"topic">> := <<"+/A">>, <<"action">> := <<"pub">>, <<"allow">> := true}, + #{<<"login">> := <<"test_username">>, <<"topic">> := <<"Topic/A">>, <<"action">> := <<"pubsub">>, <<"allow">> := true}] + = get_http_data(Result3), + + {ok, Result4} = request_http_rest_lookup(<<"$all">>), + #{<<"login">> := <<"$all">>, <<"topic">> := <<"+/A">>, <<"action">> := <<"pub">>, <<"allow">> := true} + = get_http_data(Result4), + + {ok, _} = request_http_rest_delete(<<"$all">>, <<"+/A">>), + {ok, _} = request_http_rest_delete(<<"test_username">>, <<"+/A">>), + {ok, _} = request_http_rest_delete(<<"test_username">>, <<"Topic/A">>), + {ok, _} = request_http_rest_delete(<<"test_username/1">>, <<"#">>), + {ok, Result5} = request_http_rest_list(), + [] = get_http_data(Result5). + + +t_run_command(_) -> + clean_all_acls(), + ?assertEqual(ok, emqx_ctl:run_command(["mqtt-acl", "add", "TestUser", "Topic/A", "sub", true])), + ?assertEqual([{emqx_acl,<<"TestUser">>,<<"Topic/A">>,<<"sub">>, true}],emqx_auth_mnesia_cli:lookup_acl(<<"TestUser">>)), + + ?assertEqual(ok, emqx_ctl:run_command(["mqtt-acl", "del", "TestUser", "Topic/A"])), + ?assertEqual([],emqx_auth_mnesia_cli:lookup_acl(<<"TestUser">>)), + + ?assertEqual(ok, emqx_ctl:run_command(["mqtt-acl", "show", "TestUser"])), + ?assertEqual(ok, emqx_ctl:run_command(["mqtt-acl", "list"])), + ?assertEqual(ok, emqx_ctl:run_command(["mqtt-acl"])). + +t_cli(_) -> + meck:new(emqx_ctl, [non_strict, passthrough]), + meck:expect(emqx_ctl, print, fun(Arg) -> emqx_ctl:format(Arg) end), + meck:expect(emqx_ctl, print, fun(Msg, Arg) -> emqx_ctl:format(Msg, Arg) end), + meck:expect(emqx_ctl, usage, fun(Usages) -> emqx_ctl:format_usage(Usages) end), + meck:expect(emqx_ctl, usage, fun(Cmd, Descr) -> emqx_ctl:format_usage(Cmd, Descr) end), + + clean_all_acls(), + ?assertMatch({match, _}, re:run(emqx_auth_mnesia_cli:acl_cli(["add", "TestUser", "Topic/A", "sub", true]), "ok")), + ?assertMatch(["Acl(login = <<\"TestUser\">> topic = <<\"Topic/A\">> action = <<\"sub\">> allow = true)\n"], emqx_auth_mnesia_cli:acl_cli(["show", "TestUser"])), + ?assertMatch(["Acl(login = <<\"TestUser\">>)\n"], emqx_auth_mnesia_cli:acl_cli(["list"])), + + ?assertMatch({match, _}, re:run(emqx_auth_mnesia_cli:acl_cli(["del", "TestUser", "Topic/A"]), "ok")), + ?assertMatch([], emqx_auth_mnesia_cli:acl_cli(["show", "TestUser"])), + ?assertMatch([], emqx_auth_mnesia_cli:acl_cli(["list"])), + + ?assertMatch({match, _}, re:run(emqx_auth_mnesia_cli:acl_cli([]), "mqtt-acl")), + + meck:unload(emqx_ctl). + +%%------------------------------------------------------------------------------ +%% Helpers +%%------------------------------------------------------------------------------ + +clean_all_acls() -> + [ mnesia:dirty_delete({emqx_acl, Login}) + || Login <- mnesia:dirty_all_keys(emqx_acl)]. + +%%-------------------------------------------------------------------- +%% HTTP Request +%%-------------------------------------------------------------------- + +request_http_rest_list() -> + request_api(get, uri(), default_auth_header()). + +request_http_rest_lookup(Login) -> + request_api(get, uri([Login]), default_auth_header()). + +request_http_rest_add(Params) -> + request_api(post, uri(), [], default_auth_header(), Params). + +request_http_rest_delete(Login, Topic) -> + request_api(delete, uri([Login, Topic]), default_auth_header()). + +uri() -> uri([]). +uri(Parts) when is_list(Parts) -> + NParts = [b2l(E) || E <- Parts], + ?HOST ++ filename:join([?BASE_PATH, ?API_VERSION, "mqtt_acl"| NParts]). + +%% @private +b2l(B) when is_binary(B) -> + http_uri:encode(binary_to_list(B)); +b2l(L) when is_list(L) -> + http_uri:encode(L). diff --git a/apps/emqx_auth_mnesia/test/emqx_auth_mnesia_SUITE.erl b/apps/emqx_auth_mnesia/test/emqx_auth_mnesia_SUITE.erl new file mode 100644 index 000000000..8979f4755 --- /dev/null +++ b/apps/emqx_auth_mnesia/test/emqx_auth_mnesia_SUITE.erl @@ -0,0 +1,259 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_mnesia_SUITE). + +-compile(export_all). + +-include("emqx_auth_mnesia.hrl"). +-include_lib("eunit/include/eunit.hrl"). +-include_lib("common_test/include/ct.hrl"). + +-import(emqx_ct_http, [ request_api/3 + , request_api/5 + , get_http_data/1 + , create_default_app/0 + , default_auth_header/0 + ]). + +-define(HOST, "http://127.0.0.1:8081/"). +-define(API_VERSION, "v4"). +-define(BASE_PATH, "api"). + +all() -> + emqx_ct:all(?MODULE). + +groups() -> + []. + +init_per_suite(Config) -> + ok = emqx_ct_helpers:start_apps([emqx_management, emqx_auth_mnesia], fun set_special_configs/1), + create_default_app(), + Config. + +end_per_suite(_Config) -> + emqx_ct_helpers:stop_apps([emqx_management, emqx_auth_mnesia]). + +init_per_testcase(t_check_as_clientid, Config) -> + Params = #{ + hash_type => application:get_env(emqx_auth_mnesia, hash_type, sha256), + key_as => clientid + }, + emqx:hook('client.authenticate', fun emqx_auth_mnesia:check/3, [Params]), + Config; + +init_per_testcase(_, Config) -> + Params = #{ + hash_type => application:get_env(emqx_auth_mnesia, hash_type, sha256), + key_as => username + }, + emqx:hook('client.authenticate', fun emqx_auth_mnesia:check/3, [Params]), + Config. + +end_per_suite(_, Config) -> + emqx:unhook('client.authenticate', fun emqx_auth_mnesia:check/3), + Config. + +set_special_configs(emqx) -> + application:set_env(emqx, allow_anonymous, true), + application:set_env(emqx, enable_acl_cache, false), + LoadedPluginPath = filename:join(["test", "emqx_SUITE_data", "loaded_plugins"]), + application:set_env(emqx, plugins_loaded_file, + emqx_ct_helpers:deps_path(emqx, LoadedPluginPath)); + +set_special_configs(_App) -> + ok. + +%%------------------------------------------------------------------------------ +%% Testcases +%%------------------------------------------------------------------------------ + +t_check_as_username(_Config) -> + clean_all_users(), + + ok = emqx_auth_mnesia_cli:add_user(<<"test_username">>, <<"password">>, true), + {error, existed} = emqx_auth_mnesia_cli:add_user(<<"test_username">>, <<"password">>, true), + + ok = emqx_auth_mnesia_cli:update_user(<<"test_username">>, <<"new_password">>, false), + {error,noexisted} = emqx_auth_mnesia_cli:update_user(<<"no_existed_user">>, <<"password">>, true), + + [<<"test_username">>] = emqx_auth_mnesia_cli:all_users(), + [{emqx_user, <<"test_username">>, _HashedPass, false}] = + emqx_auth_mnesia_cli:lookup_user(<<"test_username">>), + + User1 = #{username => <<"test_username">>, + password => <<"new_password">>, + zone => external}, + + {ok, #{is_superuser := false, + auth_result := success, + anonymous := false}} = emqx_access_control:authenticate(User1), + + {error,password_error} = emqx_access_control:authenticate(User1#{password => <<"error_password">>}), + + ok = emqx_auth_mnesia_cli:remove_user(<<"test_username">>), + {ok, #{auth_result := success, + anonymous := true }} = emqx_access_control:authenticate(User1). + +t_check_as_clientid(_Config) -> + clean_all_users(), + + ok = emqx_auth_mnesia_cli:add_user(<<"test_clientid">>, <<"password">>, false), + {error, existed} = emqx_auth_mnesia_cli:add_user(<<"test_clientid">>, <<"password">>, false), + + ok = emqx_auth_mnesia_cli:update_user(<<"test_clientid">>, <<"new_password">>, true), + {error,noexisted} = emqx_auth_mnesia_cli:update_user(<<"no_existed_user">>, <<"password">>, true), + + [<<"test_clientid">>] = emqx_auth_mnesia_cli:all_users(), + [{emqx_user, <<"test_clientid">>, _HashedPass, true}] = + emqx_auth_mnesia_cli:lookup_user(<<"test_clientid">>), + + User1 = #{clientid => <<"test_clientid">>, + password => <<"new_password">>, + zone => external}, + + {ok, #{is_superuser := true, + auth_result := success, + anonymous := false}} = emqx_access_control:authenticate(User1), + + {error,password_error} = emqx_access_control:authenticate(User1#{password => <<"error_password">>}), + + ok = emqx_auth_mnesia_cli:remove_user(<<"test_clientid">>), + {ok, #{auth_result := success, + anonymous := true }} = emqx_access_control:authenticate(User1). + +t_rest_api(_Config) -> + clean_all_users(), + + {ok, Result1} = request_http_rest_list(), + [] = get_http_data(Result1), + + Params = #{<<"login">> => <<"test_username">>, <<"password">> => <<"password">>, <<"is_superuser">> => true}, + {ok, _} = request_http_rest_add(Params), + + Params1 = [ + #{<<"login">> => <<"test_username">>, <<"password">> => <<"password">>, <<"is_superuser">> => true}, + #{<<"login">> => <<"test_username/1">>, <<"password">> => <<"password">>, <<"is_superuser">> => error_format}, + #{<<"login">> => <<"test_username/2">>, <<"password">> => <<"password">>, <<"is_superuser">> => true} + ], + {ok, Result2} = request_http_rest_add(Params1), + #{ + <<"test_username">> := <<"{error,existed}">>, + <<"test_username/1">> := <<"{error,is_superuser}">>, + <<"test_username/2">> := <<"ok">> + } = get_http_data(Result2), + + {ok, Result3} = request_http_rest_lookup(<<"test_username">>), + #{<<"login">> := <<"test_username">>, <<"is_superuser">> := true} = get_http_data(Result3), + + {ok, _} = request_http_rest_update(<<"test_username">>, <<"new_password">>, error_format), + {ok, _} = request_http_rest_update(<<"error_username">>, <<"new_password">>, false), + + {ok, _} = request_http_rest_update(<<"test_username">>, <<"new_password">>, false), + {ok, Result4} = request_http_rest_lookup(<<"test_username">>), + #{<<"login">> := <<"test_username">>, <<"is_superuser">> := false} = get_http_data(Result4), + + User1 = #{username => <<"test_username">>, + password => <<"new_password">>, + zone => external}, + + {ok, #{is_superuser := false, + auth_result := success, + anonymous := false}} = emqx_access_control:authenticate(User1), + + {ok, _} = request_http_rest_delete(<<"test_username">>), + {ok, #{auth_result := success, + anonymous := true }} = emqx_access_control:authenticate(User1). + +t_run_command(_) -> + clean_all_users(), + ?assertEqual(ok, emqx_ctl:run_command(["mqtt-user", "add", "TestUser", "Password", false])), + ?assertMatch([{emqx_user, <<"TestUser">>, _, false}], emqx_auth_mnesia_cli:lookup_user(<<"TestUser">>)), + + ?assertEqual(ok, emqx_ctl:run_command(["mqtt-user", "update", "TestUser", "NewPassword", true])), + ?assertMatch([{emqx_user, <<"TestUser">>, _, true}], emqx_auth_mnesia_cli:lookup_user(<<"TestUser">>)), + + ?assertEqual(ok, emqx_ctl:run_command(["mqtt-user", "del", "TestUser"])), + ?assertMatch([], emqx_auth_mnesia_cli:lookup_user(<<"TestUser">>)), + + ?assertEqual(ok, emqx_ctl:run_command(["mqtt-user", "show", "TestUser"])), + ?assertEqual(ok, emqx_ctl:run_command(["mqtt-user", "list"])), + ?assertEqual(ok, emqx_ctl:run_command(["mqtt-user"])). + +t_cli(_) -> + meck:new(emqx_ctl, [non_strict, passthrough]), + meck:expect(emqx_ctl, print, fun(Arg) -> emqx_ctl:format(Arg) end), + meck:expect(emqx_ctl, print, fun(Msg, Arg) -> emqx_ctl:format(Msg, Arg) end), + meck:expect(emqx_ctl, usage, fun(Usages) -> emqx_ctl:format_usage(Usages) end), + meck:expect(emqx_ctl, usage, fun(Cmd, Descr) -> emqx_ctl:format_usage(Cmd, Descr) end), + + clean_all_users(), + + ?assertMatch({match, _}, re:run(emqx_auth_mnesia_cli:auth_cli(["add", "TestUser", "Password", true]), "ok")), + ?assertMatch({match, _}, re:run(emqx_auth_mnesia_cli:auth_cli(["add", "TestUser", "Password", true]), "Error")), + + ?assertMatch({match, _}, re:run(emqx_auth_mnesia_cli:auth_cli(["update", "NoExisted", "Password", false]), "Error")), + ?assertMatch({match, _}, re:run(emqx_auth_mnesia_cli:auth_cli(["update", "TestUser", "Password", false]), "ok")), + + ?assertMatch(["User(login = <<\"TestUser\">> is_super = false)\n"], emqx_auth_mnesia_cli:auth_cli(["show", "TestUser"])), + ?assertMatch(["User(login = <<\"TestUser\">>)\n"], emqx_auth_mnesia_cli:auth_cli(["list"])), + + ?assertMatch({match, _}, re:run(emqx_auth_mnesia_cli:auth_cli(["del", "TestUser"]), "ok")), + ?assertMatch([], emqx_auth_mnesia_cli:auth_cli(["show", "TestUser"])), + ?assertMatch([], emqx_auth_mnesia_cli:auth_cli(["list"])), + + ?assertMatch({match, _}, re:run(emqx_auth_mnesia_cli:auth_cli([]), "mqtt-user")), + + meck:unload(emqx_ctl). + +%%------------------------------------------------------------------------------ +%% Helpers +%%------------------------------------------------------------------------------ + +clean_all_users() -> + [ mnesia:dirty_delete({emqx_user, Login}) + || Login <- mnesia:dirty_all_keys(emqx_user)]. + +%%-------------------------------------------------------------------- +%% HTTP Request +%%-------------------------------------------------------------------- + +request_http_rest_list() -> + request_api(get, uri(), default_auth_header()). + +request_http_rest_lookup(Login) -> + request_api(get, uri([Login]), default_auth_header()). + +request_http_rest_add(Params) -> + request_api(post, uri(), [], default_auth_header(), Params). + +request_http_rest_update(Login, Password, IsSuperuser) -> + Params = #{<<"password">> => Password, <<"is_superuser">> => IsSuperuser}, + request_api(put, uri([Login]), [], default_auth_header(), Params). + +request_http_rest_delete(Login) -> + request_api(delete, uri([Login]), default_auth_header()). + +uri() -> uri([]). +uri(Parts) when is_list(Parts) -> + NParts = [b2l(E) || E <- Parts], + ?HOST ++ filename:join([?BASE_PATH, ?API_VERSION, "mqtt_user"| NParts]). + +%% @private +b2l(B) when is_binary(B) -> + binary_to_list(B); +b2l(L) when is_list(L) -> + L. diff --git a/apps/emqx_auth_mongo/CHANGES b/apps/emqx_auth_mongo/CHANGES new file mode 100644 index 000000000..4bddd63a9 --- /dev/null +++ b/apps/emqx_auth_mongo/CHANGES @@ -0,0 +1,31 @@ + +2.0.7 (2017-01-20) +------------------ + +Tag 2.0.7 - use `cuttlefish:unset()` for commented ACL/super config + +2.0.1 (2016-11-30) +------------------ + +Tag 2.0.1 + +2.0-beta.1 (2016-08-24) +----------------------- + +gen_conf + +1.1.3-beta (2016-08-19) +----------------------- + +Bump version to 1.1.3 + +1.1.2-beta (2016-06-30) +----------------------- + +Bump version to 1.1.2 + +1.1-beta (2016-05-28) +--------------------- + +First public release + diff --git a/apps/emqx_auth_mongo/README.md b/apps/emqx_auth_mongo/README.md new file mode 100644 index 000000000..3bacfca5b --- /dev/null +++ b/apps/emqx_auth_mongo/README.md @@ -0,0 +1,192 @@ +emqx_auth_mongo +=============== + +EMQ X Authentication/ACL with MongoDB + +Build the Plugin +---------------- + +``` +make & make tests +``` + +Configuration +------------- + +File: etc/emqx_auth_mongo.conf + +``` +## MongoDB Topology Type. +## +## Value: single | unknown | sharded | rs +auth.mongo.type = single + +## Sets the set name if type is rs. +## +## Value: String +## auth.mongo.rs_set_name = + +## MongoDB server list. +## +## Value: String +## +## Examples: 127.0.0.1:27017,127.0.0.2:27017... +auth.mongo.server = 127.0.0.1:27017 + +## MongoDB pool size +## +## Value: Number +auth.mongo.pool = 8 + +## MongoDB login user. +## +## Value: String +## auth.mongo.login = + +## MongoDB password. +## +## Value: String +## auth.mongo.password = + +## MongoDB AuthSource +## +## Value: String +## Default: mqtt +## auth.mongo.auth_source = admin + +## MongoDB database +## +## Value: String +auth.mongo.database = mqtt + +## MongoDB write mode. +## +## Value: unsafe | safe +## auth.mongo.w_mode = + +## Mongo read mode. +## +## Value: master | slave_ok +## auth.mongo.r_mode = + +## MongoDB topology options. +auth.mongo.topology.pool_size = 1 +auth.mongo.topology.max_overflow = 0 +## auth.mongo.topology.overflow_ttl = 1000 +## auth.mongo.topology.overflow_check_period = 1000 +## auth.mongo.topology.local_threshold_ms = 1000 +## auth.mongo.topology.connect_timeout_ms = 20000 +## auth.mongo.topology.socket_timeout_ms = 100 +## auth.mongo.topology.server_selection_timeout_ms = 30000 +## auth.mongo.topology.wait_queue_timeout_ms = 1000 +## auth.mongo.topology.heartbeat_frequency_ms = 10000 +## auth.mongo.topology.min_heartbeat_frequency_ms = 1000 + +## Authentication query. +auth.mongo.auth_query.collection = mqtt_user + +auth.mongo.auth_query.password_field = password + +## Password hash. +## +## Value: plain | md5 | sha | sha256 | bcrypt +auth.mongo.auth_query.password_hash = sha256 + +## sha256 with salt suffix +## auth.mongo.auth_query.password_hash = sha256,salt + +## sha256 with salt prefix +## auth.mongo.auth_query.password_hash = salt,sha256 + +## bcrypt with salt prefix +## auth.mongo.auth_query.password_hash = salt,bcrypt + +## pbkdf2 with macfun iterations dklen +## macfun: md4, md5, ripemd160, sha, sha224, sha256, sha384, sha512 +## auth.mongo.auth_query.password_hash = pbkdf2,sha256,1000,20 + +auth.mongo.auth_query.selector = username=%u + +## Enable superuser query. +auth.mongo.super_query = on + +auth.mongo.super_query.collection = mqtt_user + +auth.mongo.super_query.super_field = is_superuser + +auth.mongo.super_query.selector = username=%u + +## Enable ACL query. +auth.mongo.acl_query = on + +auth.mongo.acl_query.collection = mqtt_acl + +auth.mongo.acl_query.selector = username=%u +``` + +Load the Plugin +--------------- + +``` +./bin/emqx_ctl plugins load emqx_auth_mongo +``` + +MongoDB Database +---------------- + +``` +use mqtt +db.createCollection("mqtt_user") +db.createCollection("mqtt_acl") +db.mqtt_user.ensureIndex({"username":1}) +``` + +mqtt_user Collection +-------------------- + +``` +{ + username: "user", + password: "password hash", + salt: "password salt", + is_superuser: boolean (true, false), + created: "datetime" +} +``` + +For example: +``` +db.mqtt_user.insert({username: "test", password: "password hash", salt: "password salt", is_superuser: false}) +db.mqtt_user.insert({username: "root", is_superuser: true}) +``` + +mqtt_acl Collection +------------------- + +``` +{ + username: "username", + clientid: "clientid", + publish: ["topic1", "topic2", ...], + subscribe: ["subtop1", "subtop2", ...], + pubsub: ["topic/#", "topic1", ...] +} +``` + +For example: + +``` +db.mqtt_acl.insert({username: "test", publish: ["t/1", "t/2"], subscribe: ["user/%u", "client/%c"]}) +db.mqtt_acl.insert({username: "admin", pubsub: ["#"]}) +``` + +License +------- + +Apache License Version 2.0 + +Author +------ + +EMQ X Team. + diff --git a/apps/emqx_auth_mongo/docker-compose-ssl.yml b/apps/emqx_auth_mongo/docker-compose-ssl.yml new file mode 100644 index 000000000..7af0981b1 --- /dev/null +++ b/apps/emqx_auth_mongo/docker-compose-ssl.yml @@ -0,0 +1,31 @@ +version: '3' + +services: + erlang: + image: erlang:22.1 + volumes: + - ./:/emqx_auth_mongo + networks: + - emqx_bridge + depends_on: + - mongo_server + tty: true + + mongo_server: + image: mongo:${MONGO_TAG} + restart: always + environment: + MONGO_INITDB_DATABASE: mqtt + volumes: + - ./test/emqx_auth_mongo_SUITE_data/mongodb.pem/:/etc/certs/mongodb.pem + networks: + - emqx_bridge + command: + --ipv6 + --bind_ip_all + --sslMode requireSSL + --sslPEMKeyFile /etc/certs/mongodb.pem + +networks: + emqx_bridge: + driver: bridge diff --git a/apps/emqx_auth_mongo/docker-compose.yml b/apps/emqx_auth_mongo/docker-compose.yml new file mode 100644 index 000000000..9ff9cce23 --- /dev/null +++ b/apps/emqx_auth_mongo/docker-compose.yml @@ -0,0 +1,27 @@ +version: '3' + +services: + erlang: + image: erlang:22.1 + volumes: + - ./:/emqx_auth_mongo + networks: + - emqx_bridge + depends_on: + - mongo_server + tty: true + + mongo_server: + image: mongo:${MONGO_TAG} + restart: always + environment: + MONGO_INITDB_DATABASE: mqtt + networks: + - emqx_bridge + command: + --ipv6 + --bind_ip_all + +networks: + emqx_bridge: + driver: bridge diff --git a/apps/emqx_auth_mongo/include/emqx_auth_mongo.hrl b/apps/emqx_auth_mongo/include/emqx_auth_mongo.hrl new file mode 100644 index 000000000..97ecf9973 --- /dev/null +++ b/apps/emqx_auth_mongo/include/emqx_auth_mongo.hrl @@ -0,0 +1,37 @@ + +-define(APP, emqx_auth_mongo). + +-define(DEFAULT_SELECTORS, [{<<"username">>, <<"%u">>}]). + +-record(superquery, {collection = <<"mqtt_user">>, + field = <<"is_superuser">>, + selector = {<<"username">>, <<"%u">>}}). + +-record(authquery, {collection = <<"mqtt_user">>, + field = <<"password">>, + hash = sha256, + selector = {<<"username">>, <<"%u">>}}). + +-record(aclquery, {collection = <<"mqtt_acl">>, + selector = {<<"username">>, <<"%u">>}}). + +-record(auth_metrics, { + success = 'client.auth.success', + failure = 'client.auth.failure', + ignore = 'client.auth.ignore' + }). + +-record(acl_metrics, { + allow = 'client.acl.allow', + deny = 'client.acl.deny', + ignore = 'client.acl.ignore' + }). + +-define(METRICS(Type), tl(tuple_to_list(#Type{}))). +-define(METRICS(Type, K), #Type{}#Type.K). + +-define(AUTH_METRICS, ?METRICS(auth_metrics)). +-define(AUTH_METRICS(K), ?METRICS(auth_metrics, K)). + +-define(ACL_METRICS, ?METRICS(acl_metrics)). +-define(ACL_METRICS(K), ?METRICS(acl_metrics, K)). diff --git a/apps/emqx_auth_mongo/priv/emqx_auth_mongo.schema b/apps/emqx_auth_mongo/priv/emqx_auth_mongo.schema new file mode 100644 index 000000000..9b331e6c4 --- /dev/null +++ b/apps/emqx_auth_mongo/priv/emqx_auth_mongo.schema @@ -0,0 +1,292 @@ +%%-*- mode: erlang -*- +%% emqx_auth_mongo config mapping + +{mapping, "auth.mongo.type", "emqx_auth_mongo.server", [ + {default, single}, + {datatype, {enum, [single, unknown, sharded, rs]}} +]}. + +{mapping, "auth.mongo.rs_set_name", "emqx_auth_mongo.server", [ + {default, "mqtt"}, + {datatype, string} +]}. + +{mapping, "auth.mongo.server", "emqx_auth_mongo.server", [ + {default, "127.0.0.1:27017"}, + {datatype, string} +]}. + +{mapping, "auth.mongo.pool", "emqx_auth_mongo.server", [ + {default, 8}, + {datatype, integer} +]}. + +{mapping, "auth.mongo.login", "emqx_auth_mongo.server", [ + {default, ""}, + {datatype, string} +]}. + +{mapping, "auth.mongo.password", "emqx_auth_mongo.server", [ + {default, ""}, + {datatype, string} +]}. + +{mapping, "auth.mongo.database", "emqx_auth_mongo.server", [ + {default, "mqtt"}, + {datatype, string} +]}. + +{mapping, "auth.mongo.auth_source", "emqx_auth_mongo.server", [ + {default, "mqtt"}, + {datatype, string} +]}. + +{mapping, "auth.mongo.ssl", "emqx_auth_mongo.server", [ + {default, false}, + {datatype, {enum, [true, false]}} +]}. + +{mapping, "auth.mongo.ssl_opts.keyfile", "emqx_auth_mongo.server", [ + {datatype, string} +]}. + +{mapping, "auth.mongo.ssl_opts.certfile", "emqx_auth_mongo.server", [ + {datatype, string} +]}. + +{mapping, "auth.mongo.ssl_opts.cacertfile", "emqx_auth_mongo.server", [ + {datatype, string} +]}. + +{mapping, "auth.mongo.w_mode", "emqx_auth_mongo.server", [ + {default, undef}, + {datatype, {enum, [safe, unsafe, undef]}} +]}. + +{mapping, "auth.mongo.r_mode", "emqx_auth_mongo.server", [ + {default, undef}, + {datatype, {enum, [master, slave_ok, undef]}} +]}. + +{mapping, "auth.mongo.topology.$name", "emqx_auth_mongo.server", [ + {datatype, integer} +]}. + +{translation, "emqx_auth_mongo.server", fun(Conf) -> + H = cuttlefish:conf_get("auth.mongo.server", Conf), + Hosts = string:tokens(H, ","), + Type0 = cuttlefish:conf_get("auth.mongo.type", Conf), + Pool = cuttlefish:conf_get("auth.mongo.pool", Conf), + Login = cuttlefish:conf_get("auth.mongo.login", Conf), + Passwd = cuttlefish:conf_get("auth.mongo.password", Conf), + DB = cuttlefish:conf_get("auth.mongo.database", Conf), + AuthSrc = cuttlefish:conf_get("auth.mongo.auth_source", Conf), + R = cuttlefish:conf_get("auth.mongo.w_mode", Conf), + W = cuttlefish:conf_get("auth.mongo.r_mode", Conf), + Login0 = case Login =:= [] of + true -> []; + false -> [{login, list_to_binary(Login)}] + end, + Passwd0 = case Passwd =:= [] of + true -> []; + false -> [{password, list_to_binary(Passwd)}] + end, + W0 = case W =:= undef of + true -> []; + false -> [{w_mode, W}] + end, + R0 = case R =:= undef of + true -> []; + false -> [{r_mode, R}] + end, + Ssl = case cuttlefish:conf_get("auth.mongo.ssl", Conf) of + true -> + Filter = fun(Opts) -> [{K, V} || {K, V} <- Opts, V =/= undefined] end, + SslOpts = fun(Prefix) -> + Filter([{keyfile, cuttlefish:conf_get(Prefix ++ ".keyfile", Conf, undefined)}, + {certfile, cuttlefish:conf_get(Prefix ++ ".certfile", Conf, undefined)}, + {cacertfile, cuttlefish:conf_get(Prefix ++ ".cacertfile", Conf, undefined)}]) + end, + [{ssl, true}, {ssl_opts, SslOpts("auth.mongo.ssl_opts")}]; + false -> + [] + end, + WorkerOptions = [{database, list_to_binary(DB)}, {auth_source, list_to_binary(AuthSrc)}] + ++ Login0 ++ Passwd0 ++ W0 ++ R0 ++ Ssl, + + Vars = cuttlefish_variable:fuzzy_matches(["auth", "mongo", "topology", "$name"], Conf), + Options = lists:map(fun({_, Name}) -> + Name2 = case Name of + "local_threshold_ms" -> "localThresholdMS"; + "connect_timeout_ms" -> "connectTimeoutMS"; + "socket_timeout_ms" -> "socketTimeoutMS"; + "server_selection_timeout_ms" -> "serverSelectionTimeoutMS"; + "wait_queue_timeout_ms" -> "waitQueueTimeoutMS"; + "heartbeat_frequency_ms" -> "heartbeatFrequencyMS"; + "min_heartbeat_frequency_ms" -> "minHeartbeatFrequencyMS"; + _ -> Name + end, + {list_to_atom(Name2), cuttlefish:conf_get("auth.mongo.topology."++Name, Conf)} + end, Vars), + + Type = case Type0 =:= rs of + true -> {Type0, list_to_binary(cuttlefish:conf_get("auth.mongo.rs_set_name", Conf))}; + false -> Type0 + end, + [{type, Type}, + {hosts, Hosts}, + {options, Options}, + {worker_options, WorkerOptions}, + {auto_reconnect, 1}, + {pool_size, Pool}] +end}. + +%% The mongodb operation timeout is specified by the value of `cursor_timeout` from application config, +%% or `infinity` if `cursor_timeout` not specified +{mapping, "auth.mongo.query_timeout", "mongodb.cursor_timeout", [ + {datatype, string} +]}. + +{translation, "mongodb.cursor_timeout", fun(Conf) -> + case cuttlefish:conf_get("auth.mongo.query_timeout", Conf, undefined) of + undefined -> infinity; + Duration -> + case cuttlefish_duration:parse(Duration, ms) of + {error, Reason} -> error(Reason); + Ms when is_integer(Ms) -> Ms + end + end +end}. + +{mapping, "auth.mongo.auth_query.collection", "emqx_auth_mongo.auth_query", [ + {default, "mqtt_user"}, + {datatype, string} +]}. + +{mapping, "auth.mongo.auth_query.password_field", "emqx_auth_mongo.auth_query", [ + {default, "password"}, + {datatype, string} +]}. + +{mapping, "auth.mongo.auth_query.password_hash", "emqx_auth_mongo.auth_query", [ + {datatype, string} +]}. + +{mapping, "auth.mongo.auth_query.selector", "emqx_auth_mongo.auth_query", [ + {default, ""}, + {datatype, string} +]}. + +{translation, "emqx_auth_mongo.auth_query", fun(Conf) -> + case cuttlefish:conf_get("auth.mongo.auth_query.collection", Conf) of + undefined -> cuttlefish:unset(); + Collection -> + PasswordField = cuttlefish:conf_get("auth.mongo.auth_query.password_field", Conf), + PasswordHash = cuttlefish:conf_get("auth.mongo.auth_query.password_hash", Conf), + SelectorStr = cuttlefish:conf_get("auth.mongo.auth_query.selector", Conf), + SelectorList = + lists:map(fun(Selector) -> + case string:tokens(Selector, "=") of + [Field, Val] -> {list_to_binary(Field), list_to_binary(Val)}; + _ -> {<<"username">>, <<"%u">>} + end + end, string:tokens(SelectorStr, ", ")), + + PasswordFields = [list_to_binary(Field) || Field <- string:tokens(PasswordField, ",")], + HashValue = + case string:tokens(PasswordHash, ",") of + [Hash] -> list_to_atom(Hash); + [Prefix, Suffix] -> {list_to_atom(Prefix), list_to_atom(Suffix)}; + [Hash, MacFun, Iterations, Dklen] -> {list_to_atom(Hash), list_to_atom(MacFun), list_to_integer(Iterations), list_to_integer(Dklen)}; + _ -> plain + end, + [{collection, Collection}, + {password_field, PasswordFields}, + {password_hash, HashValue}, + {selector, SelectorList}] + end +end}. + +{mapping, "auth.mongo.super_query", "emqx_auth_mongo.super_query", [ + {default, off}, + {datatype, flag} +]}. + +{mapping, "auth.mongo.super_query.collection", "emqx_auth_mongo.super_query", [ + {default, "mqtt_user"}, + {datatype, string} +]}. + +{mapping, "auth.mongo.super_query.super_field", "emqx_auth_mongo.super_query", [ + {default, "is_superuser"}, + {datatype, string} +]}. + +{mapping, "auth.mongo.super_query.selector", "emqx_auth_mongo.super_query", [ + {default, ""}, + {datatype, string} +]}. + +{translation, "emqx_auth_mongo.super_query", fun(Conf) -> + case cuttlefish:conf_get("auth.mongo.super_query.collection", Conf) of + undefined -> cuttlefish:unset(); + Collection -> + SuperField = cuttlefish:conf_get("auth.mongo.super_query.super_field", Conf), + SelectorStr = cuttlefish:conf_get("auth.mongo.super_query.selector", Conf), + SelectorList = + lists:map(fun(Selector) -> + case string:tokens(Selector, "=") of + [Field, Val] -> {list_to_binary(Field), list_to_binary(Val)}; + _ -> {<<"username">>, <<"%u">>} + end + end, string:tokens(SelectorStr, ", ")), + [{collection, Collection}, {super_field, SuperField}, {selector, SelectorList}] + end +end}. + +{mapping, "auth.mongo.acl_query", "emqx_auth_mongo.acl_query", [ + {default, off}, + {datatype, flag} +]}. + +{mapping, "auth.mongo.acl_query.collection", "emqx_auth_mongo.acl_query", [ + {default, "mqtt_user"}, + {datatype, string} +]}. + +{mapping, "auth.mongo.acl_query.selector", "emqx_auth_mongo.acl_query", [ + {default, ""}, + {datatype, string} +]}. +{mapping, "auth.mongo.acl_query.selector.$id", "emqx_auth_mongo.acl_query", [ + {default, ""}, + {datatype, string} +]}. + +{translation, "emqx_auth_mongo.acl_query", fun(Conf) -> + case cuttlefish:conf_get("auth.mongo.acl_query.collection", Conf) of + undefined -> cuttlefish:unset(); + Collection -> + SelectorStrList = + lists:map( + fun + ({["auth","mongo","acl_query","selector"], ConfEntry}) -> + ConfEntry; + ({["auth","mongo","acl_query","selector", _], ConfEntry}) -> + ConfEntry + end, + cuttlefish_variable:filter_by_prefix("auth.mongo.acl_query.selector", Conf)), + SelectorListList = + lists:map( + fun(SelectorStr) -> + lists:map(fun(Selector) -> + case string:tokens(Selector, "=") of + [Field, Val] -> {list_to_binary(Field), list_to_binary(Val)}; + _ -> {<<"username">>, <<"%u">>} + end + end, string:tokens(SelectorStr, ", ")) + end, + SelectorStrList), + [{collection, Collection}, {selector, SelectorListList}] + end +end}. diff --git a/apps/emqx_auth_mongo/rebar.config b/apps/emqx_auth_mongo/rebar.config new file mode 100644 index 000000000..f913dd272 --- /dev/null +++ b/apps/emqx_auth_mongo/rebar.config @@ -0,0 +1,2 @@ +{deps, + [{mongodb, {git,"https://github.com/emqx/mongodb-erlang", {tag, "v3.0.7"}}}]}. \ No newline at end of file diff --git a/apps/emqx_auth_mongo/src/emqx_acl_mongo.erl b/apps/emqx_auth_mongo/src/emqx_acl_mongo.erl new file mode 100644 index 000000000..1982b13d6 --- /dev/null +++ b/apps/emqx_auth_mongo/src/emqx_acl_mongo.erl @@ -0,0 +1,91 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_acl_mongo). + +-include("emqx_auth_mongo.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). + +%% ACL callbacks +-export([ register_metrics/0 + , check_acl/5 + , description/0 + ]). +-spec(register_metrics() -> ok). +register_metrics() -> + lists:foreach(fun emqx_metrics:ensure/1, ?ACL_METRICS). + +check_acl(#{username := <<$$, _/binary>>}, _PubSub, _Topic, _AclResult, _State) -> + ok; + +check_acl(ClientInfo, PubSub, Topic, _AclResult, Env = #{aclquery := AclQuery}) -> + #aclquery{collection = Coll, selector = SelectorList} = AclQuery, + Pool = maps:get(pool, Env, ?APP), + SelectorMapList = + lists:map(fun(Selector) -> + maps:from_list(emqx_auth_mongo:replvars(Selector, ClientInfo)) + end, SelectorList), + case emqx_auth_mongo:query_multi(Pool, Coll, SelectorMapList) of + [] -> ok; + Rows -> + try match(ClientInfo, Topic, topics(PubSub, Rows)) of + matched -> emqx_metrics:inc(?ACL_METRICS(allow)), + {stop, allow}; + nomatch -> emqx_metrics:inc(?ACL_METRICS(deny)), + {stop, deny} + catch + _Err:Reason-> + ?LOG(error, "[MongoDB] Check mongo ~p ACL failed, got ACL config: ~p, error: :~p", + [PubSub, Rows, Reason]), + emqx_metrics:inc(?ACL_METRICS(ignore)), + ignore + end + end. + + +match(_ClientInfo, _Topic, []) -> + nomatch; +match(ClientInfo, Topic, [TopicFilter|More]) -> + case emqx_topic:match(Topic, feedvar(ClientInfo, TopicFilter)) of + true -> matched; + false -> match(ClientInfo, Topic, More) + end. + +topics(publish, Rows) -> + lists:foldl(fun(Row, Acc) -> + Topics = maps:get(<<"publish">>, Row, []) ++ maps:get(<<"pubsub">>, Row, []), + lists:umerge(Acc, Topics) + end, [], Rows); + +topics(subscribe, Rows) -> + lists:foldl(fun(Row, Acc) -> + Topics = maps:get(<<"subscribe">>, Row, []) ++ maps:get(<<"pubsub">>, Row, []), + lists:umerge(Acc, Topics) + end, [], Rows). + +feedvar(#{clientid := ClientId, username := Username}, Str) -> + lists:foldl(fun({Var, Val}, Acc) -> + feedvar(Acc, Var, Val) + end, Str, [{"%u", Username}, {"%c", ClientId}]). + +feedvar(Str, _Var, undefined) -> + Str; +feedvar(Str, Var, Val) -> + re:replace(Str, Var, Val, [global, {return, binary}]). + +description() -> "ACL with MongoDB". + diff --git a/apps/emqx_auth_mongo/src/emqx_auth_mongo.app.src b/apps/emqx_auth_mongo/src/emqx_auth_mongo.app.src new file mode 100644 index 000000000..a33184809 --- /dev/null +++ b/apps/emqx_auth_mongo/src/emqx_auth_mongo.app.src @@ -0,0 +1,14 @@ +{application, emqx_auth_mongo, + [{description, "EMQ X Authentication/ACL with MongoDB"}, + {vsn, "5.0.0"}, % strict semver, bump manually! + {modules, []}, + {registered, [emqx_auth_mongo_sup]}, + {applications, [kernel,stdlib,mongodb,ecpool,emqx_passwd,emqx_libs]}, + {mod, {emqx_auth_mongo_app,[]}}, + {env, []}, + {licenses, ["Apache-2.0"]}, + {maintainers, ["EMQ X Team "]}, + {links, [{"Homepage", "https://emqx.io/"}, + {"Github", "https://github.com/emqx/emqx-auth-mongo"} + ]} + ]}. diff --git a/apps/emqx_auth_mongo/src/emqx_auth_mongo.erl b/apps/emqx_auth_mongo/src/emqx_auth_mongo.erl new file mode 100644 index 000000000..e0a5bb4ed --- /dev/null +++ b/apps/emqx_auth_mongo/src/emqx_auth_mongo.erl @@ -0,0 +1,134 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_mongo). + +-behaviour(ecpool_worker). + +-include("emqx_auth_mongo.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). +-include_lib("emqx_libs/include/types.hrl"). + +-export([ register_metrics/0 + , check/3 + , description/0 + ]). + +-export([ replvar/2 + , replvars/2 + , connect/1 + , query/3 + , query_multi/3 + ]). + +-spec(register_metrics() -> ok). +register_metrics() -> + lists:foreach(fun emqx_metrics:ensure/1, ?AUTH_METRICS). + +check(ClientInfo = #{password := Password}, AuthResult, + Env = #{authquery := AuthQuery, superquery := SuperQuery}) -> + #authquery{collection = Collection, field = Fields, + hash = HashType, selector = Selector} = AuthQuery, + Pool = maps:get(pool, Env, ?APP), + case query(Pool, Collection, maps:from_list(replvars(Selector, ClientInfo))) of + undefined -> emqx_metrics:inc(?AUTH_METRICS(ignore)); + {error, Reason} -> + ?LOG(error, "[MongoDB] Can't connect to MongoDB server: ~0p", [Reason]), + ok = emqx_metrics:inc(?AUTH_METRICS(failure)), + {stop, AuthResult#{auth_result => not_authorized, anonymous => false}}; + UserMap -> + Result = case [maps:get(Field, UserMap, undefined) || Field <- Fields] of + [undefined] -> {error, password_error}; + [PassHash] -> + check_pass({PassHash, Password}, HashType); + [PassHash, Salt|_] -> + check_pass({PassHash, Salt, Password}, HashType) + end, + case Result of + ok -> + ok = emqx_metrics:inc(?AUTH_METRICS(success)), + {stop, AuthResult#{is_superuser => is_superuser(Pool, SuperQuery, ClientInfo), + anonymous => false, + auth_result => success}}; + {error, Error} -> + ?LOG(error, "[MongoDB] check auth fail: ~p", [Error]), + ok = emqx_metrics:inc(?AUTH_METRICS(failure)), + {stop, AuthResult#{auth_result => Error, anonymous => false}} + end + end. + +check_pass(Password, HashType) -> + case emqx_passwd:check_pass(Password, HashType) of + ok -> ok; + {error, _Reason} -> {error, not_authorized} + end. + +description() -> "Authentication with MongoDB". + +%%-------------------------------------------------------------------- +%% Is Superuser? +%%-------------------------------------------------------------------- + +-spec(is_superuser(string(), maybe(#superquery{}), emqx_types:clientinfo()) -> boolean()). +is_superuser(_Pool, undefined, _ClientInfo) -> + false; +is_superuser(Pool, #superquery{collection = Coll, field = Field, selector = Selector}, ClientInfo) -> + Row = query(Pool, Coll, maps:from_list(replvars(Selector, ClientInfo))), + case maps:get(Field, Row, false) of + true -> true; + _False -> false + end. + +replvars(VarList, ClientInfo) -> + lists:map(fun(Var) -> replvar(Var, ClientInfo) end, VarList). + +replvar({Field, <<"%u">>}, #{username := Username}) -> + {Field, Username}; +replvar({Field, <<"%c">>}, #{clientid := ClientId}) -> + {Field, ClientId}; +replvar({Field, <<"%C">>}, #{cn := CN}) -> + {Field, CN}; +replvar({Field, <<"%d">>}, #{dn := DN}) -> + {Field, DN}; +replvar(Selector, _ClientInfo) -> + Selector. + +%%-------------------------------------------------------------------- +%% MongoDB Connect/Query +%%-------------------------------------------------------------------- + +connect(Opts) -> + Type = proplists:get_value(type, Opts, single), + Hosts = proplists:get_value(hosts, Opts, []), + Options = proplists:get_value(options, Opts, []), + WorkerOptions = proplists:get_value(worker_options, Opts, []), + mongo_api:connect(Type, Hosts, Options, WorkerOptions). + +query(Pool, Collection, Selector) -> + ecpool:with_client(Pool, fun(Conn) -> mongo_api:find_one(Conn, Collection, Selector, #{}) end). + +query_multi(Pool, Collection, SelectorList) -> + lists:reverse(lists:flatten(lists:foldl(fun(Selector, Acc1) -> + Batch = ecpool:with_client(Pool, fun(Conn) -> + case mongo_api:find(Conn, Collection, Selector, #{}) of + [] -> []; + {ok, Cursor} -> + mc_cursor:foldl(fun(O, Acc2) -> [O|Acc2] end, [], Cursor, 1000) + end + end), + [Batch|Acc1] + end, [], SelectorList))). diff --git a/apps/emqx_auth_mongo/src/emqx_auth_mongo_app.erl b/apps/emqx_auth_mongo/src/emqx_auth_mongo_app.erl new file mode 100644 index 000000000..e13fe30b7 --- /dev/null +++ b/apps/emqx_auth_mongo/src/emqx_auth_mongo_app.erl @@ -0,0 +1,87 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_mongo_app). + +-behaviour(application). + +-emqx_plugin(auth). + +-include("emqx_auth_mongo.hrl"). + +-import(proplists, [get_value/3]). + +%% Application callbacks +-export([ start/2 + , prep_stop/1 + , stop/1 + ]). + +%%-------------------------------------------------------------------- +%% Application callbacks +%%-------------------------------------------------------------------- + +start(_StartType, _StartArgs) -> + {ok, Sup} = emqx_auth_mongo_sup:start_link(), + with_env(auth_query, fun reg_authmod/1), + with_env(acl_query, fun reg_aclmod/1), + {ok, Sup}. + +prep_stop(State) -> + ok = emqx:unhook('client.authenticate', fun emqx_auth_mongo:check/3), + ok = emqx:unhook('client.check_acl', fun emqx_acl_mongo:check_acl/5), + State. + +stop(_State) -> + ok. + +reg_authmod(AuthQuery) -> + emqx_auth_mongo:register_metrics(), + SuperQuery = r(super_query, application:get_env(?APP, super_query, undefined)), + ok = emqx:hook('client.authenticate', fun emqx_auth_mongo:check/3, + [#{authquery => AuthQuery, superquery => SuperQuery, pool => ?APP}]). + +reg_aclmod(AclQuery) -> + emqx_acl_mongo:register_metrics(), + ok = emqx:hook('client.check_acl', fun emqx_acl_mongo:check_acl/5, [#{aclquery => AclQuery, pool => ?APP}]). + +%%-------------------------------------------------------------------- +%% Internal functions +%%-------------------------------------------------------------------- + +with_env(Name, Fun) -> + case application:get_env(?APP, Name) of + undefined -> ok; + {ok, Config} -> Fun(r(Name, Config)) + end. + +r(super_query, undefined) -> + undefined; +r(super_query, Config) -> + #superquery{collection = list_to_binary(get_value(collection, Config, "mqtt_user")), + field = list_to_binary(get_value(super_field, Config, "is_superuser")), + selector = get_value(selector, Config, ?DEFAULT_SELECTORS)}; + +r(auth_query, Config) -> + #authquery{collection = list_to_binary(get_value(collection, Config, "mqtt_user")), + field = get_value(password_field, Config, [<<"password">>]), + hash = get_value(password_hash, Config, sha256), + selector = get_value(selector, Config, ?DEFAULT_SELECTORS)}; + +r(acl_query, Config) -> + #aclquery{collection = list_to_binary(get_value(collection, Config, "mqtt_acl")), + selector = get_value(selector, Config, [?DEFAULT_SELECTORS])}. + diff --git a/apps/emqx_auth_mongo/src/emqx_auth_mongo_sup.erl b/apps/emqx_auth_mongo/src/emqx_auth_mongo_sup.erl new file mode 100644 index 000000000..dc2c37fd4 --- /dev/null +++ b/apps/emqx_auth_mongo/src/emqx_auth_mongo_sup.erl @@ -0,0 +1,34 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_mongo_sup). + +-behaviour(supervisor). + +-include("emqx_auth_mongo.hrl"). + +-export([start_link/0]). + +-export([init/1]). + +start_link() -> + supervisor:start_link({local, ?MODULE}, ?MODULE, []). + +init([]) -> + {ok, PoolEnv} = application:get_env(?APP, server), + PoolSpec = ecpool:pool_spec(?APP, ?APP, ?APP, PoolEnv), + {ok, {{one_for_all, 10, 100}, [PoolSpec]}}. + diff --git a/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE.erl b/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE.erl new file mode 100644 index 000000000..077dde7bd --- /dev/null +++ b/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE.erl @@ -0,0 +1,174 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_mongo_SUITE). + +-compile(export_all). +-compile(nowarn_export_all). + +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("common_test/include/ct.hrl"). +-include_lib("eunit/include/eunit.hrl"). + +-define(APP, emqx_auth_mongo). + +-define(POOL(App), ecpool_worker:client(gproc_pool:pick_worker({ecpool, App}))). + +-define(MONGO_CL_ACL, <<"mqtt_acl">>). +-define(MONGO_CL_USER, <<"mqtt_user">>). + +-define(INIT_ACL, [{<<"username">>, <<"testuser">>, <<"clientid">>, <<"null">>, <<"subscribe">>, [<<"#">>]}, + {<<"username">>, <<"dashboard">>, <<"clientid">>, <<"null">>, <<"pubsub">>, [<<"$SYS/#">>]}, + {<<"username">>, <<"user3">>, <<"clientid">>, <<"null">>, <<"publish">>, [<<"a/b/c">>]}]). + +-define(INIT_AUTH, [{<<"username">>, <<"plain">>, <<"password">>, <<"plain">>, <<"salt">>, <<"salt">>, <<"is_superuser">>, true}, + {<<"username">>, <<"md5">>, <<"password">>, <<"1bc29b36f623ba82aaf6724fd3b16718">>, <<"salt">>, <<"salt">>, <<"is_superuser">>, false}, + {<<"username">>, <<"sha">>, <<"password">>, <<"d8f4590320e1343a915b6394170650a8f35d6926">>, <<"salt">>, <<"salt">>, <<"is_superuser">>, false}, + {<<"username">>, <<"sha256">>, <<"password">>, <<"5d5b09f6dcb2d53a5fffc60c4ac0d55fabdf556069d6631545f42aa6e3500f2e">>, <<"salt">>, <<"salt">>, <<"is_superuser">>, false}, + {<<"username">>, <<"pbkdf2_password">>, <<"password">>, <<"cdedb5281bb2f801565a1122b2563515">>, <<"salt">>, <<"ATHENA.MIT.EDUraeburn">>, <<"is_superuser">>, false}, + {<<"username">>, <<"bcrypt_foo">>, <<"password">>, <<"$2a$12$sSS8Eg.ovVzaHzi1nUHYK.HbUIOdlQI0iS22Q5rd5z.JVVYH6sfm6">>, <<"salt">>, <<"$2a$12$sSS8Eg.ovVzaHzi1nUHYK.">>, <<"is_superuser">>, false} + ]). + +%%-------------------------------------------------------------------- +%% Setups +%%-------------------------------------------------------------------- + +all() -> + emqx_ct:all(?MODULE). + +init_per_suite(Cfg) -> + emqx_ct_helpers:start_apps([emqx_auth_mongo], fun set_special_confs/1), + emqx_modules:load_module(emqx_mod_acl_internal, false), + init_mongo_data(), + Cfg. + +end_per_suite(_Cfg) -> + deinit_mongo_data(), + emqx_ct_helpers:stop_apps([emqx_auth_mongo]). + +set_special_confs(emqx) -> + application:set_env(emqx, acl_nomatch, deny), + application:set_env(emqx, acl_file, + emqx_ct_helpers:deps_path(emqx, "test/emqx_SUITE_data/acl.conf")), + application:set_env(emqx, allow_anonymous, false), + application:set_env(emqx, enable_acl_cache, false), + application:set_env(emqx, plugins_loaded_file, + emqx_ct_helpers:deps_path(emqx, "test/emqx_SUITE_data/loaded_plugins")); +set_special_confs(_App) -> + ok. + +init_mongo_data() -> + %% Users + {ok, Connection} = ?POOL(?APP), + mongo_api:delete(Connection, ?MONGO_CL_USER, {}), + ?assertMatch({{true, _}, _}, mongo_api:insert(Connection, ?MONGO_CL_USER, ?INIT_AUTH)), + %% ACLs + mongo_api:delete(Connection, ?MONGO_CL_ACL, {}), + ?assertMatch({{true, _}, _}, mongo_api:insert(Connection, ?MONGO_CL_ACL, ?INIT_ACL)). + +deinit_mongo_data() -> + {ok, Connection} = ?POOL(?APP), + mongo_api:delete(Connection, ?MONGO_CL_USER, {}), + mongo_api:delete(Connection, ?MONGO_CL_ACL, {}). + +%%-------------------------------------------------------------------- +%% Test cases +%%-------------------------------------------------------------------- + +t_check_auth(_) -> + Plain = #{zone => external, clientid => <<"client1">>, username => <<"plain">>}, + Plain1 = #{zone => external, clientid => <<"client1">>, username => <<"plain2">>}, + Md5 = #{zone => external, clientid => <<"md5">>, username => <<"md5">>}, + Sha = #{zone => external, clientid => <<"sha">>, username => <<"sha">>}, + Sha256 = #{zone => external, clientid => <<"sha256">>, username => <<"sha256">>}, + Pbkdf2 = #{zone => external, clientid => <<"pbkdf2_password">>, username => <<"pbkdf2_password">>}, + Bcrypt = #{zone => external, clientid => <<"bcrypt_foo">>, username => <<"bcrypt_foo">>}, + User1 = #{zone => external, clientid => <<"bcrypt_foo">>, username => <<"user">>}, + reload({auth_query, [{password_hash, plain}]}), + %% With exactly username/password, connection success + {ok, #{is_superuser := true}} = emqx_access_control:authenticate(Plain#{password => <<"plain">>}), + %% With exactly username and wrong password, connection fail + {error, _} = emqx_access_control:authenticate(Plain#{password => <<"error_pwd">>}), + %% With wrong username and wrong password, emqx_auth_mongo auth fail, then allow anonymous authentication + {error, _} = emqx_access_control:authenticate(Plain1#{password => <<"error_pwd">>}), + %% With wrong username and exactly password, emqx_auth_mongo auth fail, then allow anonymous authentication + {error, _} = emqx_access_control:authenticate(Plain1#{password => <<"plain">>}), + reload({auth_query, [{password_hash, md5}]}), + {ok, #{is_superuser := false}} = emqx_access_control:authenticate(Md5#{password => <<"md5">>}), + reload({auth_query, [{password_hash, sha}]}), + {ok, #{is_superuser := false}} = emqx_access_control:authenticate(Sha#{password => <<"sha">>}), + reload({auth_query, [{password_hash, sha256}]}), + {ok, #{is_superuser := false}} = emqx_access_control:authenticate(Sha256#{password => <<"sha256">>}), + %%pbkdf2 sha + reload({auth_query, [{password_hash, {pbkdf2, sha, 1, 16}}, {password_field, [<<"password">>, <<"salt">>]}]}), + {ok, #{is_superuser := false}} = emqx_access_control:authenticate(Pbkdf2#{password => <<"password">>}), + reload({auth_query, [{password_hash, {salt, bcrypt}}]}), + {ok, #{is_superuser := false}} = emqx_access_control:authenticate(Bcrypt#{password => <<"foo">>}), + {error, _} = emqx_access_control:authenticate(User1#{password => <<"foo">>}). + +t_check_acl(_) -> + {ok, Connection} = ?POOL(?APP), + User1 = #{zone => external, clientid => <<"client1">>, username => <<"testuser">>}, + User2 = #{zone => external, clientid => <<"client2">>, username => <<"dashboard">>}, + User3 = #{zone => external, clientid => <<"client2">>, username => <<"user3">>}, + User4 = #{zone => external, clientid => <<"$$client2">>, username => <<"$$user3">>}, + 3 = mongo_api:count(Connection, ?MONGO_CL_ACL, {}, 17), + %% ct log output + allow = emqx_access_control:check_acl(User1, subscribe, <<"users/testuser/1">>), + deny = emqx_access_control:check_acl(User1, subscribe, <<"$SYS/testuser/1">>), + deny = emqx_access_control:check_acl(User2, subscribe, <<"a/b/c">>), + allow = emqx_access_control:check_acl(User2, subscribe, <<"$SYS/testuser/1">>), + allow = emqx_access_control:check_acl(User3, publish, <<"a/b/c">>), + deny = emqx_access_control:check_acl(User3, publish, <<"c">>), + allow = emqx_access_control:check_acl(User4, publish, <<"a/b/c">>). + +t_acl_super(_) -> + reload({auth_query, [{password_hash, plain}, {password_field, [<<"password">>]}]}), + {ok, C} = emqtt:start_link([{clientid, <<"simpleClient">>}, + {username, <<"plain">>}, + {password, <<"plain">>}]), + {ok, _} = emqtt:connect(C), + timer:sleep(10), + emqtt:subscribe(C, <<"TopicA">>, qos2), + timer:sleep(1000), + emqtt:publish(C, <<"TopicA">>, <<"Payload">>, qos2), + timer:sleep(1000), + receive + {publish, #{payload := Payload}} -> + ?assertEqual(<<"Payload">>, Payload) + after + 1000 -> + ct:fail({receive_timeout, <<"Payload">>}), + ok + end, + emqtt:disconnect(C). + +%%-------------------------------------------------------------------- +%% Utils +%%-------------------------------------------------------------------- + +reload({Par, Vals}) when is_list(Vals) -> + application:stop(?APP), + {ok, TupleVals} = application:get_env(?APP, Par), + NewVals = + lists:filtermap(fun({K, V}) -> + case lists:keymember(K, 1, Vals) of + false ->{true, {K, V}}; + _ -> false + end + end, TupleVals), + application:set_env(?APP, Par, lists:append(NewVals, Vals)), + application:start(?APP). diff --git a/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE_data/ca-key.pem b/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE_data/ca-key.pem new file mode 100644 index 000000000..e9717011e --- /dev/null +++ b/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE_data/ca-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA0kGUBi9NDp65jgdxKfizIfuSr2wpwb44yM9SuP4oUQSULOA2 +4iFpLR/c5FAYHU81y9Vx91dQjdZfffaBZuv2zVvteXUkol8Nez7boKbo2E41MTew +8edtNKZAQVvnaHAC2NCZxjchCzUCDEoUUcl+cIERZ8R48FBqK5iTVcMRIx1akwus ++dhBqP0ykA5TGOWZkJrLM9aUXSPQha9+wXlOpkvu0Ur2nkX8PPJnifWao9UShSar +ll1IqPZNCSlZMwcFYcQNBCpdvITUUYlHvMRQV64bUpOxUGDuJkQL3dLKBlNuBRlJ +BcjBAKw7rFnwwHZcMmQ9tan/dZzpzwjo/T0XjwIDAQABAoIBAQCSHvUqnzDkWjcG +l/Fzg92qXlYBCCC0/ugj1sHcwvVt6Mq5rVE3MpUPwTcYjPlVVTlD4aEEjm/zQuq2 +ddxUlOS+r4aIhHrjRT/vSS4FpjnoKeIZxGR6maVxk6DQS3i1QjMYT1CvSpzyVvKH +a+xXMrtmoKxh+085ZAmFJtIuJhUA2yEa4zggCxWnvz8ecLClUPfVDPhdLBHc3KmL +CRpHEC6L/wanvDPRdkkzfKyaJuIJlTDaCg63AY5sDkTW2I57iI/nJ3haSeidfQKz +39EfbnM1A/YprIakafjAu3frBIsjBVcxwGihZmL/YriTHjOggJF841kT5zFkkv2L +/530Wk6xAoGBAOqZLZ4DIi/zLndEOz1mRbUfjc7GQUdYplBnBwJ22VdS0P4TOXnd +UbJth2MA92NM7ocTYVFl4TVIZY/Y+Prxk7KQdHWzR7JPpKfx9OEVgtSqV0vF9eGI +rKp79Y1T4Mvc3UcQCXX6TP7nHLihEzpS8odm2LW4txrOiLsn4Fq/IWrLAoGBAOVv +6U4tm3lImotUupKLZPKEBYwruo9qRysoug9FiorP4TjaBVOfltiiHbAQD6aGfVtN +SZpZZtrs17wL7Xl4db5asgMcZd+8Hkfo5siR7AuGW9FZloOjDcXb5wCh9EvjJ74J +Cjw7RqyVymq9t7IP6wnVwj5Ck48YhlOZCz/mzlnNAoGAWq7NYFgLvgc9feLFF23S +IjpJQZWHJEITP98jaYNxbfzYRm49+GphqxwFinKULjFNvq7yHlnIXSVYBOu1CqOZ +GRwXuGuNmlKI7lZr9xmukfAqgGLMMdr4C4qRF4lFyufcLRz42z7exmWlx4ST/yaT +E13hBRWayeTuG5JFei6Jh1MCgYEAqmX4LyC+JFBgvvQZcLboLRkSCa18bADxhENG +FAuAvmFvksqRRC71WETmqZj0Fqgxt7pp3KFjO1rFSprNLvbg85PmO1s+6fCLyLpX +lESTu2d5D71qhK93jigooxalGitFm+SY3mzjq0/AOpBWOn+J/w7rqVPGxXLgaHv0 +l+vx+00CgYBOvo9/ImjwYii2jFl+sHEoCzlvpITi2temRlT2j6ulSjCLJgjwEFw9 +8e+vvfQumQOsutakUVyURrkMGNDiNlIv8kv5YLCCkrwN22E6Ghyi69MJUvHQXkc/ +QZhjn/luyfpB5f/BeHFS2bkkxAXo+cfG45ApY3Qfz6/7o+H+vDa6/A== +-----END RSA PRIVATE KEY----- diff --git a/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE_data/ca.pem b/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE_data/ca.pem new file mode 100644 index 000000000..00b31d8a4 --- /dev/null +++ b/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE_data/ca.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDAzCCAeugAwIBAgIBATANBgkqhkiG9w0BAQsFADA8MTowOAYDVQQDDDFNeVNR +TF9TZXJ2ZXJfOC4wLjE5X0F1dG9fR2VuZXJhdGVkX0NBX0NlcnRpZmljYXRlMB4X +DTIwMDYxMTAzMzg0NloXDTMwMDYwOTAzMzg0NlowPDE6MDgGA1UEAwwxTXlTUUxf +U2VydmVyXzguMC4xOV9BdXRvX0dlbmVyYXRlZF9DQV9DZXJ0aWZpY2F0ZTCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANJBlAYvTQ6euY4HcSn4syH7kq9s +KcG+OMjPUrj+KFEElCzgNuIhaS0f3ORQGB1PNcvVcfdXUI3WX332gWbr9s1b7Xl1 +JKJfDXs+26Cm6NhONTE3sPHnbTSmQEFb52hwAtjQmcY3IQs1AgxKFFHJfnCBEWfE +ePBQaiuYk1XDESMdWpMLrPnYQaj9MpAOUxjlmZCayzPWlF0j0IWvfsF5TqZL7tFK +9p5F/DzyZ4n1mqPVEoUmq5ZdSKj2TQkpWTMHBWHEDQQqXbyE1FGJR7zEUFeuG1KT +sVBg7iZEC93SygZTbgUZSQXIwQCsO6xZ8MB2XDJkPbWp/3Wc6c8I6P09F48CAwEA +AaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEADKz6bIpP5anp +GgLB0jkclRWuMlS4qqIt4itSsMXPJ/ezpHwECixmgW2TIQl6S1woRkUeMxhT2/Ay +Sn/7aKxuzRagyE5NEGOvrOuAP5RO2ZdNJ/X3/Rh533fK1sOTEEbSsWUvW6iSkZef +rsfZBVP32xBhRWkKRdLeLB4W99ADMa0IrTmZPCXHSSE2V4e1o6zWLXcOZeH1Qh8N +SkelBweR+8r1Fbvy1r3s7eH7DCbYoGEDVLQGOLvzHKBisQHmoDnnF5E9g1eeNRdg +o+vhOKfYCOzeNREJIqS42PHcGhdNRk90ycigPmfUJclz1mDHoMjKR2S5oosTpr65 +tNPx3CL7GA== +-----END CERTIFICATE----- diff --git a/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE_data/client-cert.pem b/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE_data/client-cert.pem new file mode 100644 index 000000000..aad1404ca --- /dev/null +++ b/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE_data/client-cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAeygAwIBAgIBAzANBgkqhkiG9w0BAQsFADA8MTowOAYDVQQDDDFNeVNR +TF9TZXJ2ZXJfOC4wLjE5X0F1dG9fR2VuZXJhdGVkX0NBX0NlcnRpZmljYXRlMB4X +DTIwMDYxMTAzMzg0N1oXDTMwMDYwOTAzMzg0N1owQDE+MDwGA1UEAww1TXlTUUxf +U2VydmVyXzguMC4xOV9BdXRvX0dlbmVyYXRlZF9DbGllbnRfQ2VydGlmaWNhdGUw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVYSWpOvCTupz82fc85Opv +EQ7rkB8X2oOMyBCpkyHKBIr1ZQgRDWBp9UVOASq3GnSElm6+T3Kb1QbOffa8GIlw +sjAueKdq5L2eSkmPIEQ7eoO5kEW+4V866hE1LeL/PmHg2lGP0iqZiJYtElhHNQO8 +3y9I7cm3xWMAA3SSWikVtpJRn3qIp2QSrH+tK+/HHbE5QwtPxdir4ULSCSOaM5Yh +Wi5Oto88TZqe1v7SXC864JVvO4LuS7TuSreCdWZyPXTJFBFeCEWSAxonKZrqHbBe +CwKML6/0NuzjaQ51c2tzmVI6xpHj3nnu4cSRx6Jf9WBm+35vm0wk4pohX3ptdzeV +AgMBAAGjDTALMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEBAByQ5zSNeFUH +Aw7JlpZHtHaSEeiiyBHke20ziQ07BK1yi/ms2HAWwQkpZv149sjNuIRH8pkTmkZn +g8PDzSefjLbC9AsWpWV0XNV22T/cdobqLqMBDDZ2+5bsV+jTrOigWd9/AHVZ93PP +IJN8HJn6rtvo2l1bh/CdsX14uVSdofXnuWGabNTydqtMvmCerZsdf6qKqLL+PYwm +RDpgWiRUY7KPBSSlKm/9lJzA+bOe4dHeJzxWFVCJcbpoiTFs1je1V8kKQaHtuW39 +ifX6LTKUMlwEECCbDKM8Yq2tm8NjkjCcnFDtKg8zKGPUu+jrFMN5otiC3wnKcP7r +O9EkaPcgYH8= +-----END CERTIFICATE----- diff --git a/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE_data/client-key.pem b/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE_data/client-key.pem new file mode 100644 index 000000000..6789d0291 --- /dev/null +++ b/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE_data/client-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEA1WElqTrwk7qc/Nn3POTqbxEO65AfF9qDjMgQqZMhygSK9WUI +EQ1gafVFTgEqtxp0hJZuvk9ym9UGzn32vBiJcLIwLninauS9nkpJjyBEO3qDuZBF +vuFfOuoRNS3i/z5h4NpRj9IqmYiWLRJYRzUDvN8vSO3Jt8VjAAN0klopFbaSUZ96 +iKdkEqx/rSvvxx2xOUMLT8XYq+FC0gkjmjOWIVouTraPPE2antb+0lwvOuCVbzuC +7ku07kq3gnVmcj10yRQRXghFkgMaJyma6h2wXgsCjC+v9Dbs42kOdXNrc5lSOsaR +49557uHEkceiX/VgZvt+b5tMJOKaIV96bXc3lQIDAQABAoIBAF7yjXmSOn7h6P0y +WCuGiTLG2mbDiLJqj2LTm2Z5i+2Cu/qZ7E76Ls63TxF4v3MemH5vGfQhEhR5ZD/6 +GRJ1sKKvB3WGRqjwA9gtojHH39S/nWGy6vYW/vMOOH37XyjIr3EIdIaUtFQBTSHd +Kd71niYrAbVn6fyWHolhADwnVmTMOl5OOAhCdEF4GN3b5aIhIu8BJ7EUzTtHBJIj +CAEfjZFjDs1y1cIgGFJkuIQxMfCpq5recU2qwip7YO6fk//WEjOPu7kSf5IEswL8 +jg1dea9rGBV6KaD2xsgsC6Ll6Sb4BbsrHMfflG3K2Lk3RdVqqTFp1Fn1PTLQE/1S +S/SZPYECgYEA9qYcHKHd0+Q5Ty5wgpxKGa4UCWkpwvfvyv4bh8qlmxueB+l2AIdo +ZvkM8gTPagPQ3WypAyC2b9iQu70uOJo1NizTtKnpjDdN1YpDjISJuS/P0x73gZwy +gmoM5AzMtN4D6IbxXtXnPaYICvwLKU80ouEN5ZPM4/ODLUu6gsp0v2UCgYEA3Xgi +zMC4JF0vEKEaK0H6QstaoXUmw/lToZGH3TEojBIkb/2LrHUclygtONh9kJSFb89/ +jbmRRLAOrx3HZKCNGUmF4H9k5OQyAIv6OGBinvLGqcbqnyNlI+Le8zxySYwKMlEj +EMrBCLmSyi0CGFrbZ3mlj/oCET/ql9rNvcK+DHECgYAEx5dH3sMjtgp+RFId1dWB +xePRgt4yTwewkVgLO5wV82UOljGZNQaK6Eyd7AXw8f38LHzh+KJQbIvxd2sL4cEi +OaAoohpKg0/Y0YMZl//rPMf0OWdmdZZs/I0fZjgZUSwWN3c59T8z7KG/RL8an9RP +S7kvN7wCttdV61/D5RR6GQKBgDxCe/WKWpBKaovzydMLWLTj7/0Oi0W3iXHkzzr4 +LTgvl4qBSofaNbVLUUKuZTv5rXUG2IYPf99YqCYtzBstNDc1MiAriaBeFtzfOW4t +i6gEFtoLLbuvPc3N5Sv5vn8Ug5G9UfU3td5R4AbyyCcoUZqOFuZd+EIJSiOXfXOs +kVmBAoGBAIU9aPAqhU5LX902oq8KsrpdySONqv5mtoStvl3wo95WIqXNEsFY60wO +q02jKQmJJ2MqhkJm2EoF2Mq8+40EZ5sz8LdgeQ/M0yQ9lAhPi4rftwhpe55Ma9dk +SE9X1c/DMCBEaIjJqVXdy0/EeArwpb8sHkguVVAZUWxzD+phm1gs +-----END RSA PRIVATE KEY----- diff --git a/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE_data/mongodb.pem b/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE_data/mongodb.pem new file mode 100644 index 000000000..1fe94891a --- /dev/null +++ b/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE_data/mongodb.pem @@ -0,0 +1,46 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAeygAwIBAgIBAjANBgkqhkiG9w0BAQsFADA8MTowOAYDVQQDDDFNeVNR +TF9TZXJ2ZXJfOC4wLjE5X0F1dG9fR2VuZXJhdGVkX0NBX0NlcnRpZmljYXRlMB4X +DTIwMDYxMTAzMzg0NloXDTMwMDYwOTAzMzg0NlowQDE+MDwGA1UEAww1TXlTUUxf +U2VydmVyXzguMC4xOV9BdXRvX0dlbmVyYXRlZF9TZXJ2ZXJfQ2VydGlmaWNhdGUw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCcEnEm5hqP1EbEJycOz8Ua +NWp29QdpFUzTWhkKGhVXk+0msmNTw4NBAFB42moY44OU8wvDideOlJNhPRWveD8z +G2lxzJA91p0UK4et8ia9MmeuCGhdC9jxJ8X69WNlUiPyy0hI/ZsqRq9Z0C2eW0iL +JPXsy4X8Xpw3SFwoXf5pR9RFY5Pb2tuyxqmSestu2VXT/NQjJg4CVDR3mFcHPXZB +4elRzH0WshExEGkgy0bg20MJeRc2Qdb5Xx+EakbmwroDWaCn3NSGqQ7jv6Vw0doy +TGvS6h6RHBxnyqRfRgKGlCoOMG9/5+rFJC00QpCUG2vHXHWGoWlMlJ3foN7rj5v9 +AgMBAAGjDTALMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEBAJ5zt2rj4Ag6 +zpN59AWC1Fur8g8l41ksHkSpKPp+PtyO/ngvbMqBpfmK1e7JCKZv/68QXfMyWWAI +hwalqZkXXWHKjuz3wE7dE25PXFXtGJtcZAaj10xt98fzdqt8lQSwh2kbfNwZIz1F +sgAStgE7+ZTcqTgvNB76Os1UK0to+/P0VBWktaVFdyub4Nc2SdPVnZNvrRBXBwOD +3V8ViwywDOFoE7DvCvwx/SVsvoC0Z4j3AMMovO6oHicP7uU83qsQgm1Qru3YeoLR ++DoVi7IPHbWvN7MqFYn3YjNlByO2geblY7MR0BlqbFlmFrqLsUfjsh2ys7/U/knC +dN/klu446fI= +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAnBJxJuYaj9RGxCcnDs/FGjVqdvUHaRVM01oZChoVV5PtJrJj +U8ODQQBQeNpqGOODlPMLw4nXjpSTYT0Vr3g/MxtpccyQPdadFCuHrfImvTJnrgho +XQvY8SfF+vVjZVIj8stISP2bKkavWdAtnltIiyT17MuF/F6cN0hcKF3+aUfURWOT +29rbssapknrLbtlV0/zUIyYOAlQ0d5hXBz12QeHpUcx9FrIRMRBpIMtG4NtDCXkX +NkHW+V8fhGpG5sK6A1mgp9zUhqkO47+lcNHaMkxr0uoekRwcZ8qkX0YChpQqDjBv +f+fqxSQtNEKQlBtrx1x1hqFpTJSd36De64+b/QIDAQABAoIBAFiah66Dt9SruLkn +WR8piUaFyLlcBib8Nq9OWSTJBhDAJERxxb4KIvvGB+l0ZgNXNp5bFPSfzsZdRwZP +PX5uj8Kd71Dxx3mz211WESMJdEC42u+MSmN4lGLkJ5t/sDwXU91E1vbJM0ve8THV +4/Ag9qA4DX2vVZOeyqT/6YHpSsPNZplqzrbAiwrfHwkctHfgqwOf3QLfhmVQgfCS +VwidBldEUv2whSIiIxh4Rv5St4kA68IBCbJxdpOpyuQBkk6CkxZ7VN9FqOuSd4Pk +Wm7iWyBMZsCmELZh5XAXld4BEt87C5R4CvbPBDZxAv3THk1DNNvpy3PFQfwARRFb +SAToYMECgYEAyL7U8yxpzHDYWd3oCx6vTi9p9N/z0FfAkWrRF6dm4UcSklNiT1Aq +EOnTA+SaW8tV3E64gCWcY23gNP8so/ZseWj6L+peHwtchaP9+KB7yGw2A+05+lOx +VetLTjAOmfpiUXFe5w1q4C1RGhLjZjjzW+GvwdAuchQgUEFaomrV+PUCgYEAxwfH +cmVGFbAktcjU4HSRjKSfawCrut+3YUOLybyku3Q/hP9amG8qkVTFe95CTLjLe2D0 +ccaTTpofFEJ32COeck0g0Ujn/qQ+KXRoauOYs4FB1DtqMpqB78wufWEUpDpbd9/h +J+gJdC/IADd4tJW9zA92g8IA7ZtFmqDtiSpQ0ekCgYAQGkaorvJZpN+l7cf0RGTZ +h7IfI2vCVZer0n6tQA9fmLzjoe6r4AlPzAHSOR8sp9XeUy43kUzHKQQoHCPvjw/K +eWJAP7OHF/k2+x2fOPhU7mEy1W+mJdp+wt4Kio5RSaVjVQ3AyPG+w8PSrJszEvRq +dWMMz+851WV2KpfjmWBKlQKBgQC++4j4DZQV5aMkSKV1CIZOBf3vaIJhXKEUFQPD +PmB4fBEjpwCg+zNGp6iktt65zi17o8qMjrb1mtCt2SY04eD932LZUHNFlwcLMmes +Ad+aiDLJ24WJL1f16eDGcOyktlblDZB5gZ/ovJzXEGOkLXglosTfo77OQculmDy2 +/UL2WQKBgGeKasmGNfiYAcWio+KXgFkHXWtAXB9B91B1OFnCa40wx+qnl71MIWQH +PQ/CZFNWOfGiNEJIZjrHsfNJoeXkhq48oKcT0AVCDYyLV0VxDO4ejT95mGW6njNd +JpvmhwwAjOvuWVr0tn4iXlSK8irjlJHmwcRjLTJq97vE9fsA2MjI +-----END RSA PRIVATE KEY----- diff --git a/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE_data/private_key.pem b/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE_data/private_key.pem new file mode 100644 index 000000000..8fbf6bdec --- /dev/null +++ b/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE_data/private_key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA1zVmMhPqpSPMmYkKh5wwlRD5XuS8YWJKEM6tjFx61VK8qxHE +YngkC2KnL5EuKAjQZIF3tJskwt0hAat047CCCZxrkNEpbVvSnvnk+A/8bg/Ww1n3 +qxzfifhsWfpUKlDnwrtH+ftt+5rZeEkf37XAPy7ZjzecAF9SDV6WSiPeAxUX2+hN +dId42Pf45woo4LFGUlQeagCFkD/R0dpNIMGwcnkKCUikiBqr2ijSIgvRtBfZ9fBG +jFGER2uE/Eay4AgcQsHue8skRwDCng8OnqtPnBtTytmqTy9V/BRgsVKUoksm6wsx +kUYwgHeaq7UCvlCm25SZ7yRyd4k8t0BKDf2h+wIDAQABAoIBAEQcrHmRACTADdNS +IjkFYALt2l8EOfMAbryfDSJtapr1kqz59JPNvmq0EIHnixo0n/APYdmReLML1ZR3 +tYkSpjVwgkLVUC1CcIjMQoGYXaZf8PLnGJHZk45RR8m6hsTV0mQ5bfBaeVa2jbma +OzJMjcnxg/3l9cPQZ2G/3AUfEPccMxOXp1KRz3mUQcGnKJGtDbN/kfmntcwYoxaE +Zg4RoeKAoMpK1SSHAiJKe7TnztINJ7uygR9XSzNd6auY8A3vomSIjpYO7XL+lh7L +izm4Ir3Gb/eCYBvWgQyQa2KCJgK/sQyEs3a09ngofSEUhQJQYhgZDwUj+fDDOGqj +hCZOA8ECgYEA+ZWuHdcUQ3ygYhLds2QcogUlIsx7C8n/Gk/FUrqqXJrTkuO0Eqqa +B47lCITvmn2zm0ODfSFIARgKEUEDLS/biZYv7SUTrFqBLcet+aGI7Dpv91CgB75R +tNzcIf8VxoiP0jPqdbh9mLbbxGi5Uc4p9TVXRljC4hkswaouebWee0sCgYEA3L2E +YB3kiHrhPI9LHS5Px9C1w+NOu5wP5snxrDGEgaFCvL6zgY6PflacppgnmTXl8D1x +im0IDKSw5dP3FFonSVXReq3CXDql7UnhfTCiLDahV7bLxTH42FofcBpDN3ERdOal +58RwQh6VrLkzQRVoObo+hbGlFiwwSAfQC509FhECgYBsRSBpVXo25IN2yBRg09cP ++gdoFyhxrsj5kw1YnB13WrrZh+oABv4WtUhp77E5ZbpaamlKCPwBbXpAjeFg4tfr +0bksuN7V79UGFQ9FsWuCfr8/nDwv38H2IbFlFhFONMOfPmJBey0Q6JJhm8R41mSh +OOiJXcv85UrjIH5U0hLUDQKBgQDVLOU5WcUJlPoOXSgiT0ZW5xWSzuOLRUUKEf6l +19BqzAzCcLy0orOrRAPW01xylt2v6/bJw1Ahva7k1ZZo/kOwjANYoZPxM+ZoSZBN +MXl8j2mzZuJVV1RFxItV3NcLJNPB/Lk+IbRz9kt/2f9InF7iWR3mSU/wIM6j0X+2 +p6yFsQKBgQCM/ldWb511lA+SNkqXB2P6WXAgAM/7+jwsNHX2ia2Ikufm4SUEKMSv +mti/nZkHDHsrHU4wb/2cOAywMELzv9EHzdcoenjBQP65OAc/1qWJs+LnBcCXfqKk +aHjEZW6+brkHdRGLLY3YAHlt/AUL+RsKPJfN72i/FSpmu+52G36eeQ== +-----END RSA PRIVATE KEY----- diff --git a/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE_data/public_key.pem b/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE_data/public_key.pem new file mode 100644 index 000000000..f9772b533 --- /dev/null +++ b/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE_data/public_key.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1zVmMhPqpSPMmYkKh5ww +lRD5XuS8YWJKEM6tjFx61VK8qxHEYngkC2KnL5EuKAjQZIF3tJskwt0hAat047CC +CZxrkNEpbVvSnvnk+A/8bg/Ww1n3qxzfifhsWfpUKlDnwrtH+ftt+5rZeEkf37XA +Py7ZjzecAF9SDV6WSiPeAxUX2+hNdId42Pf45woo4LFGUlQeagCFkD/R0dpNIMGw +cnkKCUikiBqr2ijSIgvRtBfZ9fBGjFGER2uE/Eay4AgcQsHue8skRwDCng8OnqtP +nBtTytmqTy9V/BRgsVKUoksm6wsxkUYwgHeaq7UCvlCm25SZ7yRyd4k8t0BKDf2h ++wIDAQAB +-----END PUBLIC KEY----- diff --git a/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE_data/server-cert.pem b/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE_data/server-cert.pem new file mode 100644 index 000000000..a2f9688df --- /dev/null +++ b/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE_data/server-cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAeygAwIBAgIBAjANBgkqhkiG9w0BAQsFADA8MTowOAYDVQQDDDFNeVNR +TF9TZXJ2ZXJfOC4wLjE5X0F1dG9fR2VuZXJhdGVkX0NBX0NlcnRpZmljYXRlMB4X +DTIwMDYxMTAzMzg0NloXDTMwMDYwOTAzMzg0NlowQDE+MDwGA1UEAww1TXlTUUxf +U2VydmVyXzguMC4xOV9BdXRvX0dlbmVyYXRlZF9TZXJ2ZXJfQ2VydGlmaWNhdGUw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCcEnEm5hqP1EbEJycOz8Ua +NWp29QdpFUzTWhkKGhVXk+0msmNTw4NBAFB42moY44OU8wvDideOlJNhPRWveD8z +G2lxzJA91p0UK4et8ia9MmeuCGhdC9jxJ8X69WNlUiPyy0hI/ZsqRq9Z0C2eW0iL +JPXsy4X8Xpw3SFwoXf5pR9RFY5Pb2tuyxqmSestu2VXT/NQjJg4CVDR3mFcHPXZB +4elRzH0WshExEGkgy0bg20MJeRc2Qdb5Xx+EakbmwroDWaCn3NSGqQ7jv6Vw0doy +TGvS6h6RHBxnyqRfRgKGlCoOMG9/5+rFJC00QpCUG2vHXHWGoWlMlJ3foN7rj5v9 +AgMBAAGjDTALMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEBAJ5zt2rj4Ag6 +zpN59AWC1Fur8g8l41ksHkSpKPp+PtyO/ngvbMqBpfmK1e7JCKZv/68QXfMyWWAI +hwalqZkXXWHKjuz3wE7dE25PXFXtGJtcZAaj10xt98fzdqt8lQSwh2kbfNwZIz1F +sgAStgE7+ZTcqTgvNB76Os1UK0to+/P0VBWktaVFdyub4Nc2SdPVnZNvrRBXBwOD +3V8ViwywDOFoE7DvCvwx/SVsvoC0Z4j3AMMovO6oHicP7uU83qsQgm1Qru3YeoLR ++DoVi7IPHbWvN7MqFYn3YjNlByO2geblY7MR0BlqbFlmFrqLsUfjsh2ys7/U/knC +dN/klu446fI= +-----END CERTIFICATE----- diff --git a/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE_data/server-key.pem b/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE_data/server-key.pem new file mode 100644 index 000000000..a1dfd5f78 --- /dev/null +++ b/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE_data/server-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAnBJxJuYaj9RGxCcnDs/FGjVqdvUHaRVM01oZChoVV5PtJrJj +U8ODQQBQeNpqGOODlPMLw4nXjpSTYT0Vr3g/MxtpccyQPdadFCuHrfImvTJnrgho +XQvY8SfF+vVjZVIj8stISP2bKkavWdAtnltIiyT17MuF/F6cN0hcKF3+aUfURWOT +29rbssapknrLbtlV0/zUIyYOAlQ0d5hXBz12QeHpUcx9FrIRMRBpIMtG4NtDCXkX +NkHW+V8fhGpG5sK6A1mgp9zUhqkO47+lcNHaMkxr0uoekRwcZ8qkX0YChpQqDjBv +f+fqxSQtNEKQlBtrx1x1hqFpTJSd36De64+b/QIDAQABAoIBAFiah66Dt9SruLkn +WR8piUaFyLlcBib8Nq9OWSTJBhDAJERxxb4KIvvGB+l0ZgNXNp5bFPSfzsZdRwZP +PX5uj8Kd71Dxx3mz211WESMJdEC42u+MSmN4lGLkJ5t/sDwXU91E1vbJM0ve8THV +4/Ag9qA4DX2vVZOeyqT/6YHpSsPNZplqzrbAiwrfHwkctHfgqwOf3QLfhmVQgfCS +VwidBldEUv2whSIiIxh4Rv5St4kA68IBCbJxdpOpyuQBkk6CkxZ7VN9FqOuSd4Pk +Wm7iWyBMZsCmELZh5XAXld4BEt87C5R4CvbPBDZxAv3THk1DNNvpy3PFQfwARRFb +SAToYMECgYEAyL7U8yxpzHDYWd3oCx6vTi9p9N/z0FfAkWrRF6dm4UcSklNiT1Aq +EOnTA+SaW8tV3E64gCWcY23gNP8so/ZseWj6L+peHwtchaP9+KB7yGw2A+05+lOx +VetLTjAOmfpiUXFe5w1q4C1RGhLjZjjzW+GvwdAuchQgUEFaomrV+PUCgYEAxwfH +cmVGFbAktcjU4HSRjKSfawCrut+3YUOLybyku3Q/hP9amG8qkVTFe95CTLjLe2D0 +ccaTTpofFEJ32COeck0g0Ujn/qQ+KXRoauOYs4FB1DtqMpqB78wufWEUpDpbd9/h +J+gJdC/IADd4tJW9zA92g8IA7ZtFmqDtiSpQ0ekCgYAQGkaorvJZpN+l7cf0RGTZ +h7IfI2vCVZer0n6tQA9fmLzjoe6r4AlPzAHSOR8sp9XeUy43kUzHKQQoHCPvjw/K +eWJAP7OHF/k2+x2fOPhU7mEy1W+mJdp+wt4Kio5RSaVjVQ3AyPG+w8PSrJszEvRq +dWMMz+851WV2KpfjmWBKlQKBgQC++4j4DZQV5aMkSKV1CIZOBf3vaIJhXKEUFQPD +PmB4fBEjpwCg+zNGp6iktt65zi17o8qMjrb1mtCt2SY04eD932LZUHNFlwcLMmes +Ad+aiDLJ24WJL1f16eDGcOyktlblDZB5gZ/ovJzXEGOkLXglosTfo77OQculmDy2 +/UL2WQKBgGeKasmGNfiYAcWio+KXgFkHXWtAXB9B91B1OFnCa40wx+qnl71MIWQH +PQ/CZFNWOfGiNEJIZjrHsfNJoeXkhq48oKcT0AVCDYyLV0VxDO4ejT95mGW6njNd +JpvmhwwAjOvuWVr0tn4iXlSK8irjlJHmwcRjLTJq97vE9fsA2MjI +-----END RSA PRIVATE KEY----- diff --git a/apps/emqx_auth_mysql/README.md b/apps/emqx_auth_mysql/README.md new file mode 100644 index 000000000..e55a2103f --- /dev/null +++ b/apps/emqx_auth_mysql/README.md @@ -0,0 +1,167 @@ +emqx_auth_mysql +=============== + +Authentication, ACL with MySQL Database. + +Notice: changed mysql driver to [mysql-otp](https://github.com/mysql-otp/mysql-otp). + +Features +--------- + +- Full *Authentication*, *Superuser*, *ACL* support +- IPv4, IPv6 and TLS support +- Connection pool by [ecpool](https://github.com/emqx/ecpool) +- Completely cover MySQL 5.7, MySQL 8 in our tests + +Build Plugin +------------- + +make && make tests + +Configure Plugin +---------------- + +File: etc/emqx_auth_mysql.conf + +``` +## MySQL server address. +## +## Value: Port | IP:Port +## +## Examples: 3306, 127.0.0.1:3306, localhost:3306 +auth.mysql.server = 127.0.0.1:3306 + +## MySQL pool size. +## +## Value: Number +auth.mysql.pool = 8 + +## MySQL username. +## +## Value: String +## auth.mysql.username = + +## MySQL Password. +## +## Value: String +## auth.mysql.password = + +## MySQL database. +## +## Value: String +auth.mysql.database = mqtt + +## Variables: %u = username, %c = clientid + +## Authentication query. +## +## Note that column names should be 'password' and 'salt' (if used). +## In case column names differ in your DB - please use aliases, +## e.g. "my_column_name as password". +## +## Value: SQL +## +## Variables: +## - %u: username +## - %c: clientid +## - %C: common name of client TLS cert +## - %d: subject of client TLS cert +## +auth.mysql.auth_query = select password from mqtt_user where username = '%u' limit 1 +## auth.mysql.auth_query = select password_hash as password from mqtt_user where username = '%u' limit 1 + +## Password hash. +## +## Value: plain | md5 | sha | sha256 | bcrypt +auth.mysql.password_hash = sha256 + +## sha256 with salt prefix +## auth.mysql.password_hash = salt,sha256 + +## bcrypt with salt only prefix +## auth.mysql.password_hash = salt,bcrypt + +## sha256 with salt suffix +## auth.mysql.password_hash = sha256,salt + +## pbkdf2 with macfun iterations dklen +## macfun: md4, md5, ripemd160, sha, sha224, sha256, sha384, sha512 +## auth.mysql.password_hash = pbkdf2,sha256,1000,20 + +## Superuser query. +## +## Value: SQL +## +## Variables: +## - %u: username +## - %c: clientid +## - %C: common name of client TLS cert +## - %d: subject of client TLS cert +auth.mysql.super_query = select is_superuser from mqtt_user where username = '%u' limit 1 + +## ACL query. +## +## Value: SQL +## +## Variables: +## - %a: ipaddr +## - %u: username +## - %c: clientid +## Note: You can add the 'ORDER BY' statement to control the rules match order +auth.mysql.acl_query = select allow, ipaddr, username, clientid, access, topic from mqtt_acl where ipaddr = '%a' or username = '%u' or username = '$all' or clientid = '%c' + +``` + +Import mqtt.sql +--------------- + +Import mqtt.sql into your database. + +Load Plugin +----------- + +./bin/emqx_ctl plugins load emqx_auth_mysql + +Auth Table +---------- + +Notice: This is a demo table. You could authenticate with any user table. + +```sql +CREATE TABLE `mqtt_user` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `username` varchar(100) DEFAULT NULL, + `password` varchar(100) DEFAULT NULL, + `salt` varchar(35) DEFAULT NULL, + `is_superuser` tinyint(1) DEFAULT 0, + `created` datetime DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `mqtt_username` (`username`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +``` + +ACL Table +---------- + +```sql +CREATE TABLE `mqtt_acl` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `allow` int(1) DEFAULT NULL COMMENT '0: deny, 1: allow', + `ipaddr` varchar(60) DEFAULT NULL COMMENT 'IpAddress', + `username` varchar(100) DEFAULT NULL COMMENT 'Username', + `clientid` varchar(100) DEFAULT NULL COMMENT 'ClientId', + `access` int(2) NOT NULL COMMENT '1: subscribe, 2: publish, 3: pubsub', + `topic` varchar(100) NOT NULL DEFAULT '' COMMENT 'Topic Filter', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +``` + +License +------- + +Apache License Version 2.0 + +Author +------ + +EMQ X Team. diff --git a/apps/emqx_auth_mysql/docker-compose-ssl.yml b/apps/emqx_auth_mysql/docker-compose-ssl.yml new file mode 100644 index 000000000..fe7d442fe --- /dev/null +++ b/apps/emqx_auth_mysql/docker-compose-ssl.yml @@ -0,0 +1,41 @@ +version: '3' + +services: + erlang: + image: erlang:22.3 + volumes: + - ./:/emqx_auth_mysql + networks: + - emqx_bridge + depends_on: + - mysql_server + tty: true + + mysql_server: + image: mysql:${MYSQL_TAG} + restart: always + environment: + MYSQL_ROOT_PASSWORD: public + MYSQL_DATABASE: mqtt + volumes: + - ./test/emqx_auth_mysql_SUITE_data/ca.pem:/etc/certs/ca-cert.pem + - ./test/emqx_auth_mysql_SUITE_data/server-cert.pem:/etc/certs/server-cert.pem + - ./test/emqx_auth_mysql_SUITE_data/server-key.pem:/etc/certs/server-key.pem + networks: + - emqx_bridge + command: + --bind-address "::" + --default-authentication-plugin=mysql_native_password + --character-set-server=utf8mb4 + --collation-server=utf8mb4_general_ci + --explicit_defaults_for_timestamp=true + --lower_case_table_names=1 + --max_allowed_packet=128M + --skip-symbolic-links + --ssl-ca=/etc/certs/ca.pem + --ssl-cert=/etc/certs/server-cert.pem + --ssl-key=/etc/certs/server-key.pem + +networks: + emqx_bridge: + driver: bridge diff --git a/apps/emqx_auth_mysql/docker-compose.yml b/apps/emqx_auth_mysql/docker-compose.yml new file mode 100644 index 000000000..c37bf983b --- /dev/null +++ b/apps/emqx_auth_mysql/docker-compose.yml @@ -0,0 +1,34 @@ +version: '3' + +services: + erlang: + image: erlang:22.3 + volumes: + - ./:/emqx_auth_mysql + networks: + - emqx_bridge + depends_on: + - mysql_server + tty: true + + mysql_server: + image: mysql:${MYSQL_TAG} + restart: always + environment: + MYSQL_ROOT_PASSWORD: public + MYSQL_DATABASE: mqtt + networks: + - emqx_bridge + command: + --bind-address "::" + --default-authentication-plugin=mysql_native_password + --character-set-server=utf8mb4 + --collation-server=utf8mb4_general_ci + --explicit_defaults_for_timestamp=true + --lower_case_table_names=1 + --max_allowed_packet=128M + --skip-symbolic-links + +networks: + emqx_bridge: + driver: bridge diff --git a/apps/emqx_auth_mysql/include/emqx_auth_mysql.hrl b/apps/emqx_auth_mysql/include/emqx_auth_mysql.hrl new file mode 100644 index 000000000..fca431e81 --- /dev/null +++ b/apps/emqx_auth_mysql/include/emqx_auth_mysql.hrl @@ -0,0 +1,23 @@ + +-define(APP, emqx_auth_mysql). + +-record(auth_metrics, { + success = 'client.auth.success', + failure = 'client.auth.failure', + ignore = 'client.auth.ignore' + }). + +-record(acl_metrics, { + allow = 'client.acl.allow', + deny = 'client.acl.deny', + ignore = 'client.acl.ignore' + }). + +-define(METRICS(Type), tl(tuple_to_list(#Type{}))). +-define(METRICS(Type, K), #Type{}#Type.K). + +-define(AUTH_METRICS, ?METRICS(auth_metrics)). +-define(AUTH_METRICS(K), ?METRICS(auth_metrics, K)). + +-define(ACL_METRICS, ?METRICS(acl_metrics)). +-define(ACL_METRICS(K), ?METRICS(acl_metrics, K)). diff --git a/apps/emqx_auth_mysql/mqtt.sql b/apps/emqx_auth_mysql/mqtt.sql new file mode 100644 index 000000000..9635bee58 --- /dev/null +++ b/apps/emqx_auth_mysql/mqtt.sql @@ -0,0 +1,41 @@ + +DROP TABLE IF EXISTS `mqtt_acl`; + +CREATE TABLE `mqtt_acl` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `allow` int(1) DEFAULT NULL COMMENT '0: deny, 1: allow', + `ipaddr` varchar(60) DEFAULT NULL COMMENT 'IpAddress', + `username` varchar(100) DEFAULT NULL COMMENT 'Username', + `clientid` varchar(100) DEFAULT NULL COMMENT 'ClientId', + `access` int(2) NOT NULL COMMENT '1: subscribe, 2: publish, 3: pubsub', + `topic` varchar(100) NOT NULL DEFAULT '' COMMENT 'Topic Filter', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +LOCK TABLES `mqtt_acl` WRITE; + +INSERT INTO `mqtt_acl` (`id`, `allow`, `ipaddr`, `username`, `clientid`, `access`, `topic`) +VALUES + (1,1,NULL,'$all',NULL,2,'#'), + (2,0,NULL,'$all',NULL,1,'$SYS/#'), + (3,0,NULL,'$all',NULL,1,'eq #'), + (4,1,'127.0.0.1',NULL,NULL,2,'$SYS/#'), + (5,1,'127.0.0.1',NULL,NULL,2,'#'), + (6,1,NULL,'dashboard',NULL,1,'$SYS/#'); + +UNLOCK TABLES; + + +DROP TABLE IF EXISTS `mqtt_user`; + +CREATE TABLE `mqtt_user` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `username` varchar(100) DEFAULT NULL, + `password` varchar(100) DEFAULT NULL, + `salt` varchar(35) DEFAULT NULL, + `is_superuser` tinyint(1) DEFAULT 0, + `created` datetime DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `mqtt_username` (`username`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; + diff --git a/apps/emqx_auth_mysql/priv/emqx_auth_mysql.schema b/apps/emqx_auth_mysql/priv/emqx_auth_mysql.schema new file mode 100644 index 000000000..37eed8a5f --- /dev/null +++ b/apps/emqx_auth_mysql/priv/emqx_auth_mysql.schema @@ -0,0 +1,129 @@ +%%-*- mode: erlang -*- +%% emqx_auth_mysql config mapping +{mapping, "auth.mysql.server", "emqx_auth_mysql.server", [ + {default, {"127.0.0.1", 3306}}, + {datatype, [integer, ip, string]} +]}. + +{mapping, "auth.mysql.pool", "emqx_auth_mysql.server", [ + {default, 8}, + {datatype, integer} +]}. + +{mapping, "auth.mysql.username", "emqx_auth_mysql.server", [ + {default, ""}, + {datatype, string} +]}. + +{mapping, "auth.mysql.password", "emqx_auth_mysql.server", [ + {default, ""}, + {datatype, string} +]}. + +{mapping, "auth.mysql.database", "emqx_auth_mysql.server", [ + {default, "mqtt"}, + {datatype, string} +]}. + +{mapping, "auth.mysql.query_timeout", "emqx_auth_mysql.server", [ + {default, ""}, + {datatype, string} +]}. + +{mapping, "auth.mysql.ssl", "emqx_auth_mysql.server", [ + {default, off}, + {datatype, flag} +]}. + +{mapping, "auth.mysql.ssl.cafile", "emqx_auth_mysql.server", [ + {default, ""}, + {datatype, string} +]}. + +{mapping, "auth.mysql.ssl.certfile", "emqx_auth_mysql.server", [ + {default, ""}, + {datatype, string} +]}. + +{mapping, "auth.mysql.ssl.keyfile", "emqx_auth_mysql.server", [ + {default, ""}, + {datatype, string} +]}. + +{translation, "emqx_auth_mysql.server", fun(Conf) -> + {MyHost, MyPort} = + case cuttlefish:conf_get("auth.mysql.server", Conf) of + {Ip, Port} -> {Ip, Port}; + S -> case string:tokens(S, ":") of + [Domain] -> {Domain, 3306}; + [Domain, Port] -> {Domain, list_to_integer(Port)} + end + end, + Pool = cuttlefish:conf_get("auth.mysql.pool", Conf), + Username = cuttlefish:conf_get("auth.mysql.username", Conf), + Passwd = cuttlefish:conf_get("auth.mysql.password", Conf), + DB = cuttlefish:conf_get("auth.mysql.database", Conf), + Timeout = case cuttlefish:conf_get("auth.mysql.query_timeout", Conf) of + "" -> 300000; + Duration -> + case cuttlefish_duration:parse(Duration, ms) of + {error, Reason} -> error(Reason); + Ms when is_integer(Ms) -> Ms + end + end, + Options = [{pool_size, Pool}, + {auto_reconnect, 1}, + {host, MyHost}, + {port, MyPort}, + {user, Username}, + {password, Passwd}, + {database, DB}, + {encoding, utf8}, + {query_timeout, Timeout}, + {keep_alive, true}], + Options1 = + case cuttlefish:conf_get("auth.mysql.ssl", Conf) of + true -> + CA = cuttlefish:conf_get("auth.mysql.ssl.cafile", Conf), + Cert = cuttlefish:conf_get("auth.mysql.ssl.certfile", Conf), + Key = cuttlefish:conf_get("auth.mysql.ssl.keyfile", Conf), + Options ++ [{ssl, {server_name_indication, disable}, + {cacertfile, CA}, + {certfile, Cert}, + {keyfile, Key}}]; + _ -> + Options + end, + case inet:parse_address(MyHost) of + {ok, IpAddr} when tuple_size(IpAddr) =:= 8 -> + [{tcp_options, [inet6]} | Options1]; + _ -> + Options1 + end +end}. + +{mapping, "auth.mysql.auth_query", "emqx_auth_mysql.auth_query", [ + {datatype, string} +]}. + +{mapping, "auth.mysql.password_hash", "emqx_auth_mysql.password_hash", [ + {datatype, string} +]}. + +{mapping, "auth.mysql.super_query", "emqx_auth_mysql.super_query", [ + {datatype, string} +]}. + +{mapping, "auth.mysql.acl_query", "emqx_auth_mysql.acl_query", [ + {datatype, string} +]}. + +{translation, "emqx_auth_mysql.password_hash", fun(Conf) -> + HashValue = cuttlefish:conf_get("auth.mysql.password_hash", Conf), + case string:tokens(HashValue, ",") of + [Hash] -> list_to_atom(Hash); + [Prefix, Suffix] -> {list_to_atom(Prefix), list_to_atom(Suffix)}; + [Hash, MacFun, Iterations, Dklen] -> {list_to_atom(Hash), list_to_atom(MacFun), list_to_integer(Iterations), list_to_integer(Dklen)}; + _ -> plain + end +end}. diff --git a/apps/emqx_auth_mysql/rebar.config b/apps/emqx_auth_mysql/rebar.config new file mode 100644 index 000000000..bc21ad1b6 --- /dev/null +++ b/apps/emqx_auth_mysql/rebar.config @@ -0,0 +1,4 @@ +{deps, + [ + {mysql, {git, "https://github.com/emqx/mysql-otp", {tag, "1.6.1"}}} + ]}. diff --git a/apps/emqx_auth_mysql/src/emqx_acl_mysql.erl b/apps/emqx_auth_mysql/src/emqx_acl_mysql.erl new file mode 100644 index 000000000..8af659719 --- /dev/null +++ b/apps/emqx_auth_mysql/src/emqx_acl_mysql.erl @@ -0,0 +1,119 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_acl_mysql). + +-include("emqx_auth_mysql.hrl"). + +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). + +%% ACL Callbacks +-export([ register_metrics/0 + , check_acl/5 + , description/0 + ]). + +-spec(register_metrics() -> ok). +register_metrics() -> + lists:foreach(fun emqx_metrics:ensure/1, ?ACL_METRICS). + +check_acl(ClientInfo, PubSub, Topic, NoMatchAction, #{pool := Pool} = State) -> + case do_check_acl(Pool, ClientInfo, PubSub, Topic, NoMatchAction, State) of + ok -> emqx_metrics:inc(?ACL_METRICS(ignore)), ok; + {stop, allow} -> emqx_metrics:inc(?ACL_METRICS(allow)), {stop, allow}; + {stop, deny} -> emqx_metrics:inc(?ACL_METRICS(deny)), {stop, deny} + end. + +do_check_acl(_Pool, #{username := <<$$, _/binary>>}, _PubSub, _Topic, _NoMatchAction, _State) -> + ok; +do_check_acl(Pool, ClientInfo, PubSub, Topic, _NoMatchAction, #{acl_query := {AclSql, AclParams}}) -> + case emqx_auth_mysql_cli:query(Pool, AclSql, AclParams, ClientInfo) of + {ok, _Columns, []} -> ok; + {ok, _Columns, Rows} -> + Rules = filter(PubSub, compile(Rows)), + case match(ClientInfo, Topic, Rules) of + {matched, allow} -> {stop, allow}; + {matched, deny} -> {stop, deny}; + nomatch -> ok + end; + {error, Reason} -> + ?LOG(error, "[MySQL] do_check_acl error: ~p~n", [Reason]), + ok + end. + +match(_ClientInfo, _Topic, []) -> + nomatch; + +match(ClientInfo, Topic, [Rule|Rules]) -> + case emqx_access_rule:match(ClientInfo, Topic, Rule) of + nomatch -> + match(ClientInfo, Topic, Rules); + {matched, AllowDeny} -> + {matched, AllowDeny} + end. + +filter(PubSub, Rules) -> + [Term || Term = {_, _, Access, _} <- Rules, + Access =:= PubSub orelse Access =:= pubsub]. + +compile(Rows) -> + compile(Rows, []). +compile([], Acc) -> + Acc; +compile([[Allow, IpAddr, Username, ClientId, Access, Topic]|T], Acc) -> + Who = who(IpAddr, Username, ClientId), + Term = {allow(Allow), Who, access(Access), [topic(Topic)]}, + compile(T, [emqx_access_rule:compile(Term) | Acc]). + +who(_, <<"$all">>, _) -> + all; +who(null, null, null) -> + throw(undefined_who); +who(CIDR, Username, ClientId) -> + Cols = [{ipaddr, b2l(CIDR)}, {user, Username}, {client, ClientId}], + case [{C, V} || {C, V} <- Cols, not empty(V)] of + [Who] -> Who; + Conds -> {'and', Conds} + end. + +allow(1) -> allow; +allow(0) -> deny; +allow(<<"1">>) -> allow; +allow(<<"0">>) -> deny. + +access(1) -> subscribe; +access(2) -> publish; +access(3) -> pubsub; +access(<<"1">>) -> subscribe; +access(<<"2">>) -> publish; +access(<<"3">>) -> pubsub. + +topic(<<"eq ", Topic/binary>>) -> + {eq, Topic}; +topic(Topic) -> + Topic. + +description() -> + "ACL with Mysql". + +b2l(null) -> null; +b2l(B) -> binary_to_list(B). + +empty(null) -> true; +empty("") -> true; +empty(<<>>) -> true; +empty(_) -> false. diff --git a/apps/emqx_auth_mysql/src/emqx_auth_mysql.app.src b/apps/emqx_auth_mysql/src/emqx_auth_mysql.app.src new file mode 100644 index 000000000..89f2822f9 --- /dev/null +++ b/apps/emqx_auth_mysql/src/emqx_auth_mysql.app.src @@ -0,0 +1,14 @@ +{application, emqx_auth_mysql, + [{description, "EMQ X Authentication/ACL with MySQL"}, + {vsn, "5.0.0"}, % strict semver, bump manually! + {modules, []}, + {registered, [emqx_auth_mysql_sup]}, + {applications, [kernel,stdlib,mysql,ecpool,emqx_passwd,emqx_libs]}, + {mod, {emqx_auth_mysql_app,[]}}, + {env, []}, + {licenses, ["Apache-2.0"]}, + {maintainers, ["EMQ X Team "]}, + {links, [{"Homepage", "https://emqx.io/"}, + {"Github", "https://github.com/emqx/emqx-auth-mysql"} + ]} + ]}. diff --git a/apps/emqx_auth_mysql/src/emqx_auth_mysql.erl b/apps/emqx_auth_mysql/src/emqx_auth_mysql.erl new file mode 100644 index 000000000..aa2e31ed8 --- /dev/null +++ b/apps/emqx_auth_mysql/src/emqx_auth_mysql.erl @@ -0,0 +1,91 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_mysql). + +-include("emqx_auth_mysql.hrl"). + +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). +-include_lib("emqx_libs/include/types.hrl"). + +-export([ register_metrics/0 + , check/3 + , description/0 + ]). + +-define(EMPTY(Username), (Username =:= undefined orelse Username =:= <<>>)). + +-spec(register_metrics() -> ok). +register_metrics() -> + lists:foreach(fun emqx_metrics:ensure/1, ?AUTH_METRICS). + +check(ClientInfo = #{password := Password}, AuthResult, + #{auth_query := {AuthSql, AuthParams}, + super_query := SuperQuery, + hash_type := HashType, + pool := Pool}) -> + CheckPass = case emqx_auth_mysql_cli:query(Pool, AuthSql, AuthParams, ClientInfo) of + {ok, [<<"password">>], [[PassHash]]} -> + check_pass({PassHash, Password}, HashType); + {ok, [<<"password">>, <<"salt">>], [[PassHash, Salt]]} -> + check_pass({PassHash, Salt, Password}, HashType); + {ok, _Columns, []} -> + {error, not_found}; + {error, Reason} -> + ?LOG(error, "[MySQL] query '~p' failed: ~p", [AuthSql, Reason]), + {error, Reason} + end, + case CheckPass of + ok -> + emqx_metrics:inc(?AUTH_METRICS(success)), + {stop, AuthResult#{is_superuser => is_superuser(Pool, SuperQuery, ClientInfo), + anonymous => false, + auth_result => success}}; + {error, not_found} -> + emqx_metrics:inc(?AUTH_METRICS(ignore)), ok; + {error, ResultCode} -> + ?LOG(error, "[MySQL] Auth from mysql failed: ~p", [ResultCode]), + emqx_metrics:inc(?AUTH_METRICS(failure)), + {stop, AuthResult#{auth_result => ResultCode, anonymous => false}} + end. + +%%-------------------------------------------------------------------- +%% Is Superuser? +%%-------------------------------------------------------------------- + +-spec(is_superuser(atom(), maybe({string(), list()}), emqx_types:client()) -> boolean()). +is_superuser(_Pool, undefined, _ClientInfo) -> false; +is_superuser(Pool, {SuperSql, Params}, ClientInfo) -> + case emqx_auth_mysql_cli:query(Pool, SuperSql, Params, ClientInfo) of + {ok, [_Super], [[1]]} -> + true; + {ok, [_Super], [[_False]]} -> + false; + {ok, [_Super], []} -> + false; + {error, _Error} -> + false + end. + +check_pass(Password, HashType) -> + case emqx_passwd:check_pass(Password, HashType) of + ok -> ok; + {error, _Reason} -> {error, not_authorized} + end. + +description() -> "Authentication with MySQL". + diff --git a/apps/emqx_auth_mysql/src/emqx_auth_mysql_app.erl b/apps/emqx_auth_mysql/src/emqx_auth_mysql_app.erl new file mode 100644 index 000000000..26895cd9a --- /dev/null +++ b/apps/emqx_auth_mysql/src/emqx_auth_mysql_app.erl @@ -0,0 +1,74 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_mysql_app). + +-behaviour(application). + +-emqx_plugin(auth). + +-include("emqx_auth_mysql.hrl"). + +-import(emqx_auth_mysql_cli, [parse_query/1]). + +%% Application callbacks +-export([ start/2 + , prep_stop/1 + , stop/1 + ]). + +%%-------------------------------------------------------------------- +%% Application callbacks +%%-------------------------------------------------------------------- + +start(_StartType, _StartArgs) -> + {ok, Sup} = emqx_auth_mysql_sup:start_link(), + if_enabled(auth_query, fun load_auth_hook/1), + if_enabled(acl_query, fun load_acl_hook/1), + + {ok, Sup}. + +prep_stop(State) -> + emqx:unhook('client.authenticate', fun emqx_auth_mysql:check/3), + emqx:unhook('client.check_acl', fun emqx_acl_mysql:check_acl/5), + State. + +stop(_State) -> + ok. + +load_auth_hook(AuthQuery) -> + ok = emqx_auth_mysql:register_metrics(), + SuperQuery = parse_query(application:get_env(?APP, super_query, undefined)), + {ok, HashType} = application:get_env(?APP, password_hash), + Params = #{auth_query => AuthQuery, + super_query => SuperQuery, + hash_type => HashType, + pool => ?APP}, + emqx:hook('client.authenticate', fun emqx_auth_mysql:check/3, [Params]). + +load_acl_hook(AclQuery) -> + ok = emqx_acl_mysql:register_metrics(), + emqx:hook('client.check_acl', fun emqx_acl_mysql:check_acl/5, [#{acl_query => AclQuery, pool =>?APP}]). + +%%-------------------------------------------------------------------- +%% Internal function +%%-------------------------------------------------------------------- + +if_enabled(Cfg, Fun) -> + case application:get_env(?APP, Cfg) of + {ok, Query} -> Fun(parse_query(Query)); + undefined -> ok + end. diff --git a/apps/emqx_auth_mysql/src/emqx_auth_mysql_cli.erl b/apps/emqx_auth_mysql/src/emqx_auth_mysql_cli.erl new file mode 100644 index 000000000..2868e83cc --- /dev/null +++ b/apps/emqx_auth_mysql/src/emqx_auth_mysql_cli.erl @@ -0,0 +1,91 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_mysql_cli). + +-behaviour(ecpool_worker). + +-include("emqx_auth_mysql.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). + +-export([ parse_query/1 + , connect/1 + , query/4 + ]). + +%%-------------------------------------------------------------------- +%% Avoid SQL Injection: Parse SQL to Parameter Query. +%%-------------------------------------------------------------------- + +parse_query(undefined) -> + undefined; +parse_query(Sql) -> + case re:run(Sql, "'%[ucCad]'", [global, {capture, all, list}]) of + {match, Variables} -> + Params = [Var || [Var] <- Variables], + {re:replace(Sql, "'%[ucCad]'", "?", [global, {return, list}]), Params}; + nomatch -> + {Sql, []} + end. + +%%-------------------------------------------------------------------- +%% MySQL Connect/Query +%%-------------------------------------------------------------------- + +connect(Options) -> + case mysql:start_link(Options) of + {ok, Pid} -> {ok, Pid}; + ignore -> {error, ignore}; + {error, Reason = {{_, {error, econnrefused}}, _}} -> + ?LOG(error, "[MySQL] Can't connect to MySQL server: Connection refused."), + {error, Reason}; + {error, Reason = {ErrorCode, _, Error}} -> + ?LOG(error, "[MySQL] Can't connect to MySQL server: ~p - ~p", [ErrorCode, Error]), + {error, Reason}; + {error, Reason} -> + ?LOG(error, "[MySQL] Can't connect to MySQL server: ~p", [Reason]), + {error, Reason} + end. + +query(Pool, Sql, Params, ClientInfo) -> + ecpool:with_client(Pool, fun(C) -> mysql:query(C, Sql, replvar(Params, ClientInfo)) end). + +replvar(Params, ClientInfo) -> + replvar(Params, ClientInfo, []). + +replvar([], _ClientInfo, Acc) -> + lists:reverse(Acc); + +replvar(["'%u'" | Params], ClientInfo, Acc) -> + replvar(Params, ClientInfo, [safe_get(username, ClientInfo) | Acc]); +replvar(["'%c'" | Params], ClientInfo = #{clientid := ClientId}, Acc) -> + replvar(Params, ClientInfo, [ClientId | Acc]); +replvar(["'%a'" | Params], ClientInfo = #{peerhost := IpAddr}, Acc) -> + replvar(Params, ClientInfo, [inet_parse:ntoa(IpAddr) | Acc]); +replvar(["'%C'" | Params], ClientInfo, Acc) -> + replvar(Params, ClientInfo, [safe_get(cn, ClientInfo)| Acc]); +replvar(["'%d'" | Params], ClientInfo, Acc) -> + replvar(Params, ClientInfo, [safe_get(dn, ClientInfo)| Acc]); +replvar([Param | Params], ClientInfo, Acc) -> + replvar(Params, ClientInfo, [Param | Acc]). + +safe_get(K, ClientInfo) -> + bin(maps:get(K, ClientInfo, "undefined")). + +bin(A) when is_atom(A) -> atom_to_binary(A, utf8); +bin(B) when is_binary(B) -> B; +bin(X) -> X. diff --git a/apps/emqx_auth_mysql/src/emqx_auth_mysql_sup.erl b/apps/emqx_auth_mysql/src/emqx_auth_mysql_sup.erl new file mode 100644 index 000000000..0b2bf2c38 --- /dev/null +++ b/apps/emqx_auth_mysql/src/emqx_auth_mysql_sup.erl @@ -0,0 +1,40 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_mysql_sup). + +-behaviour(supervisor). + +-include("emqx_auth_mysql.hrl"). + +-export([start_link/0]). + +%% Supervisor callbacks +-export([init/1]). + +start_link() -> + supervisor:start_link({local, ?MODULE}, ?MODULE, []). + +%%-------------------------------------------------------------------- +%% Supervisor callbacks +%%-------------------------------------------------------------------- + +init([]) -> + %% MySQL Connection Pool. + {ok, Server} = application:get_env(?APP, server), + PoolSpec = ecpool:pool_spec(?APP, ?APP, emqx_auth_mysql_cli, Server), + {ok, {{one_for_one, 10, 100}, [PoolSpec]}}. + diff --git a/apps/emqx_auth_mysql/test/emqx_auth_mysql_SUITE.erl b/apps/emqx_auth_mysql/test/emqx_auth_mysql_SUITE.erl new file mode 100644 index 000000000..0d4c16e03 --- /dev/null +++ b/apps/emqx_auth_mysql/test/emqx_auth_mysql_SUITE.erl @@ -0,0 +1,234 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_mysql_SUITE). + +-compile(export_all). +-compile(nowarn_export_all). + +-define(APP, emqx_auth_mysql). + +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("eunit/include/eunit.hrl"). +-include_lib("common_test/include/ct.hrl"). + +-define(DROP_ACL_TABLE, <<"DROP TABLE IF EXISTS mqtt_acl">>). + +-define(CREATE_ACL_TABLE, <<"CREATE TABLE mqtt_acl (" + " id int(11) unsigned NOT NULL AUTO_INCREMENT," + " allow int(1) DEFAULT NULL COMMENT '0: deny, 1: allow'," + " ipaddr varchar(60) DEFAULT NULL COMMENT 'IpAddress'," + " username varchar(100) DEFAULT NULL COMMENT 'Username'," + " clientid varchar(100) DEFAULT NULL COMMENT 'ClientId'," + " access int(2) NOT NULL COMMENT '1: subscribe, 2: publish, 3: pubsub'," + " topic varchar(100) NOT NULL DEFAULT '' COMMENT 'Topic Filter'," + " PRIMARY KEY (`id`)" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4">>). + +-define(INIT_ACL, <<"INSERT INTO mqtt_acl (id, allow, ipaddr, username, clientid, access, topic)" + "VALUES (1,1,'127.0.0.1','u1','c1',1,'t1')," + "(2,0,'127.0.0.1','u2','c2',1,'t1')," + "(3,1,'10.10.0.110','u1','c1',1,'t1')," + "(4,1,'127.0.0.1','u3','c3',3,'t1')">>). + +-define(DROP_AUTH_TABLE, <<"DROP TABLE IF EXISTS `mqtt_user`">>). + +-define(CREATE_AUTH_TABLE, <<"CREATE TABLE `mqtt_user` (" + "`id` int(11) unsigned NOT NULL AUTO_INCREMENT," + "`username` varchar(100) DEFAULT NULL," + "`password` varchar(100) DEFAULT NULL," + "`salt` varchar(100) DEFAULT NULL," + "`is_superuser` tinyint(1) DEFAULT 0," + "`created` datetime DEFAULT NULL," + "PRIMARY KEY (`id`)," + "UNIQUE KEY `mqtt_username` (`username`)" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4">>). + +-define(INIT_AUTH, <<"INSERT INTO mqtt_user (id, is_superuser, username, password, salt)" + "VALUES (1, 1, 'plain', 'plain', 'salt')," + "(2, 0, 'md5', '1bc29b36f623ba82aaf6724fd3b16718', 'salt')," + "(3, 0, 'sha', 'd8f4590320e1343a915b6394170650a8f35d6926', 'salt')," + "(4, 0, 'sha256', '5d5b09f6dcb2d53a5fffc60c4ac0d55fabdf556069d6631545f42aa6e3500f2e', 'salt')," + "(5, 0, 'pbkdf2_password', 'cdedb5281bb2f801565a1122b2563515', 'ATHENA.MIT.EDUraeburn')," + "(6, 0, 'bcrypt_foo', '$2a$12$sSS8Eg.ovVzaHzi1nUHYK.HbUIOdlQI0iS22Q5rd5z.JVVYH6sfm6', '$2a$12$sSS8Eg.ovVzaHzi1nUHYK.')," + "(7, 0, 'bcrypt', '$2y$16$rEVsDarhgHYB0TGnDFJzyu5f.T.Ha9iXMTk9J36NCMWWM7O16qyaK', 'salt')," + "(8, 0, 'bcrypt_wrong', '$2y$16$rEVsDarhgHYB0TGnDFJzyu', 'salt')">>). + +%%-------------------------------------------------------------------- +%% Setups +%%-------------------------------------------------------------------- + +all() -> + emqx_ct:all(?MODULE). + +init_per_suite(Cfg) -> + emqx_ct_helpers:start_apps([emqx_auth_mysql], fun set_special_configs/1), + init_mysql_data(), + Cfg. + +end_per_suite(_) -> + deinit_mysql_data(), + emqx_ct_helpers:stop_apps([emqx_auth_mysql]), + ok. + +set_special_configs(emqx) -> + application:set_env(emqx, allow_anonymous, false), + application:set_env(emqx, enable_acl_cache, false), + application:set_env(emqx, plugins_loaded_file, + emqx_ct_helpers:deps_path(emqx, "test/emqx_SUITE_data/loaded_plugins")); + +set_special_configs(_App) -> + ok. + +init_mysql_data() -> + {ok, Pid} = ecpool_worker:client(gproc_pool:pick_worker({ecpool, ?APP})), + %% Users + ok = mysql:query(Pid, ?DROP_AUTH_TABLE), + ok = mysql:query(Pid, ?CREATE_AUTH_TABLE), + ok = mysql:query(Pid, ?INIT_AUTH), + + %% ACLs + ok = mysql:query(Pid, ?DROP_ACL_TABLE), + ok = mysql:query(Pid, ?CREATE_ACL_TABLE), + ok = mysql:query(Pid, ?INIT_ACL). + +deinit_mysql_data() -> + {ok, Pid} = ecpool_worker:client(gproc_pool:pick_worker({ecpool, ?APP})), + ok = mysql:query(Pid, ?DROP_AUTH_TABLE), + ok = mysql:query(Pid, ?DROP_ACL_TABLE). + +%%-------------------------------------------------------------------- +%% Test cases +%%-------------------------------------------------------------------- + +t_check_acl(_) -> + User0 = #{zone => external,peerhost => {127,0,0,1}}, + allow = emqx_access_control:check_acl(User0, subscribe, <<"t1">>), + User1 = #{zone => external, clientid => <<"c1">>, username => <<"u1">>, peerhost => {127,0,0,1}}, + User2 = #{zone => external, clientid => <<"c2">>, username => <<"u2">>, peerhost => {127,0,0,1}}, + allow = emqx_access_control:check_acl(User1, subscribe, <<"t1">>), + deny = emqx_access_control:check_acl(User2, subscribe, <<"t1">>), + + User3 = #{zone => external, peerhost => {10,10,0,110}, clientid => <<"c1">>, username => <<"u1">>}, + User4 = #{zone => external, peerhost => {10,10,10,110}, clientid => <<"c1">>, username => <<"u1">>}, + allow = emqx_access_control:check_acl(User3, subscribe, <<"t1">>), + allow = emqx_access_control:check_acl(User3, subscribe, <<"t1">>), + allow = emqx_access_control:check_acl(User3, subscribe, <<"t2">>),%% nomatch -> ignore -> emqx acl + allow = emqx_access_control:check_acl(User4, subscribe, <<"t1">>),%% nomatch -> ignore -> emqx acl + User5 = #{zone => external, peerhost => {127,0,0,1}, clientid => <<"c3">>, username => <<"u3">>}, + allow = emqx_access_control:check_acl(User5, subscribe, <<"t1">>), + allow = emqx_access_control:check_acl(User5, publish, <<"t1">>). + +t_acl_super(_Config) -> + reload([{password_hash, plain}, + {auth_query, "select password from mqtt_user where username = '%u' limit 1"}]), + {ok, C} = emqtt:start_link([{host, "localhost"}, + {clientid, <<"simpleClient">>}, + {username, <<"plain">>}, + {password, <<"plain">>}]), + {ok, _} = emqtt:connect(C), + timer:sleep(10), + emqtt:subscribe(C, <<"TopicA">>, qos2), + timer:sleep(1000), + emqtt:publish(C, <<"TopicA">>, <<"Payload">>, qos2), + timer:sleep(1000), + receive + {publish, #{payload := Payload}} -> + ?assertEqual(<<"Payload">>, Payload) + after + 1000 -> + ct:fail({receive_timeout, <<"Payload">>}), + ok + end, + emqtt:disconnect(C). + +t_check_auth(_) -> + Plain = #{clientid => <<"client1">>, username => <<"plain">>, zone => external}, + Md5 = #{clientid => <<"md5">>, username => <<"md5">>, zone => external}, + Sha = #{clientid => <<"sha">>, username => <<"sha">>, zone => external}, + Sha256 = #{clientid => <<"sha256">>, username => <<"sha256">>, zone => external}, + Pbkdf2 = #{clientid => <<"pbkdf2_password">>, username => <<"pbkdf2_password">>, zone => external}, + BcryptFoo = #{clientid => <<"bcrypt_foo">>, username => <<"bcrypt_foo">>, zone => external}, + User1 = #{clientid => <<"bcrypt_foo">>, username => <<"user">>, zone => external}, + Bcrypt = #{clientid => <<"bcrypt">>, username => <<"bcrypt">>, zone => external}, + BcryptWrong = #{clientid => <<"bcrypt_wrong">>, username => <<"bcrypt_wrong">>, zone => external}, + reload([{password_hash, plain}]), + {ok,#{is_superuser := true}} = + emqx_access_control:authenticate(Plain#{password => <<"plain">>}), + reload([{password_hash, md5}]), + {ok,#{is_superuser := false}} = + emqx_access_control:authenticate(Md5#{password => <<"md5">>}), + reload([{password_hash, sha}]), + {ok,#{is_superuser := false}} = + emqx_access_control:authenticate(Sha#{password => <<"sha">>}), + reload([{password_hash, sha256}]), + {ok,#{is_superuser := false}} = + emqx_access_control:authenticate(Sha256#{password => <<"sha256">>}), + reload([{password_hash, bcrypt}]), + {ok,#{is_superuser := false}} = + emqx_access_control:authenticate(Bcrypt#{password => <<"password">>}), + {error, not_authorized} = + emqx_access_control:authenticate(BcryptWrong#{password => <<"password">>}), + %%pbkdf2 sha + reload([{password_hash, {pbkdf2, sha, 1, 16}}, + {auth_query, "select password, salt from mqtt_user where username = '%u' limit 1"}]), + {ok,#{is_superuser := false}} = + emqx_access_control:authenticate(Pbkdf2#{password => <<"password">>}), + reload([{password_hash, {salt, bcrypt}}]), + {ok,#{is_superuser := false}} = + emqx_access_control:authenticate(BcryptFoo#{password => <<"foo">>}), + {error, _} = emqx_access_control:authenticate(User1#{password => <<"foo">>}), + {error, not_authorized} = emqx_access_control:authenticate(Bcrypt#{password => <<"password">>}). + +t_comment_config(_) -> + application:stop(?APP), + [application:unset_env(?APP, Par) || Par <- [acl_query, auth_query]], + application:start(?APP). + +t_placeholders(_) -> + ClientA = #{username => <<"plain">>, clientid => <<"plain">>, zone => external}, + + reload([{password_hash, plain}, + {auth_query, "select password from mqtt_user where username = '%u' and 'a_cn_val' = '%C' limit 1"}]), + {error, not_authorized} = + emqx_access_control:authenticate(ClientA#{password => <<"plain">>}), + {error, not_authorized} = + emqx_access_control:authenticate(ClientA#{password => <<"plain">>, cn => undefined}), + {ok, _} = + emqx_access_control:authenticate(ClientA#{password => <<"plain">>, cn => <<"a_cn_val">>}), + + reload([{auth_query, "select password from mqtt_user where username = '%c' and 'a_dn_val' = '%d' limit 1"}]), + {error, not_authorized} = + emqx_access_control:authenticate(ClientA#{password => <<"plain">>}), + {error, not_authorized} = + emqx_access_control:authenticate(ClientA#{password => <<"plain">>, dn => undefined}), + {ok, _} = + emqx_access_control:authenticate(ClientA#{password => <<"plain">>, dn => <<"a_dn_val">>}), + + reload([{auth_query, "select password from mqtt_user where username = '%u' and '192.168.1.5' = '%a' limit 1"}]), + {error, not_authorized} = + emqx_access_control:authenticate(ClientA#{password => <<"plain">>}), + {ok, _} = + emqx_access_control:authenticate(ClientA#{password => <<"plain">>, peerhost => {192,168,1,5}}). + +%%-------------------------------------------------------------------- +%% Internal funcs +%%-------------------------------------------------------------------- + +reload(Config) when is_list(Config) -> + application:stop(?APP), + [application:set_env(?APP, K, V) || {K, V} <- Config], + application:start(?APP). diff --git a/apps/emqx_auth_mysql/test/emqx_auth_mysql_SUITE_data/ca-key.pem b/apps/emqx_auth_mysql/test/emqx_auth_mysql_SUITE_data/ca-key.pem new file mode 100644 index 000000000..e9717011e --- /dev/null +++ b/apps/emqx_auth_mysql/test/emqx_auth_mysql_SUITE_data/ca-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA0kGUBi9NDp65jgdxKfizIfuSr2wpwb44yM9SuP4oUQSULOA2 +4iFpLR/c5FAYHU81y9Vx91dQjdZfffaBZuv2zVvteXUkol8Nez7boKbo2E41MTew +8edtNKZAQVvnaHAC2NCZxjchCzUCDEoUUcl+cIERZ8R48FBqK5iTVcMRIx1akwus ++dhBqP0ykA5TGOWZkJrLM9aUXSPQha9+wXlOpkvu0Ur2nkX8PPJnifWao9UShSar +ll1IqPZNCSlZMwcFYcQNBCpdvITUUYlHvMRQV64bUpOxUGDuJkQL3dLKBlNuBRlJ +BcjBAKw7rFnwwHZcMmQ9tan/dZzpzwjo/T0XjwIDAQABAoIBAQCSHvUqnzDkWjcG +l/Fzg92qXlYBCCC0/ugj1sHcwvVt6Mq5rVE3MpUPwTcYjPlVVTlD4aEEjm/zQuq2 +ddxUlOS+r4aIhHrjRT/vSS4FpjnoKeIZxGR6maVxk6DQS3i1QjMYT1CvSpzyVvKH +a+xXMrtmoKxh+085ZAmFJtIuJhUA2yEa4zggCxWnvz8ecLClUPfVDPhdLBHc3KmL +CRpHEC6L/wanvDPRdkkzfKyaJuIJlTDaCg63AY5sDkTW2I57iI/nJ3haSeidfQKz +39EfbnM1A/YprIakafjAu3frBIsjBVcxwGihZmL/YriTHjOggJF841kT5zFkkv2L +/530Wk6xAoGBAOqZLZ4DIi/zLndEOz1mRbUfjc7GQUdYplBnBwJ22VdS0P4TOXnd +UbJth2MA92NM7ocTYVFl4TVIZY/Y+Prxk7KQdHWzR7JPpKfx9OEVgtSqV0vF9eGI +rKp79Y1T4Mvc3UcQCXX6TP7nHLihEzpS8odm2LW4txrOiLsn4Fq/IWrLAoGBAOVv +6U4tm3lImotUupKLZPKEBYwruo9qRysoug9FiorP4TjaBVOfltiiHbAQD6aGfVtN +SZpZZtrs17wL7Xl4db5asgMcZd+8Hkfo5siR7AuGW9FZloOjDcXb5wCh9EvjJ74J +Cjw7RqyVymq9t7IP6wnVwj5Ck48YhlOZCz/mzlnNAoGAWq7NYFgLvgc9feLFF23S +IjpJQZWHJEITP98jaYNxbfzYRm49+GphqxwFinKULjFNvq7yHlnIXSVYBOu1CqOZ +GRwXuGuNmlKI7lZr9xmukfAqgGLMMdr4C4qRF4lFyufcLRz42z7exmWlx4ST/yaT +E13hBRWayeTuG5JFei6Jh1MCgYEAqmX4LyC+JFBgvvQZcLboLRkSCa18bADxhENG +FAuAvmFvksqRRC71WETmqZj0Fqgxt7pp3KFjO1rFSprNLvbg85PmO1s+6fCLyLpX +lESTu2d5D71qhK93jigooxalGitFm+SY3mzjq0/AOpBWOn+J/w7rqVPGxXLgaHv0 +l+vx+00CgYBOvo9/ImjwYii2jFl+sHEoCzlvpITi2temRlT2j6ulSjCLJgjwEFw9 +8e+vvfQumQOsutakUVyURrkMGNDiNlIv8kv5YLCCkrwN22E6Ghyi69MJUvHQXkc/ +QZhjn/luyfpB5f/BeHFS2bkkxAXo+cfG45ApY3Qfz6/7o+H+vDa6/A== +-----END RSA PRIVATE KEY----- diff --git a/apps/emqx_auth_mysql/test/emqx_auth_mysql_SUITE_data/ca.pem b/apps/emqx_auth_mysql/test/emqx_auth_mysql_SUITE_data/ca.pem new file mode 100644 index 000000000..00b31d8a4 --- /dev/null +++ b/apps/emqx_auth_mysql/test/emqx_auth_mysql_SUITE_data/ca.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDAzCCAeugAwIBAgIBATANBgkqhkiG9w0BAQsFADA8MTowOAYDVQQDDDFNeVNR +TF9TZXJ2ZXJfOC4wLjE5X0F1dG9fR2VuZXJhdGVkX0NBX0NlcnRpZmljYXRlMB4X +DTIwMDYxMTAzMzg0NloXDTMwMDYwOTAzMzg0NlowPDE6MDgGA1UEAwwxTXlTUUxf +U2VydmVyXzguMC4xOV9BdXRvX0dlbmVyYXRlZF9DQV9DZXJ0aWZpY2F0ZTCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANJBlAYvTQ6euY4HcSn4syH7kq9s +KcG+OMjPUrj+KFEElCzgNuIhaS0f3ORQGB1PNcvVcfdXUI3WX332gWbr9s1b7Xl1 +JKJfDXs+26Cm6NhONTE3sPHnbTSmQEFb52hwAtjQmcY3IQs1AgxKFFHJfnCBEWfE +ePBQaiuYk1XDESMdWpMLrPnYQaj9MpAOUxjlmZCayzPWlF0j0IWvfsF5TqZL7tFK +9p5F/DzyZ4n1mqPVEoUmq5ZdSKj2TQkpWTMHBWHEDQQqXbyE1FGJR7zEUFeuG1KT +sVBg7iZEC93SygZTbgUZSQXIwQCsO6xZ8MB2XDJkPbWp/3Wc6c8I6P09F48CAwEA +AaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEADKz6bIpP5anp +GgLB0jkclRWuMlS4qqIt4itSsMXPJ/ezpHwECixmgW2TIQl6S1woRkUeMxhT2/Ay +Sn/7aKxuzRagyE5NEGOvrOuAP5RO2ZdNJ/X3/Rh533fK1sOTEEbSsWUvW6iSkZef +rsfZBVP32xBhRWkKRdLeLB4W99ADMa0IrTmZPCXHSSE2V4e1o6zWLXcOZeH1Qh8N +SkelBweR+8r1Fbvy1r3s7eH7DCbYoGEDVLQGOLvzHKBisQHmoDnnF5E9g1eeNRdg +o+vhOKfYCOzeNREJIqS42PHcGhdNRk90ycigPmfUJclz1mDHoMjKR2S5oosTpr65 +tNPx3CL7GA== +-----END CERTIFICATE----- diff --git a/apps/emqx_auth_mysql/test/emqx_auth_mysql_SUITE_data/client-cert.pem b/apps/emqx_auth_mysql/test/emqx_auth_mysql_SUITE_data/client-cert.pem new file mode 100644 index 000000000..aad1404ca --- /dev/null +++ b/apps/emqx_auth_mysql/test/emqx_auth_mysql_SUITE_data/client-cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAeygAwIBAgIBAzANBgkqhkiG9w0BAQsFADA8MTowOAYDVQQDDDFNeVNR +TF9TZXJ2ZXJfOC4wLjE5X0F1dG9fR2VuZXJhdGVkX0NBX0NlcnRpZmljYXRlMB4X +DTIwMDYxMTAzMzg0N1oXDTMwMDYwOTAzMzg0N1owQDE+MDwGA1UEAww1TXlTUUxf +U2VydmVyXzguMC4xOV9BdXRvX0dlbmVyYXRlZF9DbGllbnRfQ2VydGlmaWNhdGUw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVYSWpOvCTupz82fc85Opv +EQ7rkB8X2oOMyBCpkyHKBIr1ZQgRDWBp9UVOASq3GnSElm6+T3Kb1QbOffa8GIlw +sjAueKdq5L2eSkmPIEQ7eoO5kEW+4V866hE1LeL/PmHg2lGP0iqZiJYtElhHNQO8 +3y9I7cm3xWMAA3SSWikVtpJRn3qIp2QSrH+tK+/HHbE5QwtPxdir4ULSCSOaM5Yh +Wi5Oto88TZqe1v7SXC864JVvO4LuS7TuSreCdWZyPXTJFBFeCEWSAxonKZrqHbBe +CwKML6/0NuzjaQ51c2tzmVI6xpHj3nnu4cSRx6Jf9WBm+35vm0wk4pohX3ptdzeV +AgMBAAGjDTALMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEBAByQ5zSNeFUH +Aw7JlpZHtHaSEeiiyBHke20ziQ07BK1yi/ms2HAWwQkpZv149sjNuIRH8pkTmkZn +g8PDzSefjLbC9AsWpWV0XNV22T/cdobqLqMBDDZ2+5bsV+jTrOigWd9/AHVZ93PP +IJN8HJn6rtvo2l1bh/CdsX14uVSdofXnuWGabNTydqtMvmCerZsdf6qKqLL+PYwm +RDpgWiRUY7KPBSSlKm/9lJzA+bOe4dHeJzxWFVCJcbpoiTFs1je1V8kKQaHtuW39 +ifX6LTKUMlwEECCbDKM8Yq2tm8NjkjCcnFDtKg8zKGPUu+jrFMN5otiC3wnKcP7r +O9EkaPcgYH8= +-----END CERTIFICATE----- diff --git a/apps/emqx_auth_mysql/test/emqx_auth_mysql_SUITE_data/client-key.pem b/apps/emqx_auth_mysql/test/emqx_auth_mysql_SUITE_data/client-key.pem new file mode 100644 index 000000000..6789d0291 --- /dev/null +++ b/apps/emqx_auth_mysql/test/emqx_auth_mysql_SUITE_data/client-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEA1WElqTrwk7qc/Nn3POTqbxEO65AfF9qDjMgQqZMhygSK9WUI +EQ1gafVFTgEqtxp0hJZuvk9ym9UGzn32vBiJcLIwLninauS9nkpJjyBEO3qDuZBF +vuFfOuoRNS3i/z5h4NpRj9IqmYiWLRJYRzUDvN8vSO3Jt8VjAAN0klopFbaSUZ96 +iKdkEqx/rSvvxx2xOUMLT8XYq+FC0gkjmjOWIVouTraPPE2antb+0lwvOuCVbzuC +7ku07kq3gnVmcj10yRQRXghFkgMaJyma6h2wXgsCjC+v9Dbs42kOdXNrc5lSOsaR +49557uHEkceiX/VgZvt+b5tMJOKaIV96bXc3lQIDAQABAoIBAF7yjXmSOn7h6P0y +WCuGiTLG2mbDiLJqj2LTm2Z5i+2Cu/qZ7E76Ls63TxF4v3MemH5vGfQhEhR5ZD/6 +GRJ1sKKvB3WGRqjwA9gtojHH39S/nWGy6vYW/vMOOH37XyjIr3EIdIaUtFQBTSHd +Kd71niYrAbVn6fyWHolhADwnVmTMOl5OOAhCdEF4GN3b5aIhIu8BJ7EUzTtHBJIj +CAEfjZFjDs1y1cIgGFJkuIQxMfCpq5recU2qwip7YO6fk//WEjOPu7kSf5IEswL8 +jg1dea9rGBV6KaD2xsgsC6Ll6Sb4BbsrHMfflG3K2Lk3RdVqqTFp1Fn1PTLQE/1S +S/SZPYECgYEA9qYcHKHd0+Q5Ty5wgpxKGa4UCWkpwvfvyv4bh8qlmxueB+l2AIdo +ZvkM8gTPagPQ3WypAyC2b9iQu70uOJo1NizTtKnpjDdN1YpDjISJuS/P0x73gZwy +gmoM5AzMtN4D6IbxXtXnPaYICvwLKU80ouEN5ZPM4/ODLUu6gsp0v2UCgYEA3Xgi +zMC4JF0vEKEaK0H6QstaoXUmw/lToZGH3TEojBIkb/2LrHUclygtONh9kJSFb89/ +jbmRRLAOrx3HZKCNGUmF4H9k5OQyAIv6OGBinvLGqcbqnyNlI+Le8zxySYwKMlEj +EMrBCLmSyi0CGFrbZ3mlj/oCET/ql9rNvcK+DHECgYAEx5dH3sMjtgp+RFId1dWB +xePRgt4yTwewkVgLO5wV82UOljGZNQaK6Eyd7AXw8f38LHzh+KJQbIvxd2sL4cEi +OaAoohpKg0/Y0YMZl//rPMf0OWdmdZZs/I0fZjgZUSwWN3c59T8z7KG/RL8an9RP +S7kvN7wCttdV61/D5RR6GQKBgDxCe/WKWpBKaovzydMLWLTj7/0Oi0W3iXHkzzr4 +LTgvl4qBSofaNbVLUUKuZTv5rXUG2IYPf99YqCYtzBstNDc1MiAriaBeFtzfOW4t +i6gEFtoLLbuvPc3N5Sv5vn8Ug5G9UfU3td5R4AbyyCcoUZqOFuZd+EIJSiOXfXOs +kVmBAoGBAIU9aPAqhU5LX902oq8KsrpdySONqv5mtoStvl3wo95WIqXNEsFY60wO +q02jKQmJJ2MqhkJm2EoF2Mq8+40EZ5sz8LdgeQ/M0yQ9lAhPi4rftwhpe55Ma9dk +SE9X1c/DMCBEaIjJqVXdy0/EeArwpb8sHkguVVAZUWxzD+phm1gs +-----END RSA PRIVATE KEY----- diff --git a/apps/emqx_auth_mysql/test/emqx_auth_mysql_SUITE_data/private_key.pem b/apps/emqx_auth_mysql/test/emqx_auth_mysql_SUITE_data/private_key.pem new file mode 100644 index 000000000..8fbf6bdec --- /dev/null +++ b/apps/emqx_auth_mysql/test/emqx_auth_mysql_SUITE_data/private_key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA1zVmMhPqpSPMmYkKh5wwlRD5XuS8YWJKEM6tjFx61VK8qxHE +YngkC2KnL5EuKAjQZIF3tJskwt0hAat047CCCZxrkNEpbVvSnvnk+A/8bg/Ww1n3 +qxzfifhsWfpUKlDnwrtH+ftt+5rZeEkf37XAPy7ZjzecAF9SDV6WSiPeAxUX2+hN +dId42Pf45woo4LFGUlQeagCFkD/R0dpNIMGwcnkKCUikiBqr2ijSIgvRtBfZ9fBG +jFGER2uE/Eay4AgcQsHue8skRwDCng8OnqtPnBtTytmqTy9V/BRgsVKUoksm6wsx +kUYwgHeaq7UCvlCm25SZ7yRyd4k8t0BKDf2h+wIDAQABAoIBAEQcrHmRACTADdNS +IjkFYALt2l8EOfMAbryfDSJtapr1kqz59JPNvmq0EIHnixo0n/APYdmReLML1ZR3 +tYkSpjVwgkLVUC1CcIjMQoGYXaZf8PLnGJHZk45RR8m6hsTV0mQ5bfBaeVa2jbma +OzJMjcnxg/3l9cPQZ2G/3AUfEPccMxOXp1KRz3mUQcGnKJGtDbN/kfmntcwYoxaE +Zg4RoeKAoMpK1SSHAiJKe7TnztINJ7uygR9XSzNd6auY8A3vomSIjpYO7XL+lh7L +izm4Ir3Gb/eCYBvWgQyQa2KCJgK/sQyEs3a09ngofSEUhQJQYhgZDwUj+fDDOGqj +hCZOA8ECgYEA+ZWuHdcUQ3ygYhLds2QcogUlIsx7C8n/Gk/FUrqqXJrTkuO0Eqqa +B47lCITvmn2zm0ODfSFIARgKEUEDLS/biZYv7SUTrFqBLcet+aGI7Dpv91CgB75R +tNzcIf8VxoiP0jPqdbh9mLbbxGi5Uc4p9TVXRljC4hkswaouebWee0sCgYEA3L2E +YB3kiHrhPI9LHS5Px9C1w+NOu5wP5snxrDGEgaFCvL6zgY6PflacppgnmTXl8D1x +im0IDKSw5dP3FFonSVXReq3CXDql7UnhfTCiLDahV7bLxTH42FofcBpDN3ERdOal +58RwQh6VrLkzQRVoObo+hbGlFiwwSAfQC509FhECgYBsRSBpVXo25IN2yBRg09cP ++gdoFyhxrsj5kw1YnB13WrrZh+oABv4WtUhp77E5ZbpaamlKCPwBbXpAjeFg4tfr +0bksuN7V79UGFQ9FsWuCfr8/nDwv38H2IbFlFhFONMOfPmJBey0Q6JJhm8R41mSh +OOiJXcv85UrjIH5U0hLUDQKBgQDVLOU5WcUJlPoOXSgiT0ZW5xWSzuOLRUUKEf6l +19BqzAzCcLy0orOrRAPW01xylt2v6/bJw1Ahva7k1ZZo/kOwjANYoZPxM+ZoSZBN +MXl8j2mzZuJVV1RFxItV3NcLJNPB/Lk+IbRz9kt/2f9InF7iWR3mSU/wIM6j0X+2 +p6yFsQKBgQCM/ldWb511lA+SNkqXB2P6WXAgAM/7+jwsNHX2ia2Ikufm4SUEKMSv +mti/nZkHDHsrHU4wb/2cOAywMELzv9EHzdcoenjBQP65OAc/1qWJs+LnBcCXfqKk +aHjEZW6+brkHdRGLLY3YAHlt/AUL+RsKPJfN72i/FSpmu+52G36eeQ== +-----END RSA PRIVATE KEY----- diff --git a/apps/emqx_auth_mysql/test/emqx_auth_mysql_SUITE_data/public_key.pem b/apps/emqx_auth_mysql/test/emqx_auth_mysql_SUITE_data/public_key.pem new file mode 100644 index 000000000..f9772b533 --- /dev/null +++ b/apps/emqx_auth_mysql/test/emqx_auth_mysql_SUITE_data/public_key.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1zVmMhPqpSPMmYkKh5ww +lRD5XuS8YWJKEM6tjFx61VK8qxHEYngkC2KnL5EuKAjQZIF3tJskwt0hAat047CC +CZxrkNEpbVvSnvnk+A/8bg/Ww1n3qxzfifhsWfpUKlDnwrtH+ftt+5rZeEkf37XA +Py7ZjzecAF9SDV6WSiPeAxUX2+hNdId42Pf45woo4LFGUlQeagCFkD/R0dpNIMGw +cnkKCUikiBqr2ijSIgvRtBfZ9fBGjFGER2uE/Eay4AgcQsHue8skRwDCng8OnqtP +nBtTytmqTy9V/BRgsVKUoksm6wsxkUYwgHeaq7UCvlCm25SZ7yRyd4k8t0BKDf2h ++wIDAQAB +-----END PUBLIC KEY----- diff --git a/apps/emqx_auth_mysql/test/emqx_auth_mysql_SUITE_data/server-cert.pem b/apps/emqx_auth_mysql/test/emqx_auth_mysql_SUITE_data/server-cert.pem new file mode 100644 index 000000000..a2f9688df --- /dev/null +++ b/apps/emqx_auth_mysql/test/emqx_auth_mysql_SUITE_data/server-cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAeygAwIBAgIBAjANBgkqhkiG9w0BAQsFADA8MTowOAYDVQQDDDFNeVNR +TF9TZXJ2ZXJfOC4wLjE5X0F1dG9fR2VuZXJhdGVkX0NBX0NlcnRpZmljYXRlMB4X +DTIwMDYxMTAzMzg0NloXDTMwMDYwOTAzMzg0NlowQDE+MDwGA1UEAww1TXlTUUxf +U2VydmVyXzguMC4xOV9BdXRvX0dlbmVyYXRlZF9TZXJ2ZXJfQ2VydGlmaWNhdGUw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCcEnEm5hqP1EbEJycOz8Ua +NWp29QdpFUzTWhkKGhVXk+0msmNTw4NBAFB42moY44OU8wvDideOlJNhPRWveD8z +G2lxzJA91p0UK4et8ia9MmeuCGhdC9jxJ8X69WNlUiPyy0hI/ZsqRq9Z0C2eW0iL +JPXsy4X8Xpw3SFwoXf5pR9RFY5Pb2tuyxqmSestu2VXT/NQjJg4CVDR3mFcHPXZB +4elRzH0WshExEGkgy0bg20MJeRc2Qdb5Xx+EakbmwroDWaCn3NSGqQ7jv6Vw0doy +TGvS6h6RHBxnyqRfRgKGlCoOMG9/5+rFJC00QpCUG2vHXHWGoWlMlJ3foN7rj5v9 +AgMBAAGjDTALMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEBAJ5zt2rj4Ag6 +zpN59AWC1Fur8g8l41ksHkSpKPp+PtyO/ngvbMqBpfmK1e7JCKZv/68QXfMyWWAI +hwalqZkXXWHKjuz3wE7dE25PXFXtGJtcZAaj10xt98fzdqt8lQSwh2kbfNwZIz1F +sgAStgE7+ZTcqTgvNB76Os1UK0to+/P0VBWktaVFdyub4Nc2SdPVnZNvrRBXBwOD +3V8ViwywDOFoE7DvCvwx/SVsvoC0Z4j3AMMovO6oHicP7uU83qsQgm1Qru3YeoLR ++DoVi7IPHbWvN7MqFYn3YjNlByO2geblY7MR0BlqbFlmFrqLsUfjsh2ys7/U/knC +dN/klu446fI= +-----END CERTIFICATE----- diff --git a/apps/emqx_auth_mysql/test/emqx_auth_mysql_SUITE_data/server-key.pem b/apps/emqx_auth_mysql/test/emqx_auth_mysql_SUITE_data/server-key.pem new file mode 100644 index 000000000..a1dfd5f78 --- /dev/null +++ b/apps/emqx_auth_mysql/test/emqx_auth_mysql_SUITE_data/server-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAnBJxJuYaj9RGxCcnDs/FGjVqdvUHaRVM01oZChoVV5PtJrJj +U8ODQQBQeNpqGOODlPMLw4nXjpSTYT0Vr3g/MxtpccyQPdadFCuHrfImvTJnrgho +XQvY8SfF+vVjZVIj8stISP2bKkavWdAtnltIiyT17MuF/F6cN0hcKF3+aUfURWOT +29rbssapknrLbtlV0/zUIyYOAlQ0d5hXBz12QeHpUcx9FrIRMRBpIMtG4NtDCXkX +NkHW+V8fhGpG5sK6A1mgp9zUhqkO47+lcNHaMkxr0uoekRwcZ8qkX0YChpQqDjBv +f+fqxSQtNEKQlBtrx1x1hqFpTJSd36De64+b/QIDAQABAoIBAFiah66Dt9SruLkn +WR8piUaFyLlcBib8Nq9OWSTJBhDAJERxxb4KIvvGB+l0ZgNXNp5bFPSfzsZdRwZP +PX5uj8Kd71Dxx3mz211WESMJdEC42u+MSmN4lGLkJ5t/sDwXU91E1vbJM0ve8THV +4/Ag9qA4DX2vVZOeyqT/6YHpSsPNZplqzrbAiwrfHwkctHfgqwOf3QLfhmVQgfCS +VwidBldEUv2whSIiIxh4Rv5St4kA68IBCbJxdpOpyuQBkk6CkxZ7VN9FqOuSd4Pk +Wm7iWyBMZsCmELZh5XAXld4BEt87C5R4CvbPBDZxAv3THk1DNNvpy3PFQfwARRFb +SAToYMECgYEAyL7U8yxpzHDYWd3oCx6vTi9p9N/z0FfAkWrRF6dm4UcSklNiT1Aq +EOnTA+SaW8tV3E64gCWcY23gNP8so/ZseWj6L+peHwtchaP9+KB7yGw2A+05+lOx +VetLTjAOmfpiUXFe5w1q4C1RGhLjZjjzW+GvwdAuchQgUEFaomrV+PUCgYEAxwfH +cmVGFbAktcjU4HSRjKSfawCrut+3YUOLybyku3Q/hP9amG8qkVTFe95CTLjLe2D0 +ccaTTpofFEJ32COeck0g0Ujn/qQ+KXRoauOYs4FB1DtqMpqB78wufWEUpDpbd9/h +J+gJdC/IADd4tJW9zA92g8IA7ZtFmqDtiSpQ0ekCgYAQGkaorvJZpN+l7cf0RGTZ +h7IfI2vCVZer0n6tQA9fmLzjoe6r4AlPzAHSOR8sp9XeUy43kUzHKQQoHCPvjw/K +eWJAP7OHF/k2+x2fOPhU7mEy1W+mJdp+wt4Kio5RSaVjVQ3AyPG+w8PSrJszEvRq +dWMMz+851WV2KpfjmWBKlQKBgQC++4j4DZQV5aMkSKV1CIZOBf3vaIJhXKEUFQPD +PmB4fBEjpwCg+zNGp6iktt65zi17o8qMjrb1mtCt2SY04eD932LZUHNFlwcLMmes +Ad+aiDLJ24WJL1f16eDGcOyktlblDZB5gZ/ovJzXEGOkLXglosTfo77OQculmDy2 +/UL2WQKBgGeKasmGNfiYAcWio+KXgFkHXWtAXB9B91B1OFnCa40wx+qnl71MIWQH +PQ/CZFNWOfGiNEJIZjrHsfNJoeXkhq48oKcT0AVCDYyLV0VxDO4ejT95mGW6njNd +JpvmhwwAjOvuWVr0tn4iXlSK8irjlJHmwcRjLTJq97vE9fsA2MjI +-----END RSA PRIVATE KEY----- diff --git a/apps/emqx_auth_pgsql/.ci/docker-compose.yml b/apps/emqx_auth_pgsql/.ci/docker-compose.yml new file mode 100644 index 000000000..8782a841d --- /dev/null +++ b/apps/emqx_auth_pgsql/.ci/docker-compose.yml @@ -0,0 +1,30 @@ +version: '3' + +services: + erlang: + image: erlang:22.3 + volumes: + - ../:/emqx_auth_pgsql + networks: + - emqx_bridge + depends_on: + - pgsql_server + tty: true + + pgsql_server: + build: + context: ./pgsql + args: + BUILD_FROM: postgres:${PGSQL_TAG} + image: emqx-pgsql + restart: always + environment: + POSTGRES_PASSWORD: public + POSTGRES_USER: root + POSTGRES_DB: mqtt + networks: + - emqx_bridge + +networks: + emqx_bridge: + driver: bridge diff --git a/apps/emqx_auth_pgsql/.ci/pgsql/Dockerfile b/apps/emqx_auth_pgsql/.ci/pgsql/Dockerfile new file mode 100644 index 000000000..785bb875f --- /dev/null +++ b/apps/emqx_auth_pgsql/.ci/pgsql/Dockerfile @@ -0,0 +1,8 @@ +ARG BUILD_FROM=postgres:11 +FROM ${BUILD_FROM} +COPY pg.conf /etc/postgresql/postgresql.conf +COPY server-cert.pem /etc/postgresql/server-cert.pem +COPY server-key.pem /etc/postgresql/server-key.pem +RUN chown -R postgres:postgres /etc/postgresql \ + && chmod 600 /etc/postgresql/*.pem +CMD ["-c", "config_file=/etc/postgresql/postgresql.conf"] diff --git a/apps/emqx_auth_pgsql/README.md b/apps/emqx_auth_pgsql/README.md new file mode 100644 index 000000000..2dccd6f53 --- /dev/null +++ b/apps/emqx_auth_pgsql/README.md @@ -0,0 +1,183 @@ +emqx_auth_pgsql +=============== + +Authentication/ACL with PostgreSQL Database. + +Build Plugin +------------ + +make && make tests + +Configuration +------------- + +File: etc/emqx_auth_pgsql.conf + +``` +## PostgreSQL server address. +## +## Value: Port | IP:Port +## +## Examples: 5432, 127.0.0.1:5432, localhost:5432 +auth.pgsql.server = 127.0.0.1:5432 + +## PostgreSQL pool size. +## +## Value: Number +auth.pgsql.pool = 8 + +## PostgreSQL username. +## +## Value: String +auth.pgsql.username = root + +## PostgreSQL password. +## +## Value: String +## auth.pgsql.password = + +## PostgreSQL database. +## +## Value: String +auth.pgsql.database = mqtt + +## PostgreSQL database encoding. +## +## Value: String +auth.pgsql.encoding = utf8 + +## Whether to enable SSL connection. +## +## Value: true | false +auth.pgsql.ssl = false + +## SSL keyfile. +## +## Value: File +## auth.pgsql.ssl_opts.keyfile = + +## SSL certfile. +## +## Value: File +## auth.pgsql.ssl_opts.certfile = + +## SSL cacertfile. +## +## Value: File +## auth.pgsql.ssl_opts.cacertfile = + +## Authentication query. +## +## Value: SQL +## +## Variables: +## - %u: username +## - %c: clientid +## +auth.pgsql.auth_query = select password from mqtt_user where username = '%u' limit 1 + +## Password hash. +## +## Value: plain | md5 | sha | sha256 | bcrypt +auth.pgsql.password_hash = sha256 + +## sha256 with salt prefix +## auth.pgsql.password_hash = salt,sha256 + +## sha256 with salt suffix +## auth.pgsql.password_hash = sha256,salt + +## bcrypt with salt prefix +## auth.pgsql.password_hash = salt,bcrypt + +## pbkdf2 with macfun iterations dklen +## macfun: md4, md5, ripemd160, sha, sha224, sha256, sha384, sha512 +## auth.pgsql.password_hash = pbkdf2,sha256,1000,20 + +## Superuser query. +## +## Value: SQL +## +## Variables: +## - %u: username +## - %c: clientid +auth.pgsql.super_query = select is_superuser from mqtt_user where username = '%u' limit 1 + +## ACL query. Comment this query, the ACL will be disabled. +## +## Value: SQL +## +## Variables: +## - %a: ipaddress +## - %u: username +## - %c: clientid +auth.pgsql.acl_query = select allow, ipaddr, username, clientid, access, topic from mqtt_acl where ipaddr = '%a' or username = '%u' or username = '$all' or clientid = '%c' +``` + +Load Plugin +----------- + +./bin/emqx_ctl plugins load emqx_auth_pgsql + +Auth Table +---------- + +Notice: This is a demo table. You could authenticate with any user table. + +```sql +CREATE TABLE mqtt_user ( + id SERIAL primary key, + is_superuser boolean, + username character varying(100), + password character varying(100), + salt character varying(40) +) +``` + +ACL Table +--------- + +```sql +CREATE TABLE mqtt_acl ( + id SERIAL primary key, + allow integer, + ipaddr character varying(60), + username character varying(100), + clientid character varying(100), + access integer, + topic character varying(100) +) + +INSERT INTO mqtt_acl (id, allow, ipaddr, username, clientid, access, topic) +VALUES + (1,1,NULL,'$all',NULL,2,'#'), + (2,0,NULL,'$all',NULL,1,'$SYS/#'), + (3,0,NULL,'$all',NULL,1,'eq #'), + (5,1,'127.0.0.1',NULL,NULL,2,'$SYS/#'), + (6,1,'127.0.0.1',NULL,NULL,2,'#'), + (7,1,NULL,'dashboard',NULL,1,'$SYS/#'); +``` +**allow:** Client's permission to access a topic. '0' means that the client does not have permission to access the topic, '1' means that the client have permission to access the topic. + +**ipaddr:** Client IP address. For all ip addresses it can be '$all' or 'NULL'. + +**username:** Client username. For all users it can be '$all' or 'NULL'. + +**clientid:** Client id. For all client ids it can be '$all' or 'NULL'. + +**access:** Operations that the client can perform. '1' means that the client can subscribe to a topic, '2' means that the client can publish to a topic, '3' means that the client can subscribe and can publish to a topic. + +**topic:** Topic name. Topic wildcards are supported. + +**Notice that only one value allowed for ipaddr, username and clientid fields.** + +License +------- + +Apache License Version 2.0 + +Author +------ + +EMQ X Team. + diff --git a/apps/emqx_auth_pgsql/include/emqx_auth_pgsql.hrl b/apps/emqx_auth_pgsql/include/emqx_auth_pgsql.hrl new file mode 100644 index 000000000..b86692752 --- /dev/null +++ b/apps/emqx_auth_pgsql/include/emqx_auth_pgsql.hrl @@ -0,0 +1,23 @@ +-define(APP, emqx_auth_pgsql). + +-record(auth_metrics, { + success = 'client.auth.success', + failure = 'client.auth.failure', + ignore = 'client.auth.ignore' + }). + +-record(acl_metrics, { + allow = 'client.acl.allow', + deny = 'client.acl.deny', + ignore = 'client.acl.ignore' + }). + +-define(METRICS(Type), tl(tuple_to_list(#Type{}))). +-define(METRICS(Type, K), #Type{}#Type.K). + +-define(AUTH_METRICS, ?METRICS(auth_metrics)). +-define(AUTH_METRICS(K), ?METRICS(auth_metrics, K)). + +-define(ACL_METRICS, ?METRICS(acl_metrics)). +-define(ACL_METRICS(K), ?METRICS(acl_metrics, K)). + diff --git a/apps/emqx_auth_pgsql/mqtt.sql b/apps/emqx_auth_pgsql/mqtt.sql new file mode 100644 index 000000000..933b0058a --- /dev/null +++ b/apps/emqx_auth_pgsql/mqtt.sql @@ -0,0 +1,28 @@ + +CREATE TABLE mqtt_user ( + id SERIAL primary key, + is_superuser boolean, + username character varying(100), + password character varying(100), + salt character varying(40) +); + +CREATE TABLE mqtt_acl ( + id SERIAL primary key, + allow integer, + ipaddr character varying(60), + username character varying(100), + clientid character varying(100), + access integer, + topic character varying(100) +); + +INSERT INTO mqtt_acl (id, allow, ipaddr, username, clientid, access, topic) +VALUES + (1,1,NULL,'$all',NULL,2,'#'), + (2,0,NULL,'$all',NULL,1,'$SYS/#'), + (3,0,NULL,'$all',NULL,1,'eq #'), + (5,1,'127.0.0.1',NULL,NULL,2,'$SYS/#'), + (6,1,'127.0.0.1',NULL,NULL,2,'#'), + (7,1,NULL,'dashboard',NULL,1,'$SYS/#'); + diff --git a/apps/emqx_auth_pgsql/priv/emqx_auth_pgsql.schema b/apps/emqx_auth_pgsql/priv/emqx_auth_pgsql.schema new file mode 100644 index 000000000..4a475ee0e --- /dev/null +++ b/apps/emqx_auth_pgsql/priv/emqx_auth_pgsql.schema @@ -0,0 +1,127 @@ +%%-*- mode: erlang -*- +%% emqx_auth_pgsl config mapping + +{mapping, "auth.pgsql.server", "emqx_auth_pgsql.server", [ + {default, {"127.0.0.1", 5432}}, + {datatype, [integer, ip, string]} +]}. + +{mapping, "auth.pgsql.pool", "emqx_auth_pgsql.server", [ + {default, 8}, + {datatype, integer} +]}. + +{mapping, "auth.pgsql.database", "emqx_auth_pgsql.server", [ + {datatype, string} +]}. + +{mapping, "auth.pgsql.username", "emqx_auth_pgsql.server", [ + {default, ""}, + {datatype, string} +]}. + +{mapping, "auth.pgsql.password", "emqx_auth_pgsql.server", [ + {default, ""}, + {datatype, string} +]}. + +{mapping, "auth.pgsql.encoding", "emqx_auth_pgsql.server", [ + {default, utf8}, + {datatype, atom} +]}. + +{mapping, "auth.pgsql.ssl", "emqx_auth_pgsql.server", [ + {default, false}, + {datatype, {enum, [true, false]}} +]}. + +{mapping, "auth.pgsql.ssl_opts.keyfile", "emqx_auth_pgsql.server", [ + {datatype, string} +]}. + +{mapping, "auth.pgsql.ssl_opts.certfile", "emqx_auth_pgsql.server", [ + {datatype, string} +]}. + +{mapping, "auth.pgsql.ssl_opts.cacertfile", "emqx_auth_pgsql.server", [ + {datatype, string} +]}. + +{translation, "emqx_auth_pgsql.server", fun(Conf) -> + {PgHost, PgPort} = + case cuttlefish:conf_get("auth.pgsql.server", Conf) of + {Ip, Port} -> {Ip, Port}; + S -> case string:tokens(S, ":") of + [Domain] -> {Domain, 5432}; + [Domain, Port] -> {Domain, list_to_integer(Port)} + end + end, + Pool = cuttlefish:conf_get("auth.pgsql.pool", Conf), + Username = cuttlefish:conf_get("auth.pgsql.username", Conf), + Passwd = cuttlefish:conf_get("auth.pgsql.password", Conf, ""), + DB = cuttlefish:conf_get("auth.pgsql.database", Conf), + Encoding = cuttlefish:conf_get("auth.pgsql.encoding", Conf), + Ssl = cuttlefish:conf_get("auth.pgsql.ssl", Conf), + + Filter = fun(Opts) -> [{K, V} || {K, V} <- Opts, V =/= undefined] end, + SslOpts = fun(Prefix) -> + Filter([{keyfile, cuttlefish:conf_get(Prefix ++ ".keyfile", Conf, undefined)}, + {certfile, cuttlefish:conf_get(Prefix ++ ".certfile", Conf, undefined)}, + {cacertfile, cuttlefish:conf_get(Prefix ++ ".cacertfile", Conf, undefined)}]) + end, + + TempHost = case inet:parse_address(PgHost) of + {ok, IpAddr} -> + IpAddr; + _ -> + PgHost + end, + [{pool_size, Pool}, + {auto_reconnect, 1}, + {host, TempHost}, + {port, PgPort}, + {username, Username}, + {password, Passwd}, + {database, DB}, + {encoding, Encoding}, + {ssl, Ssl}, + {ssl_opts, SslOpts("auth.pgsql.ssl_opts")}] +end}. + +{mapping, "auth.pgsql.auth_query", "emqx_auth_pgsql.auth_query", [ + {datatype, string} +]}. + +{mapping, "auth.pgsql.password_hash", "emqx_auth_pgsql.password_hash", [ + {datatype, string} +]}. + +{mapping, "auth.pgsql.pbkdf2_macfun", "emqx_auth_pgsql.pbkdf2_macfun", [ + {datatype, atom} +]}. + +{mapping, "auth.pgsql.pbkdf2_iterations", "emqx_auth_pgsql.pbkdf2_iterations", [ + {datatype, integer} +]}. + +{mapping, "auth.pgsql.pbkdf2_dklen", "emqx_auth_pgsql.pbkdf2_dklen", [ + {datatype, integer} +]}. + +{mapping, "auth.pgsql.super_query", "emqx_auth_pgsql.super_query", [ + {datatype, string} +]}. + +{mapping, "auth.pgsql.acl_query", "emqx_auth_pgsql.acl_query", [ + {datatype, string} +]}. + +{translation, "emqx_auth_pgsql.password_hash", fun(Conf) -> + HashValue = cuttlefish:conf_get("auth.pgsql.password_hash", Conf), + case string:tokens(HashValue, ",") of + [Hash] -> list_to_atom(Hash); + [Prefix, Suffix] -> {list_to_atom(Prefix), list_to_atom(Suffix)}; + [Hash, MacFun, Iterations, Dklen] -> {list_to_atom(Hash), list_to_atom(MacFun), list_to_integer(Iterations), list_to_integer(Dklen)}; + _ -> plain + end +end}. diff --git a/apps/emqx_auth_pgsql/rebar.config b/apps/emqx_auth_pgsql/rebar.config new file mode 100644 index 000000000..a56845649 --- /dev/null +++ b/apps/emqx_auth_pgsql/rebar.config @@ -0,0 +1,3 @@ +{deps, + [{epgsql, {git, "https://github.com/epgsql/epgsql", {tag, "4.4.0"}}} + ]}. \ No newline at end of file diff --git a/apps/emqx_auth_pgsql/src/emqx_acl_pgsql.erl b/apps/emqx_auth_pgsql/src/emqx_acl_pgsql.erl new file mode 100644 index 000000000..fcad696e2 --- /dev/null +++ b/apps/emqx_auth_pgsql/src/emqx_acl_pgsql.erl @@ -0,0 +1,117 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_acl_pgsql). + +-include("emqx_auth_pgsql.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). + +%% ACL callbacks +-export([ register_metrics/0 + , check_acl/5 + , description/0 + ]). + +-spec(register_metrics() -> ok). +register_metrics() -> + lists:foreach(fun emqx_metrics:ensure/1, ?ACL_METRICS). + +check_acl(ClientInfo, PubSub, Topic, NoMatchAction, #{pool := Pool} = State) -> + case do_check_acl(Pool, ClientInfo, PubSub, Topic, NoMatchAction, State) of + ok -> emqx_metrics:inc(?ACL_METRICS(ignore)), ok; + {stop, allow} -> emqx_metrics:inc(?ACL_METRICS(allow)), {stop, allow}; + {stop, deny} -> emqx_metrics:inc(?ACL_METRICS(deny)), {stop, deny} + end. + +do_check_acl(_Pool, #{username := <<$$, _/binary>>}, _PubSub, _Topic, _NoMatchAction, _State) -> + ok; +do_check_acl(Pool, ClientInfo, PubSub, Topic, _NoMatchAction, #{acl_query := {AclSql, AclParams}}) -> + case emqx_auth_pgsql_cli:equery(Pool, AclSql, AclParams, ClientInfo) of + {ok, _, []} -> ok; + {ok, _, Rows} -> + Rules = filter(PubSub, compile(Rows)), + case match(ClientInfo, Topic, Rules) of + {matched, allow} -> {stop, allow}; + {matched, deny} -> {stop, deny}; + nomatch -> ok + end; + {error, Reason} -> + ?LOG(error, "[Postgres] do_check_acl error: ~p~n", [Reason]), + ok + end. + +match(_ClientInfo, _Topic, []) -> + nomatch; + +match(ClientInfo, Topic, [Rule|Rules]) -> + case emqx_access_rule:match(ClientInfo, Topic, Rule) of + nomatch -> match(ClientInfo, Topic, Rules); + {matched, AllowDeny} -> {matched, AllowDeny} + end. + +filter(PubSub, Rules) -> + [Term || Term = {_, _, Access, _} <- Rules, + Access =:= PubSub orelse Access =:= pubsub]. + +compile(Rows) -> + compile(Rows, []). +compile([], Acc) -> + Acc; +compile([{Allow, IpAddr, Username, ClientId, Access, Topic}|T], Acc) -> + Who = who(IpAddr, Username, ClientId), + Term = {allow(Allow), Who, access(Access), [topic(Topic)]}, + compile(T, [emqx_access_rule:compile(Term) | Acc]). + +who(_, <<"$all">>, _) -> + all; +who(null, null, null) -> + throw(undefined_who); +who(CIDR, Username, ClientId) -> + Cols = [{ipaddr, b2l(CIDR)}, {user, Username}, {client, ClientId}], + case [{C, V} || {C, V} <- Cols, not empty(V)] of + [Who] -> Who; + Conds -> {'and', Conds} + end. + +allow(1) -> allow; +allow(0) -> deny; +allow(<<"1">>) -> allow; +allow(<<"0">>) -> deny. + +access(1) -> subscribe; +access(2) -> publish; +access(3) -> pubsub; +access(<<"1">>) -> subscribe; +access(<<"2">>) -> publish; +access(<<"3">>) -> pubsub. + +topic(<<"eq ", Topic/binary>>) -> + {eq, Topic}; +topic(Topic) -> + Topic. + +description() -> + "ACL with Postgres". + +b2l(null) -> null; +b2l(B) -> binary_to_list(B). + +empty(null) -> true; +empty("") -> true; +empty(<<>>) -> true; +empty(_) -> false. + diff --git a/apps/emqx_auth_pgsql/src/emqx_auth_pgsql.app.src b/apps/emqx_auth_pgsql/src/emqx_auth_pgsql.app.src new file mode 100644 index 000000000..2bc948f3f --- /dev/null +++ b/apps/emqx_auth_pgsql/src/emqx_auth_pgsql.app.src @@ -0,0 +1,14 @@ +{application, emqx_auth_pgsql, + [{description, "EMQ X Authentication/ACL with PostgreSQL"}, + {vsn, "5.0.0"}, % strict semver, bump manually! + {modules, []}, + {registered, [emqx_auth_pgsql_sup]}, + {applications, [kernel,stdlib,epgsql,ecpool,emqx_passwd,emqx_libs]}, + {mod, {emqx_auth_pgsql_app,[]}}, + {env, []}, + {licenses, ["Apache-2.0"]}, + {maintainers, ["EMQ X Team "]}, + {links, [{"Homepage", "https://emqx.io/"}, + {"Github", "https://github.com/emqx/emqx-auth-pgsql"} + ]} + ]}. diff --git a/apps/emqx_auth_pgsql/src/emqx_auth_pgsql.erl b/apps/emqx_auth_pgsql/src/emqx_auth_pgsql.erl new file mode 100644 index 000000000..ad1973737 --- /dev/null +++ b/apps/emqx_auth_pgsql/src/emqx_auth_pgsql.erl @@ -0,0 +1,91 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_pgsql). + +-include("emqx_auth_pgsql.hrl"). + +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). + +-export([ register_metrics/0 + , check/3 + , description/0 + ]). + +-spec(register_metrics() -> ok). +register_metrics() -> + lists:foreach(fun emqx_metrics:ensure/1, ?AUTH_METRICS). + +%%-------------------------------------------------------------------- +%% Auth Module Callbacks +%%-------------------------------------------------------------------- + +check(ClientInfo = #{password := Password}, AuthResult, + #{auth_query := {AuthSql, AuthParams}, + super_query := SuperQuery, + hash_type := HashType, + pool := Pool}) -> + CheckPass = case emqx_auth_pgsql_cli:equery(Pool, AuthSql, AuthParams, ClientInfo) of + {ok, _, [Record]} -> + check_pass(erlang:append_element(Record, Password), HashType); + {ok, _, []} -> + {error, not_found}; + {error, Reason} -> + ?LOG(error, "[Postgres] query '~p' failed: ~p", [AuthSql, Reason]), + {error, not_found} + end, + case CheckPass of + ok -> + emqx_metrics:inc(?AUTH_METRICS(success)), + {stop, AuthResult#{is_superuser => is_superuser(Pool, SuperQuery, ClientInfo), + anonymous => false, + auth_result => success}}; + {error, not_found} -> + emqx_metrics:inc(?AUTH_METRICS(ignore)), ok; + {error, ResultCode} -> + ?LOG(error, "[Postgres] Auth from pgsql failed: ~p", [ResultCode]), + emqx_metrics:inc(?AUTH_METRICS(failure)), + {stop, AuthResult#{auth_result => ResultCode, anonymous => false}} + end. + +%%-------------------------------------------------------------------- +%% Is Superuser? +%%-------------------------------------------------------------------- + +-spec(is_superuser(atom(),undefined | {string(), list()}, emqx_types:client()) -> boolean()). +is_superuser(_Pool, undefined, _Client) -> + false; +is_superuser(Pool, {SuperSql, Params}, ClientInfo) -> + case emqx_auth_pgsql_cli:equery(Pool, SuperSql, Params, ClientInfo) of + {ok, [_Super], [{true}]} -> + true; + {ok, [_Super], [_False]} -> + false; + {ok, [_Super], []} -> + false; + {error, _Error} -> + false + end. + +check_pass(Password, HashType) -> + case emqx_passwd:check_pass(Password, HashType) of + ok -> ok; + {error, _Reason} -> {error, not_authorized} + end. + +description() -> "Authentication with PostgreSQL". + diff --git a/apps/emqx_auth_pgsql/src/emqx_auth_pgsql_app.erl b/apps/emqx_auth_pgsql/src/emqx_auth_pgsql_app.erl new file mode 100644 index 000000000..1d05f6b8a --- /dev/null +++ b/apps/emqx_auth_pgsql/src/emqx_auth_pgsql_app.erl @@ -0,0 +1,63 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_pgsql_app). + +-behaviour(application). + +-emqx_plugin(auth). + +-include("emqx_auth_pgsql.hrl"). + +-import(emqx_auth_pgsql_cli, [parse_query/2]). + +%% Application callbacks +-export([ start/2 + , stop/1 + ]). + +%%-------------------------------------------------------------------- +%% Application callbacks +%%-------------------------------------------------------------------- + +start(_StartType, _StartArgs) -> + {ok, Sup} = emqx_auth_pgsql_sup:start_link(), + if_enabled(auth_query, fun(AuthQuery) -> + SuperQuery = parse_query(super_query, application:get_env(?APP, super_query, undefined)), + {ok, HashType} = application:get_env(?APP, password_hash), + AuthEnv = #{auth_query => AuthQuery, + super_query => SuperQuery, + hash_type => HashType, + pool => ?APP}, + ok = emqx_auth_pgsql:register_metrics(), + ok = emqx:hook('client.authenticate', fun emqx_auth_pgsql:check/3, [AuthEnv]) + end), + if_enabled(acl_query, fun(AclQuery) -> + ok = emqx_acl_pgsql:register_metrics(), + ok = emqx:hook('client.check_acl', fun emqx_acl_pgsql:check_acl/5, [#{acl_query => AclQuery, pool => ?APP}]) + end), + {ok, Sup}. + +stop(_State) -> + ok = emqx:unhook('client.authenticate', fun emqx_auth_pgsql:check/3), + ok = emqx:unhook('client.check_acl', fun emqx_acl_pgsql:check_acl/5). + +if_enabled(Par, Fun) -> + case application:get_env(?APP, Par) of + {ok, Query} -> Fun(parse_query(Par, Query)); + undefined -> ok + end. + diff --git a/apps/emqx_auth_pgsql/src/emqx_auth_pgsql_cli.erl b/apps/emqx_auth_pgsql/src/emqx_auth_pgsql_cli.erl new file mode 100644 index 000000000..a748140ad --- /dev/null +++ b/apps/emqx_auth_pgsql/src/emqx_auth_pgsql_cli.erl @@ -0,0 +1,138 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_pgsql_cli). + +-behaviour(ecpool_worker). + +-include("emqx_auth_pgsql.hrl"). + +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). + +-export([connect/1]). +-export([parse_query/2]). +-export([ equery/4 + , equery/3 + ]). + +%%-------------------------------------------------------------------- +%% Avoid SQL Injection: Parse SQL to Parameter Query. +%%-------------------------------------------------------------------- + +parse_query(_Par, undefined) -> + undefined; +parse_query(Par, Sql) -> + case re:run(Sql, "'%[ucCad]'", [global, {capture, all, list}]) of + {match, Variables} -> + Params = [Var || [Var] <- Variables], + {atom_to_list(Par), Params}; + nomatch -> + {atom_to_list(Par), []} + end. + +pgvar(Sql, Params) -> + Vars = ["$" ++ integer_to_list(I) || I <- lists:seq(1, length(Params))], + lists:foldl(fun({Param, Var}, S) -> + re:replace(S, Param, Var, [{return, list}]) + end, Sql, lists:zip(Params, Vars)). + +%%-------------------------------------------------------------------- +%% PostgreSQL Connect/Query +%%-------------------------------------------------------------------- + +connect(Opts) -> + Host = proplists:get_value(host, Opts), + Username = proplists:get_value(username, Opts), + Password = proplists:get_value(password, Opts), + case epgsql:connect(Host, Username, Password, conn_opts(Opts)) of + {ok, C} -> + conn_post(C), + {ok, C}; + {error, Reason = econnrefused} -> + ?LOG(error, "[Postgres] Can't connect to Postgres server: Connection refused."), + {error, Reason}; + {error, Reason = invalid_authorization_specification} -> + ?LOG(error, "[Postgres] Can't connect to Postgres server: Invalid authorization specification."), + {error, Reason}; + {error, Reason = invalid_password} -> + ?LOG(error, "[Postgres] Can't connect to Postgres server: Invalid password."), + {error, Reason}; + {error, Reason} -> + ?LOG(error, "[Postgres] Can't connect to Postgres server: ~p", [Reason]), + {error, Reason} + end. + +conn_post(Connection) -> + lists:foreach(fun(Par) -> + Sql0 = application:get_env(?APP, Par, undefined), + case parse_query(Par, Sql0) of + undefined -> ok; + {_, Params} -> + Sql = pgvar(Sql0, Params), + epgsql:parse(Connection, atom_to_list(Par), Sql, []) + end + end, [auth_query, acl_query, super_query]). + +conn_opts(Opts) -> + conn_opts(Opts, []). +conn_opts([], Acc) -> + Acc; +conn_opts([Opt = {database, _}|Opts], Acc) -> + conn_opts(Opts, [Opt|Acc]); +conn_opts([Opt = {ssl, _}|Opts], Acc) -> + conn_opts(Opts, [Opt|Acc]); +conn_opts([Opt = {port, _}|Opts], Acc) -> + conn_opts(Opts, [Opt|Acc]); +conn_opts([Opt = {timeout, _}|Opts], Acc) -> + conn_opts(Opts, [Opt|Acc]); +conn_opts([Opt = {ssl_opts, _}|Opts], Acc) -> + conn_opts(Opts, [Opt|Acc]); +conn_opts([_Opt|Opts], Acc) -> + conn_opts(Opts, Acc). + +equery(Pool, Sql, Params) -> + ecpool:with_client(Pool, fun(C) -> epgsql:prepared_query(C, Sql, Params) end). + +equery(Pool, Sql, Params, ClientInfo) -> + ecpool:with_client(Pool, fun(C) -> epgsql:prepared_query(C, Sql, replvar(Params, ClientInfo)) end). + +replvar(Params, ClientInfo) -> + replvar(Params, ClientInfo, []). + +replvar([], _ClientInfo, Acc) -> + lists:reverse(Acc); + +replvar(["'%u'" | Params], ClientInfo = #{username := Username}, Acc) -> + replvar(Params, ClientInfo, [Username | Acc]); +replvar(["'%c'" | Params], ClientInfo = #{clientid := ClientId}, Acc) -> + replvar(Params, ClientInfo, [ClientId | Acc]); +replvar(["'%a'" | Params], ClientInfo = #{peerhost := IpAddr}, Acc) -> + replvar(Params, ClientInfo, [inet_parse:ntoa(IpAddr) | Acc]); +replvar(["'%C'" | Params], ClientInfo, Acc) -> + replvar(Params, ClientInfo, [safe_get(cn, ClientInfo)| Acc]); +replvar(["'%d'" | Params], ClientInfo, Acc) -> + replvar(Params, ClientInfo, [safe_get(dn, ClientInfo)| Acc]); +replvar([Param | Params], ClientInfo, Acc) -> + replvar(Params, ClientInfo, [Param | Acc]). + +safe_get(K, ClientInfo) -> + bin(maps:get(K, ClientInfo, undefined)). + +bin(A) when is_atom(A) -> atom_to_binary(A, utf8); +bin(B) when is_binary(B) -> B; +bin(X) -> X. + diff --git a/apps/emqx_auth_pgsql/src/emqx_auth_pgsql_sup.erl b/apps/emqx_auth_pgsql/src/emqx_auth_pgsql_sup.erl new file mode 100644 index 000000000..162d04747 --- /dev/null +++ b/apps/emqx_auth_pgsql/src/emqx_auth_pgsql_sup.erl @@ -0,0 +1,37 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_pgsql_sup). + +-behaviour(supervisor). + +-include("emqx_auth_pgsql.hrl"). + +%% API +-export([start_link/0]). + +%% Supervisor callbacks +-export([init/1]). + +start_link() -> + supervisor:start_link({local, ?MODULE}, ?MODULE, []). + +init([]) -> + %% PgSQL Connection Pool + {ok, Opts} = application:get_env(?APP, server), + PoolSpec = ecpool:pool_spec(?APP, ?APP, emqx_auth_pgsql_cli, Opts), + {ok, {{one_for_one, 10, 100}, [PoolSpec]}}. + diff --git a/apps/emqx_auth_pgsql/test/.placeholder b/apps/emqx_auth_pgsql/test/.placeholder new file mode 100644 index 000000000..e69de29bb diff --git a/apps/emqx_auth_pgsql/test/emqx_auth_pgsql_SUITE.erl b/apps/emqx_auth_pgsql/test/emqx_auth_pgsql_SUITE.erl new file mode 100644 index 000000000..8c3b53621 --- /dev/null +++ b/apps/emqx_auth_pgsql/test/emqx_auth_pgsql_SUITE.erl @@ -0,0 +1,247 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_pgsql_SUITE). + +-compile(export_all). + +-define(POOL, emqx_auth_pgsql). + +-define(APP, emqx_auth_pgsql). + +-include_lib("emqx_libs/include/emqx.hrl"). + +-include_lib("eunit/include/eunit.hrl"). + +-include_lib("common_test/include/ct.hrl"). + +%%setp1 init table +-define(DROP_ACL_TABLE, "DROP TABLE IF EXISTS mqtt_acl_test"). + +-define(CREATE_ACL_TABLE, "CREATE TABLE mqtt_acl_test ( + id SERIAL primary key, + allow integer, + ipaddr character varying(60), + username character varying(100), + clientid character varying(100), + access integer, + topic character varying(100))"). + +-define(INIT_ACL, "INSERT INTO mqtt_acl_test (id, allow, ipaddr, username, clientid, access, topic) + VALUES + (1,1,'127.0.0.1','u1','c1',1,'t1'), + (2,0,'127.0.0.1','u2','c2',1,'t1'), + (3,1,'10.10.0.110','u1','c1',1,'t1'), + (4,1,'127.0.0.1','u3','c3',3,'t1')"). + +-define(DROP_AUTH_TABLE, "DROP TABLE IF EXISTS mqtt_user_test"). + +-define(CREATE_AUTH_TABLE, "CREATE TABLE mqtt_user_test ( + id SERIAL primary key, + is_superuser boolean, + username character varying(100), + password character varying(100), + salt character varying(40))"). + +-define(INIT_AUTH, "INSERT INTO mqtt_user_test (id, is_superuser, username, password, salt) + VALUES + (1, true, 'plain', 'plain', 'salt'), + (2, false, 'md5', '1bc29b36f623ba82aaf6724fd3b16718', 'salt'), + (3, false, 'sha', 'd8f4590320e1343a915b6394170650a8f35d6926', 'salt'), + (4, false, 'sha256', '5d5b09f6dcb2d53a5fffc60c4ac0d55fabdf556069d6631545f42aa6e3500f2e', 'salt'), + (5, false, 'pbkdf2_password', 'cdedb5281bb2f801565a1122b2563515', 'ATHENA.MIT.EDUraeburn'), + (6, false, 'bcrypt_foo', '$2a$12$sSS8Eg.ovVzaHzi1nUHYK.HbUIOdlQI0iS22Q5rd5z.JVVYH6sfm6', '$2a$12$sSS8Eg.ovVzaHzi1nUHYK.'), + (7, false, 'bcrypt', '$2y$16$rEVsDarhgHYB0TGnDFJzyu5f.T.Ha9iXMTk9J36NCMWWM7O16qyaK', 'salt')"). + +all() -> + [{group, ssl}, {group, nossl}]. + +groups() -> + Cases = emqx_ct:all(?MODULE), + [{ssl, [sequence], Cases}, {nossl, [sequence], Cases}]. + +init_per_group(Name, Config) -> + case Name of + ssl -> + emqx_ct_helpers:start_apps([emqx_auth_pgsql], fun set_special_configs_ssl/1); + nossl -> + emqx_ct_helpers:start_apps([emqx_auth_pgsql], fun set_special_configs/1) + end, + init_auth_(), + init_acl_(), + Config. + +end_per_group(_, Config) -> + drop_auth_(), + drop_acl_(), + emqx_ct_helpers:stop_apps([emqx_auth_pgsql]), + Config. + +set_special_configs_ssl(Name) -> + Server = application:get_env(?APP, server, []), + Path = emqx_ct_helpers:deps_path(emqx_auth_pgsql, "test/emqx_auth_pgsql_SUITE_data/"), + Sslopts = [{keyfile, Path ++ "/client-key.pem"}, + {certfile, Path ++ "/client-cert.pem"}, + {cacertfile, Path ++ "/ca.pem"}], + Temp = lists:keyreplace(ssl, 1, Server, {ssl, true}), + application:set_env(?APP, server, Temp), + application:set_env(?APP, server, lists:keyreplace(ssl_opts, 1, Temp, {ssl_opts, Sslopts})), + set_special_configs(Name). + +set_special_configs(emqx) -> + application:set_env(emqx, acl_nomatch, deny), + application:set_env(emqx, acl_file, + emqx_ct_helpers:deps_path(emqx, "test/emqx_SUITE_data/acl.conf")), + application:set_env(emqx, allow_anonymous, false), + application:set_env(emqx, enable_acl_cache, false), + application:set_env(emqx, plugins_loaded_file, + emqx_ct_helpers:deps_path(emqx, "test/emqx_SUITE_data/loaded_plugins")); + +set_special_configs(emqx_auth_pgsql) -> + Server = application:get_env(?APP, server, []), + application:set_env(?APP, server, + lists:keyreplace(password, + 1, + lists:keyreplace(pool_size, 1, Server, {pool_size, 1}), + {password, "public"})), + application:set_env(?APP, acl_query, "select allow, ipaddr, username, clientid, access, topic from mqtt_acl_test where ipaddr = '%a' or username = '%u' or username = '$all' or clientid = '%c'"), + application:set_env(?APP, super_query, "select is_superuser from mqtt_user_test where username = '%u' limit 1"), + application:set_env(?APP, auth_query, "select password from mqtt_user_test where username = '%u' limit 1"); +set_special_configs(_App) -> + ok. + +t_comment_config(_) -> + AuthCount = length(emqx_hooks:lookup('client.authenticate')), + AclCount = length(emqx_hooks:lookup('client.check_acl')), + application:stop(?APP), + [application:unset_env(?APP, Par) || Par <- [acl_query, auth_query]], + application:start(?APP), + ?assertEqual([], emqx_hooks:lookup('client.authenticate')), + ?assertEqual(AuthCount - 1, length(emqx_hooks:lookup('client.authenticate'))), + ?assertEqual(AclCount - 1, length(emqx_hooks:lookup('client.check_acl'))). + +t_placeholders(_) -> + ClientA = #{username => <<"plain">>, clientid => <<"plain">>, zone => external}, + reload([{password_hash, plain}, + {auth_query, "select password from mqtt_user_test where username = '%u' and 'a_cn_val' = '%C' limit 1"}]), + {error, not_authorized} = + emqx_access_control:authenticate(ClientA#{password => <<"plain">>}), + {error, not_authorized} = + emqx_access_control:authenticate(ClientA#{password => <<"plain">>, cn => undefined}), + {ok, _} = + emqx_access_control:authenticate(ClientA#{password => <<"plain">>, cn => <<"a_cn_val">>}), + + reload([{auth_query, "select password from mqtt_user_test where username = '%c' and 'a_dn_val' = '%d' limit 1"}]), + {error, not_authorized} = + emqx_access_control:authenticate(ClientA#{password => <<"plain">>}), + {error, not_authorized} = + emqx_access_control:authenticate(ClientA#{password => <<"plain">>, dn => undefined}), + {ok, _} = + emqx_access_control:authenticate(ClientA#{password => <<"plain">>, dn => <<"a_dn_val">>}), + + reload([{auth_query, "select password from mqtt_user_test where username = '%u' and '192.168.1.5' = '%a' limit 1"}]), + {error, not_authorized} = + emqx_access_control:authenticate(ClientA#{password => <<"plain">>}), + {ok, _} = + emqx_access_control:authenticate(ClientA#{password => <<"plain">>, peerhost => {192,168,1,5}}). + +t_check_auth(_) -> + Plain = #{clientid => <<"client1">>, username => <<"plain">>, zone => external}, + Md5 = #{clientid => <<"md5">>, username => <<"md5">>, zone => external}, + Sha = #{clientid => <<"sha">>, username => <<"sha">>, zone => external}, + Sha256 = #{clientid => <<"sha256">>, username => <<"sha256">>, zone => external}, + Pbkdf2 = #{clientid => <<"pbkdf2_password">>, username => <<"pbkdf2_password">>, zone => external}, + BcryptFoo = #{clientid => <<"bcrypt_foo">>, username => <<"bcrypt_foo">>, zone => external}, + User1 = #{clientid => <<"bcrypt_foo">>, username => <<"user">>, zone => external}, + Bcrypt = #{clientid => <<"bcrypt">>, username => <<"bcrypt">>, zone => external}, + reload([{password_hash, plain}, + {auth_query, "select password from mqtt_user_test where username = '%u' limit 1"}]), + {ok, #{is_superuser := true}} = emqx_access_control:authenticate(Plain#{password => <<"plain">>}), + reload([{password_hash, md5}]), + {ok, #{is_superuser := false}} = emqx_access_control:authenticate(Md5#{password => <<"md5">>}), + reload([{password_hash, sha}]), + {ok, #{is_superuser := false}} = emqx_access_control:authenticate(Sha#{password => <<"sha">>}), + reload([{password_hash, sha256}]), + {ok, #{is_superuser := false}} = emqx_access_control:authenticate(Sha256#{password => <<"sha256">>}), + reload([{password_hash, bcrypt}]), + {ok, #{is_superuser := false}} = emqx_access_control:authenticate(Bcrypt#{password => <<"password">>}), + %%pbkdf2 sha + reload([{password_hash, {pbkdf2, sha, 1, 16}}, {auth_query, "select password, salt from mqtt_user_test where username = '%u' limit 1"}]), + {ok, #{is_superuser := false}} = emqx_access_control:authenticate(Pbkdf2#{password => <<"password">>}), + reload([{password_hash, {salt, bcrypt}}]), + {ok, #{is_superuser := false}} = emqx_access_control:authenticate(BcryptFoo#{password => <<"foo">>}), + {error, _} = emqx_access_control:authenticate(User1#{password => <<"foo">>}), + {error, not_authorized} = emqx_access_control:authenticate(Bcrypt#{password => <<"password">>}). +t_check_acl(_) -> + emqx_modules:load_module(emqx_mod_acl_internal, false), + User1 = #{zone => external, peerhost => {127,0,0,1}, clientid => <<"c1">>, username => <<"u1">>}, + User2 = #{zone => external, peerhost => {127,0,0,1}, clientid => <<"c2">>, username => <<"u2">>}, + reload([{acl_query, "select allow, ipaddr, username, clientid, access, topic from mqtt_acl_test where ipaddr = '%a' or username = '%u' or username = '$all' or clientid = '%c'"}]), + allow = emqx_access_control:check_acl(User1, subscribe, <<"t1">>), + deny = emqx_access_control:check_acl(User2, subscribe, <<"t1">>), + User3 = #{zone => external, peerhost => {10,10,0,110}, clientid => <<"c1">>, username => <<"u1">>}, + User4 = #{zone => external, peerhost => {10,10,10,110}, clientid => <<"c1">>, username => <<"u1">>}, + allow = emqx_access_control:check_acl(User3, subscribe, <<"t1">>), + allow = emqx_access_control:check_acl(User3, subscribe, <<"t1">>), + allow = emqx_access_control:check_acl(User3, subscribe, <<"t2">>),%% nomatch -> ignore -> emqttd acl + allow = emqx_access_control:check_acl(User4, subscribe, <<"t1">>),%% nomatch -> ignore -> emqttd acl + User5 = #{zone => external, peerhost => {127,0,0,1}, clientid => <<"c3">>, username => <<"u3">>}, + allow = emqx_access_control:check_acl(User5, subscribe, <<"t1">>), + allow = emqx_access_control:check_acl(User5, publish, <<"t1">>). + +t_acl_super(_) -> + reload([{password_hash, plain}, {auth_query, "select password from mqtt_user_test where username = '%u' limit 1"}]), + {ok, C} = emqtt:start_link([{host, "localhost"}, {clientid, <<"simpleClient">>}, + {username, <<"plain">>}, {password, <<"plain">>}]), + {ok, _} = emqtt:connect(C), + timer:sleep(10), + emqtt:subscribe(C, <<"TopicA">>, qos2), + emqtt:publish(C, <<"TopicA">>, <<"Payload">>, qos2), + timer:sleep(1000), + receive + {publish, #{payload := Payload}} -> + ?assertEqual(<<"Payload">>, Payload) + after + 1000 -> + ct:fail({receive_timeout, <<"Payload">>}), + ok + end, + emqtt:disconnect(C). + +reload(Config) when is_list(Config) -> + application:stop(?APP), + [application:set_env(?APP, K, V) || {K, V} <- Config], + application:start(?APP). + +init_acl_() -> + {ok, Pid} = ecpool_worker:client(gproc_pool:pick_worker({ecpool, ?POOL})), + {ok, [], []} = epgsql:squery(Pid, ?DROP_ACL_TABLE), + {ok, [], []} = epgsql:squery(Pid, ?CREATE_ACL_TABLE), + {ok, _} = epgsql:equery(Pid, ?INIT_ACL). + +drop_acl_() -> + {ok, Pid} = ecpool_worker:client(gproc_pool:pick_worker({ecpool, ?POOL})), + {ok, [], []}= epgsql:squery(Pid, ?DROP_ACL_TABLE). + +init_auth_() -> + {ok, Pid} = ecpool_worker:client(gproc_pool:pick_worker({ecpool, ?POOL})), + {ok, [], []} = epgsql:squery(Pid, ?DROP_AUTH_TABLE), + {ok, [], []} = epgsql:squery(Pid, ?CREATE_AUTH_TABLE), + {ok, _} = epgsql:equery(Pid, ?INIT_AUTH). + +drop_auth_() -> + {ok, Pid} = ecpool_worker:client(gproc_pool:pick_worker({ecpool, ?POOL})), + {ok, [], []} = epgsql:squery(Pid, ?DROP_AUTH_TABLE). diff --git a/apps/emqx_auth_pgsql/test/emqx_auth_pgsql_SUITE_data/ca.pem b/apps/emqx_auth_pgsql/test/emqx_auth_pgsql_SUITE_data/ca.pem new file mode 100644 index 000000000..00b31d8a4 --- /dev/null +++ b/apps/emqx_auth_pgsql/test/emqx_auth_pgsql_SUITE_data/ca.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDAzCCAeugAwIBAgIBATANBgkqhkiG9w0BAQsFADA8MTowOAYDVQQDDDFNeVNR +TF9TZXJ2ZXJfOC4wLjE5X0F1dG9fR2VuZXJhdGVkX0NBX0NlcnRpZmljYXRlMB4X +DTIwMDYxMTAzMzg0NloXDTMwMDYwOTAzMzg0NlowPDE6MDgGA1UEAwwxTXlTUUxf +U2VydmVyXzguMC4xOV9BdXRvX0dlbmVyYXRlZF9DQV9DZXJ0aWZpY2F0ZTCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANJBlAYvTQ6euY4HcSn4syH7kq9s +KcG+OMjPUrj+KFEElCzgNuIhaS0f3ORQGB1PNcvVcfdXUI3WX332gWbr9s1b7Xl1 +JKJfDXs+26Cm6NhONTE3sPHnbTSmQEFb52hwAtjQmcY3IQs1AgxKFFHJfnCBEWfE +ePBQaiuYk1XDESMdWpMLrPnYQaj9MpAOUxjlmZCayzPWlF0j0IWvfsF5TqZL7tFK +9p5F/DzyZ4n1mqPVEoUmq5ZdSKj2TQkpWTMHBWHEDQQqXbyE1FGJR7zEUFeuG1KT +sVBg7iZEC93SygZTbgUZSQXIwQCsO6xZ8MB2XDJkPbWp/3Wc6c8I6P09F48CAwEA +AaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEADKz6bIpP5anp +GgLB0jkclRWuMlS4qqIt4itSsMXPJ/ezpHwECixmgW2TIQl6S1woRkUeMxhT2/Ay +Sn/7aKxuzRagyE5NEGOvrOuAP5RO2ZdNJ/X3/Rh533fK1sOTEEbSsWUvW6iSkZef +rsfZBVP32xBhRWkKRdLeLB4W99ADMa0IrTmZPCXHSSE2V4e1o6zWLXcOZeH1Qh8N +SkelBweR+8r1Fbvy1r3s7eH7DCbYoGEDVLQGOLvzHKBisQHmoDnnF5E9g1eeNRdg +o+vhOKfYCOzeNREJIqS42PHcGhdNRk90ycigPmfUJclz1mDHoMjKR2S5oosTpr65 +tNPx3CL7GA== +-----END CERTIFICATE----- diff --git a/apps/emqx_auth_pgsql/test/emqx_auth_pgsql_SUITE_data/client-cert.pem b/apps/emqx_auth_pgsql/test/emqx_auth_pgsql_SUITE_data/client-cert.pem new file mode 100644 index 000000000..aad1404ca --- /dev/null +++ b/apps/emqx_auth_pgsql/test/emqx_auth_pgsql_SUITE_data/client-cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAeygAwIBAgIBAzANBgkqhkiG9w0BAQsFADA8MTowOAYDVQQDDDFNeVNR +TF9TZXJ2ZXJfOC4wLjE5X0F1dG9fR2VuZXJhdGVkX0NBX0NlcnRpZmljYXRlMB4X +DTIwMDYxMTAzMzg0N1oXDTMwMDYwOTAzMzg0N1owQDE+MDwGA1UEAww1TXlTUUxf +U2VydmVyXzguMC4xOV9BdXRvX0dlbmVyYXRlZF9DbGllbnRfQ2VydGlmaWNhdGUw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVYSWpOvCTupz82fc85Opv +EQ7rkB8X2oOMyBCpkyHKBIr1ZQgRDWBp9UVOASq3GnSElm6+T3Kb1QbOffa8GIlw +sjAueKdq5L2eSkmPIEQ7eoO5kEW+4V866hE1LeL/PmHg2lGP0iqZiJYtElhHNQO8 +3y9I7cm3xWMAA3SSWikVtpJRn3qIp2QSrH+tK+/HHbE5QwtPxdir4ULSCSOaM5Yh +Wi5Oto88TZqe1v7SXC864JVvO4LuS7TuSreCdWZyPXTJFBFeCEWSAxonKZrqHbBe +CwKML6/0NuzjaQ51c2tzmVI6xpHj3nnu4cSRx6Jf9WBm+35vm0wk4pohX3ptdzeV +AgMBAAGjDTALMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEBAByQ5zSNeFUH +Aw7JlpZHtHaSEeiiyBHke20ziQ07BK1yi/ms2HAWwQkpZv149sjNuIRH8pkTmkZn +g8PDzSefjLbC9AsWpWV0XNV22T/cdobqLqMBDDZ2+5bsV+jTrOigWd9/AHVZ93PP +IJN8HJn6rtvo2l1bh/CdsX14uVSdofXnuWGabNTydqtMvmCerZsdf6qKqLL+PYwm +RDpgWiRUY7KPBSSlKm/9lJzA+bOe4dHeJzxWFVCJcbpoiTFs1je1V8kKQaHtuW39 +ifX6LTKUMlwEECCbDKM8Yq2tm8NjkjCcnFDtKg8zKGPUu+jrFMN5otiC3wnKcP7r +O9EkaPcgYH8= +-----END CERTIFICATE----- diff --git a/apps/emqx_auth_pgsql/test/emqx_auth_pgsql_SUITE_data/client-key.pem b/apps/emqx_auth_pgsql/test/emqx_auth_pgsql_SUITE_data/client-key.pem new file mode 100644 index 000000000..6789d0291 --- /dev/null +++ b/apps/emqx_auth_pgsql/test/emqx_auth_pgsql_SUITE_data/client-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEA1WElqTrwk7qc/Nn3POTqbxEO65AfF9qDjMgQqZMhygSK9WUI +EQ1gafVFTgEqtxp0hJZuvk9ym9UGzn32vBiJcLIwLninauS9nkpJjyBEO3qDuZBF +vuFfOuoRNS3i/z5h4NpRj9IqmYiWLRJYRzUDvN8vSO3Jt8VjAAN0klopFbaSUZ96 +iKdkEqx/rSvvxx2xOUMLT8XYq+FC0gkjmjOWIVouTraPPE2antb+0lwvOuCVbzuC +7ku07kq3gnVmcj10yRQRXghFkgMaJyma6h2wXgsCjC+v9Dbs42kOdXNrc5lSOsaR +49557uHEkceiX/VgZvt+b5tMJOKaIV96bXc3lQIDAQABAoIBAF7yjXmSOn7h6P0y +WCuGiTLG2mbDiLJqj2LTm2Z5i+2Cu/qZ7E76Ls63TxF4v3MemH5vGfQhEhR5ZD/6 +GRJ1sKKvB3WGRqjwA9gtojHH39S/nWGy6vYW/vMOOH37XyjIr3EIdIaUtFQBTSHd +Kd71niYrAbVn6fyWHolhADwnVmTMOl5OOAhCdEF4GN3b5aIhIu8BJ7EUzTtHBJIj +CAEfjZFjDs1y1cIgGFJkuIQxMfCpq5recU2qwip7YO6fk//WEjOPu7kSf5IEswL8 +jg1dea9rGBV6KaD2xsgsC6Ll6Sb4BbsrHMfflG3K2Lk3RdVqqTFp1Fn1PTLQE/1S +S/SZPYECgYEA9qYcHKHd0+Q5Ty5wgpxKGa4UCWkpwvfvyv4bh8qlmxueB+l2AIdo +ZvkM8gTPagPQ3WypAyC2b9iQu70uOJo1NizTtKnpjDdN1YpDjISJuS/P0x73gZwy +gmoM5AzMtN4D6IbxXtXnPaYICvwLKU80ouEN5ZPM4/ODLUu6gsp0v2UCgYEA3Xgi +zMC4JF0vEKEaK0H6QstaoXUmw/lToZGH3TEojBIkb/2LrHUclygtONh9kJSFb89/ +jbmRRLAOrx3HZKCNGUmF4H9k5OQyAIv6OGBinvLGqcbqnyNlI+Le8zxySYwKMlEj +EMrBCLmSyi0CGFrbZ3mlj/oCET/ql9rNvcK+DHECgYAEx5dH3sMjtgp+RFId1dWB +xePRgt4yTwewkVgLO5wV82UOljGZNQaK6Eyd7AXw8f38LHzh+KJQbIvxd2sL4cEi +OaAoohpKg0/Y0YMZl//rPMf0OWdmdZZs/I0fZjgZUSwWN3c59T8z7KG/RL8an9RP +S7kvN7wCttdV61/D5RR6GQKBgDxCe/WKWpBKaovzydMLWLTj7/0Oi0W3iXHkzzr4 +LTgvl4qBSofaNbVLUUKuZTv5rXUG2IYPf99YqCYtzBstNDc1MiAriaBeFtzfOW4t +i6gEFtoLLbuvPc3N5Sv5vn8Ug5G9UfU3td5R4AbyyCcoUZqOFuZd+EIJSiOXfXOs +kVmBAoGBAIU9aPAqhU5LX902oq8KsrpdySONqv5mtoStvl3wo95WIqXNEsFY60wO +q02jKQmJJ2MqhkJm2EoF2Mq8+40EZ5sz8LdgeQ/M0yQ9lAhPi4rftwhpe55Ma9dk +SE9X1c/DMCBEaIjJqVXdy0/EeArwpb8sHkguVVAZUWxzD+phm1gs +-----END RSA PRIVATE KEY----- diff --git a/apps/emqx_auth_pgsql/test/emqx_auth_pgsql_SUITE_data/pg.conf b/apps/emqx_auth_pgsql/test/emqx_auth_pgsql_SUITE_data/pg.conf new file mode 100644 index 000000000..7b78cd1e3 --- /dev/null +++ b/apps/emqx_auth_pgsql/test/emqx_auth_pgsql_SUITE_data/pg.conf @@ -0,0 +1,21 @@ +# - Connection Settings - + +listen_addresses = '*' +port = 5432 # (change requires restart) +max_connections = 100 # (change requires restart) +# - SSL - + +ssl = on +ssl_cert_file = '/etc/postgresql/server-cert.pem' +ssl_key_file = '/etc/postgresql/server-key.pem' +shared_buffers = 128MB # min 128kB +checkpoint_timeout = 5min # range 30s-1d +max_wal_size = 1GB +min_wal_size = 80MB +datestyle = 'iso, mdy' +timezone = 'Etc/UTC' +lc_messages = 'en_US.utf8' # locale for system error message +lc_monetary = 'en_US.utf8' # locale for monetary formatting +lc_numeric = 'en_US.utf8' # locale for number formatting +lc_time = 'en_US.utf8' # locale for time formatting +default_text_search_config = 'pg_catalog.english' diff --git a/apps/emqx_auth_pgsql/test/emqx_auth_pgsql_SUITE_data/server-cert.pem b/apps/emqx_auth_pgsql/test/emqx_auth_pgsql_SUITE_data/server-cert.pem new file mode 100644 index 000000000..a2f9688df --- /dev/null +++ b/apps/emqx_auth_pgsql/test/emqx_auth_pgsql_SUITE_data/server-cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAeygAwIBAgIBAjANBgkqhkiG9w0BAQsFADA8MTowOAYDVQQDDDFNeVNR +TF9TZXJ2ZXJfOC4wLjE5X0F1dG9fR2VuZXJhdGVkX0NBX0NlcnRpZmljYXRlMB4X +DTIwMDYxMTAzMzg0NloXDTMwMDYwOTAzMzg0NlowQDE+MDwGA1UEAww1TXlTUUxf +U2VydmVyXzguMC4xOV9BdXRvX0dlbmVyYXRlZF9TZXJ2ZXJfQ2VydGlmaWNhdGUw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCcEnEm5hqP1EbEJycOz8Ua +NWp29QdpFUzTWhkKGhVXk+0msmNTw4NBAFB42moY44OU8wvDideOlJNhPRWveD8z +G2lxzJA91p0UK4et8ia9MmeuCGhdC9jxJ8X69WNlUiPyy0hI/ZsqRq9Z0C2eW0iL +JPXsy4X8Xpw3SFwoXf5pR9RFY5Pb2tuyxqmSestu2VXT/NQjJg4CVDR3mFcHPXZB +4elRzH0WshExEGkgy0bg20MJeRc2Qdb5Xx+EakbmwroDWaCn3NSGqQ7jv6Vw0doy +TGvS6h6RHBxnyqRfRgKGlCoOMG9/5+rFJC00QpCUG2vHXHWGoWlMlJ3foN7rj5v9 +AgMBAAGjDTALMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEBAJ5zt2rj4Ag6 +zpN59AWC1Fur8g8l41ksHkSpKPp+PtyO/ngvbMqBpfmK1e7JCKZv/68QXfMyWWAI +hwalqZkXXWHKjuz3wE7dE25PXFXtGJtcZAaj10xt98fzdqt8lQSwh2kbfNwZIz1F +sgAStgE7+ZTcqTgvNB76Os1UK0to+/P0VBWktaVFdyub4Nc2SdPVnZNvrRBXBwOD +3V8ViwywDOFoE7DvCvwx/SVsvoC0Z4j3AMMovO6oHicP7uU83qsQgm1Qru3YeoLR ++DoVi7IPHbWvN7MqFYn3YjNlByO2geblY7MR0BlqbFlmFrqLsUfjsh2ys7/U/knC +dN/klu446fI= +-----END CERTIFICATE----- diff --git a/apps/emqx_auth_pgsql/test/emqx_auth_pgsql_SUITE_data/server-key.pem b/apps/emqx_auth_pgsql/test/emqx_auth_pgsql_SUITE_data/server-key.pem new file mode 100644 index 000000000..a1dfd5f78 --- /dev/null +++ b/apps/emqx_auth_pgsql/test/emqx_auth_pgsql_SUITE_data/server-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAnBJxJuYaj9RGxCcnDs/FGjVqdvUHaRVM01oZChoVV5PtJrJj +U8ODQQBQeNpqGOODlPMLw4nXjpSTYT0Vr3g/MxtpccyQPdadFCuHrfImvTJnrgho +XQvY8SfF+vVjZVIj8stISP2bKkavWdAtnltIiyT17MuF/F6cN0hcKF3+aUfURWOT +29rbssapknrLbtlV0/zUIyYOAlQ0d5hXBz12QeHpUcx9FrIRMRBpIMtG4NtDCXkX +NkHW+V8fhGpG5sK6A1mgp9zUhqkO47+lcNHaMkxr0uoekRwcZ8qkX0YChpQqDjBv +f+fqxSQtNEKQlBtrx1x1hqFpTJSd36De64+b/QIDAQABAoIBAFiah66Dt9SruLkn +WR8piUaFyLlcBib8Nq9OWSTJBhDAJERxxb4KIvvGB+l0ZgNXNp5bFPSfzsZdRwZP +PX5uj8Kd71Dxx3mz211WESMJdEC42u+MSmN4lGLkJ5t/sDwXU91E1vbJM0ve8THV +4/Ag9qA4DX2vVZOeyqT/6YHpSsPNZplqzrbAiwrfHwkctHfgqwOf3QLfhmVQgfCS +VwidBldEUv2whSIiIxh4Rv5St4kA68IBCbJxdpOpyuQBkk6CkxZ7VN9FqOuSd4Pk +Wm7iWyBMZsCmELZh5XAXld4BEt87C5R4CvbPBDZxAv3THk1DNNvpy3PFQfwARRFb +SAToYMECgYEAyL7U8yxpzHDYWd3oCx6vTi9p9N/z0FfAkWrRF6dm4UcSklNiT1Aq +EOnTA+SaW8tV3E64gCWcY23gNP8so/ZseWj6L+peHwtchaP9+KB7yGw2A+05+lOx +VetLTjAOmfpiUXFe5w1q4C1RGhLjZjjzW+GvwdAuchQgUEFaomrV+PUCgYEAxwfH +cmVGFbAktcjU4HSRjKSfawCrut+3YUOLybyku3Q/hP9amG8qkVTFe95CTLjLe2D0 +ccaTTpofFEJ32COeck0g0Ujn/qQ+KXRoauOYs4FB1DtqMpqB78wufWEUpDpbd9/h +J+gJdC/IADd4tJW9zA92g8IA7ZtFmqDtiSpQ0ekCgYAQGkaorvJZpN+l7cf0RGTZ +h7IfI2vCVZer0n6tQA9fmLzjoe6r4AlPzAHSOR8sp9XeUy43kUzHKQQoHCPvjw/K +eWJAP7OHF/k2+x2fOPhU7mEy1W+mJdp+wt4Kio5RSaVjVQ3AyPG+w8PSrJszEvRq +dWMMz+851WV2KpfjmWBKlQKBgQC++4j4DZQV5aMkSKV1CIZOBf3vaIJhXKEUFQPD +PmB4fBEjpwCg+zNGp6iktt65zi17o8qMjrb1mtCt2SY04eD932LZUHNFlwcLMmes +Ad+aiDLJ24WJL1f16eDGcOyktlblDZB5gZ/ovJzXEGOkLXglosTfo77OQculmDy2 +/UL2WQKBgGeKasmGNfiYAcWio+KXgFkHXWtAXB9B91B1OFnCa40wx+qnl71MIWQH +PQ/CZFNWOfGiNEJIZjrHsfNJoeXkhq48oKcT0AVCDYyLV0VxDO4ejT95mGW6njNd +JpvmhwwAjOvuWVr0tn4iXlSK8irjlJHmwcRjLTJq97vE9fsA2MjI +-----END RSA PRIVATE KEY----- diff --git a/apps/emqx_auth_redis/.ci/docker-compose.yml b/apps/emqx_auth_redis/.ci/docker-compose.yml new file mode 100644 index 000000000..27794546e --- /dev/null +++ b/apps/emqx_auth_redis/.ci/docker-compose.yml @@ -0,0 +1,26 @@ +version: '3' + +services: + erlang: + image: erlang:22.1 + volumes: + - ../:/emqx_auth_redis + networks: + - emqx_bridge + depends_on: + - redis_server + tty: true + + redis_server: + build: + context: ./emqx-redis + args: + BUILD_FROM: redis:${REDIS_TAG} + image: emqx-redis + restart: always + networks: + - emqx_bridge + +networks: + emqx_bridge: + driver: bridge diff --git a/apps/emqx_auth_redis/.ci/emqx-redis/Dockerfile b/apps/emqx_auth_redis/.ci/emqx-redis/Dockerfile new file mode 100644 index 000000000..9fe51e86e --- /dev/null +++ b/apps/emqx_auth_redis/.ci/emqx-redis/Dockerfile @@ -0,0 +1,4 @@ +ARG BUILD_FROM=redis:5 +FROM ${BUILD_FROM} +COPY redis.conf /usr/local/etc/redis/redis.conf +CMD [ "redis-server", "/usr/local/etc/redis/redis.conf" ] diff --git a/apps/emqx_auth_redis/.ci/emqx-redis/redis.conf b/apps/emqx_auth_redis/.ci/emqx-redis/redis.conf new file mode 100644 index 000000000..8415f9d5f --- /dev/null +++ b/apps/emqx_auth_redis/.ci/emqx-redis/redis.conf @@ -0,0 +1,1377 @@ +# Redis configuration file example. +# +# Note that in order to read the configuration file, Redis must be +# started with the file path as first argument: +# +# ./redis-server /path/to/redis.conf + +# Note on units: when memory size is needed, it is possible to specify +# it in the usual form of 1k 5GB 4M and so forth: +# +# 1k => 1000 bytes +# 1kb => 1024 bytes +# 1m => 1000000 bytes +# 1mb => 1024*1024 bytes +# 1g => 1000000000 bytes +# 1gb => 1024*1024*1024 bytes +# +# units are case insensitive so 1GB 1Gb 1gB are all the same. + +################################## INCLUDES ################################### + +# Include one or more other config files here. This is useful if you +# have a standard template that goes to all Redis servers but also need +# to customize a few per-server settings. Include files can include +# other files, so use this wisely. +# +# Notice option "include" won't be rewritten by command "CONFIG REWRITE" +# from admin or Redis Sentinel. Since Redis always uses the last processed +# line as value of a configuration directive, you'd better put includes +# at the beginning of this file to avoid overwriting config change at runtime. +# +# If instead you are interested in using includes to override configuration +# options, it is better to use include as the last line. +# +# include /path/to/local.conf +# include /path/to/other.conf + +################################## MODULES ##################################### + +# Load modules at startup. If the server is not able to load modules +# it will abort. It is possible to use multiple loadmodule directives. +# +# loadmodule /path/to/my_module.so +# loadmodule /path/to/other_module.so + +################################## NETWORK ##################################### + +# By default, if no "bind" configuration directive is specified, Redis listens +# for connections from all the network interfaces available on the server. +# It is possible to listen to just one or multiple selected interfaces using +# the "bind" configuration directive, followed by one or more IP addresses. +# +# Examples: +# +# bind 192.168.1.100 10.0.0.1 +# bind 127.0.0.1 ::1 +# +# ~~~ WARNING ~~~ If the computer running Redis is directly exposed to the +# internet, binding to all the interfaces is dangerous and will expose the +# instance to everybody on the internet. So by default we uncomment the +# following bind directive, that will force Redis to listen only into +# the IPv4 loopback interface address (this means Redis will be able to +# accept connections only from clients running into the same computer it +# is running). +# +# IF YOU ARE SURE YOU WANT YOUR INSTANCE TO LISTEN TO ALL THE INTERFACES +# JUST COMMENT THE FOLLOWING LINE. +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +bind 0.0.0.0 :: + +# Protected mode is a layer of security protection, in order to avoid that +# Redis instances left open on the internet are accessed and exploited. +# +# When protected mode is on and if: +# +# 1) The server is not binding explicitly to a set of addresses using the +# "bind" directive. +# 2) No password is configured. +# +# The server only accepts connections from clients connecting from the +# IPv4 and IPv6 loopback addresses 127.0.0.1 and ::1, and from Unix domain +# sockets. +# +# By default protected mode is enabled. You should disable it only if +# you are sure you want clients from other hosts to connect to Redis +# even if no authentication is configured, nor a specific set of interfaces +# are explicitly listed using the "bind" directive. +protected-mode no + +# Accept connections on the specified port, default is 6379 (IANA #815344). +# If port 0 is specified Redis will not listen on a TCP socket. +port 6379 + +# TCP listen() backlog. +# +# In high requests-per-second environments you need an high backlog in order +# to avoid slow clients connections issues. Note that the Linux kernel +# will silently truncate it to the value of /proc/sys/net/core/somaxconn so +# make sure to raise both the value of somaxconn and tcp_max_syn_backlog +# in order to get the desired effect. +tcp-backlog 511 + +# Unix socket. +# +# Specify the path for the Unix socket that will be used to listen for +# incoming connections. There is no default, so Redis will not listen +# on a unix socket when not specified. +# +# unixsocket /tmp/redis.sock +# unixsocketperm 700 + +# Close the connection after a client is idle for N seconds (0 to disable) +timeout 0 + +# TCP keepalive. +# +# If non-zero, use SO_KEEPALIVE to send TCP ACKs to clients in absence +# of communication. This is useful for two reasons: +# +# 1) Detect dead peers. +# 2) Take the connection alive from the point of view of network +# equipment in the middle. +# +# On Linux, the specified value (in seconds) is the period used to send ACKs. +# Note that to close the connection the double of the time is needed. +# On other kernels the period depends on the kernel configuration. +# +# A reasonable value for this option is 300 seconds, which is the new +# Redis default starting with Redis 3.2.1. +tcp-keepalive 300 + +################################# GENERAL ##################################### + +# By default Redis does not run as a daemon. Use 'yes' if you need it. +# Note that Redis will write a pid file in /var/run/redis.pid when daemonized. +daemonize no + +# If you run Redis from upstart or systemd, Redis can interact with your +# supervision tree. Options: +# supervised no - no supervision interaction +# supervised upstart - signal upstart by putting Redis into SIGSTOP mode +# supervised systemd - signal systemd by writing READY=1 to $NOTIFY_SOCKET +# supervised auto - detect upstart or systemd method based on +# UPSTART_JOB or NOTIFY_SOCKET environment variables +# Note: these supervision methods only signal "process is ready." +# They do not enable continuous liveness pings back to your supervisor. +supervised no + +# If a pid file is specified, Redis writes it where specified at startup +# and removes it at exit. +# +# When the server runs non daemonized, no pid file is created if none is +# specified in the configuration. When the server is daemonized, the pid file +# is used even if not specified, defaulting to "/var/run/redis.pid". +# +# Creating a pid file is best effort: if Redis is not able to create it +# nothing bad happens, the server will start and run normally. +pidfile /var/run/redis_6379.pid + +# Specify the server verbosity level. +# This can be one of: +# debug (a lot of information, useful for development/testing) +# verbose (many rarely useful info, but not a mess like the debug level) +# notice (moderately verbose, what you want in production probably) +# warning (only very important / critical messages are logged) +loglevel notice + +# Specify the log file name. Also the empty string can be used to force +# Redis to log on the standard output. Note that if you use standard +# output for logging but daemonize, logs will be sent to /dev/null +logfile "" + +# To enable logging to the system logger, just set 'syslog-enabled' to yes, +# and optionally update the other syslog parameters to suit your needs. +# syslog-enabled no + +# Specify the syslog identity. +# syslog-ident redis + +# Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7. +# syslog-facility local0 + +# Set the number of databases. The default database is DB 0, you can select +# a different one on a per-connection basis using SELECT where +# dbid is a number between 0 and 'databases'-1 +databases 16 + +# By default Redis shows an ASCII art logo only when started to log to the +# standard output and if the standard output is a TTY. Basically this means +# that normally a logo is displayed only in interactive sessions. +# +# However it is possible to force the pre-4.0 behavior and always show a +# ASCII art logo in startup logs by setting the following option to yes. +always-show-logo yes + +################################ SNAPSHOTTING ################################ +# +# Save the DB on disk: +# +# save +# +# Will save the DB if both the given number of seconds and the given +# number of write operations against the DB occurred. +# +# In the example below the behaviour will be to save: +# after 900 sec (15 min) if at least 1 key changed +# after 300 sec (5 min) if at least 10 keys changed +# after 60 sec if at least 10000 keys changed +# +# Note: you can disable saving completely by commenting out all "save" lines. +# +# It is also possible to remove all the previously configured save +# points by adding a save directive with a single empty string argument +# like in the following example: +# +# save "" + +save 900 1 +save 300 10 +save 60 10000 + +# By default Redis will stop accepting writes if RDB snapshots are enabled +# (at least one save point) and the latest background save failed. +# This will make the user aware (in a hard way) that data is not persisting +# on disk properly, otherwise chances are that no one will notice and some +# disaster will happen. +# +# If the background saving process will start working again Redis will +# automatically allow writes again. +# +# However if you have setup your proper monitoring of the Redis server +# and persistence, you may want to disable this feature so that Redis will +# continue to work as usual even if there are problems with disk, +# permissions, and so forth. +stop-writes-on-bgsave-error yes + +# Compress string objects using LZF when dump .rdb databases? +# For default that's set to 'yes' as it's almost always a win. +# If you want to save some CPU in the saving child set it to 'no' but +# the dataset will likely be bigger if you have compressible values or keys. +rdbcompression yes + +# Since version 5 of RDB a CRC64 checksum is placed at the end of the file. +# This makes the format more resistant to corruption but there is a performance +# hit to pay (around 10%) when saving and loading RDB files, so you can disable it +# for maximum performances. +# +# RDB files created with checksum disabled have a checksum of zero that will +# tell the loading code to skip the check. +rdbchecksum yes + +# The filename where to dump the DB +dbfilename dump.rdb + +# The working directory. +# +# The DB will be written inside this directory, with the filename specified +# above using the 'dbfilename' configuration directive. +# +# The Append Only File will also be created inside this directory. +# +# Note that you must specify a directory here, not a file name. +dir ./ + +################################# REPLICATION ################################# + +# Master-Replica replication. Use replicaof to make a Redis instance a copy of +# another Redis server. A few things to understand ASAP about Redis replication. +# +# +------------------+ +---------------+ +# | Master | ---> | Replica | +# | (receive writes) | | (exact copy) | +# +------------------+ +---------------+ +# +# 1) Redis replication is asynchronous, but you can configure a master to +# stop accepting writes if it appears to be not connected with at least +# a given number of replicas. +# 2) Redis replicas are able to perform a partial resynchronization with the +# master if the replication link is lost for a relatively small amount of +# time. You may want to configure the replication backlog size (see the next +# sections of this file) with a sensible value depending on your needs. +# 3) Replication is automatic and does not need user intervention. After a +# network partition replicas automatically try to reconnect to masters +# and resynchronize with them. +# +# replicaof + +# If the master is password protected (using the "requirepass" configuration +# directive below) it is possible to tell the replica to authenticate before +# starting the replication synchronization process, otherwise the master will +# refuse the replica request. +# +# masterauth + +# When a replica loses its connection with the master, or when the replication +# is still in progress, the replica can act in two different ways: +# +# 1) if replica-serve-stale-data is set to 'yes' (the default) the replica will +# still reply to client requests, possibly with out of date data, or the +# data set may just be empty if this is the first synchronization. +# +# 2) if replica-serve-stale-data is set to 'no' the replica will reply with +# an error "SYNC with master in progress" to all the kind of commands +# but to INFO, replicaOF, AUTH, PING, SHUTDOWN, REPLCONF, ROLE, CONFIG, +# SUBSCRIBE, UNSUBSCRIBE, PSUBSCRIBE, PUNSUBSCRIBE, PUBLISH, PUBSUB, +# COMMAND, POST, HOST: and LATENCY. +# +replica-serve-stale-data yes + +# You can configure a replica instance to accept writes or not. Writing against +# a replica instance may be useful to store some ephemeral data (because data +# written on a replica will be easily deleted after resync with the master) but +# may also cause problems if clients are writing to it because of a +# misconfiguration. +# +# Since Redis 2.6 by default replicas are read-only. +# +# Note: read only replicas are not designed to be exposed to untrusted clients +# on the internet. It's just a protection layer against misuse of the instance. +# Still a read only replica exports by default all the administrative commands +# such as CONFIG, DEBUG, and so forth. To a limited extent you can improve +# security of read only replicas using 'rename-command' to shadow all the +# administrative / dangerous commands. +replica-read-only yes + +# Replication SYNC strategy: disk or socket. +# +# ------------------------------------------------------- +# WARNING: DISKLESS REPLICATION IS EXPERIMENTAL CURRENTLY +# ------------------------------------------------------- +# +# New replicas and reconnecting replicas that are not able to continue the replication +# process just receiving differences, need to do what is called a "full +# synchronization". An RDB file is transmitted from the master to the replicas. +# The transmission can happen in two different ways: +# +# 1) Disk-backed: The Redis master creates a new process that writes the RDB +# file on disk. Later the file is transferred by the parent +# process to the replicas incrementally. +# 2) Diskless: The Redis master creates a new process that directly writes the +# RDB file to replica sockets, without touching the disk at all. +# +# With disk-backed replication, while the RDB file is generated, more replicas +# can be queued and served with the RDB file as soon as the current child producing +# the RDB file finishes its work. With diskless replication instead once +# the transfer starts, new replicas arriving will be queued and a new transfer +# will start when the current one terminates. +# +# When diskless replication is used, the master waits a configurable amount of +# time (in seconds) before starting the transfer in the hope that multiple replicas +# will arrive and the transfer can be parallelized. +# +# With slow disks and fast (large bandwidth) networks, diskless replication +# works better. +repl-diskless-sync no + +# When diskless replication is enabled, it is possible to configure the delay +# the server waits in order to spawn the child that transfers the RDB via socket +# to the replicas. +# +# This is important since once the transfer starts, it is not possible to serve +# new replicas arriving, that will be queued for the next RDB transfer, so the server +# waits a delay in order to let more replicas arrive. +# +# The delay is specified in seconds, and by default is 5 seconds. To disable +# it entirely just set it to 0 seconds and the transfer will start ASAP. +repl-diskless-sync-delay 5 + +# Replicas send PINGs to server in a predefined interval. It's possible to change +# this interval with the repl_ping_replica_period option. The default value is 10 +# seconds. +# +# repl-ping-replica-period 10 + +# The following option sets the replication timeout for: +# +# 1) Bulk transfer I/O during SYNC, from the point of view of replica. +# 2) Master timeout from the point of view of replicas (data, pings). +# 3) Replica timeout from the point of view of masters (REPLCONF ACK pings). +# +# It is important to make sure that this value is greater than the value +# specified for repl-ping-replica-period otherwise a timeout will be detected +# every time there is low traffic between the master and the replica. +# +# repl-timeout 60 + +# Disable TCP_NODELAY on the replica socket after SYNC? +# +# If you select "yes" Redis will use a smaller number of TCP packets and +# less bandwidth to send data to replicas. But this can add a delay for +# the data to appear on the replica side, up to 40 milliseconds with +# Linux kernels using a default configuration. +# +# If you select "no" the delay for data to appear on the replica side will +# be reduced but more bandwidth will be used for replication. +# +# By default we optimize for low latency, but in very high traffic conditions +# or when the master and replicas are many hops away, turning this to "yes" may +# be a good idea. +repl-disable-tcp-nodelay no + +# Set the replication backlog size. The backlog is a buffer that accumulates +# replica data when replicas are disconnected for some time, so that when a replica +# wants to reconnect again, often a full resync is not needed, but a partial +# resync is enough, just passing the portion of data the replica missed while +# disconnected. +# +# The bigger the replication backlog, the longer the time the replica can be +# disconnected and later be able to perform a partial resynchronization. +# +# The backlog is only allocated once there is at least a replica connected. +# +# repl-backlog-size 1mb + +# After a master has no longer connected replicas for some time, the backlog +# will be freed. The following option configures the amount of seconds that +# need to elapse, starting from the time the last replica disconnected, for +# the backlog buffer to be freed. +# +# Note that replicas never free the backlog for timeout, since they may be +# promoted to masters later, and should be able to correctly "partially +# resynchronize" with the replicas: hence they should always accumulate backlog. +# +# A value of 0 means to never release the backlog. +# +# repl-backlog-ttl 3600 + +# The replica priority is an integer number published by Redis in the INFO output. +# It is used by Redis Sentinel in order to select a replica to promote into a +# master if the master is no longer working correctly. +# +# A replica with a low priority number is considered better for promotion, so +# for instance if there are three replicas with priority 10, 100, 25 Sentinel will +# pick the one with priority 10, that is the lowest. +# +# However a special priority of 0 marks the replica as not able to perform the +# role of master, so a replica with priority of 0 will never be selected by +# Redis Sentinel for promotion. +# +# By default the priority is 100. +replica-priority 100 + +# It is possible for a master to stop accepting writes if there are less than +# N replicas connected, having a lag less or equal than M seconds. +# +# The N replicas need to be in "online" state. +# +# The lag in seconds, that must be <= the specified value, is calculated from +# the last ping received from the replica, that is usually sent every second. +# +# This option does not GUARANTEE that N replicas will accept the write, but +# will limit the window of exposure for lost writes in case not enough replicas +# are available, to the specified number of seconds. +# +# For example to require at least 3 replicas with a lag <= 10 seconds use: +# +# min-replicas-to-write 3 +# min-replicas-max-lag 10 +# +# Setting one or the other to 0 disables the feature. +# +# By default min-replicas-to-write is set to 0 (feature disabled) and +# min-replicas-max-lag is set to 10. + +# A Redis master is able to list the address and port of the attached +# replicas in different ways. For example the "INFO replication" section +# offers this information, which is used, among other tools, by +# Redis Sentinel in order to discover replica instances. +# Another place where this info is available is in the output of the +# "ROLE" command of a master. +# +# The listed IP and address normally reported by a replica is obtained +# in the following way: +# +# IP: The address is auto detected by checking the peer address +# of the socket used by the replica to connect with the master. +# +# Port: The port is communicated by the replica during the replication +# handshake, and is normally the port that the replica is using to +# listen for connections. +# +# However when port forwarding or Network Address Translation (NAT) is +# used, the replica may be actually reachable via different IP and port +# pairs. The following two options can be used by a replica in order to +# report to its master a specific set of IP and port, so that both INFO +# and ROLE will report those values. +# +# There is no need to use both the options if you need to override just +# the port or the IP address. +# +# replica-announce-ip 5.5.5.5 +# replica-announce-port 1234 + +################################## SECURITY ################################### + +# Require clients to issue AUTH before processing any other +# commands. This might be useful in environments in which you do not trust +# others with access to the host running redis-server. +# +# This should stay commented out for backward compatibility and because most +# people do not need auth (e.g. they run their own servers). +# +# Warning: since Redis is pretty fast an outside user can try up to +# 150k passwords per second against a good box. This means that you should +# use a very strong password otherwise it will be very easy to break. +# +# requirepass foobared + +# Command renaming. +# +# It is possible to change the name of dangerous commands in a shared +# environment. For instance the CONFIG command may be renamed into something +# hard to guess so that it will still be available for internal-use tools +# but not available for general clients. +# +# Example: +# +# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52 +# +# It is also possible to completely kill a command by renaming it into +# an empty string: +# +# rename-command CONFIG "" +# +# Please note that changing the name of commands that are logged into the +# AOF file or transmitted to replicas may cause problems. + +################################### CLIENTS #################################### + +# Set the max number of connected clients at the same time. By default +# this limit is set to 10000 clients, however if the Redis server is not +# able to configure the process file limit to allow for the specified limit +# the max number of allowed clients is set to the current file limit +# minus 32 (as Redis reserves a few file descriptors for internal uses). +# +# Once the limit is reached Redis will close all the new connections sending +# an error 'max number of clients reached'. +# +# maxclients 10000 + +############################## MEMORY MANAGEMENT ################################ + +# Set a memory usage limit to the specified amount of bytes. +# When the memory limit is reached Redis will try to remove keys +# according to the eviction policy selected (see maxmemory-policy). +# +# If Redis can't remove keys according to the policy, or if the policy is +# set to 'noeviction', Redis will start to reply with errors to commands +# that would use more memory, like SET, LPUSH, and so on, and will continue +# to reply to read-only commands like GET. +# +# This option is usually useful when using Redis as an LRU or LFU cache, or to +# set a hard memory limit for an instance (using the 'noeviction' policy). +# +# WARNING: If you have replicas attached to an instance with maxmemory on, +# the size of the output buffers needed to feed the replicas are subtracted +# from the used memory count, so that network problems / resyncs will +# not trigger a loop where keys are evicted, and in turn the output +# buffer of replicas is full with DELs of keys evicted triggering the deletion +# of more keys, and so forth until the database is completely emptied. +# +# In short... if you have replicas attached it is suggested that you set a lower +# limit for maxmemory so that there is some free RAM on the system for replica +# output buffers (but this is not needed if the policy is 'noeviction'). +# +# maxmemory + +# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory +# is reached. You can select among five behaviors: +# +# volatile-lru -> Evict using approximated LRU among the keys with an expire set. +# allkeys-lru -> Evict any key using approximated LRU. +# volatile-lfu -> Evict using approximated LFU among the keys with an expire set. +# allkeys-lfu -> Evict any key using approximated LFU. +# volatile-random -> Remove a random key among the ones with an expire set. +# allkeys-random -> Remove a random key, any key. +# volatile-ttl -> Remove the key with the nearest expire time (minor TTL) +# noeviction -> Don't evict anything, just return an error on write operations. +# +# LRU means Least Recently Used +# LFU means Least Frequently Used +# +# Both LRU, LFU and volatile-ttl are implemented using approximated +# randomized algorithms. +# +# Note: with any of the above policies, Redis will return an error on write +# operations, when there are no suitable keys for eviction. +# +# At the date of writing these commands are: set setnx setex append +# incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd +# sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby +# zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby +# getset mset msetnx exec sort +# +# The default is: +# +# maxmemory-policy noeviction + +# LRU, LFU and minimal TTL algorithms are not precise algorithms but approximated +# algorithms (in order to save memory), so you can tune it for speed or +# accuracy. For default Redis will check five keys and pick the one that was +# used less recently, you can change the sample size using the following +# configuration directive. +# +# The default of 5 produces good enough results. 10 Approximates very closely +# true LRU but costs more CPU. 3 is faster but not very accurate. +# +# maxmemory-samples 5 + +# Starting from Redis 5, by default a replica will ignore its maxmemory setting +# (unless it is promoted to master after a failover or manually). It means +# that the eviction of keys will be just handled by the master, sending the +# DEL commands to the replica as keys evict in the master side. +# +# This behavior ensures that masters and replicas stay consistent, and is usually +# what you want, however if your replica is writable, or you want the replica to have +# a different memory setting, and you are sure all the writes performed to the +# replica are idempotent, then you may change this default (but be sure to understand +# what you are doing). +# +# Note that since the replica by default does not evict, it may end using more +# memory than the one set via maxmemory (there are certain buffers that may +# be larger on the replica, or data structures may sometimes take more memory and so +# forth). So make sure you monitor your replicas and make sure they have enough +# memory to never hit a real out-of-memory condition before the master hits +# the configured maxmemory setting. +# +# replica-ignore-maxmemory yes + +############################# LAZY FREEING #################################### + +# Redis has two primitives to delete keys. One is called DEL and is a blocking +# deletion of the object. It means that the server stops processing new commands +# in order to reclaim all the memory associated with an object in a synchronous +# way. If the key deleted is associated with a small object, the time needed +# in order to execute the DEL command is very small and comparable to most other +# O(1) or O(log_N) commands in Redis. However if the key is associated with an +# aggregated value containing millions of elements, the server can block for +# a long time (even seconds) in order to complete the operation. +# +# For the above reasons Redis also offers non blocking deletion primitives +# such as UNLINK (non blocking DEL) and the ASYNC option of FLUSHALL and +# FLUSHDB commands, in order to reclaim memory in background. Those commands +# are executed in constant time. Another thread will incrementally free the +# object in the background as fast as possible. +# +# DEL, UNLINK and ASYNC option of FLUSHALL and FLUSHDB are user-controlled. +# It's up to the design of the application to understand when it is a good +# idea to use one or the other. However the Redis server sometimes has to +# delete keys or flush the whole database as a side effect of other operations. +# Specifically Redis deletes objects independently of a user call in the +# following scenarios: +# +# 1) On eviction, because of the maxmemory and maxmemory policy configurations, +# in order to make room for new data, without going over the specified +# memory limit. +# 2) Because of expire: when a key with an associated time to live (see the +# EXPIRE command) must be deleted from memory. +# 3) Because of a side effect of a command that stores data on a key that may +# already exist. For example the RENAME command may delete the old key +# content when it is replaced with another one. Similarly SUNIONSTORE +# or SORT with STORE option may delete existing keys. The SET command +# itself removes any old content of the specified key in order to replace +# it with the specified string. +# 4) During replication, when a replica performs a full resynchronization with +# its master, the content of the whole database is removed in order to +# load the RDB file just transferred. +# +# In all the above cases the default is to delete objects in a blocking way, +# like if DEL was called. However you can configure each case specifically +# in order to instead release memory in a non-blocking way like if UNLINK +# was called, using the following configuration directives: + +lazyfree-lazy-eviction no +lazyfree-lazy-expire no +lazyfree-lazy-server-del no +replica-lazy-flush no + +############################## APPEND ONLY MODE ############################### + +# By default Redis asynchronously dumps the dataset on disk. This mode is +# good enough in many applications, but an issue with the Redis process or +# a power outage may result into a few minutes of writes lost (depending on +# the configured save points). +# +# The Append Only File is an alternative persistence mode that provides +# much better durability. For instance using the default data fsync policy +# (see later in the config file) Redis can lose just one second of writes in a +# dramatic event like a server power outage, or a single write if something +# wrong with the Redis process itself happens, but the operating system is +# still running correctly. +# +# AOF and RDB persistence can be enabled at the same time without problems. +# If the AOF is enabled on startup Redis will load the AOF, that is the file +# with the better durability guarantees. +# +# Please check http://redis.io/topics/persistence for more information. + +appendonly no + +# The name of the append only file (default: "appendonly.aof") + +appendfilename "appendonly.aof" + +# The fsync() call tells the Operating System to actually write data on disk +# instead of waiting for more data in the output buffer. Some OS will really flush +# data on disk, some other OS will just try to do it ASAP. +# +# Redis supports three different modes: +# +# no: don't fsync, just let the OS flush the data when it wants. Faster. +# always: fsync after every write to the append only log. Slow, Safest. +# everysec: fsync only one time every second. Compromise. +# +# The default is "everysec", as that's usually the right compromise between +# speed and data safety. It's up to you to understand if you can relax this to +# "no" that will let the operating system flush the output buffer when +# it wants, for better performances (but if you can live with the idea of +# some data loss consider the default persistence mode that's snapshotting), +# or on the contrary, use "always" that's very slow but a bit safer than +# everysec. +# +# More details please check the following article: +# http://antirez.com/post/redis-persistence-demystified.html +# +# If unsure, use "everysec". + +# appendfsync always +appendfsync everysec +# appendfsync no + +# When the AOF fsync policy is set to always or everysec, and a background +# saving process (a background save or AOF log background rewriting) is +# performing a lot of I/O against the disk, in some Linux configurations +# Redis may block too long on the fsync() call. Note that there is no fix for +# this currently, as even performing fsync in a different thread will block +# our synchronous write(2) call. +# +# In order to mitigate this problem it's possible to use the following option +# that will prevent fsync() from being called in the main process while a +# BGSAVE or BGREWRITEAOF is in progress. +# +# This means that while another child is saving, the durability of Redis is +# the same as "appendfsync none". In practical terms, this means that it is +# possible to lose up to 30 seconds of log in the worst scenario (with the +# default Linux settings). +# +# If you have latency problems turn this to "yes". Otherwise leave it as +# "no" that is the safest pick from the point of view of durability. + +no-appendfsync-on-rewrite no + +# Automatic rewrite of the append only file. +# Redis is able to automatically rewrite the log file implicitly calling +# BGREWRITEAOF when the AOF log size grows by the specified percentage. +# +# This is how it works: Redis remembers the size of the AOF file after the +# latest rewrite (if no rewrite has happened since the restart, the size of +# the AOF at startup is used). +# +# This base size is compared to the current size. If the current size is +# bigger than the specified percentage, the rewrite is triggered. Also +# you need to specify a minimal size for the AOF file to be rewritten, this +# is useful to avoid rewriting the AOF file even if the percentage increase +# is reached but it is still pretty small. +# +# Specify a percentage of zero in order to disable the automatic AOF +# rewrite feature. + +auto-aof-rewrite-percentage 100 +auto-aof-rewrite-min-size 64mb + +# An AOF file may be found to be truncated at the end during the Redis +# startup process, when the AOF data gets loaded back into memory. +# This may happen when the system where Redis is running +# crashes, especially when an ext4 filesystem is mounted without the +# data=ordered option (however this can't happen when Redis itself +# crashes or aborts but the operating system still works correctly). +# +# Redis can either exit with an error when this happens, or load as much +# data as possible (the default now) and start if the AOF file is found +# to be truncated at the end. The following option controls this behavior. +# +# If aof-load-truncated is set to yes, a truncated AOF file is loaded and +# the Redis server starts emitting a log to inform the user of the event. +# Otherwise if the option is set to no, the server aborts with an error +# and refuses to start. When the option is set to no, the user requires +# to fix the AOF file using the "redis-check-aof" utility before to restart +# the server. +# +# Note that if the AOF file will be found to be corrupted in the middle +# the server will still exit with an error. This option only applies when +# Redis will try to read more data from the AOF file but not enough bytes +# will be found. +aof-load-truncated yes + +# When rewriting the AOF file, Redis is able to use an RDB preamble in the +# AOF file for faster rewrites and recoveries. When this option is turned +# on the rewritten AOF file is composed of two different stanzas: +# +# [RDB file][AOF tail] +# +# When loading Redis recognizes that the AOF file starts with the "REDIS" +# string and loads the prefixed RDB file, and continues loading the AOF +# tail. +aof-use-rdb-preamble yes + +################################ LUA SCRIPTING ############################### + +# Max execution time of a Lua script in milliseconds. +# +# If the maximum execution time is reached Redis will log that a script is +# still in execution after the maximum allowed time and will start to +# reply to queries with an error. +# +# When a long running script exceeds the maximum execution time only the +# SCRIPT KILL and SHUTDOWN NOSAVE commands are available. The first can be +# used to stop a script that did not yet called write commands. The second +# is the only way to shut down the server in the case a write command was +# already issued by the script but the user doesn't want to wait for the natural +# termination of the script. +# +# Set it to 0 or a negative value for unlimited execution without warnings. +lua-time-limit 5000 + +################################ REDIS CLUSTER ############################### +# +# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# WARNING EXPERIMENTAL: Redis Cluster is considered to be stable code, however +# in order to mark it as "mature" we need to wait for a non trivial percentage +# of users to deploy it in production. +# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# Normal Redis instances can't be part of a Redis Cluster; only nodes that are +# started as cluster nodes can. In order to start a Redis instance as a +# cluster node enable the cluster support uncommenting the following: +# +# cluster-enabled yes + +# Every cluster node has a cluster configuration file. This file is not +# intended to be edited by hand. It is created and updated by Redis nodes. +# Every Redis Cluster node requires a different cluster configuration file. +# Make sure that instances running in the same system do not have +# overlapping cluster configuration file names. +# +# cluster-config-file nodes-6379.conf + +# Cluster node timeout is the amount of milliseconds a node must be unreachable +# for it to be considered in failure state. +# Most other internal time limits are multiple of the node timeout. +# +# cluster-node-timeout 15000 + +# A replica of a failing master will avoid to start a failover if its data +# looks too old. +# +# There is no simple way for a replica to actually have an exact measure of +# its "data age", so the following two checks are performed: +# +# 1) If there are multiple replicas able to failover, they exchange messages +# in order to try to give an advantage to the replica with the best +# replication offset (more data from the master processed). +# Replicas will try to get their rank by offset, and apply to the start +# of the failover a delay proportional to their rank. +# +# 2) Every single replica computes the time of the last interaction with +# its master. This can be the last ping or command received (if the master +# is still in the "connected" state), or the time that elapsed since the +# disconnection with the master (if the replication link is currently down). +# If the last interaction is too old, the replica will not try to failover +# at all. +# +# The point "2" can be tuned by user. Specifically a replica will not perform +# the failover if, since the last interaction with the master, the time +# elapsed is greater than: +# +# (node-timeout * replica-validity-factor) + repl-ping-replica-period +# +# So for example if node-timeout is 30 seconds, and the replica-validity-factor +# is 10, and assuming a default repl-ping-replica-period of 10 seconds, the +# replica will not try to failover if it was not able to talk with the master +# for longer than 310 seconds. +# +# A large replica-validity-factor may allow replicas with too old data to failover +# a master, while a too small value may prevent the cluster from being able to +# elect a replica at all. +# +# For maximum availability, it is possible to set the replica-validity-factor +# to a value of 0, which means, that replicas will always try to failover the +# master regardless of the last time they interacted with the master. +# (However they'll always try to apply a delay proportional to their +# offset rank). +# +# Zero is the only value able to guarantee that when all the partitions heal +# the cluster will always be able to continue. +# +# cluster-replica-validity-factor 10 + +# Cluster replicas are able to migrate to orphaned masters, that are masters +# that are left without working replicas. This improves the cluster ability +# to resist to failures as otherwise an orphaned master can't be failed over +# in case of failure if it has no working replicas. +# +# Replicas migrate to orphaned masters only if there are still at least a +# given number of other working replicas for their old master. This number +# is the "migration barrier". A migration barrier of 1 means that a replica +# will migrate only if there is at least 1 other working replica for its master +# and so forth. It usually reflects the number of replicas you want for every +# master in your cluster. +# +# Default is 1 (replicas migrate only if their masters remain with at least +# one replica). To disable migration just set it to a very large value. +# A value of 0 can be set but is useful only for debugging and dangerous +# in production. +# +# cluster-migration-barrier 1 + +# By default Redis Cluster nodes stop accepting queries if they detect there +# is at least an hash slot uncovered (no available node is serving it). +# This way if the cluster is partially down (for example a range of hash slots +# are no longer covered) all the cluster becomes, eventually, unavailable. +# It automatically returns available as soon as all the slots are covered again. +# +# However sometimes you want the subset of the cluster which is working, +# to continue to accept queries for the part of the key space that is still +# covered. In order to do so, just set the cluster-require-full-coverage +# option to no. +# +# cluster-require-full-coverage yes + +# This option, when set to yes, prevents replicas from trying to failover its +# master during master failures. However the master can still perform a +# manual failover, if forced to do so. +# +# This is useful in different scenarios, especially in the case of multiple +# data center operations, where we want one side to never be promoted if not +# in the case of a total DC failure. +# +# cluster-replica-no-failover no + +# In order to setup your cluster make sure to read the documentation +# available at http://redis.io web site. + +########################## CLUSTER DOCKER/NAT support ######################## + +# In certain deployments, Redis Cluster nodes address discovery fails, because +# addresses are NAT-ted or because ports are forwarded (the typical case is +# Docker and other containers). +# +# In order to make Redis Cluster working in such environments, a static +# configuration where each node knows its public address is needed. The +# following two options are used for this scope, and are: +# +# * cluster-announce-ip +# * cluster-announce-port +# * cluster-announce-bus-port +# +# Each instruct the node about its address, client port, and cluster message +# bus port. The information is then published in the header of the bus packets +# so that other nodes will be able to correctly map the address of the node +# publishing the information. +# +# If the above options are not used, the normal Redis Cluster auto-detection +# will be used instead. +# +# Note that when remapped, the bus port may not be at the fixed offset of +# clients port + 10000, so you can specify any port and bus-port depending +# on how they get remapped. If the bus-port is not set, a fixed offset of +# 10000 will be used as usually. +# +# Example: +# +# cluster-announce-ip 10.1.1.5 +# cluster-announce-port 6379 +# cluster-announce-bus-port 6380 + +################################## SLOW LOG ################################### + +# The Redis Slow Log is a system to log queries that exceeded a specified +# execution time. The execution time does not include the I/O operations +# like talking with the client, sending the reply and so forth, +# but just the time needed to actually execute the command (this is the only +# stage of command execution where the thread is blocked and can not serve +# other requests in the meantime). +# +# You can configure the slow log with two parameters: one tells Redis +# what is the execution time, in microseconds, to exceed in order for the +# command to get logged, and the other parameter is the length of the +# slow log. When a new command is logged the oldest one is removed from the +# queue of logged commands. + +# The following time is expressed in microseconds, so 1000000 is equivalent +# to one second. Note that a negative number disables the slow log, while +# a value of zero forces the logging of every command. +slowlog-log-slower-than 10000 + +# There is no limit to this length. Just be aware that it will consume memory. +# You can reclaim memory used by the slow log with SLOWLOG RESET. +slowlog-max-len 128 + +################################ LATENCY MONITOR ############################## + +# The Redis latency monitoring subsystem samples different operations +# at runtime in order to collect data related to possible sources of +# latency of a Redis instance. +# +# Via the LATENCY command this information is available to the user that can +# print graphs and obtain reports. +# +# The system only logs operations that were performed in a time equal or +# greater than the amount of milliseconds specified via the +# latency-monitor-threshold configuration directive. When its value is set +# to zero, the latency monitor is turned off. +# +# By default latency monitoring is disabled since it is mostly not needed +# if you don't have latency issues, and collecting data has a performance +# impact, that while very small, can be measured under big load. Latency +# monitoring can easily be enabled at runtime using the command +# "CONFIG SET latency-monitor-threshold " if needed. +latency-monitor-threshold 0 + +############################# EVENT NOTIFICATION ############################## + +# Redis can notify Pub/Sub clients about events happening in the key space. +# This feature is documented at http://redis.io/topics/notifications +# +# For instance if keyspace events notification is enabled, and a client +# performs a DEL operation on key "foo" stored in the Database 0, two +# messages will be published via Pub/Sub: +# +# PUBLISH __keyspace@0__:foo del +# PUBLISH __keyevent@0__:del foo +# +# It is possible to select the events that Redis will notify among a set +# of classes. Every class is identified by a single character: +# +# K Keyspace events, published with __keyspace@__ prefix. +# E Keyevent events, published with __keyevent@__ prefix. +# g Generic commands (non-type specific) like DEL, EXPIRE, RENAME, ... +# $ String commands +# l List commands +# s Set commands +# h Hash commands +# z Sorted set commands +# x Expired events (events generated every time a key expires) +# e Evicted events (events generated when a key is evicted for maxmemory) +# A Alias for g$lshzxe, so that the "AKE" string means all the events. +# +# The "notify-keyspace-events" takes as argument a string that is composed +# of zero or multiple characters. The empty string means that notifications +# are disabled. +# +# Example: to enable list and generic events, from the point of view of the +# event name, use: +# +# notify-keyspace-events Elg +# +# Example 2: to get the stream of the expired keys subscribing to channel +# name __keyevent@0__:expired use: +# +# notify-keyspace-events Ex +# +# By default all notifications are disabled because most users don't need +# this feature and the feature has some overhead. Note that if you don't +# specify at least one of K or E, no events will be delivered. +notify-keyspace-events "" + +############################### ADVANCED CONFIG ############################### + +# Hashes are encoded using a memory efficient data structure when they have a +# small number of entries, and the biggest entry does not exceed a given +# threshold. These thresholds can be configured using the following directives. +hash-max-ziplist-entries 512 +hash-max-ziplist-value 64 + +# Lists are also encoded in a special way to save a lot of space. +# The number of entries allowed per internal list node can be specified +# as a fixed maximum size or a maximum number of elements. +# For a fixed maximum size, use -5 through -1, meaning: +# -5: max size: 64 Kb <-- not recommended for normal workloads +# -4: max size: 32 Kb <-- not recommended +# -3: max size: 16 Kb <-- probably not recommended +# -2: max size: 8 Kb <-- good +# -1: max size: 4 Kb <-- good +# Positive numbers mean store up to _exactly_ that number of elements +# per list node. +# The highest performing option is usually -2 (8 Kb size) or -1 (4 Kb size), +# but if your use case is unique, adjust the settings as necessary. +list-max-ziplist-size -2 + +# Lists may also be compressed. +# Compress depth is the number of quicklist ziplist nodes from *each* side of +# the list to *exclude* from compression. The head and tail of the list +# are always uncompressed for fast push/pop operations. Settings are: +# 0: disable all list compression +# 1: depth 1 means "don't start compressing until after 1 node into the list, +# going from either the head or tail" +# So: [head]->node->node->...->node->[tail] +# [head], [tail] will always be uncompressed; inner nodes will compress. +# 2: [head]->[next]->node->node->...->node->[prev]->[tail] +# 2 here means: don't compress head or head->next or tail->prev or tail, +# but compress all nodes between them. +# 3: [head]->[next]->[next]->node->node->...->node->[prev]->[prev]->[tail] +# etc. +list-compress-depth 0 + +# Sets have a special encoding in just one case: when a set is composed +# of just strings that happen to be integers in radix 10 in the range +# of 64 bit signed integers. +# The following configuration setting sets the limit in the size of the +# set in order to use this special memory saving encoding. +set-max-intset-entries 512 + +# Similarly to hashes and lists, sorted sets are also specially encoded in +# order to save a lot of space. This encoding is only used when the length and +# elements of a sorted set are below the following limits: +zset-max-ziplist-entries 128 +zset-max-ziplist-value 64 + +# HyperLogLog sparse representation bytes limit. The limit includes the +# 16 bytes header. When an HyperLogLog using the sparse representation crosses +# this limit, it is converted into the dense representation. +# +# A value greater than 16000 is totally useless, since at that point the +# dense representation is more memory efficient. +# +# The suggested value is ~ 3000 in order to have the benefits of +# the space efficient encoding without slowing down too much PFADD, +# which is O(N) with the sparse encoding. The value can be raised to +# ~ 10000 when CPU is not a concern, but space is, and the data set is +# composed of many HyperLogLogs with cardinality in the 0 - 15000 range. +hll-sparse-max-bytes 3000 + +# Streams macro node max size / items. The stream data structure is a radix +# tree of big nodes that encode multiple items inside. Using this configuration +# it is possible to configure how big a single node can be in bytes, and the +# maximum number of items it may contain before switching to a new node when +# appending new stream entries. If any of the following settings are set to +# zero, the limit is ignored, so for instance it is possible to set just a +# max entires limit by setting max-bytes to 0 and max-entries to the desired +# value. +stream-node-max-bytes 4096 +stream-node-max-entries 100 + +# Active rehashing uses 1 millisecond every 100 milliseconds of CPU time in +# order to help rehashing the main Redis hash table (the one mapping top-level +# keys to values). The hash table implementation Redis uses (see dict.c) +# performs a lazy rehashing: the more operation you run into a hash table +# that is rehashing, the more rehashing "steps" are performed, so if the +# server is idle the rehashing is never complete and some more memory is used +# by the hash table. +# +# The default is to use this millisecond 10 times every second in order to +# actively rehash the main dictionaries, freeing memory when possible. +# +# If unsure: +# use "activerehashing no" if you have hard latency requirements and it is +# not a good thing in your environment that Redis can reply from time to time +# to queries with 2 milliseconds delay. +# +# use "activerehashing yes" if you don't have such hard requirements but +# want to free memory asap when possible. +activerehashing yes + +# The client output buffer limits can be used to force disconnection of clients +# that are not reading data from the server fast enough for some reason (a +# common reason is that a Pub/Sub client can't consume messages as fast as the +# publisher can produce them). +# +# The limit can be set differently for the three different classes of clients: +# +# normal -> normal clients including MONITOR clients +# replica -> replica clients +# pubsub -> clients subscribed to at least one pubsub channel or pattern +# +# The syntax of every client-output-buffer-limit directive is the following: +# +# client-output-buffer-limit +# +# A client is immediately disconnected once the hard limit is reached, or if +# the soft limit is reached and remains reached for the specified number of +# seconds (continuously). +# So for instance if the hard limit is 32 megabytes and the soft limit is +# 16 megabytes / 10 seconds, the client will get disconnected immediately +# if the size of the output buffers reach 32 megabytes, but will also get +# disconnected if the client reaches 16 megabytes and continuously overcomes +# the limit for 10 seconds. +# +# By default normal clients are not limited because they don't receive data +# without asking (in a push way), but just after a request, so only +# asynchronous clients may create a scenario where data is requested faster +# than it can read. +# +# Instead there is a default limit for pubsub and replica clients, since +# subscribers and replicas receive data in a push fashion. +# +# Both the hard or the soft limit can be disabled by setting them to zero. +client-output-buffer-limit normal 0 0 0 +client-output-buffer-limit replica 256mb 64mb 60 +client-output-buffer-limit pubsub 32mb 8mb 60 + +# Client query buffers accumulate new commands. They are limited to a fixed +# amount by default in order to avoid that a protocol desynchronization (for +# instance due to a bug in the client) will lead to unbound memory usage in +# the query buffer. However you can configure it here if you have very special +# needs, such us huge multi/exec requests or alike. +# +# client-query-buffer-limit 1gb + +# In the Redis protocol, bulk requests, that are, elements representing single +# strings, are normally limited ot 512 mb. However you can change this limit +# here. +# +# proto-max-bulk-len 512mb + +# Redis calls an internal function to perform many background tasks, like +# closing connections of clients in timeout, purging expired keys that are +# never requested, and so forth. +# +# Not all tasks are performed with the same frequency, but Redis checks for +# tasks to perform according to the specified "hz" value. +# +# By default "hz" is set to 10. Raising the value will use more CPU when +# Redis is idle, but at the same time will make Redis more responsive when +# there are many keys expiring at the same time, and timeouts may be +# handled with more precision. +# +# The range is between 1 and 500, however a value over 100 is usually not +# a good idea. Most users should use the default of 10 and raise this up to +# 100 only in environments where very low latency is required. +hz 10 + +# Normally it is useful to have an HZ value which is proportional to the +# number of clients connected. This is useful in order, for instance, to +# avoid too many clients are processed for each background task invocation +# in order to avoid latency spikes. +# +# Since the default HZ value by default is conservatively set to 10, Redis +# offers, and enables by default, the ability to use an adaptive HZ value +# which will temporary raise when there are many connected clients. +# +# When dynamic HZ is enabled, the actual configured HZ will be used as +# as a baseline, but multiples of the configured HZ value will be actually +# used as needed once more clients are connected. In this way an idle +# instance will use very little CPU time while a busy instance will be +# more responsive. +dynamic-hz yes + +# When a child rewrites the AOF file, if the following option is enabled +# the file will be fsync-ed every 32 MB of data generated. This is useful +# in order to commit the file to the disk more incrementally and avoid +# big latency spikes. +aof-rewrite-incremental-fsync yes + +# When redis saves RDB file, if the following option is enabled +# the file will be fsync-ed every 32 MB of data generated. This is useful +# in order to commit the file to the disk more incrementally and avoid +# big latency spikes. +rdb-save-incremental-fsync yes + +# Redis LFU eviction (see maxmemory setting) can be tuned. However it is a good +# idea to start with the default settings and only change them after investigating +# how to improve the performances and how the keys LFU change over time, which +# is possible to inspect via the OBJECT FREQ command. +# +# There are two tunable parameters in the Redis LFU implementation: the +# counter logarithm factor and the counter decay time. It is important to +# understand what the two parameters mean before changing them. +# +# The LFU counter is just 8 bits per key, it's maximum value is 255, so Redis +# uses a probabilistic increment with logarithmic behavior. Given the value +# of the old counter, when a key is accessed, the counter is incremented in +# this way: +# +# 1. A random number R between 0 and 1 is extracted. +# 2. A probability P is calculated as 1/(old_value*lfu_log_factor+1). +# 3. The counter is incremented only if R < P. +# +# The default lfu-log-factor is 10. This is a table of how the frequency +# counter changes with a different number of accesses with different +# logarithmic factors: +# +# +--------+------------+------------+------------+------------+------------+ +# | factor | 100 hits | 1000 hits | 100K hits | 1M hits | 10M hits | +# +--------+------------+------------+------------+------------+------------+ +# | 0 | 104 | 255 | 255 | 255 | 255 | +# +--------+------------+------------+------------+------------+------------+ +# | 1 | 18 | 49 | 255 | 255 | 255 | +# +--------+------------+------------+------------+------------+------------+ +# | 10 | 10 | 18 | 142 | 255 | 255 | +# +--------+------------+------------+------------+------------+------------+ +# | 100 | 8 | 11 | 49 | 143 | 255 | +# +--------+------------+------------+------------+------------+------------+ +# +# NOTE: The above table was obtained by running the following commands: +# +# redis-benchmark -n 1000000 incr foo +# redis-cli object freq foo +# +# NOTE 2: The counter initial value is 5 in order to give new objects a chance +# to accumulate hits. +# +# The counter decay time is the time, in minutes, that must elapse in order +# for the key counter to be divided by two (or decremented if it has a value +# less <= 10). +# +# The default value for the lfu-decay-time is 1. A Special value of 0 means to +# decay the counter every time it happens to be scanned. +# +# lfu-log-factor 10 +# lfu-decay-time 1 + +########################### ACTIVE DEFRAGMENTATION ####################### +# +# WARNING THIS FEATURE IS EXPERIMENTAL. However it was stress tested +# even in production and manually tested by multiple engineers for some +# time. +# +# What is active defragmentation? +# ------------------------------- +# +# Active (online) defragmentation allows a Redis server to compact the +# spaces left between small allocations and deallocations of data in memory, +# thus allowing to reclaim back memory. +# +# Fragmentation is a natural process that happens with every allocator (but +# less so with Jemalloc, fortunately) and certain workloads. Normally a server +# restart is needed in order to lower the fragmentation, or at least to flush +# away all the data and create it again. However thanks to this feature +# implemented by Oran Agra for Redis 4.0 this process can happen at runtime +# in an "hot" way, while the server is running. +# +# Basically when the fragmentation is over a certain level (see the +# configuration options below) Redis will start to create new copies of the +# values in contiguous memory regions by exploiting certain specific Jemalloc +# features (in order to understand if an allocation is causing fragmentation +# and to allocate it in a better place), and at the same time, will release the +# old copies of the data. This process, repeated incrementally for all the keys +# will cause the fragmentation to drop back to normal values. +# +# Important things to understand: +# +# 1. This feature is disabled by default, and only works if you compiled Redis +# to use the copy of Jemalloc we ship with the source code of Redis. +# This is the default with Linux builds. +# +# 2. You never need to enable this feature if you don't have fragmentation +# issues. +# +# 3. Once you experience fragmentation, you can enable this feature when +# needed with the command "CONFIG SET activedefrag yes". +# +# The configuration parameters are able to fine tune the behavior of the +# defragmentation process. If you are not sure about what they mean it is +# a good idea to leave the defaults untouched. + +# Enabled active defragmentation +# activedefrag yes + +# Minimum amount of fragmentation waste to start active defrag +# active-defrag-ignore-bytes 100mb + +# Minimum percentage of fragmentation to start active defrag +# active-defrag-threshold-lower 10 + +# Maximum percentage of fragmentation at which we use maximum effort +# active-defrag-threshold-upper 100 + +# Minimal effort for defrag in CPU percentage +# active-defrag-cycle-min 5 + +# Maximal effort for defrag in CPU percentage +# active-defrag-cycle-max 75 + +# Maximum number of set/hash/zset/list fields that will be processed from +# the main dictionary scan +# active-defrag-max-scan-fields 1000 diff --git a/apps/emqx_auth_redis/README.md b/apps/emqx_auth_redis/README.md new file mode 100644 index 000000000..9aa851f88 --- /dev/null +++ b/apps/emqx_auth_redis/README.md @@ -0,0 +1,171 @@ +emqx_auth_redis +=============== + +EMQ X Redis Authentication/ACL Plugin + +Features +--------- + +- Full *Authentication*, *Superuser*, *ACL* support +- IPv4, IPv6 support +- Connection pool by [ecpool](https://github.com/emqx/ecpool) +- Support `single`, `sentinel`, `cluster` deployment structures of Redis +- Completely cover Redis 5, Redis 6 in our tests + + +Build Plugin +------------ + +``` +make && make tests +``` + +Configure Plugin +---------------- + +File: etc/emqx_auth_redis.conf + +``` +## Redis server address. +## +## Value: Port | IP:Port +## +## Redis Server: 6379, 127.0.0.1:6379, localhost:6379, Redis Sentinel: 127.0.0.1:26379 +auth.redis.server = 127.0.0.1:6379 + +## redis sentinel cluster name +## auth.redis.sentinel = mymaster + +## Redis pool size. +## +## Value: Number +auth.redis.pool = 8 + +## Redis database no. +## +## Value: Number +auth.redis.database = 0 + +## Redis password. +## +## Value: String +## auth.redis.password = + +## Authentication query command. +## +## Value: Redis cmd +## +## Variables: +## - %u: username +## - %c: clientid +## - %C: common name of client TLS cert +## - %d: subject of client TLS cert +## +## Examples: +## - HGET mqtt_user:%u password +## - HMGET mqtt_user:%u password +## - HMGET mqtt_user:%u password salt +auth.redis.auth_cmd = HMGET mqtt_user:%u password + +## Password hash. +## +## Value: plain | md5 | sha | sha256 | bcrypt +auth.redis.password_hash = plain + +## sha256 with salt prefix +## auth.redis.password_hash = salt,sha256 + +## sha256 with salt suffix +## auth.redis.password_hash = sha256,salt + +## bcrypt with salt prefix +## auth.redis.password_hash = salt,bcrypt + +## pbkdf2 with macfun iterations dklen +## macfun: md4, md5, ripemd160, sha, sha224, sha256, sha384, sha512 +## auth.redis.password_hash = pbkdf2,sha256,1000,20 + +## Superuser query command. +## +## Value: Redis cmd +## +## Variables: +## - %u: username +## - %c: clientid +## - %C: common name of client TLS cert +## - %d: subject of client TLS cert +auth.redis.super_cmd = HGET mqtt_user:%u is_superuser + +## ACL query command. +## +## Value: Redis cmd +## +## Variables: +## - %u: username +## - %c: clientid +auth.redis.acl_cmd = HGETALL mqtt_acl:%u +``` + +SuperUser +--------- + +``` +HSET mqtt_user: is_superuser 1 +``` + +User Hash with Password Salt +---------------------------- + +Set a 'user' hash with 'password' 'salt' field, for example: + +``` +HMSET mqtt_user: password "password" salt "salt" +``` + +User Set with Password +----------------------- + +Set a 'user' Set with 'password' field for example: + +``` +HSET mqtt_user: password "password" +``` + +ACL Rule Hash +------------- + +The plugin uses a redis hash to store ACL rules: + +``` +HSET mqtt_acl: topic1 1 +HSET mqtt_acl: topic2 2 +HSET mqtt_acl: topic3 3 +``` + +NOTE: 1: subscribe, 2: publish, 3: pubsub + +Subscription Hash +----------------- + +NOTICE: Move to emqx_backend_redis... + +The plugin could store the static subscriptions into a redis Hash: + +``` +HSET mqtt_sub: topic1 0 +HSET mqtt_sub: topic2 1 +HSET mqtt_sub: topic3 2 +``` + +Load Plugin +----------- + +``` +./bin/emqx_ctl plugins load emqx_auth_redis +``` + +Author +------ + +EMQ X Team. + diff --git a/apps/emqx_auth_redis/include/emqx_auth_redis.hrl b/apps/emqx_auth_redis/include/emqx_auth_redis.hrl new file mode 100644 index 000000000..204d8ef70 --- /dev/null +++ b/apps/emqx_auth_redis/include/emqx_auth_redis.hrl @@ -0,0 +1,23 @@ + +-define(APP, emqx_auth_redis). + +-record(auth_metrics, { + success = 'client.auth.success', + failure = 'client.auth.failure', + ignore = 'client.auth.ignore' + }). + +-record(acl_metrics, { + allow = 'client.acl.allow', + deny = 'client.acl.deny', + ignore = 'client.acl.ignore' + }). + +-define(METRICS(Type), tl(tuple_to_list(#Type{}))). +-define(METRICS(Type, K), #Type{}#Type.K). + +-define(AUTH_METRICS, ?METRICS(auth_metrics)). +-define(AUTH_METRICS(K), ?METRICS(auth_metrics, K)). + +-define(ACL_METRICS, ?METRICS(acl_metrics)). +-define(ACL_METRICS(K), ?METRICS(acl_metrics, K)). diff --git a/apps/emqx_auth_redis/priv/emqx_auth_redis.schema b/apps/emqx_auth_redis/priv/emqx_auth_redis.schema new file mode 100644 index 000000000..eb09fa627 --- /dev/null +++ b/apps/emqx_auth_redis/priv/emqx_auth_redis.schema @@ -0,0 +1,106 @@ +%%-*- mode: erlang -*- +%% emqx_auth_redis config mapping + +{mapping, "auth.redis.type", "emqx_auth_redis.server", [ + {default, single}, + {datatype, {enum, [single, sentinel, cluster]}} +]}. + +{mapping, "auth.redis.server", "emqx_auth_redis.server", [ + {default, "127.0.0.1:6379"}, + {datatype, [string]} +]}. + +{mapping, "auth.redis.sentinel", "emqx_auth_redis.server", [ + {default, ""}, + {datatype, string}, + hidden +]}. + +{mapping, "auth.redis.pool", "emqx_auth_redis.server", [ + {default, 8}, + {datatype, integer} +]}. + +{mapping, "auth.redis.database", "emqx_auth_redis.server", [ + {default, 0}, + {datatype, integer} +]}. + +{mapping, "auth.redis.password", "emqx_auth_redis.server", [ + {default, ""}, + {datatype, string}, + hidden +]}. + +{translation, "emqx_auth_redis.server", fun(Conf) -> + Fun = fun(S) -> + case string:split(S, ":", trailing) of + [Domain] -> {Domain, 6379}; + [Domain, Port] -> {Domain, list_to_integer(Port)} + end + end, + Servers = cuttlefish:conf_get("auth.redis.server", Conf), + Type = cuttlefish:conf_get("auth.redis.type", Conf), + Server = case Type of + single -> + {Host, Port} = Fun(Servers), + [{host, Host}, {port, Port}]; + _ -> + S = string:tokens(Servers, ","), + [{servers, [Fun(S1) || S1 <- S]}] + end, + Pool = cuttlefish:conf_get("auth.redis.pool", Conf), + Passwd = cuttlefish:conf_get("auth.redis.password", Conf), + DB = cuttlefish:conf_get("auth.redis.database", Conf), + Sentinel = cuttlefish:conf_get("auth.redis.sentinel", Conf), + [{type, Type}, + {pool_size, Pool}, + {auto_reconnect, 1}, + {database, DB}, + {password, Passwd}, + {sentinel, Sentinel}] ++ Server +end}. + +{mapping, "auth.redis.query_timeout", "emqx_auth_redis.query_timeout", [ + {default, ""}, + {datatype, string} +]}. + +{translation, "emqx_auth_redis.query_timeout", fun(Conf) -> + case cuttlefish:conf_get("auth.redis.query_timeout", Conf) of + "" -> infinity; + Duration -> + case cuttlefish_duration:parse(Duration, ms) of + {error, Reason} -> error(Reason); + Ms when is_integer(Ms) -> Ms + end + end +end}. + +{mapping, "auth.redis.auth_cmd", "emqx_auth_redis.auth_cmd", [ + {datatype, string} +]}. + +{mapping, "auth.redis.password_hash", "emqx_auth_redis.password_hash", [ + {datatype, string} +]}. + +{mapping, "auth.redis.super_cmd", "emqx_auth_redis.super_cmd", [ + {datatype, string} +]}. + +{mapping, "auth.redis.acl_cmd", "emqx_auth_redis.acl_cmd", [ + {datatype, string} +]}. + +{translation, "emqx_auth_redis.password_hash", fun(Conf) -> + HashValue = cuttlefish:conf_get("auth.redis.password_hash", Conf), + case string:tokens(HashValue, ",") of + [Hash] -> list_to_atom(Hash); + [Prefix, Suffix] -> {list_to_atom(Prefix), list_to_atom(Suffix)}; + [Hash, MacFun, Iterations, Dklen] -> {list_to_atom(Hash), list_to_atom(MacFun), list_to_integer(Iterations), list_to_integer(Dklen)}; + _ -> plain + end +end}. + diff --git a/apps/emqx_auth_redis/rebar.config b/apps/emqx_auth_redis/rebar.config new file mode 100644 index 000000000..dfdf44cc2 --- /dev/null +++ b/apps/emqx_auth_redis/rebar.config @@ -0,0 +1,3 @@ +{deps, + [{eredis_cluster, {git, "https://github.com/emqx/eredis_cluster", {tag, "v0.6.1"}}} + ]}. \ No newline at end of file diff --git a/apps/emqx_auth_redis/src/emqx_acl_redis.erl b/apps/emqx_auth_redis/src/emqx_acl_redis.erl new file mode 100644 index 000000000..efaccb461 --- /dev/null +++ b/apps/emqx_auth_redis/src/emqx_acl_redis.erl @@ -0,0 +1,86 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_acl_redis). + +-include("emqx_auth_redis.hrl"). + +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). + +-export([ register_metrics/0 + , check_acl/5 + , description/0 + ]). + +-spec(register_metrics() -> ok). +register_metrics() -> + lists:foreach(fun emqx_metrics:ensure/1, ?ACL_METRICS). + +check_acl(ClientInfo, PubSub, Topic, AclResult, Config) -> + case do_check_acl(ClientInfo, PubSub, Topic, AclResult, Config) of + ok -> emqx_metrics:inc(?ACL_METRICS(ignore)), ok; + {stop, allow} -> emqx_metrics:inc(?ACL_METRICS(allow)), {stop, allow}; + {stop, deny} -> emqx_metrics:inc(?ACL_METRICS(deny)), {stop, deny} + end. + +do_check_acl(#{username := <<$$, _/binary>>}, _PubSub, _Topic, _AclResult, _Config) -> + ok; +do_check_acl(ClientInfo, PubSub, Topic, _AclResult, + #{acl_cmd := AclCmd, timeout := Timeout, type := Type, pool := Pool}) -> + case emqx_auth_redis_cli:q(Pool, Type, AclCmd, ClientInfo, Timeout) of + {ok, []} -> ok; + {ok, Rules} -> + case match(ClientInfo, PubSub, Topic, Rules) of + allow -> {stop, allow}; + nomatch -> {stop, deny} + end; + {error, Reason} -> + ?LOG(error, "[Redis] do_check_acl error: ~p", [Reason]), + ok + end. + +match(_ClientInfo, _PubSub, _Topic, []) -> + nomatch; +match(ClientInfo, PubSub, Topic, [Filter, Access | Rules]) -> + case {match_topic(Topic, feed_var(ClientInfo, Filter)), + match_access(PubSub, b2i(Access))} of + {true, true} -> allow; + {_, _} -> match(ClientInfo, PubSub, Topic, Rules) + end. + +match_topic(Topic, Filter) -> + emqx_topic:match(Topic, Filter). + +match_access(subscribe, Access) -> + (1 band Access) > 0; +match_access(publish, Access) -> + (2 band Access) > 0. + +feed_var(#{clientid := ClientId, username := Username}, Str) -> + lists:foldl(fun({Var, Val}, Acc) -> + feed_var(Acc, Var, Val) + end, Str, [{"%u", Username}, {"%c", ClientId}]). + +feed_var(Str, _Var, undefined) -> + Str; +feed_var(Str, Var, Val) -> + re:replace(Str, Var, Val, [global, {return, binary}]). + +b2i(Bin) -> list_to_integer(binary_to_list(Bin)). + +description() -> "Redis ACL Module". + diff --git a/apps/emqx_auth_redis/src/emqx_auth_redis.app.src b/apps/emqx_auth_redis/src/emqx_auth_redis.app.src new file mode 100644 index 000000000..24cac879b --- /dev/null +++ b/apps/emqx_auth_redis/src/emqx_auth_redis.app.src @@ -0,0 +1,14 @@ +{application, emqx_auth_redis, + [{description, "EMQ X Authentication/ACL with Redis"}, + {vsn, "5.0.0"}, % strict semver, bump manually! + {modules, []}, + {registered, [emqx_auth_redis_sup]}, + {applications, [kernel,stdlib,eredis,eredis_cluster,ecpool,emqx_passwd,emqx_libs]}, + {mod, {emqx_auth_redis_app, []}}, + {env, []}, + {licenses, ["Apache-2.0"]}, + {maintainers, ["EMQ X Team "]}, + {links, [{"Homepage", "https://emqx.io/"}, + {"Github", "https://github.com/emqx/emqx-auth-redis"} + ]} + ]}. diff --git a/apps/emqx_auth_redis/src/emqx_auth_redis.erl b/apps/emqx_auth_redis/src/emqx_auth_redis.erl new file mode 100644 index 000000000..1b4b6046f --- /dev/null +++ b/apps/emqx_auth_redis/src/emqx_auth_redis.erl @@ -0,0 +1,85 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_redis). + +-include("emqx_auth_redis.hrl"). + +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). + +-export([ register_metrics/0 + , check/3 + , description/0 + ]). + +-spec(register_metrics() -> ok). +register_metrics() -> + lists:foreach(fun emqx_metrics:ensure/1, ?AUTH_METRICS). + +check(ClientInfo = #{password := Password}, AuthResult, + #{auth_cmd := AuthCmd, + super_cmd := SuperCmd, + hash_type := HashType, + timeout := Timeout, + type := Type, + pool := Pool}) -> + CheckPass = case emqx_auth_redis_cli:q(Pool, Type, AuthCmd, ClientInfo, Timeout) of + {ok, PassHash} when is_binary(PassHash) -> + check_pass({PassHash, Password}, HashType); + {ok, [undefined|_]} -> + {error, not_found}; + {ok, [PassHash]} -> + check_pass({PassHash, Password}, HashType); + {ok, [PassHash, Salt|_]} -> + check_pass({PassHash, Salt, Password}, HashType); + {error, Reason} -> + ?LOG(error, "[Redis] Command: ~p failed: ~p", [AuthCmd, Reason]), + {error, not_found} + end, + case CheckPass of + ok -> + ok = emqx_metrics:inc(?AUTH_METRICS(success)), + IsSuperuser = is_superuser(Pool, Type, SuperCmd, ClientInfo, Timeout), + {stop, AuthResult#{is_superuser => IsSuperuser, + anonymous => false, + auth_result => success}}; + {error, not_found} -> + ok = emqx_metrics:inc(?AUTH_METRICS(ignore)); + {error, ResultCode} -> + ok = emqx_metrics:inc(?AUTH_METRICS(failure)), + ?LOG(error, "[Redis] Auth from redis failed: ~p", [ResultCode]), + {stop, AuthResult#{auth_result => ResultCode, anonymous => false}} + end. + +description() -> "Authentication with Redis". + +-spec(is_superuser(atom(), atom(), undefined|list(), emqx_types:client(), timeout()) -> boolean()). +is_superuser(_Pool, _Type, undefined, _ClientInfo, _Timeout) -> false; +is_superuser(Pool, Type, SuperCmd, ClientInfo, Timeout) -> + case emqx_auth_redis_cli:q(Pool, Type, SuperCmd, ClientInfo, Timeout) of + {ok, undefined} -> false; + {ok, <<"1">>} -> true; + {ok, _Other} -> false; + {error, _Error} -> false + end. + +check_pass(Password, HashType) -> + case emqx_passwd:check_pass(Password, HashType) of + ok -> ok; + {error, _Reason} -> {error, not_authorized} + end. + diff --git a/apps/emqx_auth_redis/src/emqx_auth_redis_app.erl b/apps/emqx_auth_redis/src/emqx_auth_redis_app.erl new file mode 100644 index 000000000..345f9f87d --- /dev/null +++ b/apps/emqx_auth_redis/src/emqx_auth_redis_app.erl @@ -0,0 +1,70 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_redis_app). + +-behaviour(application). + +-emqx_plugin(auth). + +-include("emqx_auth_redis.hrl"). + +-export([ start/2 + , stop/1 + ]). + +start(_StartType, _StartArgs) -> + {ok, Sup} = emqx_auth_redis_sup:start_link(), + if_cmd_enabled(auth_cmd, fun load_auth_hook/1), + if_cmd_enabled(acl_cmd, fun load_acl_hook/1), + {ok, Sup}. + +stop(_State) -> + emqx:unhook('client.authenticate', fun emqx_auth_redis:check/3), + emqx:unhook('client.check_acl', fun emqx_acl_redis:check_acl/5), + %% Ensure stop cluster pool if the server type is cluster + eredis_cluster:stop_pool(?APP). + +load_auth_hook(AuthCmd) -> + SuperCmd = application:get_env(?APP, super_cmd, undefined), + {ok, HashType} = application:get_env(?APP, password_hash), + {ok, Timeout} = application:get_env(?APP, query_timeout), + Type = proplists:get_value(type, application:get_env(?APP, server, [])), + Config = #{auth_cmd => AuthCmd, + super_cmd => SuperCmd, + hash_type => HashType, + timeout => Timeout, + type => Type, + pool => ?APP}, + ok = emqx_auth_redis:register_metrics(), + emqx:hook('client.authenticate', fun emqx_auth_redis:check/3, [Config]). + +load_acl_hook(AclCmd) -> + {ok, Timeout} = application:get_env(?APP, query_timeout), + Type = proplists:get_value(type, application:get_env(?APP, server, [])), + Config = #{acl_cmd => AclCmd, + timeout => Timeout, + type => Type, + pool => ?APP}, + ok = emqx_acl_redis:register_metrics(), + emqx:hook('client.check_acl', fun emqx_acl_redis:check_acl/5, [Config]). + +if_cmd_enabled(Par, Fun) -> + case application:get_env(?APP, Par) of + {ok, Cmd} -> Fun(Cmd); + undefined -> ok + end. + diff --git a/apps/emqx_auth_redis/src/emqx_auth_redis_cli.erl b/apps/emqx_auth_redis/src/emqx_auth_redis_cli.erl new file mode 100644 index 000000000..c1eb2a1bc --- /dev/null +++ b/apps/emqx_auth_redis/src/emqx_auth_redis_cli.erl @@ -0,0 +1,89 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_redis_cli). + +-behaviour(ecpool_worker). + +-include("emqx_auth_redis.hrl"). + +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). + +-import(proplists, [get_value/2, get_value/3]). + +-export([ connect/1 + , q/5 + ]). + +%%-------------------------------------------------------------------- +%% Redis Connect/Query +%%-------------------------------------------------------------------- + +connect(Opts) -> + Sentinel = get_value(sentinel, Opts), + Host = case Sentinel =:= "" of + true -> get_value(host, Opts); + false -> + eredis_sentinel:start_link(get_value(servers, Opts)), + "sentinel:" ++ Sentinel + end, + case eredis:start_link( + Host, + get_value(port, Opts, 6379), + get_value(database, Opts), + get_value(password, Opts), + no_reconnect + ) of + {ok, Pid} -> {ok, Pid}; + {error, Reason = {connection_error, _}} -> + ?LOG(error, "[Redis] Can't connect to Redis server: Connection refused."), + {error, Reason}; + {error, Reason = {authentication_error, _}} -> + ?LOG(error, "[Redis] Can't connect to Redis server: Authentication failed."), + {error, Reason}; + {error, Reason} -> + ?LOG(error, "[Redis] Can't connect to Redis server: ~p", [Reason]), + {error, Reason} + end. + +%% Redis Query. +-spec(q(atom(), atom(), string(), emqx_types:credentials(), timeout()) + -> {ok, undefined | binary() | list()} | {error, atom() | binary()}). +q(Pool, Type, CmdStr, Credentials, Timeout) -> + Cmd = string:tokens(replvar(CmdStr, Credentials), " "), + case Type of + cluster -> eredis_cluster:q(Pool, Cmd); + _ -> ecpool:with_client(Pool, fun(C) -> eredis:q(C, Cmd, Timeout) end) + end. + +replvar(Cmd, Credentials = #{cn := CN}) -> + replvar(repl(Cmd, "%C", CN), maps:remove(cn, Credentials)); +replvar(Cmd, Credentials = #{dn := DN}) -> + replvar(repl(Cmd, "%d", DN), maps:remove(dn, Credentials)); +replvar(Cmd, Credentials = #{clientid := ClientId}) -> + replvar(repl(Cmd, "%c", ClientId), maps:remove(clientid, Credentials)); +replvar(Cmd, Credentials = #{username := Username}) -> + replvar(repl(Cmd, "%u", Username), maps:remove(username, Credentials)); +replvar(Cmd, _) -> + Cmd. + +repl(S, _Var, undefined) -> + S; +repl(S, Var, Val) -> + NVal = re:replace(Val, "&", "\\\\&", [global, {return, list}]), + re:replace(S, Var, NVal, [{return, list}]). + diff --git a/apps/emqx_auth_redis/src/emqx_auth_redis_sup.erl b/apps/emqx_auth_redis/src/emqx_auth_redis_sup.erl new file mode 100644 index 000000000..41148c88e --- /dev/null +++ b/apps/emqx_auth_redis/src/emqx_auth_redis_sup.erl @@ -0,0 +1,42 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_redis_sup). + +-behaviour(supervisor). + +-include("emqx_auth_redis.hrl"). + +-export([start_link/0]). + +-export([init/1]). + +start_link() -> + supervisor:start_link({local, ?MODULE}, ?MODULE, []). + +init([]) -> + {ok, Server} = application:get_env(?APP, server), + {ok, {{one_for_one, 10, 100}, pool_spec(Server)}}. + +pool_spec(Server) -> + case proplists:get_value(type, Server) of + cluster -> + eredis_cluster:start_pool(?APP, Server), + []; + _ -> + [ecpool:pool_spec(?APP, ?APP, emqx_auth_redis_cli, Server)] + end. + diff --git a/apps/emqx_auth_redis/test/emqx_auth_redis_SUITE.erl b/apps/emqx_auth_redis/test/emqx_auth_redis_SUITE.erl new file mode 100644 index 000000000..3b827e74d --- /dev/null +++ b/apps/emqx_auth_redis/test/emqx_auth_redis_SUITE.erl @@ -0,0 +1,174 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_redis_SUITE). + +-compile(export_all). + +-include_lib("emqx_libs/include/emqx.hrl"). + +-include_lib("common_test/include/ct.hrl"). + +-include_lib("eunit/include/eunit.hrl"). + +-define(APP, emqx_auth_redis). + +-define(POOL(App), ecpool_worker:client(gproc_pool:pick_worker({ecpool, App}))). + +-define(INIT_ACL, [{"mqtt_acl:test1", "topic1", "2"}, + {"mqtt_acl:test2", "topic2", "1"}, + {"mqtt_acl:test3", "topic3", "3"}]). + +-define(INIT_AUTH, [{"mqtt_user:plain", ["password", "plain", "salt", "salt", "is_superuser", "1"]}, + {"mqtt_user:special&symbol", ["password", "plain", "salt", "salt", "is_superuser", "0"]}, + {"mqtt_user:md5", ["password", "1bc29b36f623ba82aaf6724fd3b16718", "salt", "salt", "is_superuser", "0"]}, + {"mqtt_user:sha", ["password", "d8f4590320e1343a915b6394170650a8f35d6926", "salt", "salt", "is_superuser", "0"]}, + {"mqtt_user:sha256", ["password", "5d5b09f6dcb2d53a5fffc60c4ac0d55fabdf556069d6631545f42aa6e3500f2e", "salt", "salt", "is_superuser", "0"]}, + {"mqtt_user:pbkdf2_password", ["password", "cdedb5281bb2f801565a1122b2563515", "salt", "ATHENA.MIT.EDUraeburn", "is_superuser", "0"]}, + {"mqtt_user:bcrypt_foo", ["password", "$2a$12$sSS8Eg.ovVzaHzi1nUHYK.HbUIOdlQI0iS22Q5rd5z.JVVYH6sfm6", "salt", "$2a$12$sSS8Eg.ovVzaHzi1nUHYK.", "is_superuser", "0"]}, + {"mqtt_user:bcrypt", ["password", "$2y$16$rEVsDarhgHYB0TGnDFJzyu5f.T.Ha9iXMTk9J36NCMWWM7O16qyaK", "salt", "salt", "is_superuser", "0"]}]). + +%%-------------------------------------------------------------------- +%% Setups +%%-------------------------------------------------------------------- + +all() -> + emqx_ct:all(?MODULE). + +init_per_suite(Cfg) -> + emqx_ct_helpers:start_apps([emqx_auth_redis], fun set_special_configs/1), + init_redis_rows(), + Cfg. + +end_per_suite(_Cfg) -> + deinit_redis_rows(), + emqx_ct_helpers:stop_apps([emqx_auth_redis]). + +set_special_configs(emqx) -> + application:set_env(emqx, allow_anonymous, false), + application:set_env(emqx, acl_nomatch, deny), + application:set_env(emqx, acl_file, + emqx_ct_helpers:deps_path(emqx, "test/emqx_SUITE_data/acl.conf")), + application:set_env(emqx, enable_acl_cache, false), + application:set_env(emqx, plugins_loaded_file, + emqx_ct_helpers:deps_path(emqx, "test/emqx_SUITE_data/loaded_plugins")); +set_special_configs(_App) -> + ok. + +init_redis_rows() -> + {ok, Connection} = ?POOL(?APP), + %% Users + [eredis:q(Connection, ["HMSET", Key|FiledValue]) || {Key, FiledValue} <- ?INIT_AUTH], + + %% ACLs + emqx_modules:load_module(emqx_mod_acl_internal, false), + Result = [eredis:q(Connection, ["HSET", Key, Filed, Value]) || {Key, Filed, Value} <- ?INIT_ACL], + ct:pal("redis init result: ~p~n", [Result]). + +deinit_redis_rows() -> + {ok, Connection} = ?POOL(?APP), + AuthKeys = [Key || {Key, _Filed, _Value} <- ?INIT_AUTH], + AclKeys = [Key || {Key, _Value} <- ?INIT_ACL], + eredis:q(Connection, ["DEL" | AuthKeys]), + eredis:q(Connection, ["DEL" | AclKeys]). + +%%-------------------------------------------------------------------- +%% Cases +%%-------------------------------------------------------------------- + +t_check_auth(_) -> + Plain = #{clientid => <<"client1">>, username => <<"plain">>, zone => external}, + SpecialSymbol = #{clientid => <<"special_symbol">>, username => <<"special&symbol">>, zone => external}, + Md5 = #{clientid => <<"md5">>, username => <<"md5">>, zone => external}, + Sha = #{clientid => <<"sha">>, username => <<"sha">>, zone => external}, + Sha256 = #{clientid => <<"sha256">>, username => <<"sha256">>, zone => external}, + Pbkdf2 = #{clientid => <<"pbkdf2_password">>, username => <<"pbkdf2_password">>, zone => external}, + BcryptFoo = #{clientid => <<"bcrypt_foo">>, username => <<"bcrypt_foo">>, zone => external}, + User1 = #{clientid => <<"bcrypt_foo">>, username => <<"user">>, zone => external}, + User3 = #{clientid => <<"client3">>, zone => external}, + Bcrypt = #{clientid => <<"bcrypt">>, username => <<"bcrypt">>, zone => external}, + {error, _} = emqx_access_control:authenticate(User3#{password => <<>>}), + reload([{password_hash, plain}]), + {ok, #{is_superuser := true}} = emqx_access_control:authenticate(Plain#{password => <<"plain">>}), + {ok, #{is_superuser := false}} = emqx_access_control:authenticate(SpecialSymbol#{password => <<"plain">>}), + reload([{password_hash, md5}]), + {ok, #{is_superuser := false}} = emqx_access_control:authenticate(Md5#{password => <<"md5">>}), + reload([{password_hash, sha}]), + {ok, #{is_superuser := false}} = emqx_access_control:authenticate(Sha#{password => <<"sha">>}), + reload([{password_hash, sha256}]), + {ok, #{is_superuser := false}} = emqx_access_control:authenticate(Sha256#{password => <<"sha256">>}), + reload([{password_hash, bcrypt}]), + {ok, #{is_superuser := false}} = emqx_access_control:authenticate(Bcrypt#{password => <<"password">>}), + %%pbkdf2 sha + reload([{password_hash, {pbkdf2, sha, 1, 16}}, {auth_cmd, "HMGET mqtt_user:%u password salt"}]), + {ok, #{is_superuser := false}} = emqx_access_control:authenticate(Pbkdf2#{password => <<"password">>}), + reload([{password_hash, {salt, bcrypt}}]), + {ok, #{is_superuser := false}} = emqx_access_control:authenticate(BcryptFoo#{password => <<"foo">>}), + {error,_} = emqx_access_control:authenticate(User1#{password => <<"foo">>}), + {error, _} = emqx_access_control:authenticate(Bcrypt#{password => <<"password">>}). + +t_check_auth_hget(_) -> + {ok, Connection} = ?POOL(?APP), + eredis:q(Connection, ["HSET", "mqtt_user:hset", "password", "hset"]), + eredis:q(Connection, ["HSET", "mqtt_user:hset", "is_superuser", "1"]), + reload([{password_hash, plain}, {auth_cmd, "HGET mqtt_user:%u password"}]), + Hset = #{clientid => <<"hset">>, username => <<"hset">>, zone => external}, + {ok, #{is_superuser := true}} = emqx_access_control:authenticate(Hset#{password => <<"hset">>}). + +t_check_acl(_) -> + User1 = #{zone => external, clientid => <<"client1">>, username => <<"test1">>}, + User2 = #{zone => external, clientid => <<"client2">>, username => <<"test2">>}, + User3 = #{zone => external, clientid => <<"client3">>, username => <<"test3">>}, + User4 = #{zone => external, clientid => <<"client4">>, username => <<"$$user4">>}, + deny = emqx_access_control:check_acl(User1, subscribe, <<"topic1">>), + allow = emqx_access_control:check_acl(User1, publish, <<"topic1">>), + + deny = emqx_access_control:check_acl(User2, publish, <<"topic2">>), + allow = emqx_access_control:check_acl(User2, subscribe, <<"topic2">>), + allow = emqx_access_control:check_acl(User3, publish, <<"topic3">>), + allow = emqx_access_control:check_acl(User3, subscribe, <<"topic3">>), + allow = emqx_access_control:check_acl(User4, publish, <<"a/b/c">>). + +t_acl_super(_) -> + reload([{password_hash, plain}]), + {ok, C} = emqtt:start_link([{host, "localhost"}, + {clientid, <<"simpleClient">>}, + {username, <<"plain">>}, + {password, <<"plain">>}]), + {ok, _} = emqtt:connect(C), + timer:sleep(10), + emqtt:subscribe(C, <<"TopicA">>, qos2), + timer:sleep(1000), + emqtt:publish(C, <<"TopicA">>, <<"Payload">>, qos2), + timer:sleep(1000), + receive + {publish, #{payload := Payload}} -> + ?assertEqual(<<"Payload">>, Payload) + after + 1000 -> + ct:fail({receive_timeout, <<"Payload">>}), + ok + end, + emqtt:disconnect(C). + +%%-------------------------------------------------------------------- +%% Internal funcs +%%-------------------------------------------------------------------- + +reload(Config) when is_list(Config) -> + application:stop(?APP), + [application:set_env(?APP, K, V) || {K, V} <- Config], + application:start(?APP). diff --git a/apps/emqx_auth_username/README.md b/apps/emqx_auth_username/README.md new file mode 100644 index 000000000..bc0dd6e04 --- /dev/null +++ b/apps/emqx_auth_username/README.md @@ -0,0 +1,111 @@ +emqx_auth_username +================== + +EMQ X Authentication with Username and Password + +Build +----- + +``` +make && make tests +``` + +Configuration +------------- + +etc/emqx_auth_username.conf: + +``` +## Password hash. +## +## Value: plain | md5 | sha | sha256 +auth.user.password_hash = sha256 +``` + +[REST API](https://developer.emqx.io/docs/emq/v3/en/rest.html) +------------ + +List all usernames +``` +# Request +GET api/v4/auth_username + +# Response +{ + "code": 0, + "data": ["username1"] +} +``` + +Add a username: +``` +# Request +POST api/v4/auth_username +{ + "username": "some_name", + "password": "password" +} + +# Response +{ + "code": 0 +} +``` + +Update password for a username: +``` +# Request +PUT api/v4/auth_username/$NAME +{ + "password": "password" +} + +# Response +{ + "code", 0 +} +``` + +Lookup a username info: +``` +# Request +GET api/v4/auth_username/$NAME + +# Response +{ + "code": 0, + "data": { + "username": "some_username", + "password": "hashed_password" + } +} +``` + +Delete a username: +``` +# Request +DELETE api/v4/auth_username/$NAME + +# Response +{ + "code": 0 +} +``` + +Load the Plugin +--------------- + +``` +./bin/emqx_ctl plugins load emqx_auth_username +``` + +License +------- + +Apache License Version 2.0 + +Author +------ + +EMQ X Team. + diff --git a/apps/emqx_auth_username/TODO b/apps/emqx_auth_username/TODO new file mode 100644 index 000000000..c968cc25a --- /dev/null +++ b/apps/emqx_auth_username/TODO @@ -0,0 +1 @@ +Upgrade test cases for 3.0 diff --git a/apps/emqx_auth_username/include/emqx_auth_username.hrl b/apps/emqx_auth_username/include/emqx_auth_username.hrl new file mode 100644 index 000000000..b70129858 --- /dev/null +++ b/apps/emqx_auth_username/include/emqx_auth_username.hrl @@ -0,0 +1,14 @@ +-define(APP, emqx_auth_username). + +-record(auth_metrics, { + success = 'client.auth.success', + failure = 'client.auth.failure', + ignore = 'client.auth.ignore' + }). + +-define(METRICS(Type), tl(tuple_to_list(#Type{}))). +-define(METRICS(Type, K), #Type{}#Type.K). + +-define(AUTH_METRICS, ?METRICS(auth_metrics)). +-define(AUTH_METRICS(K), ?METRICS(auth_metrics, K)). + diff --git a/apps/emqx_auth_username/priv/emqx_auth_username.schema b/apps/emqx_auth_username/priv/emqx_auth_username.schema new file mode 100644 index 000000000..6e449fee6 --- /dev/null +++ b/apps/emqx_auth_username/priv/emqx_auth_username.schema @@ -0,0 +1,26 @@ +%%-*- mode: erlang -*- +%% emqx_auth_username config mapping + +{mapping, "auth.user.password_hash", "emqx_auth_username.password_hash", [ + {default, sha256}, + {datatype, {enum, [plain, md5, sha, sha256]}} +]}. + +{mapping, "auth.user.$id.username", "emqx_auth_username.userlist", [ + {datatype, string} +]}. + +{mapping, "auth.user.$id.password", "emqx_auth_username.userlist", [ + {datatype, string} +]}. + +{translation, "emqx_auth_username.userlist", fun(Conf) -> + Userlist = cuttlefish_variable:filter_by_prefix("auth.user", Conf), + lists:foldl( + fun({["auth", "user", Id, "username"], Username}, AccIn) -> + [{Username, cuttlefish:conf_get("auth.user." ++ Id ++ ".password", Conf)} | AccIn]; + (_, AccIn) -> + AccIn + end, [], Userlist) +end}. + diff --git a/apps/emqx_auth_username/rebar.config b/apps/emqx_auth_username/rebar.config new file mode 100644 index 000000000..7b30a8fd8 --- /dev/null +++ b/apps/emqx_auth_username/rebar.config @@ -0,0 +1 @@ +{deps, []}. diff --git a/apps/emqx_auth_username/src/emqx_auth_username.app.src b/apps/emqx_auth_username/src/emqx_auth_username.app.src new file mode 100644 index 000000000..c48c1de24 --- /dev/null +++ b/apps/emqx_auth_username/src/emqx_auth_username.app.src @@ -0,0 +1,14 @@ +{application, emqx_auth_username, + [{description, "EMQ X Authentication with Username and Password"}, + {vsn, "5.0.0"}, % strict semver, bump manually! + {modules, []}, + {registered, []}, + {applications, [kernel,stdlib,emqx_libs]}, + {mod, {emqx_auth_username_app,[]}}, + {env, []}, + {licenses, ["Apache-2.0"]}, + {maintainers, ["EMQ X Team "]}, + {links, [{"Homepage", "https://emqx.io/"}, + {"Github", "https://github.com/emqx/emqx-auth-username"} + ]} + ]}. diff --git a/apps/emqx_auth_username/src/emqx_auth_username.erl b/apps/emqx_auth_username/src/emqx_auth_username.erl new file mode 100644 index 000000000..b5c089b49 --- /dev/null +++ b/apps/emqx_auth_username/src/emqx_auth_username.erl @@ -0,0 +1,173 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_username). + +-include("emqx_auth_username.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). + +%% CLI callbacks +-export([cli/1]). + +%% APIs +-export([ add_user/2 + , update_password/2 + , remove_user/1 + , lookup_user/1 + , all_users/0 + ]). + +-export([unwrap_salt/1]). + +%% Auth callbacks +-export([ init/1 + , register_metrics/0 + , check/3 + , description/0 + ]). + +-define(TAB, ?MODULE). + +-record(?TAB, {username, password}). + +%%-------------------------------------------------------------------- +%% CLI +%%-------------------------------------------------------------------- + +cli(["list"]) -> + Usernames = mnesia:dirty_all_keys(?TAB), + [emqx_ctl:print("~s~n", [Username]) || Username <- Usernames]; + +cli(["add", Username, Password]) -> + Ok = add_user(iolist_to_binary(Username), iolist_to_binary(Password)), + emqx_ctl:print("~p~n", [Ok]); + +cli(["update", Username, NewPassword]) -> + Ok = update_password(iolist_to_binary(Username), iolist_to_binary(NewPassword)), + emqx_ctl:print("~p~n", [Ok]); + +cli(["del", Username]) -> + emqx_ctl:print("~p~n", [remove_user(iolist_to_binary(Username))]); + +cli(_) -> + emqx_ctl:usage([{"users list", "List users"}, + {"users add ", "Add User"}, + {"users update ", "Update User"}, + {"users del ", "Delete User"}]). + +%%-------------------------------------------------------------------- +%% API +%%-------------------------------------------------------------------- + +%% @doc Add User +-spec(add_user(binary(), binary()) -> ok | {error, any()}). +add_user(Username, Password) -> + User = #?TAB{username = Username, password = encrypted_data(Password)}, + ret(mnesia:transaction(fun insert_user/1, [User])). + +insert_user(User = #?TAB{username = Username}) -> + case mnesia:read(?TAB, Username) of + [] -> mnesia:write(User); + [_|_] -> mnesia:abort(existed) + end. + +%% @doc Update User +-spec(update_password(binary(), binary()) -> ok | {error, any()}). +update_password(Username, NewPassword) -> + User = #?TAB{username = Username, password = encrypted_data(NewPassword)}, + ret(mnesia:transaction(fun do_update_password/1, [User])). + +do_update_password(User = #?TAB{username = Username}) -> + case mnesia:read(?TAB, Username) of + [_|_] -> mnesia:write(User); + [] -> mnesia:abort(noexisted) + end. + +%% @doc Lookup user by username +-spec(lookup_user(binary()) -> list()). +lookup_user(Username) -> + mnesia:dirty_read(?TAB, Username). + +%% @doc Remove user +-spec(remove_user(binary()) -> ok | {error, any()}). +remove_user(Username) -> + ret(mnesia:transaction(fun mnesia:delete/1, [{?TAB, Username}])). + +ret({atomic, ok}) -> ok; +ret({aborted, Error}) -> {error, Error}. + +%% @doc All usernames +-spec(all_users() -> list()). +all_users() -> mnesia:dirty_all_keys(?TAB). + +unwrap_salt(<<_Salt:4/binary, HashPasswd/binary>>) -> + HashPasswd. + +%%-------------------------------------------------------------------- +%% Auth callbacks +%%-------------------------------------------------------------------- + +init(DefaultUsers) -> + ok = ekka_mnesia:create_table(?TAB, [ + {disc_copies, [node()]}, + {attributes, record_info(fields, ?TAB)}, + {storage_properties, [{ets, [{read_concurrency, true}]}]}]), + ok = lists:foreach(fun add_default_user/1, DefaultUsers), + ok = ekka_mnesia:copy_table(?TAB, disc_copies). + +%% @private +add_default_user({Username, Password}) -> + add_user(iolist_to_binary(Username), iolist_to_binary(Password)). + +-spec(register_metrics() -> ok). +register_metrics() -> + lists:foreach(fun emqx_metrics:ensure/1, ?AUTH_METRICS). + +check(#{username := Username, password := Password}, AuthResult, #{hash_type := HashType}) -> + case mnesia:dirty_read(?TAB, Username) of + [] -> emqx_metrics:inc(?AUTH_METRICS(ignore)); + [#?TAB{password = <>}] -> + case Hash =:= hash(Password, Salt, HashType) of + true -> + ok = emqx_metrics:inc(?AUTH_METRICS(success)), + {stop, AuthResult#{auth_result => success, anonymous => false}}; + false -> + ok = emqx_metrics:inc(?AUTH_METRICS(failure)), + {stop, AuthResult#{auth_result => not_authorized, anonymous => false}} + end + end. + +description() -> + "Username password Authentication Module". + +%%-------------------------------------------------------------------- +%% Internal functions +%%-------------------------------------------------------------------- + +encrypted_data(Password) -> + HashType = application:get_env(emqx_auth_username, password_hash, sha256), + SaltBin = salt(), + <>. + +hash(undefined, SaltBin, HashType) -> + hash(<<>>, SaltBin, HashType); +hash(Password, SaltBin, HashType) -> + emqx_passwd:hash(HashType, <>). + +salt() -> + rand:seed(exsplus, erlang:timestamp()), + Salt = rand:uniform(16#ffffffff), <>. + diff --git a/apps/emqx_auth_username/src/emqx_auth_username_api.erl b/apps/emqx_auth_username/src/emqx_auth_username_api.erl new file mode 100644 index 000000000..725a7471d --- /dev/null +++ b/apps/emqx_auth_username/src/emqx_auth_username_api.erl @@ -0,0 +1,123 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_username_api). + +-include("emqx_auth_username.hrl"). + +-import(proplists, [get_value/2]). + +-import(minirest, [return/0, return/1]). + +-rest_api(#{name => list_username, + method => 'GET', + path => "/auth_username", + func => list, + descr => "List available username in the cluster" + }). + +-rest_api(#{name => lookup_username, + method => 'GET', + path => "/auth_username/:bin:username", + func => lookup, + descr => "Lookup username in the cluster" + }). + +-rest_api(#{name => add_username, + method => 'POST', + path => "/auth_username", + func => add, + descr => "Add username in the cluster" + }). + +-rest_api(#{name => update_username, + method => 'PUT', + path => "/auth_username/:bin:username", + func => update, + descr => "Update username in the cluster" + }). + +-rest_api(#{name => delete_username, + method => 'DELETE', + path => "/auth_username/:bin:username", + func => delete, + descr => "Delete username in the cluster" + }). + +-export([ list/2 + , lookup/2 + , add/2 + , update/2 + , delete/2 + ]). + +list(_Bindings, _Params) -> + return({ok, emqx_auth_username:all_users()}). + +lookup(#{username := Username}, _Params) -> + return({ok, format(emqx_auth_username:lookup_user(Username))}). + +add(_Bindings, Params) -> + Username = get_value(<<"username">>, Params), + Password = get_value(<<"password">>, Params), + case validate([username, password], [Username, Password]) of + ok -> + case emqx_auth_username:add_user(Username, Password) of + ok -> return(); + Err -> return(Err) + end; + Err -> return(Err) + end. + +update(#{username := Username}, Params) -> + Password = get_value(<<"password">>, Params), + case validate([password], [Password]) of + ok -> + case emqx_auth_username:update_password(Username, Password) of + ok -> return(); + Err -> return(Err) + end; + Err -> return(Err) + end. + +delete(#{username := Username}, _) -> + ok = emqx_auth_username:remove_user(Username), + return(). + +%%------------------------------------------------------------------------------ +%% Interval Funcs +%%------------------------------------------------------------------------------ + +format([{?APP, Username, Password}]) -> + #{username => Username, + password => emqx_auth_username:unwrap_salt(Password)}. + +validate([], []) -> + ok; +validate([K|Keys], [V|Values]) -> + case validation(K, V) of + false -> {error, K}; + true -> validate(Keys, Values) + end. + +validation(username, V) when is_binary(V) + andalso byte_size(V) > 0 -> + true; +validation(password, V) when is_binary(V) + andalso byte_size(V) > 0 -> + true; +validation(_, _) -> + false. diff --git a/apps/emqx_auth_username/src/emqx_auth_username_app.erl b/apps/emqx_auth_username/src/emqx_auth_username_app.erl new file mode 100644 index 000000000..5308d2cdb --- /dev/null +++ b/apps/emqx_auth_username/src/emqx_auth_username_app.erl @@ -0,0 +1,49 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_auth_username_app). + +-include("emqx_auth_username.hrl"). + +-behaviour(application). +-behaviour(supervisor). + +-emqx_plugin(auth). + +-export([ start/2 + , stop/1 + ]). +-export([init/1]). + +start(_Type, _Args) -> + emqx_ctl:register_command(users, {?APP, cli}, []), + ok = emqx_auth_username:register_metrics(), + HashType = application:get_env(?APP, password_hash, sha256), + Params = #{hash_type => HashType}, + emqx:hook('client.authenticate', fun emqx_auth_username:check/3, [Params]), + DefaultUsers = application:get_env(?APP, userlist, []), + ok = emqx_auth_username:init(DefaultUsers), + supervisor:start_link({local, ?MODULE}, ?MODULE, []). + +stop(_State) -> + emqx:unhook('client.authenticate', fun emqx_auth_username:check/3), + emqx_ctl:unregister_command(users). + +%%-------------------------------------------------------------------- + +init([]) -> + {ok, { {one_for_all, 1, 10}, []} }. + diff --git a/apps/emqx_auth_username/test/emqx_auth_username_SUITE.erl b/apps/emqx_auth_username/test/emqx_auth_username_SUITE.erl new file mode 100644 index 000000000..872f0c3e0 --- /dev/null +++ b/apps/emqx_auth_username/test/emqx_auth_username_SUITE.erl @@ -0,0 +1,176 @@ +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. + +-module(emqx_auth_username_SUITE). + +-compile(nowarn_export_all). +-compile(export_all). + +-include_lib("emqx_libs/include/emqx.hrl"). + +-include_lib("eunit/include/eunit.hrl"). +-include_lib("common_test/include/ct.hrl"). + +-define(TAB, emqx_auth_username). + +all() -> + emqx_ct:all(?MODULE). + +init_per_suite(Config) -> + emqx_ct_helpers:start_apps([emqx_auth_username], fun set_special_configs/1), + Config. + +end_per_suite(_Config) -> + emqx_ct_helpers:stop_apps([emqx_auth_username]). + +set_special_configs(emqx) -> + application:set_env(emqx, allow_anonymous, true), + application:set_env(emqx, enable_acl_cache, false), + LoadedPluginPath = filename:join(["test", "emqx_SUITE_data", "loaded_plugins"]), + application:set_env(emqx, plugins_loaded_file, + emqx_ct_helpers:deps_path(emqx, LoadedPluginPath)); + +set_special_configs(_App) -> + ok. + +%%------------------------------------------------------------------------------ +%% Testcases +%%------------------------------------------------------------------------------ + +t_managing(_Config) -> + clean_all_users(), + + ok = emqx_auth_username:add_user(<<"test_username">>, <<"password">>), + [{?TAB, <<"test_username">>, _HashedPass}] = + emqx_auth_username:lookup_user(<<"test_username">>), + User1 = #{username => <<"test_username">>, + password => <<"password">>, + zone => external}, + + {ok, #{auth_result := success, + anonymous := false}} = emqx_access_control:authenticate(User1), + + ok = emqx_auth_username:remove_user(<<"test_username">>), + {ok, #{auth_result := success, + anonymous := true }} = emqx_access_control:authenticate(User1). + +t_rest_api(_Config) -> + clean_all_users(), + + Username = <<"username">>, + Password = <<"password">>, + Password1 = <<"password1">>, + User = #{username => Username, zone => external}, + + ?assertEqual(return(), + emqx_auth_username_api:add(#{}, rest_params(Username, Password))), + ?assertEqual(return({error, existed}), + emqx_auth_username_api:add(#{}, rest_params(Username, Password))), + ?assertEqual(return([Username]), + emqx_auth_username_api:list(#{}, [])), + + {ok, #{code := 0, data := Data}} = + emqx_auth_username_api:lookup(rest_binding(Username), []), + ?assertEqual(true, match_password(maps:get(username, Data), Password)), + + {ok, _} = emqx_access_control:authenticate(User#{password => Password}), + + ?assertEqual(return(), + emqx_auth_username_api:update(rest_binding(Username), rest_params(Password))), + ?assertEqual(return({error, noexisted}), + emqx_auth_username_api:update(#{username => <<"another_user">>}, rest_params(<<"another_passwd">>))), + + {error, _} = emqx_access_control:authenticate(User#{password => Password1}), + + ?assertEqual(return(), + emqx_auth_username_api:delete(rest_binding(Username), [])), + {ok, #{auth_result := success, + anonymous := true}} = emqx_access_control:authenticate(User#{password => Password}). + +t_cli(_Config) -> + clean_all_users(), + + emqx_auth_username:cli(["add", "username", "password"]), + ?assertEqual(true, match_password(<<"username">>, <<"password">>)), + + emqx_auth_username:cli(["update", "username", "newpassword"]), + ?assertEqual(true, match_password(<<"username">>, <<"newpassword">>)), + + emqx_auth_username:cli(["del", "username"]), + [] = emqx_auth_username:lookup_user(<<"username">>), + emqx_auth_username:cli(["add", "user1", "pass1"]), + emqx_auth_username:cli(["add", "user2", "pass2"]), + UserList = emqx_auth_username:cli(["list"]), + 2 = length(UserList), + emqx_auth_username:cli(usage). + +t_conf_not_override_existed(_) -> + clean_all_users(), + + Username = <<"username">>, + Password = <<"password">>, + NPassword = <<"password1">>, + User = #{username => Username, zone => external}, + + application:stop(emqx_auth_username), + application:set_env(emqx_auth_username, userlist, [{Username, Password}]), + application:ensure_all_started(emqx_auth_username), + + {ok, _} = emqx_access_control:authenticate(User#{password => Password}), + emqx_auth_username:cli(["update", Username, NPassword]), + + {error, _} = emqx_access_control:authenticate(User#{password => Password}), + {ok, _} = emqx_access_control:authenticate(User#{password => NPassword}), + + application:stop(emqx_auth_username), + application:ensure_all_started(emqx_auth_username), + {ok, _} = emqx_access_control:authenticate(User#{password => NPassword}), + + ?assertEqual(return(), + emqx_auth_username_api:update(rest_binding(Username), rest_params(Password))), + application:stop(emqx_auth_username), + application:ensure_all_started(emqx_auth_username), + {ok, _} = emqx_access_control:authenticate(User#{password => Password}). + +%%------------------------------------------------------------------------------ +%% Helpers +%%------------------------------------------------------------------------------ + +clean_all_users() -> + [ mnesia:dirty_delete({emqx_auth_username, Username}) + || Username <- mnesia:dirty_all_keys(emqx_auth_username)]. + +match_password(Username, PlainPassword) -> + HashType = application:get_env(emqx_auth_username, password_hash, sha256), + [{?TAB, Username, <>}] = + emqx_auth_username:lookup_user(Username), + Hash =:= emqx_passwd:hash(HashType, <>). + +rest_params(Passwd) -> + [{<<"password">>, Passwd}]. + +rest_params(Username, Passwd) -> + [{<<"username">>, Username}, + {<<"password">>, Passwd}]. + +rest_binding(Username) -> + #{username => Username}. + +return() -> + {ok, #{code => 0}}. +return({error, Err}) -> + {ok, #{message => Err}}; +return(Data) -> + {ok, #{code => 0, data => Data}}. + diff --git a/apps/emqx_bridge_mqtt/README.md b/apps/emqx_bridge_mqtt/README.md new file mode 100644 index 000000000..6656aa36f --- /dev/null +++ b/apps/emqx_bridge_mqtt/README.md @@ -0,0 +1,265 @@ +# EMQ Bridge MQTT + +The concept of **Bridge** means that EMQ X supports forwarding messages +of one of its own topics to another MQTT Broker in some way. + +**Bridge** differs from **Cluster** in that the bridge does not +replicate the topic trie and routing tables and only forwards MQTT +messages based on bridging rules. + +At present, the bridging methods supported by EMQ X are as follows: + +- RPC bridge: RPC Bridge only supports message forwarding and does not + support subscribing to the topic of remote nodes to synchronize + data; +- MQTT Bridge: MQTT Bridge supports both forwarding and data + synchronization through subscription topic. + +These concepts are shown below: + +![bridge](docs/images/bridge.png) + +In addition, the EMQ X message broker supports multi-node bridge mode interconnection + +``` + --------- --------- --------- +Publisher --> | Node1 | --Bridge Forward--> | Node2 | --Bridge Forward--> | Node3 | --> Subscriber + --------- --------- --------- +``` + +In EMQ X, bridge is configured by modifying `etc/emqx.conf`. EMQ X distinguishes between different bridges based on different names. E.g + +``` +## Bridge address: node name for local bridge, host:port for remote. +bridge.mqtt.aws.address = 127.0.0.1:1883 +``` + +This configuration declares a bridge named `aws` and specifies that it is bridged to the MQTT broker of 127.0.0.1:1883 by MQTT mode. + +In case of creating multiple bridges, it is convenient to replicate all configuration items of the first bridge, and modify the bridge name and other configuration items if necessary (such as bridge.$name.address, where $name refers to the name of bridge) + +The next two sections describe how to create a bridge in RPC and MQTT mode respectively and create a forwarding rule that forwards the messages from sensors. Assuming that two EMQ X nodes are running on two hosts: + + +| Name | Node | MQTT Port | +|------|-------------------|-----------| +| emqx1| emqx1@192.168.1.1.| 1883 | +| emqx2| emqx2@192.168.1.2 | 1883 | + + +## EMQ X RPC Bridge Configuration + +The following is the basic configuration of RPC bridging. A simplest RPC bridging only requires the following three items + +``` +## Bridge Address: Use node name (nodename@host) for rpc bridging, and host:port for mqtt connection +bridge.mqtt.emqx2.address = emqx2@192.168.1.2 + +## Forwarding topics of the message +bridge.mqtt.emqx2.forwards = sensor1/#,sensor2/# + +## bridged mountpoint +bridge.mqtt.emqx2.mountpoint = bridge/emqx2/${node}/ +``` + +If the messages received by the local node emqx1 matches the topic `sersor1/#` or `sensor2/#`, these messages will be forwarded to the `sensor1/#` or `sensor2/#` topic of the remote node emqx2. + +`forwards` is used to specify topics. Messages of the in `forwards` specified topics on local node are forwarded to the remote node. + +`mountpoint` is used to add a topic prefix when forwarding a message. To use `mountpoint`, the `forwards` directive must be set. In the above example, a message with the topic `sensor1/hello` received by the local node will be forwarded to the remote node with the topic `bridge/emqx2/emqx1@192.168.1.1/sensor1/hello`. + +Limitations of RPC bridging: + +1. The RPC bridge of emqx can only forward local messages to the remote node, and cannot synchronize the messages of the remote node to the local node; + +2. RPC bridge can only bridge two EMQ X broker together and cannot bridge EMQ X broker to other MQTT brokers. + +## EMQ X MQTT Bridge Configuration + +EMQ X 3.0 officially introduced MQTT bridge, so that EMQ X can bridge any MQTT broker. Because of the characteristics of the MQTT protocol, EMQ X can subscribe to the remote mqtt broker's topic through MQTT bridge, and then synchronize the remote MQTT broker's message to the local. + +EMQ X MQTT bridging principle: Create an MQTT client on the EMQ X broker, and connect this MQTT client to the remote MQTT broker. Therefore, in the MQTT bridge configuration, following fields may be set for the EMQ X to connect to the remote broker as an mqtt client + +``` +## Bridge Address: Use node name for rpc bridging, use host:port for mqtt connection +bridge.mqtt.emqx2.address = 192.168.1.2:1883 + +## Bridged Protocol Version +## Enumeration value: mqttv3 | mqttv4 | mqttv5 +bridge.mqtt.emqx2.proto_ver = mqttv4 + +## mqtt client's clientid +bridge.mqtt.emqx2.clientid = bridge_emq + +## mqtt client's clean_start field +## Note: Some MQTT Brokers need to set the clean_start value as `true` +bridge.mqtt.emqx2.clean_start = true + +## mqtt client's username field +bridge.mqtt.emqx2.username = user + +## mqtt client's password field +bridge.mqtt.emqx2.password = passwd + +## Whether the mqtt client uses ssl to connect to a remote serve or not +bridge.mqtt.emqx2.ssl = off + +## CA Certificate of Client SSL Connection (PEM format) +bridge.mqtt.emqx2.cacertfile = etc/certs/cacert.pem + +## SSL certificate of Client SSL connection +bridge.mqtt.emqx2.certfile = etc/certs/client-cert.pem + +## Key file of Client SSL connection +bridge.mqtt.emqx2.keyfile = etc/certs/client-key.pem + +## SSL encryption +bridge.mqtt.emqx2.ciphers = ECDHE-ECDSA-AES256-GCM-SHA384,ECDHE-RSA-AES256-GCM-SHA384 + +## TTLS PSK password +## Note 'listener.ssl.external.ciphers' and 'listener.ssl.external.psk_ciphers' cannot be configured at the same time +## +## See 'https://tools.ietf.org/html/rfc4279#section-2'. +## bridge.mqtt.emqx2.psk_ciphers = PSK-AES128-CBC-SHA,PSK-AES256-CBC-SHA,PSK-3DES-EDE-CBC-SHA,PSK-RC4-SHA + +## Client's heartbeat interval +bridge.mqtt.emqx2.keepalive = 60s + +## Supported TLS version +bridge.mqtt.emqx2.tls_versions = tlsv1.2,tlsv1.1,tlsv1 + +## Forwarding topics of the message +bridge.mqtt.emqx2.forwards = sensor1/#,sensor2/# + +## Bridged mountpoint +bridge.mqtt.emqx2.mountpoint = bridge/emqx2/${node}/ + +## Subscription topic for bridging +bridge.mqtt.emqx2.subscription.1.topic = cmd/topic1 + +## Subscription qos for bridging +bridge.mqtt.emqx2.subscription.1.qos = 1 + +## Subscription topic for bridging +bridge.mqtt.emqx2.subscription.2.topic = cmd/topic2 + +## Subscription qos for bridging +bridge.mqtt.emqx2.subscription.2.qos = 1 + +## Bridging reconnection interval +## Default: 30s +bridge.mqtt.emqx2.reconnect_interval = 30s + +## QoS1 message retransmission interval +bridge.mqtt.emqx2.retry_interval = 20s + +## Inflight Size. +bridge.mqtt.emqx2.max_inflight_batches = 32 +``` + +## Bridge Cache Configuration + +The bridge of EMQ X has a message caching mechanism. The caching mechanism is applicable to both RPC bridging and MQTT bridging. When the bridge is disconnected (such as when the network connection is unstable), the messages with a topic specified in `forwards` can be cached to the local message queue. Until the bridge is restored, these messages are re-forwarded to the remote node. The configuration of the cache queue is as follows + +``` +## emqx_bridge internal number of messages used for batch +bridge.mqtt.emqx2.queue.batch_count_limit = 32 + +## emqx_bridge internal number of message bytes used for batch +bridge.mqtt.emqx2.queue.batch_bytes_limit = 1000MB + +## The path for placing replayq queue. If it is not specified, then replayq will run in `mem-only` mode and messages will not be cached on disk. +bridge.mqtt.emqx2.queue.replayq_dir = data/emqx_emqx2_bridge/ + +## Replayq data segment size +bridge.mqtt.emqx2.queue.replayq_seg_bytes = 10MB +``` + +`bridge.mqtt.emqx2.queue.replayq_dir` is a configuration parameter for specifying the path of the bridge storage queue. + +`bridge.mqtt.emqx2.queue.replayq_seg_bytes` is used to specify the size of the largest single file of the message queue that is cached on disk. If the message queue size exceeds the specified value, a new file is created to store the message queue. + +## CLI for EMQ X Bridge MQTT + +CLI for EMQ X Bridge MQTT: + +``` bash +$ cd emqx1/ && ./bin/emqx_ctl bridges +bridges list # List bridges +bridges start # Start a bridge +bridges stop # Stop a bridge +bridges forwards # Show a bridge forward topic +bridges add-forward # Add bridge forward topic +bridges del-forward # Delete bridge forward topic +bridges subscriptions # Show a bridge subscriptions topic +bridges add-subscription # Add bridge subscriptions topic +``` + +List all bridge states + +``` bash +$ ./bin/emqx_ctl bridges list +name: emqx status: Stopped $ ./bin/emqx_ctl bridges list +name: emqx status: Stopped +``` + +Start the specified bridge + +``` bash +$ ./bin/emqx_ctl bridges start emqx +Start bridge successfully. +``` + +Stop the specified bridge + +``` bash +$ ./bin/emqx_ctl bridges stop emqx +Stop bridge successfully. +``` +List the forwarding topics for the specified bridge + +``` bash +$ ./bin/emqx_ctl bridges forwards emqx +topic: topic1/# +topic: topic2/# +``` + +Add a forwarding topic for the specified bridge + +``` bash +$ ./bin/emqx_ctl bridges add-forwards emqx topic3/# +Add-forward topic successfully. +``` + +Delete the forwarding topic for the specified bridge + + +``` bash +$ ./bin/emqx_ctl bridges del-forwards emqx topic3/# +Del-forward topic successfully. +``` + +List subscriptions for the specified bridge + +``` bash +$ ./bin/emqx_ctl bridges subscriptions emqx +topic: cmd/topic1, qos: 1 +topic: cmd/topic2, qos: 1 +``` + +Add a subscription topic for the specified bridge + +``` bash +$ ./bin/emqx_ctl bridges add-subscription emqx cmd/topic3 1 +Add-subscription topic successfully. +``` + +Delete the subscription topic for the specified bridge + +``` bash +$ ./bin/emqx_ctl bridges del-subscription emqx cmd/topic3 +Del-subscription topic successfully. +``` + +Note: In case of creating multiple bridges, it is convenient to replicate all configuration items of the first bridge, and modify the bridge name and other configuration items if necessary. + diff --git a/apps/emqx_bridge_mqtt/docs/guide.rst b/apps/emqx_bridge_mqtt/docs/guide.rst new file mode 100644 index 000000000..73350ca1f --- /dev/null +++ b/apps/emqx_bridge_mqtt/docs/guide.rst @@ -0,0 +1,286 @@ + +EMQ Bridge MQTT +=============== + +The concept of **Bridge** means that EMQ X supports forwarding messages +of one of its own topics to another MQTT Broker in some way. + +**Bridge** differs from **Cluster** in that the bridge does not +replicate the topic trie and routing tables and only forwards MQTT +messages based on bridging rules. + +At present, the bridging methods supported by EMQ X are as follows: + + +* RPC bridge: RPC Bridge only supports message forwarding and does not + support subscribing to the topic of remote nodes to synchronize + data; +* MQTT Bridge: MQTT Bridge supports both forwarding and data + synchronization through subscription topic. + +These concepts are shown below: + + +.. image:: images/bridge.png + :target: images/bridge.png + :alt: bridge + + +In addition, the EMQ X message broker supports multi-node bridge mode interconnection + +.. code-block:: + + --------- --------- --------- + Publisher --> | Node1 | --Bridge Forward--> | Node2 | --Bridge Forward--> | Node3 | --> Subscriber + --------- --------- --------- + +In EMQ X, bridge is configured by modifying ``etc/emqx.conf``. EMQ X distinguishes between different bridges based on different names. E.g + +.. code-block:: + + ## Bridge address: node name for local bridge, host:port for remote. + bridge.mqtt.aws.address = 127.0.0.1:1883 + +This configuration declares a bridge named ``aws`` and specifies that it is bridged to the MQTT broker of 127.0.0.1:1883 by MQTT mode. + +In case of creating multiple bridges, it is convenient to replicate all configuration items of the first bridge, and modify the bridge name and other configuration items if necessary (such as bridge.$name.address, where $name refers to the name of bridge) + +The next two sections describe how to create a bridge in RPC and MQTT mode respectively and create a forwarding rule that forwards the messages from sensors. Assuming that two EMQ X nodes are running on two hosts: + +.. list-table:: + :header-rows: 1 + + * - Name + - Node + - MQTT Port + * - emqx1 + - emqx1@192.168.1.1. + - 1883 + * - emqx2 + - emqx2@192.168.1.2 + - 1883 + + +EMQ X RPC Bridge Configuration +------------------------------ + +The following is the basic configuration of RPC bridging. A simplest RPC bridging only requires the following three items + +.. code-block:: + + ## Bridge Address: Use node name (nodename@host) for rpc bridging, and host:port for mqtt connection + bridge.mqtt.emqx2.address = emqx2@192.168.1.2 + + ## Forwarding topics of the message + bridge.mqtt.emqx2.forwards = sensor1/#,sensor2/# + + ## bridged mountpoint + bridge.mqtt.emqx2.mountpoint = bridge/emqx2/${node}/ + +If the messages received by the local node emqx1 matches the topic ``sersor1/#`` or ``sensor2/#``\ , these messages will be forwarded to the ``sensor1/#`` or ``sensor2/#`` topic of the remote node emqx2. + +``forwards`` is used to specify topics. Messages of the in ``forwards`` specified topics on local node are forwarded to the remote node. + +``mountpoint`` is used to add a topic prefix when forwarding a message. To use ``mountpoint``\ , the ``forwards`` directive must be set. In the above example, a message with the topic ``sensor1/hello`` received by the local node will be forwarded to the remote node with the topic ``bridge/emqx2/emqx1@192.168.1.1/sensor1/hello``. + +Limitations of RPC bridging: + + +#. + The RPC bridge of emqx can only forward local messages to the remote node, and cannot synchronize the messages of the remote node to the local node; + +#. + RPC bridge can only bridge two EMQ X broker together and cannot bridge EMQ X broker to other MQTT brokers. + +EMQ X MQTT Bridge Configuration +------------------------------- + +EMQ X 3.0 officially introduced MQTT bridge, so that EMQ X can bridge any MQTT broker. Because of the characteristics of the MQTT protocol, EMQ X can subscribe to the remote mqtt broker's topic through MQTT bridge, and then synchronize the remote MQTT broker's message to the local. + +EMQ X MQTT bridging principle: Create an MQTT client on the EMQ X broker, and connect this MQTT client to the remote MQTT broker. Therefore, in the MQTT bridge configuration, following fields may be set for the EMQ X to connect to the remote broker as an mqtt client + +.. code-block:: + + ## Bridge Address: Use node name for rpc bridging, use host:port for mqtt connection + bridge.mqtt.emqx2.address = 192.168.1.2:1883 + + ## Bridged Protocol Version + ## Enumeration value: mqttv3 | mqttv4 | mqttv5 + bridge.mqtt.emqx2.proto_ver = mqttv4 + + ## mqtt client's clientid + bridge.mqtt.emqx2.clientid = bridge_emq + + ## mqtt client's clean_start field + ## Note: Some MQTT Brokers need to set the clean_start value as `true` + bridge.mqtt.emqx2.clean_start = true + + ## mqtt client's username field + bridge.mqtt.emqx2.username = user + + ## mqtt client's password field + bridge.mqtt.emqx2.password = passwd + + ## Whether the mqtt client uses ssl to connect to a remote serve or not + bridge.mqtt.emqx2.ssl = off + + ## CA Certificate of Client SSL Connection (PEM format) + bridge.mqtt.emqx2.cacertfile = etc/certs/cacert.pem + + ## SSL certificate of Client SSL connection + bridge.mqtt.emqx2.certfile = etc/certs/client-cert.pem + + ## Key file of Client SSL connection + bridge.mqtt.emqx2.keyfile = etc/certs/client-key.pem + + ## SSL encryption + bridge.mqtt.emqx2.ciphers = ECDHE-ECDSA-AES256-GCM-SHA384,ECDHE-RSA-AES256-GCM-SHA384 + + ## TTLS PSK password + ## Note 'listener.ssl.external.ciphers' and 'listener.ssl.external.psk_ciphers' cannot be configured at the same time + ## + ## See 'https://tools.ietf.org/html/rfc4279#section-2'. + ## bridge.mqtt.emqx2.psk_ciphers = PSK-AES128-CBC-SHA,PSK-AES256-CBC-SHA,PSK-3DES-EDE-CBC-SHA,PSK-RC4-SHA + + ## Client's heartbeat interval + bridge.mqtt.emqx2.keepalive = 60s + + ## Supported TLS version + bridge.mqtt.emqx2.tls_versions = tlsv1.2,tlsv1.1,tlsv1 + + ## Forwarding topics of the message + bridge.mqtt.emqx2.forwards = sensor1/#,sensor2/# + + ## Bridged mountpoint + bridge.mqtt.emqx2.mountpoint = bridge/emqx2/${node}/ + + ## Subscription topic for bridging + bridge.mqtt.emqx2.subscription.1.topic = cmd/topic1 + + ## Subscription qos for bridging + bridge.mqtt.emqx2.subscription.1.qos = 1 + + ## Subscription topic for bridging + bridge.mqtt.emqx2.subscription.2.topic = cmd/topic2 + + ## Subscription qos for bridging + bridge.mqtt.emqx2.subscription.2.qos = 1 + + ## Bridging reconnection interval + ## Default: 30s + bridge.mqtt.emqx2.reconnect_interval = 30s + + ## QoS1 message retransmission interval + bridge.mqtt.emqx2.retry_interval = 20s + + ## Inflight Size. + bridge.mqtt.emqx2.max_inflight_batches = 32 + +Bridge Cache Configuration +-------------------------- + +The bridge of EMQ X has a message caching mechanism. The caching mechanism is applicable to both RPC bridging and MQTT bridging. When the bridge is disconnected (such as when the network connection is unstable), the messages with a topic specified in ``forwards`` can be cached to the local message queue. Until the bridge is restored, these messages are re-forwarded to the remote node. The configuration of the cache queue is as follows + +.. code-block:: + + ## emqx_bridge internal number of messages used for batch + bridge.mqtt.emqx2.queue.batch_count_limit = 32 + + ## emqx_bridge internal number of message bytes used for batch + bridge.mqtt.emqx2.queue.batch_bytes_limit = 1000MB + + ## The path for placing replayq queue. If it is not specified, then replayq will run in `mem-only` mode and messages will not be cached on disk. + bridge.mqtt.emqx2.queue.replayq_dir = data/emqx_emqx2_bridge/ + + ## Replayq data segment size + bridge.mqtt.emqx2.queue.replayq_seg_bytes = 10MB + +``bridge.mqtt.emqx2.queue.replayq_dir`` is a configuration parameter for specifying the path of the bridge storage queue. + +``bridge.mqtt.emqx2.queue.replayq_seg_bytes`` is used to specify the size of the largest single file of the message queue that is cached on disk. If the message queue size exceeds the specified value, a new file is created to store the message queue. + +CLI for EMQ X Bridge MQTT +------------------------- + +CLI for EMQ X Bridge MQTT: + +.. code-block:: bash + + $ cd emqx1/ && ./bin/emqx_ctl bridges + bridges list # List bridges + bridges start # Start a bridge + bridges stop # Stop a bridge + bridges forwards # Show a bridge forward topic + bridges add-forward # Add bridge forward topic + bridges del-forward # Delete bridge forward topic + bridges subscriptions # Show a bridge subscriptions topic + bridges add-subscription # Add bridge subscriptions topic + +List all bridge states + +.. code-block:: bash + + $ ./bin/emqx_ctl bridges list + name: emqx status: Stopped $ ./bin/emqx_ctl bridges list + name: emqx status: Stopped + +Start the specified bridge + +.. code-block:: bash + + $ ./bin/emqx_ctl bridges start emqx + Start bridge successfully. + +Stop the specified bridge + +.. code-block:: bash + + $ ./bin/emqx_ctl bridges stop emqx + Stop bridge successfully. + +List the forwarding topics for the specified bridge + +.. code-block:: bash + + $ ./bin/emqx_ctl bridges forwards emqx + topic: topic1/# + topic: topic2/# + +Add a forwarding topic for the specified bridge + +.. code-block:: bash + + $ ./bin/emqx_ctl bridges add-forwards emqx topic3/# + Add-forward topic successfully. + +Delete the forwarding topic for the specified bridge + +.. code-block:: bash + + $ ./bin/emqx_ctl bridges del-forwards emqx topic3/# + Del-forward topic successfully. + +List subscriptions for the specified bridge + +.. code-block:: bash + + $ ./bin/emqx_ctl bridges subscriptions emqx + topic: cmd/topic1, qos: 1 + topic: cmd/topic2, qos: 1 + +Add a subscription topic for the specified bridge + +.. code-block:: bash + + $ ./bin/emqx_ctl bridges add-subscription emqx cmd/topic3 1 + Add-subscription topic successfully. + +Delete the subscription topic for the specified bridge + +.. code-block:: bash + + $ ./bin/emqx_ctl bridges del-subscription emqx cmd/topic3 + Del-subscription topic successfully. + +Note: In case of creating multiple bridges, it is convenient to replicate all configuration items of the first bridge, and modify the bridge name and other configuration items if necessary. + diff --git a/apps/emqx_bridge_mqtt/docs/images/bridge.png b/apps/emqx_bridge_mqtt/docs/images/bridge.png new file mode 100644 index 000000000..9bb9c024c Binary files /dev/null and b/apps/emqx_bridge_mqtt/docs/images/bridge.png differ diff --git a/apps/emqx_bridge_mqtt/include/emqx_bridge_mqtt.hrl b/apps/emqx_bridge_mqtt/include/emqx_bridge_mqtt.hrl new file mode 100644 index 000000000..4bc9ede14 --- /dev/null +++ b/apps/emqx_bridge_mqtt/include/emqx_bridge_mqtt.hrl @@ -0,0 +1,18 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-define(APP, emqx_bridge_mqtt). + diff --git a/apps/emqx_bridge_mqtt/priv/emqx_bridge_mqtt.schema b/apps/emqx_bridge_mqtt/priv/emqx_bridge_mqtt.schema new file mode 100644 index 000000000..9d5f3fe29 --- /dev/null +++ b/apps/emqx_bridge_mqtt/priv/emqx_bridge_mqtt.schema @@ -0,0 +1,242 @@ +%%-*- mode: erlang -*- +%%-------------------------------------------------------------------- +%% Bridges +%%-------------------------------------------------------------------- +{mapping, "bridge.mqtt.$name.address", "emqx_bridge_mqtt.bridges", [ + {datatype, string} +]}. + +{mapping, "bridge.mqtt.$name.proto_ver", "emqx_bridge_mqtt.bridges", [ + {datatype, {enum, [mqttv3, mqttv4, mqttv5]}} +]}. + +{mapping, "bridge.mqtt.$name.bridge_mode", "emqx_bridge_mqtt.bridges", [ + {default, false}, + {datatype, {enum, [true, false]}} +]}. + +{mapping, "bridge.mqtt.$name.start_type", "emqx_bridge_mqtt.bridges", [ + {datatype, {enum, [manual, auto]}}, + {default, auto} +]}. + +{mapping, "bridge.mqtt.$name.clientid", "emqx_bridge_mqtt.bridges", [ + {datatype, string} +]}. + +{mapping, "bridge.mqtt.$name.clean_start", "emqx_bridge_mqtt.bridges", [ + {default, true}, + {datatype, {enum, [true, false]}} +]}. + +{mapping, "bridge.mqtt.$name.username", "emqx_bridge_mqtt.bridges", [ + {datatype, string} +]}. + +{mapping, "bridge.mqtt.$name.password", "emqx_bridge_mqtt.bridges", [ + {datatype, string} +]}. + +{mapping, "bridge.mqtt.$name.forwards", "emqx_bridge_mqtt.bridges", [ + {datatype, string}, + {default, ""} +]}. + +{mapping, "bridge.mqtt.$name.forward_mountpoint", "emqx_bridge_mqtt.bridges", [ + {datatype, string} +]}. + +{mapping, "bridge.mqtt.$name.subscription.$id.topic", "emqx_bridge_mqtt.bridges", [ + {datatype, string} +]}. + +{mapping, "bridge.mqtt.$name.subscription.$id.qos", "emqx_bridge_mqtt.bridges", [ + {datatype, integer} +]}. + +{mapping, "bridge.mqtt.$name.receive_mountpoint", "emqx_bridge_mqtt.bridges", [ + {datatype, string} +]}. + +{mapping, "bridge.mqtt.$name.ssl", "emqx_bridge_mqtt.bridges", [ + {datatype, flag}, + {default, off} +]}. + +{mapping, "bridge.mqtt.$name.cacertfile", "emqx_bridge_mqtt.bridges", [ + {datatype, string} +]}. + +{mapping, "bridge.mqtt.$name.certfile", "emqx_bridge_mqtt.bridges", [ + {datatype, string} +]}. + +{mapping, "bridge.mqtt.$name.keyfile", "emqx_bridge_mqtt.bridges", [ + {datatype, string} +]}. + +{mapping, "bridge.mqtt.$name.ciphers", "emqx_bridge_mqtt.bridges", [ + {datatype, string} +]}. + +{mapping, "bridge.mqtt.$name.psk_ciphers", "emqx_bridge_mqtt.bridges", [ + {datatype, string} +]}. + +{mapping, "bridge.mqtt.$name.keepalive", "emqx_bridge_mqtt.bridges", [ + {default, "10s"}, + {datatype, {duration, s}} +]}. + +{mapping, "bridge.mqtt.$name.tls_versions", "emqx_bridge_mqtt.bridges", [ + {datatype, string}, + {default, "tlsv1,tlsv1.1,tlsv1.2"} +]}. + +{mapping, "bridge.mqtt.$name.reconnect_interval", "emqx_bridge_mqtt.bridges", [ + {default, "30s"}, + {datatype, {duration, ms}} +]}. + +{mapping, "bridge.mqtt.$name.retry_interval", "emqx_bridge_mqtt.bridges", [ + {default, "20s"}, + {datatype, {duration, ms}} +]}. + +{mapping, "bridge.mqtt.$name.max_inflight_size", "emqx_bridge_mqtt.bridges", [ + {default, 0}, + {datatype, integer} + ]}. + +{mapping, "bridge.mqtt.$name.batch_size", "emqx_bridge_mqtt.bridges", [ + {default, 0}, + {datatype, integer} +]}. + +{mapping, "bridge.mqtt.$name.queue.replayq_dir", "emqx_bridge_mqtt.bridges", [ + {datatype, string} +]}. + +{mapping, "bridge.mqtt.$name.queue.replayq_seg_bytes", "emqx_bridge_mqtt.bridges", [ + {datatype, bytesize} +]}. + +{mapping, "bridge.mqtt.$name.queue.max_total_size", "emqx_bridge_mqtt.bridges", [ + {datatype, bytesize} +]}. + +{translation, "emqx_bridge_mqtt.bridges", fun(Conf) -> + + MapPSKCiphers = fun(PSKCiphers) -> + lists:map( + fun("PSK-AES128-CBC-SHA") -> {psk, aes_128_cbc, sha}; + ("PSK-AES256-CBC-SHA") -> {psk, aes_256_cbc, sha}; + ("PSK-3DES-EDE-CBC-SHA") -> {psk, '3des_ede_cbc', sha}; + ("PSK-RC4-SHA") -> {psk, rc4_128, sha} + end, PSKCiphers) + end, + + Split = fun(undefined) -> undefined; (S) -> string:tokens(S, ",") end, + + IsSsl = fun(cacertfile) -> true; + (certfile) -> true; + (keyfile) -> true; + (ciphers) -> true; + (psk_ciphers) -> true; + (tls_versions) -> true; + (_Opt) -> false + end, + + Parse = fun(tls_versions, Vers) -> + [{versions, [list_to_atom(S) || S <- Split(Vers)]}]; + (ciphers, Ciphers) -> + [{ciphers, Split(Ciphers)}]; + (psk_ciphers, Ciphers) -> + [{ciphers, MapPSKCiphers(Split(Ciphers))}, {user_lookup_fun, {fun emqx_psk:lookup/3, <<>>}}]; + (Opt, Val) -> + [{Opt, Val}] + end, + + Merge = fun(forwards, Val, Opts) -> + [{forwards, string:tokens(Val, ",")}|Opts]; + (Opt, Val, Opts) -> + case IsSsl(Opt) of + true -> + SslOpts = Parse(Opt, Val) ++ proplists:get_value(ssl_opts, Opts, []), + lists:ukeymerge(1, [{ssl_opts, SslOpts}], lists:usort(Opts)); + false -> + [{Opt, Val}|Opts] + end + end, + Queue = fun(Name) -> + Configs = cuttlefish_variable:filter_by_prefix("bridge.mqtt." ++ Name ++ ".queue", Conf), + + QOpts = [{list_to_atom(QOpt), QValue}|| {[_, _, _, "queue", QOpt], QValue} <- Configs], + maps:from_list(QOpts) + end, + Subscriptions = fun(Name) -> + Configs = cuttlefish_variable:filter_by_prefix("bridge.mqtt." ++ Name ++ ".subscription", Conf), + lists:zip([Topic || {_, Topic} <- lists:sort([{I, Topic} || {[_, _, _, "subscription", I, "topic"], Topic} <- Configs])], + [QoS || {_, QoS} <- lists:sort([{I, QoS} || {[_, _, _, "subscription", I, "qos"], QoS} <- Configs])]) + end, + IsNodeAddr = fun(Addr) -> + case string:tokens(Addr, "@") of + [_NodeName, _Hostname] -> true; + _ -> false + end + end, + ConnMod = fun(Name) -> + + [AddrConfig] = cuttlefish_variable:filter_by_prefix("bridge.mqtt." ++ Name ++ ".address", Conf), + {_, Addr} = AddrConfig, + + Subs = Subscriptions(Name), + case IsNodeAddr(Addr) of + true when Subs =/= [] -> + error({"subscriptions are not supported when bridging between emqx nodes", Name, Subs}); + true -> + emqx_bridge_rpc; + false -> + emqx_bridge_mqtt + end + end, + + %% to be backward compatible + Translate = + fun Tr(queue, Q, Cfg) -> + NewQ = maps:fold(Tr, #{}, Q), + Cfg#{queue => NewQ}; + Tr(address, Addr0, Cfg) -> + Addr = case IsNodeAddr(Addr0) of + true -> list_to_atom(Addr0); + false -> Addr0 + end, + Cfg#{address => Addr}; + Tr(reconnect_interval, Ms, Cfg) -> + Cfg#{reconnect_delay_ms => Ms}; + Tr(proto_ver, Ver, Cfg) -> + Cfg#{proto_ver => + case Ver of + mqttv3 -> v3; + mqttv4 -> v4; + mqttv5 -> v5; + _ -> v4 + end}; + Tr(Key, Value, Cfg) -> + Cfg#{Key => Value} + end, + C = lists:foldl( + fun({["bridge", "mqtt", Name, Opt], Val}, Acc) -> + %% e.g #{aws => [{OptKey, OptVal}]} + Init = [{list_to_atom(Opt), Val}, + {connect_module, ConnMod(Name)}, + {subscriptions, Subscriptions(Name)}, + {queue, Queue(Name)}], + maps:update_with(list_to_atom(Name), fun(Opts) -> Merge(list_to_atom(Opt), Val, Opts) end, Init, Acc); + (_, Acc) -> Acc + end, #{}, lists:usort(cuttlefish_variable:filter_by_prefix("bridge.mqtt", Conf))), + C1 = maps:map(fun(Bn, Bc) -> + maps:to_list(maps:fold(Translate, #{}, maps:from_list(Bc))) + end, C), + maps:to_list(C1) +end}. diff --git a/apps/emqx_bridge_mqtt/rebar.config b/apps/emqx_bridge_mqtt/rebar.config new file mode 100644 index 000000000..7b1f06cca --- /dev/null +++ b/apps/emqx_bridge_mqtt/rebar.config @@ -0,0 +1 @@ +{deps, []}. \ No newline at end of file diff --git a/apps/emqx_bridge_mqtt/src/emqx_bridge_connect.erl b/apps/emqx_bridge_mqtt/src/emqx_bridge_connect.erl new file mode 100644 index 000000000..fedc2ceb2 --- /dev/null +++ b/apps/emqx_bridge_mqtt/src/emqx_bridge_connect.erl @@ -0,0 +1,74 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_bridge_connect). + +-export([start/2]). + +-export_type([config/0, connection/0]). + +-optional_callbacks([ensure_subscribed/3, ensure_unsubscribed/2]). + +%% map fields depend on implementation +-type(config() :: map()). +-type(connection() :: term()). +-type(batch() :: emqx_protal:batch()). +-type(ack_ref() :: emqx_bridge_worker:ack_ref()). +-type(topic() :: emqx_topic:topic()). +-type(qos() :: emqx_mqtt_types:qos()). + +-include_lib("emqx_libs/include/logger.hrl"). + +-logger_header("[Bridge Connect]"). + +%% establish the connection to remote node/cluster +%% protal worker (the caller process) should be expecting +%% a message {disconnected, conn_ref()} when disconnected. +-callback start(config()) -> {ok, connection()} | {error, any()}. + +%% send to remote node/cluster +%% bridge worker (the caller process) should be expecting +%% a message {batch_ack, reference()} when batch is acknowledged by remote node/cluster +-callback send(connection(), batch()) -> {ok, ack_ref()} | {ok, integer()} | {error, any()}. + +%% called when owner is shutting down. +-callback stop(connection()) -> ok. + +-callback ensure_subscribed(connection(), topic(), qos()) -> ok. + +-callback ensure_unsubscribed(connection(), topic()) -> ok. + +start(Module, Config) -> + case Module:start(Config) of + {ok, Conn} -> + {ok, Conn}; + {error, Reason} -> + Config1 = obfuscate(Config), + ?LOG(error, "Failed to connect with module=~p\n" + "config=~p\nreason:~p", [Module, Config1, Reason]), + {error, Reason} + end. + +obfuscate(Map) -> + maps:fold(fun(K, V, Acc) -> + case is_sensitive(K) of + true -> [{K, '***'} | Acc]; + false -> [{K, V} | Acc] + end + end, [], Map). + +is_sensitive(password) -> true; +is_sensitive(_) -> false. diff --git a/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt.app.src b/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt.app.src new file mode 100644 index 000000000..c8662b3fd --- /dev/null +++ b/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt.app.src @@ -0,0 +1,14 @@ +{application, emqx_bridge_mqtt, + [{description, "EMQ X Bridge to MQTT Broker"}, + {vsn, "5.0.0"}, % strict semver, bump manually! + {modules, []}, + {registered, []}, + {applications, [kernel,stdlib,replayq,emqtt,emqx_libs]}, + {mod, {emqx_bridge_mqtt_app, []}}, + {env, []}, + {licenses, ["Apache-2.0"]}, + {maintainers, ["EMQ X Team "]}, + {links, [{"Homepage", "https://emqx.io/"}, + {"Github", "https://github.com/emqx/emqx-bridge-mqtt"} + ]} + ]}. diff --git a/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt.erl b/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt.erl new file mode 100644 index 000000000..52762990c --- /dev/null +++ b/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt.erl @@ -0,0 +1,185 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +%% @doc This module implements EMQX Bridge transport layer on top of MQTT protocol + +-module(emqx_bridge_mqtt). + +-behaviour(emqx_bridge_connect). + +%% behaviour callbacks +-export([ start/1 + , send/2 + , stop/1 + ]). + +%% optional behaviour callbacks +-export([ ensure_subscribed/3 + , ensure_unsubscribed/2 + ]). + +-include_lib("emqx_libs/include/logger.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). + +-define(ACK_REF(ClientPid, PktId), {ClientPid, PktId}). + +%% Messages towards ack collector process +-define(REF_IDS(Ref, Ids), {Ref, Ids}). + +%%-------------------------------------------------------------------- +%% emqx_bridge_connect callbacks +%%-------------------------------------------------------------------- + +start(Config = #{address := Address}) -> + Parent = self(), + Mountpoint = maps:get(receive_mountpoint, Config, undefined), + Handlers = make_hdlr(Parent, Mountpoint), + {Host, Port} = case string:tokens(Address, ":") of + [H] -> {H, 1883}; + [H, P] -> {H, list_to_integer(P)} + end, + ClientConfig = Config#{msg_handler => Handlers, + host => Host, + port => Port, + force_ping => true + }, + case emqtt:start_link(replvar(ClientConfig)) of + {ok, Pid} -> + case emqtt:connect(Pid) of + {ok, _} -> + try + subscribe_remote_topics(Pid, maps:get(subscriptions, Config, [])), + {ok, #{client_pid => Pid}} + catch + throw : Reason -> + ok = stop(#{client_pid => Pid}), + {error, Reason} + end; + {error, Reason} -> + ok = stop(#{client_pid => Pid}), + {error, Reason} + end; + {error, Reason} -> + {error, Reason} + end. + +stop(#{client_pid := Pid}) -> + safe_stop(Pid, fun() -> emqtt:stop(Pid) end, 1000), + ok. + +ensure_subscribed(#{client_pid := Pid}, Topic, QoS) when is_pid(Pid) -> + case emqtt:subscribe(Pid, Topic, QoS) of + {ok, _, _} -> ok; + Error -> Error + end; +ensure_subscribed(_Conn, _Topic, _QoS) -> + %% return ok for now, next re-connect should should call start with new topic added to config + ok. + +ensure_unsubscribed(#{client_pid := Pid}, Topic) when is_pid(Pid) -> + case emqtt:unsubscribe(Pid, Topic) of + {ok, _, _} -> ok; + Error -> Error + end; +ensure_unsubscribed(_, _) -> + %% return ok for now, next re-connect should should call start with this topic deleted from config + ok. + +safe_stop(Pid, StopF, Timeout) -> + MRef = monitor(process, Pid), + unlink(Pid), + try + StopF() + catch + _ : _ -> + ok + end, + receive + {'DOWN', MRef, _, _, _} -> + ok + after + Timeout -> + exit(Pid, kill) + end. + +send(Conn, Msgs) -> + send(Conn, Msgs, undefined). +send(_Conn, [], PktId) -> + {ok, PktId}; +send(#{client_pid := ClientPid} = Conn, [Msg | Rest], _PktId) -> + case emqtt:publish(ClientPid, Msg) of + ok -> + Ref = make_ref(), + self() ! {batch_ack, Ref}, + send(Conn, Rest, Ref); + {ok, PktId} -> + send(Conn, Rest, PktId); + {error, Reason} -> + %% NOTE: There is no partial sucess of a batch and recover from the middle + %% only to retry all messages in one batch + {error, Reason} + end. + + +handle_puback(Parent, #{packet_id := PktId, reason_code := RC}) + when RC =:= ?RC_SUCCESS; + RC =:= ?RC_NO_MATCHING_SUBSCRIBERS -> + Parent ! {batch_ack, PktId}, ok; +handle_puback(_Parent, #{packet_id := PktId, reason_code := RC}) -> + ?LOG(warning, "Publish ~p to remote node falied, reason_code: ~p", [PktId, RC]). + +handle_publish(Msg, Mountpoint) -> + emqx_broker:publish(emqx_bridge_msg:to_broker_msg(Msg, Mountpoint)). + +handle_disconnected(Parent, Reason) -> + Parent ! {disconnected, self(), Reason}. + +make_hdlr(Parent, Mountpoint) -> + #{puback => fun(Ack) -> handle_puback(Parent, Ack) end, + publish => fun(Msg) -> handle_publish(Msg, Mountpoint) end, + disconnected => fun(Reason) -> handle_disconnected(Parent, Reason) end + }. + +subscribe_remote_topics(ClientPid, Subscriptions) -> + lists:foreach(fun({Topic, Qos}) -> + case emqtt:subscribe(ClientPid, Topic, Qos) of + {ok, _, _} -> ok; + Error -> throw(Error) + end + end, Subscriptions). + +%%-------------------------------------------------------------------- +%% Internal funcs +%%-------------------------------------------------------------------- + +replvar(Options) -> + replvar([clientid], Options). + +replvar([], Options) -> + Options; +replvar([Key|More], Options) -> + case maps:get(Key, Options, undefined) of + undefined -> + replvar(More, Options); + Val -> + replvar(More, maps:put(Key, feedvar(Key, Val, Options), Options)) + end. + +%% ${node} => node() +feedvar(clientid, ClientId, _) -> + iolist_to_binary(re:replace(ClientId, "\\${node}", atom_to_list(node()))); +feedvar(_, Val, _) -> + Val. diff --git a/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt_actions.erl b/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt_actions.erl new file mode 100644 index 000000000..bba790bbc --- /dev/null +++ b/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt_actions.erl @@ -0,0 +1,771 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +%% @doc This module implements EMQX Bridge transport layer on top of MQTT protocol + +-module(emqx_bridge_mqtt_actions). + +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). + +-import(emqx_rule_utils, [str/1]). + +-export([ on_resource_create/2 + , on_get_resource_status/2 + , on_resource_destroy/2 + ]). + +%% Callbacks of ecpool Worker +-export([connect/1]). + +-export([subscriptions/1]). + +-export([on_action_create_data_to_mqtt_broker/2]). + +-define(RESOURCE_TYPE_MQTT, 'bridge_mqtt'). +-define(RESOURCE_TYPE_MQTT_SUB, 'bridge_mqtt_sub'). +-define(RESOURCE_TYPE_RPC, 'bridge_rpc'). + +-define(RESOURCE_CONFIG_SPEC_MQTT, #{ + address => #{ + order => 1, + type => string, + required => true, + default => <<"127.0.0.1:1883">>, + title => #{en => <<" Broker Address">>, + zh => <<"远程 broker 地址"/utf8>>}, + description => #{en => <<"The MQTT Remote Address">>, + zh => <<"远程 MQTT Broker 的地址"/utf8>>} + }, + pool_size => #{ + order => 2, + type => number, + required => true, + default => 8, + title => #{en => <<"Pool Size">>, + zh => <<"连接池大小"/utf8>>}, + description => #{en => <<"MQTT Connection Pool Size">>, + zh => <<"连接池大小"/utf8>>} + }, + clientid => #{ + order => 3, + type => string, + required => true, + default => <<"client">>, + title => #{en => <<"ClientId">>, + zh => <<"客户端 Id"/utf8>>}, + description => #{en => <<"ClientId for connecting to remote MQTT broker">>, + zh => <<"连接远程 Broker 的 ClientId"/utf8>>} + }, + append => #{ + order => 4, + type => boolean, + required => false, + default => true, + title => #{en => <<"Append GUID">>, + zh => <<"附加 GUID"/utf8>>}, + description => #{en => <<"Append GUID to MQTT ClientId?">>, + zh => <<"是否将GUID附加到 MQTT ClientId 后"/utf8>>} + }, + username => #{ + order => 5, + type => string, + required => false, + default => <<"">>, + title => #{en => <<"Username">>, zh => <<"用户名"/utf8>>}, + description => #{en => <<"Username for connecting to remote MQTT Broker">>, + zh => <<"连接远程 Broker 的用户名"/utf8>>} + }, + password => #{ + order => 6, + type => string, + required => false, + default => <<"">>, + title => #{en => <<"Password">>, + zh => <<"密码"/utf8>>}, + description => #{en => <<"Password for connecting to remote MQTT Broker">>, + zh => <<"连接远程 Broker 的密码"/utf8>>} + }, + mountpoint => #{ + order => 7, + type => string, + required => false, + default => <<"bridge/aws/${node}/">>, + title => #{en => <<"Bridge MountPoint">>, + zh => <<"桥接挂载点"/utf8>>}, + description => #{ + en => <<"MountPoint for bridge topic:
" + "Example: The topic of messages sent to `topic1` on local node" + "will be transformed to `bridge/aws/${node}/topic1`">>, + zh => <<"桥接主题的挂载点:
" + "示例: 本地节点向 `topic1` 发消息,远程桥接节点的主题" + "会变换为 `bridge/aws/${node}/topic1`"/utf8>> + } + }, + disk_cache => #{ + order => 8, + type => string, + required => false, + default => <<"off">>, + enum => [<<"on">>, <<"off">>], + title => #{en => <<"Disk Cache">>, + zh => <<"磁盘缓存"/utf8>>}, + description => #{en => <<"The flag which determines whether messages" + "can be cached on local disk when bridge is" + "disconnected">>, + zh => <<"当桥接断开时用于控制是否将消息缓存到本地磁" + "盘队列上"/utf8>>} + }, + proto_ver => #{ + order => 9, + type => string, + required => false, + default => <<"mqttv4">>, + enum => [<<"mqttv3">>, <<"mqttv4">>, <<"mqttv5">>], + title => #{en => <<"Protocol Version">>, + zh => <<"协议版本"/utf8>>}, + description => #{en => <<"MQTTT Protocol version">>, + zh => <<"MQTT 协议版本"/utf8>>} + }, + keepalive => #{ + order => 10, + type => string, + required => false, + default => <<"60s">> , + title => #{en => <<"Keepalive">>, + zh => <<"心跳间隔"/utf8>>}, + description => #{en => <<"Keepalive">>, + zh => <<"心跳间隔"/utf8>>} + }, + reconnect_interval => #{ + order => 11, + type => string, + required => false, + default => <<"30s">>, + title => #{en => <<"Reconnect Interval">>, + zh => <<"重连间隔"/utf8>>}, + description => #{en => <<"Reconnect interval of bridge:
">>, + zh => <<"重连间隔"/utf8>>} + }, + retry_interval => #{ + order => 12, + type => string, + required => false, + default => <<"20s">>, + title => #{en => <<"Retry interval">>, + zh => <<"重传间隔"/utf8>>}, + description => #{en => <<"Retry interval for bridge QoS1 message delivering">>, + zh => <<"消息重传间隔"/utf8>>} + }, + bridge_mode => #{ + order => 13, + type => boolean, + required => false, + default => false, + title => #{en => <<"Bridge Mode">>, + zh => <<"桥接模式"/utf8>>}, + description => #{en => <<"Bridge mode for MQTT bridge connection">>, + zh => <<"MQTT 连接是否为桥接模式"/utf8>>} + }, + ssl => #{ + order => 14, + type => string, + required => false, + default => <<"off">>, + enum => [<<"on">>, <<"off">>], + title => #{en => <<"Bridge SSL">>, + zh => <<"Bridge SSL"/utf8>>}, + description => #{en => <<"Switch which used to enable ssl connection of the bridge">>, + zh => <<"是否启用 Bridge SSL 连接"/utf8>>} + }, + cacertfile => #{ + order => 15, + type => string, + required => false, + default => <<"etc/certs/cacert.pem">>, + title => #{en => <<"CA certificates">>, + zh => <<"CA 证书"/utf8>>}, + description => #{en => <<"The file path of the CA certificates">>, + zh => <<"CA 证书路径"/utf8>>} + }, + certfile => #{ + order => 16, + type => string, + required => false, + default => <<"etc/certs/client-cert.pem">>, + title => #{en => <<"SSL Certfile">>, + zh => <<"SSL 客户端证书"/utf8>>}, + description => #{en => <<"The file path of the client certfile">>, + zh => <<"客户端证书路径"/utf8>>} + }, + keyfile => #{ + order => 17, + type => string, + required => false, + default => <<"etc/certs/client-key.pem">>, + title => #{en => <<"SSL Keyfile">>, + zh => <<"SSL 密钥文件"/utf8>>}, + description => #{en => <<"The file path of the client keyfile">>, + zh => <<"客户端密钥路径"/utf8>>} + }, + ciphers => #{ + order => 18, + type => string, + required => false, + default => <<"ECDHE-ECDSA-AES256-GCM-SHA384,ECDHE-RSA-AES256-GCM-SHA384,", + "ECDHE-ECDSA-AES256-SHA384,ECDHE-RSA-AES256-SHA384,ECDHE-ECDSA-DES-CBC3-SHA,", + "ECDH-ECDSA-AES256-GCM-SHA384,ECDH-RSA-AES256-GCM-SHA384,ECDH-ECDSA-AES256-SHA384,", + "ECDH-RSA-AES256-SHA384,DHE-DSS-AES256-GCM-SHA384,DHE-DSS-AES256-SHA256,AES256-GCM-SHA384,", + "AES256-SHA256,ECDHE-ECDSA-AES128-GCM-SHA256,ECDHE-RSA-AES128-GCM-SHA256,", + "ECDHE-ECDSA-AES128-SHA256,ECDHE-RSA-AES128-SHA256,ECDH-ECDSA-AES128-GCM-SHA256,", + "ECDH-RSA-AES128-GCM-SHA256,ECDH-ECDSA-AES128-SHA256,ECDH-RSA-AES128-SHA256,", + "DHE-DSS-AES128-GCM-SHA256,DHE-DSS-AES128-SHA256,AES128-GCM-SHA256,AES128-SHA256,", + "ECDHE-ECDSA-AES256-SHA,ECDHE-RSA-AES256-SHA,DHE-DSS-AES256-SHA,ECDH-ECDSA-AES256-SHA,", + "ECDH-RSA-AES256-SHA,AES256-SHA,ECDHE-ECDSA-AES128-SHA,ECDHE-RSA-AES128-SHA,", + "DHE-DSS-AES128-SHA,ECDH-ECDSA-AES128-SHA,ECDH-RSA-AES128-SHA,AES128-SHA">>, + title => #{en => <<"SSL Ciphers">>, + zh => <<"SSL 加密算法"/utf8>>}, + description => #{en => <<"SSL Ciphers">>, + zh => <<"SSL 加密算法"/utf8>>} + } + }). + + +-define(RESOURCE_CONFIG_SPEC_MQTT_SUB, #{ + address => #{ + order => 1, + type => string, + required => true, + default => <<"127.0.0.1:1883">>, + title => #{en => <<" Broker Address">>, + zh => <<"远程 broker 地址"/utf8>>}, + description => #{en => <<"The MQTT Remote Address">>, + zh => <<"远程 MQTT Broker 的地址"/utf8>>} + }, + pool_size => #{ + order => 2, + type => number, + required => true, + default => 8, + title => #{en => <<"Pool Size">>, + zh => <<"连接池大小"/utf8>>}, + description => #{en => <<"MQTT Connection Pool Size">>, + zh => <<"连接池大小"/utf8>>} + }, + clientid => #{ + order => 3, + type => string, + required => true, + default => <<"client">>, + title => #{en => <<"ClientId">>, + zh => <<"客户端 Id"/utf8>>}, + description => #{en => <<"ClientId for connecting to remote MQTT broker">>, + zh => <<"连接远程 Broker 的 ClientId"/utf8>>} + }, + append => #{ + order => 4, + type => boolean, + required => true, + default => true, + title => #{en => <<"Append GUID">>, + zh => <<"附加 GUID"/utf8>>}, + description => #{en => <<"Append GUID to MQTT ClientId?">>, + zh => <<"是否将GUID附加到 MQTT ClientId 后"/utf8>>} + }, + username => #{ + order => 5, + type => string, + required => false, + default => <<"">>, + title => #{en => <<"Username">>, zh => <<"用户名"/utf8>>}, + description => #{en => <<"Username for connecting to remote MQTT Broker">>, + zh => <<"连接远程 Broker 的用户名"/utf8>>} + }, + password => #{ + order => 6, + type => string, + required => false, + default => <<"">>, + title => #{en => <<"Password">>, + zh => <<"密码"/utf8>>}, + description => #{en => <<"Password for connecting to remote MQTT Broker">>, + zh => <<"连接远程 Broker 的密码"/utf8>>} + }, + subscription_opts => #{ + order => 7, + type => array, + items => #{ + type => object, + schema => #{ + topic => #{ + order => 1, + type => string, + default => <<>>, + title => #{en => <<"MQTT Topic">>, + zh => <<"MQTT 主题"/utf8>>}, + description => #{en => <<"MQTT Topic">>, + zh => <<"MQTT 主题"/utf8>>} + }, + qos => #{ + order => 2, + type => number, + enum => [0, 1, 2], + default => 0, + title => #{en => <<"MQTT Topic QoS">>, + zh => <<"MQTT 服务质量"/utf8>>}, + description => #{en => <<"MQTT Topic QoS">>, + zh => <<"MQTT 服务质量"/utf8>>} + } + } + }, + default => [], + title => #{en => <<"Subscription Opts">>, + zh => <<"订阅选项"/utf8>>}, + description => #{en => <<"Subscription Opts">>, + zh => <<"订阅选项"/utf8>>} + }, + proto_ver => #{ + order => 8, + type => string, + required => false, + default => <<"mqttv4">>, + enum => [<<"mqttv3">>, <<"mqttv4">>, <<"mqttv5">>], + title => #{en => <<"Protocol Version">>, + zh => <<"协议版本"/utf8>>}, + description => #{en => <<"MQTTT Protocol version">>, + zh => <<"MQTT 协议版本"/utf8>>} + }, + keepalive => #{ + order => 9, + type => string, + required => false, + default => <<"60s">> , + title => #{en => <<"Keepalive">>, + zh => <<"心跳间隔"/utf8>>}, + description => #{en => <<"Keepalive">>, + zh => <<"心跳间隔"/utf8>>} + }, + reconnect_interval => #{ + order => 10, + type => string, + required => false, + default => <<"30s">>, + title => #{en => <<"Reconnect Interval">>, + zh => <<"重连间隔"/utf8>>}, + description => #{en => <<"Reconnect interval of bridge">>, + zh => <<"重连间隔"/utf8>>} + }, + ssl => #{ + order => 11, + type => string, + required => false, + default => <<"off">>, + enum => [<<"on">>, <<"off">>], + title => #{en => <<"Bridge SSL">>, + zh => <<"Bridge SSL"/utf8>>}, + description => #{en => <<"Switch which used to enable ssl connection of the bridge">>, + zh => <<"是否启用 Bridge SSL 连接"/utf8>>} + }, + cacertfile => #{ + order => 12, + type => string, + required => false, + default => <<"etc/certs/cacert.pem">>, + title => #{en => <<"CA certificates">>, + zh => <<"CA 证书"/utf8>>}, + description => #{en => <<"The file path of the CA certificates">>, + zh => <<"CA 证书路径"/utf8>>} + }, + certfile => #{ + order => 13, + type => string, + required => false, + default => <<"etc/certs/client-cert.pem">>, + title => #{en => <<"SSL Certfile">>, + zh => <<"SSL 客户端证书"/utf8>>}, + description => #{en => <<"The file path of the client certfile">>, + zh => <<"客户端证书路径"/utf8>>} + }, + keyfile => #{ + order => 14, + type => string, + required => false, + default => <<"etc/certs/client-key.pem">>, + title => #{en => <<"SSL Keyfile">>, + zh => <<"SSL 密钥文件"/utf8>>}, + description => #{en => <<"The file path of the client keyfile">>, + zh => <<"客户端密钥路径"/utf8>>} + }, + ciphers => #{ + order => 15, + type => string, + required => false, + default => <<"ECDHE-ECDSA-AES256-GCM-SHA384,ECDHE-RSA-AES256-GCM-SHA384">>, + title => #{en => <<"SSL Ciphers">>, + zh => <<"SSL 加密算法"/utf8>>}, + description => #{en => <<"SSL Ciphers">>, + zh => <<"SSL 加密算法"/utf8>>} + } + }). + + +-define(RESOURCE_CONFIG_SPEC_RPC, #{ + address => #{ + order => 1, + type => string, + required => true, + default => <<"emqx2@127.0.0.1">>, + title => #{en => <<"EMQ X Node Name">>, + zh => <<"EMQ X 节点名称"/utf8>>}, + description => #{en => <<"EMQ X Remote Node Name">>, + zh => <<"远程 EMQ X 节点名称 "/utf8>>} + }, + mountpoint => #{ + order => 2, + type => string, + required => false, + default => <<"bridge/emqx/${node}/">>, + title => #{en => <<"Bridge MountPoint">>, + zh => <<"桥接挂载点"/utf8>>}, + description => #{en => <<"MountPoint for bridge topic
" + "Example: The topic of messages sent to `topic1` on local node" + "will be transformed to `bridge/aws/${node}/topic1`">>, + zh => <<"桥接主题的挂载点
" + "示例: 本地节点向 `topic1` 发消息,远程桥接节点的主题" + "会变换为 `bridge/aws/${node}/topic1`"/utf8>>} + }, + pool_size => #{ + order => 3, + type => number, + required => true, + default => 8, + title => #{en => <<"Pool Size">>, + zh => <<"连接池大小"/utf8>>}, + description => #{en => <<"MQTT/RPC Connection Pool Size">>, + zh => <<"连接池大小"/utf8>>} + }, + reconnect_interval => #{ + order => 4, + type => string, + required => false, + default => <<"30s">>, + title => #{en => <<"Reconnect Interval">>, + zh => <<"重连间隔"/utf8>>}, + description => #{en => <<"Reconnect Interval of bridge">>, + zh => <<"重连间隔"/utf8>>} + }, + batch_size => #{ + order => 5, + type => number, + required => false, + default => 32, + title => #{en => <<"Batch Size">>, + zh => <<"批处理大小"/utf8>>}, + description => #{en => <<"Batch Size">>, + zh => <<"批处理大小"/utf8>>} + }, + disk_cache => #{ + order => 6, + type => string, + required => false, + default => <<"off">>, + enum => [<<"on">>, <<"off">>], + title => #{en => <<"Disk Cache">>, + zh => <<"磁盘缓存"/utf8>>}, + description => #{en => <<"The flag which determines whether messages" + "can be cached on local disk when bridge is" + "disconnected">>, + zh => <<"当桥接断开时用于控制是否将消息缓存到本地磁" + "盘队列上"/utf8>>} + } + }). + +-define(ACTION_PARAM_RESOURCE, #{ + type => string, + required => true, + title => #{en => <<"Resource ID">>, zh => <<"资源 ID"/utf8>>}, + description => #{en => <<"Bind a resource to this action">>, + zh => <<"给动作绑定一个资源"/utf8>>} + }). + +-resource_type(#{ + name => ?RESOURCE_TYPE_MQTT, + create => on_resource_create, + status => on_get_resource_status, + destroy => on_resource_destroy, + params => ?RESOURCE_CONFIG_SPEC_MQTT, + title => #{en => <<"MQTT Bridge">>, zh => <<"MQTT Bridge"/utf8>>}, + description => #{en => <<"MQTT Message Bridge">>, zh => <<"MQTT 消息桥接"/utf8>>} + }). + +-resource_type(#{ + name => ?RESOURCE_TYPE_MQTT_SUB, + create => on_resource_create, + status => on_get_resource_status, + destroy => on_resource_destroy, + params => ?RESOURCE_CONFIG_SPEC_MQTT_SUB, + title => #{en => <<"MQTT Subscribe">>, zh => <<"MQTT Subscribe"/utf8>>}, + description => #{en => <<"MQTT Subscribe">>, zh => <<"MQTT 订阅消息"/utf8>>} + }). + +-resource_type(#{ + name => ?RESOURCE_TYPE_RPC, + create => on_resource_create, + status => on_get_resource_status, + destroy => on_resource_destroy, + params => ?RESOURCE_CONFIG_SPEC_RPC, + title => #{en => <<"EMQX Bridge">>, zh => <<"EMQX Bridge"/utf8>>}, + description => #{en => <<"EMQ X RPC Bridge">>, zh => <<"EMQ X RPC 消息桥接"/utf8>>} + }). + +-rule_action(#{ + name => data_to_mqtt_broker, + category => data_forward, + for => 'message.publish', + types => [?RESOURCE_TYPE_MQTT, ?RESOURCE_TYPE_RPC], + create => on_action_create_data_to_mqtt_broker, + params => #{'$resource' => ?ACTION_PARAM_RESOURCE, + forward_topic => #{ + order => 1, + type => string, + required => false, + default => <<"">>, + title => #{en => <<"Forward Topic">>, + zh => <<"转发消息主题"/utf8>>}, + description => #{en => <<"The topic used when forwarding the message. Defaults to the topic of the bridge message if not provided.">>, + zh => <<"转发消息时使用的主题。如果未提供,则默认为桥接消息的主题。"/utf8>>} + }, + payload_tmpl => #{ + order => 2, + type => string, + input => textarea, + required => false, + default => <<"">>, + title => #{en => <<"Payload Template">>, + zh => <<"消息内容模板"/utf8>>}, + description => #{en => <<"The payload template, variable interpolation is supported. If using empty template (default), then the payload will be all the available vars in JOSN format">>, + zh => <<"消息内容模板,支持变量。若使用空模板(默认),消息内容为 JSON 格式的所有字段"/utf8>>} + } + }, + title => #{en => <<"Data bridge to MQTT Broker">>, + zh => <<"桥接数据到 MQTT Broker"/utf8>>}, + description => #{en => <<"Bridge Data to MQTT Broker">>, + zh => <<"桥接数据到 MQTT Broker"/utf8>>} + }). + +on_resource_create(ResId, Params) -> + ?LOG(info, "Initiating Resource ~p, ResId: ~p", [?RESOURCE_TYPE_MQTT, ResId]), + {ok, _} = application:ensure_all_started(ecpool), + PoolName = pool_name(ResId), + Options = options(Params, PoolName), + start_resource(ResId, PoolName, Options), + case test_resource_status(PoolName) of + true -> ok; + false -> + on_resource_destroy(ResId, #{<<"pool">> => PoolName}), + error({{?RESOURCE_TYPE_MQTT, ResId}, connection_failed}) + end, + #{<<"pool">> => PoolName}. + +start_resource(ResId, PoolName, Options) -> + case ecpool:start_sup_pool(PoolName, ?MODULE, Options) of + {ok, _} -> + ?LOG(info, "Initiated Resource ~p Successfully, ResId: ~p", [?RESOURCE_TYPE_MQTT, ResId]); + {error, {already_started, _Pid}} -> + on_resource_destroy(ResId, #{<<"pool">> => PoolName}), + start_resource(ResId, PoolName, Options); + {error, Reason} -> + ?LOG(error, "Initiate Resource ~p failed, ResId: ~p, ~p", [?RESOURCE_TYPE_MQTT, ResId, Reason]), + on_resource_destroy(ResId, #{<<"pool">> => PoolName}), + error({{?RESOURCE_TYPE_MQTT, ResId}, create_failed}) + end. + +test_resource_status(PoolName) -> + IsConnected = fun(Worker) -> + case ecpool_worker:client(Worker) of + {ok, Bridge} -> + try emqx_bridge_worker:status(Bridge) of + connected -> true; + _ -> false + catch _Error:_Reason -> + false + end; + {error, _} -> + false + end + end, + Status = [IsConnected(Worker) || {_WorkerName, Worker} <- ecpool:workers(PoolName)], + lists:any(fun(St) -> St =:= true end, Status). + +-spec(on_get_resource_status(ResId::binary(), Params::map()) -> Status::map()). +on_get_resource_status(_ResId, #{<<"pool">> := PoolName}) -> + IsAlive = test_resource_status(PoolName), + #{is_alive => IsAlive}. + +on_resource_destroy(ResId, #{<<"pool">> := PoolName}) -> + ?LOG(info, "Destroying Resource ~p, ResId: ~p", [?RESOURCE_TYPE_MQTT, ResId]), + case ecpool:stop_sup_pool(PoolName) of + ok -> + ?LOG(info, "Destroyed Resource ~p Successfully, ResId: ~p", [?RESOURCE_TYPE_MQTT, ResId]); + {error, Reason} -> + ?LOG(error, "Destroy Resource ~p failed, ResId: ~p, ~p", [?RESOURCE_TYPE_MQTT, ResId, Reason]), + error({{?RESOURCE_TYPE_MQTT, ResId}, destroy_failed}) + end. + +on_action_create_data_to_mqtt_broker(_Id, #{<<"pool">> := PoolName, + <<"forward_topic">> := ForwardTopic, + <<"payload_tmpl">> := PayloadTmpl}) -> + ?LOG(info, "Initiating Action ~p.", [?FUNCTION_NAME]), + PayloadTks = emqx_rule_utils:preproc_tmpl(PayloadTmpl), + TopicTks = case ForwardTopic == <<"">> of + true -> undefined; + false -> emqx_rule_utils:preproc_tmpl(ForwardTopic) + end, + fun(Msg, _Env = #{id := Id, clientid := From, flags := Flags, + topic := Topic, timestamp := TimeStamp, qos := QoS}) -> + Topic1 = case TopicTks =:= undefined of + true -> Topic; + false -> emqx_rule_utils:proc_tmpl(TopicTks, Msg) + end, + BrokerMsg = #message{id = Id, + qos = QoS, + from = From, + flags = Flags, + topic = Topic1, + payload = format_data(PayloadTks, Msg), + timestamp = TimeStamp}, + ecpool:with_client(PoolName, fun(BridgePid) -> + BridgePid ! {deliver, rule_engine, BrokerMsg} + end) + end. + +format_data([], Msg) -> + emqx_json:encode(Msg); + +format_data(Tokens, Msg) -> + emqx_rule_utils:proc_tmpl(Tokens, Msg). + +tls_versions() -> + ['tlsv1.2','tlsv1.1', tlsv1]. + +ciphers(Ciphers) -> + string:tokens(str(Ciphers), ", "). + +subscriptions(Subscriptions) -> + scan_binary(<<"[", Subscriptions/binary, "].">>). + +is_node_addr(Addr0) -> + Addr = binary_to_list(Addr0), + case string:tokens(Addr, "@") of + [_NodeName, _Hostname] -> true; + _ -> false + end. + +scan_binary(Bin) -> + TermString = binary_to_list(Bin), + scan_string(TermString). + +scan_string(TermString) -> + {ok, Tokens, _} = erl_scan:string(TermString), + {ok, Term} = erl_parse:parse_term(Tokens), + Term. + +connect(Options) when is_list(Options) -> + connect(maps:from_list(Options)); +connect(Options = #{disk_cache := DiskCache, ecpool_worker_id := Id, pool_name := Pool}) -> + Options0 = case DiskCache of + true -> + DataDir = filename:join([emqx:get_env(data_dir), replayq, Pool, integer_to_list(Id)]), + QueueOption = #{replayq_dir => DataDir}, + Options#{queue => QueueOption}; + false -> + Options + end, + Options1 = case maps:is_key(append, Options0) of + false -> Options0; + true -> + case maps:get(append, Options0, false) of + true -> + ClientId = lists:concat([str(maps:get(clientid, Options0)), "_", str(emqx_guid:to_hexstr(emqx_guid:gen()))]), + Options0#{clientid => ClientId}; + false -> + Options0 + end + end, + Options2 = maps:without([ecpool_worker_id, pool_name, append], Options1), + emqx_bridge_worker:start_link(name(Pool, Id), Options2). +name(Pool, Id) -> + list_to_atom(atom_to_list(Pool) ++ ":" ++ integer_to_list(Id)). +pool_name(ResId) -> + list_to_atom("bridge_mqtt:" ++ str(ResId)). + +options(Options, PoolName) -> + GetD = fun(Key, Default) -> maps:get(Key, Options, Default) end, + Get = fun(Key) -> GetD(Key, undefined) end, + Address = Get(<<"address">>), + [{max_inflight_batches, 32}, + {forward_mountpoint, str(Get(<<"mountpoint">>))}, + {disk_cache, cuttlefish_flag:parse(str(GetD(<<"disk_cache">>, "off")))}, + {start_type, auto}, + {reconnect_delay_ms, cuttlefish_duration:parse(str(Get(<<"reconnect_interval">>)), ms)}, + {if_record_metrics, false}, + {pool_size, GetD(<<"pool_size">>, 1)}, + {pool_name, PoolName} + ] ++ case is_node_addr(Address) of + true -> + [{address, binary_to_atom(Get(<<"address">>), utf8)}, + {connect_module, emqx_bridge_rpc}, + {batch_size, Get(<<"batch_size">>)}]; + false -> + Subscriptions = format_subscriptions(GetD(<<"subscription_opts">>, [])), + Subscriptions1 = case Get(<<"topic">>) of + undefined -> Subscriptions; + Topic -> + [{subscriptions, [{Topic, Get(<<"qos">>)}]} | Subscriptions] + end, + [{address, binary_to_list(Address)}, + {bridge_mode, GetD(<<"bridge_mode">>, true)}, + {clean_start, true}, + {clientid, str(Get(<<"clientid">>))}, + {append, Get(<<"append">>)}, + {connect_module, emqx_bridge_mqtt}, + {keepalive, cuttlefish_duration:parse(str(Get(<<"keepalive">>)), s)}, + {username, str(Get(<<"username">>))}, + {password, str(Get(<<"password">>))}, + {proto_ver, mqtt_ver(Get(<<"proto_ver">>))}, + {retry_interval, cuttlefish_duration:parse(str(GetD(<<"retry_interval">>, "30s")), ms)}, + {ssl, cuttlefish_flag:parse(str(Get(<<"ssl">>)))}, + {ssl_opts, [{versions, tls_versions()}, + {ciphers, ciphers(Get(<<"ciphers">>))}, + {keyfile, str(Get(<<"keyfile">>))}, + {certfile, str(Get(<<"certfile">>))}, + {cacertfile, str(Get(<<"cacertfile">>))} + ]}] ++ Subscriptions1 + end. + + +mqtt_ver(ProtoVer) -> + case ProtoVer of + <<"mqttv3">> -> v3; + <<"mqttv4">> -> v4; + <<"mqttv5">> -> v5; + _ -> v4 + end. + +format_subscriptions(SubOpts) -> + lists:map(fun(Sub) -> + {maps:get(<<"topic">>, Sub), maps:get(<<"qos">>, Sub)} + end, SubOpts). diff --git a/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt_app.erl b/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt_app.erl new file mode 100644 index 000000000..2c0a0b9a9 --- /dev/null +++ b/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt_app.erl @@ -0,0 +1,33 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_bridge_mqtt_app). + +-emqx_plugin(bridge). + +-behaviour(application). + +-export([start/2, stop/1]). + +start(_StartType, _StartArgs) -> + emqx_ctl:register_command(bridges, {emqx_bridge_mqtt_cli, cli}, []), + emqx_bridge_worker:register_metrics(), + emqx_bridge_mqtt_sup:start_link(). + +stop(_State) -> + emqx_ctl:unregister_command(bridges), + ok. + diff --git a/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt_cli.erl b/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt_cli.erl new file mode 100644 index 000000000..1ee5a90c6 --- /dev/null +++ b/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt_cli.erl @@ -0,0 +1,98 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_bridge_mqtt_cli). + +-include("emqx_bridge_mqtt.hrl"). + +-import(lists, [foreach/2]). + +-export([cli/1]). + +cli(["list"]) -> + foreach(fun({Name, State0}) -> + State = case State0 of + connected -> <<"Running">>; + _ -> <<"Stopped">> + end, + emqx_ctl:print("name: ~s status: ~s~n", [Name, State]) + end, emqx_bridge_mqtt_sup:bridges()); + +cli(["start", Name]) -> + emqx_ctl:print("~s.~n", [try emqx_bridge_worker:ensure_started(Name) of + ok -> <<"Start bridge successfully">>; + connected -> <<"Bridge already started">>; + _ -> <<"Start bridge failed">> + catch + _Error:_Reason -> + <<"Start bridge failed">> + end]); + +cli(["stop", Name]) -> + emqx_ctl:print("~s.~n", [try emqx_bridge_worker:ensure_stopped(Name) of + ok -> <<"Stop bridge successfully">>; + _ -> <<"Stop bridge failed">> + catch + _Error:_Reason -> + <<"Stop bridge failed">> + end]); + +cli(["forwards", Name]) -> + foreach(fun(Topic) -> + emqx_ctl:print("topic: ~s~n", [Topic]) + end, emqx_bridge_worker:get_forwards(Name)); + +cli(["add-forward", Name, Topic]) -> + case emqx_bridge_worker:ensure_forward_present(Name, iolist_to_binary(Topic)) of + ok -> emqx_ctl:print("Add-forward topic successfully.~n"); + {error, Reason} -> emqx_ctl:print("Add-forward failed reason: ~p.~n", [Reason]) + end; + +cli(["del-forward", Name, Topic]) -> + case emqx_bridge_worker:ensure_forward_absent(Name, iolist_to_binary(Topic)) of + ok -> emqx_ctl:print("Del-forward topic successfully.~n"); + {error, Reason} -> emqx_ctl:print("Del-forward failed reason: ~p.~n", [Reason]) + end; + +cli(["subscriptions", Name]) -> + foreach(fun({Topic, Qos}) -> + emqx_ctl:print("topic: ~s, qos: ~p~n", [Topic, Qos]) + end, emqx_bridge_worker:get_subscriptions(Name)); + +cli(["add-subscription", Name, Topic, Qos]) -> + case emqx_bridge_worker:ensure_subscription_present(Name, Topic, list_to_integer(Qos)) of + ok -> emqx_ctl:print("Add-subscription topic successfully.~n"); + {error, Reason} -> emqx_ctl:print("Add-subscription failed reason: ~p.~n", [Reason]) + end; + +cli(["del-subscription", Name, Topic]) -> + case emqx_bridge_worker:ensure_subscription_absent(Name, Topic) of + ok -> emqx_ctl:print("Del-subscription topic successfully.~n"); + {error, Reason} -> emqx_ctl:print("Del-subscription failed reason: ~p.~n", [Reason]) + end; + +cli(_) -> + emqx_ctl:usage([{"bridges list", "List bridges"}, + {"bridges start ", "Start a bridge"}, + {"bridges stop ", "Stop a bridge"}, + {"bridges forwards ", "Show a bridge forward topic"}, + {"bridges add-forward ", "Add bridge forward topic"}, + {"bridges del-forward ", "Delete bridge forward topic"}, + {"bridges subscriptions ", "Show a bridge subscriptions topic"}, + {"bridges add-subscription ", "Add bridge subscriptions topic"}, + {"bridges del-subscription ", "Delete bridge subscriptions topic"}]). + + diff --git a/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt_sup.erl b/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt_sup.erl new file mode 100644 index 000000000..e549b43ce --- /dev/null +++ b/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt_sup.erl @@ -0,0 +1,84 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_bridge_mqtt_sup). +-behaviour(supervisor). + +-include("emqx_bridge_mqtt.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). + +-logger_header("[Bridge]"). + +%% APIs +-export([ start_link/0 + , start_link/1 + ]). + +-export([ create_bridge/2 + , drop_bridge/1 + , bridges/0 + , is_bridge_exist/1 + ]). + +%% supervisor callbacks +-export([init/1]). + +-define(SUP, ?MODULE). +-define(WORKER_SUP, emqx_bridge_worker_sup). + +start_link() -> start_link(?SUP). + +start_link(Name) -> + supervisor:start_link({local, Name}, ?MODULE, Name). + +init(?SUP) -> + BridgesConf = application:get_env(?APP, bridges, []), + BridgeSpec = lists:map(fun bridge_spec/1, BridgesConf), + SupFlag = #{strategy => one_for_one, + intensity => 100, + period => 10}, + {ok, {SupFlag, BridgeSpec}}. + +bridge_spec({Name, Config}) -> + #{id => Name, + start => {emqx_bridge_worker, start_link, [Name, Config]}, + restart => permanent, + shutdown => 5000, + type => worker, + modules => [emqx_bridge_worker]}. + +-spec(bridges() -> [{node(), map()}]). +bridges() -> + [{Name, emqx_bridge_worker:status(Pid)} || {Name, Pid, _, _} <- supervisor:which_children(?SUP)]. + +-spec(is_bridge_exist(atom() | pid()) -> boolean()). +is_bridge_exist(Id) -> + case supervisor:get_childspec(?SUP, Id) of + {ok, _ChildSpec} -> true; + {error, _Error} -> false + end. + +create_bridge(Id, Config) -> + supervisor:start_child(?SUP, bridge_spec({Id, Config})). + +drop_bridge(Id) -> + case supervisor:terminate_child(?SUP, Id) of + ok -> + supervisor:delete_child(?SUP, Id); + {error, Error} -> + ?LOG(error, "Delete bridge failed, error : ~p", [Error]), + {error, Error} + end. diff --git a/apps/emqx_bridge_mqtt/src/emqx_bridge_msg.erl b/apps/emqx_bridge_mqtt/src/emqx_bridge_msg.erl new file mode 100644 index 000000000..dca69d3df --- /dev/null +++ b/apps/emqx_bridge_mqtt/src/emqx_bridge_msg.erl @@ -0,0 +1,98 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_bridge_msg). + +-export([ to_binary/1 + , from_binary/1 + , to_export/3 + , to_broker_msgs/1 + , to_broker_msg/1 + , to_broker_msg/2 + , estimate_size/1 + ]). + +-export_type([msg/0]). + +-include_lib("emqx_libs/include/emqx.hrl"). + +-include_lib("emqx_bridge_mqtt/include/emqx_bridge_mqtt.hrl"). +-include_lib("emqtt/include/emqtt.hrl"). + + +-type msg() :: emqx_types:message(). +-type exp_msg() :: emqx_types:message() | #mqtt_msg{}. + +%% @doc Make export format: +%% 1. Mount topic to a prefix +%% 2. Fix QoS to 1 +%% @end +%% Shame that we have to know the callback module here +%% would be great if we can get rid of #mqtt_msg{} record +%% and use #message{} in all places. +-spec to_export(emqx_bridge_rpc | emqx_bridge_worker, + undefined | binary(), msg()) -> exp_msg(). +to_export(emqx_bridge_mqtt, Mountpoint, + #message{topic = Topic, + payload = Payload, + flags = Flags, + qos = QoS + }) -> + Retain = maps:get(retain, Flags, false), + #mqtt_msg{qos = QoS, + retain = Retain, + topic = topic(Mountpoint, Topic), + payload = Payload}; +to_export(_Module, Mountpoint, + #message{topic = Topic} = Msg) -> + Msg#message{topic = topic(Mountpoint, Topic)}. + +%% @doc Make `binary()' in order to make iodata to be persisted on disk. +-spec to_binary(msg()) -> binary(). +to_binary(Msg) -> term_to_binary(Msg). + +%% @doc Unmarshal binary into `msg()'. +-spec from_binary(binary()) -> msg(). +from_binary(Bin) -> binary_to_term(Bin). + +%% @doc Estimate the size of a message. +%% Count only the topic length + payload size +-spec estimate_size(msg()) -> integer(). +estimate_size(#message{topic = Topic, payload = Payload}) -> + size(Topic) + size(Payload). + +%% @doc By message/batch receiver, transform received batch into +%% messages to deliver to local brokers. +to_broker_msgs(Batch) -> lists:map(fun to_broker_msg/1, Batch). + +to_broker_msg(#message{} = Msg) -> + %% internal format from another EMQX node via rpc + Msg; +to_broker_msg(Msg) -> + to_broker_msg(Msg, undefined). +to_broker_msg(#{qos := QoS, dup := Dup, retain := Retain, topic := Topic, + properties := Props, payload := Payload}, Mountpoint) -> + %% published from remote node over a MQTT connection + set_headers(Props, + emqx_message:set_flags(#{dup => Dup, retain => Retain}, + emqx_message:make(bridge, QoS, topic(Mountpoint, Topic), Payload))). + +set_headers(undefined, Msg) -> + Msg; +set_headers(Val, Msg) -> + emqx_message:set_headers(Val, Msg). +topic(undefined, Topic) -> Topic; +topic(Prefix, Topic) -> emqx_topic:prepend(Prefix, Topic). diff --git a/apps/emqx_bridge_mqtt/src/emqx_bridge_rpc.erl b/apps/emqx_bridge_mqtt/src/emqx_bridge_rpc.erl new file mode 100644 index 000000000..92ef0c60a --- /dev/null +++ b/apps/emqx_bridge_mqtt/src/emqx_bridge_rpc.erl @@ -0,0 +1,99 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +%% @doc This module implements EMQX Bridge transport layer based on gen_rpc. + +-module(emqx_bridge_rpc). + +-behaviour(emqx_bridge_connect). + +%% behaviour callbacks +-export([ start/1 + , send/2 + , stop/1 + ]). + +%% Internal exports +-export([ handle_send/1 + , heartbeat/2 + ]). + +-type ack_ref() :: emqx_bridge_worker:ack_ref(). +-type batch() :: emqx_bridge_worker:batch(). + +-define(HEARTBEAT_INTERVAL, timer:seconds(1)). + +-define(RPC, emqx_rpc). + +start(#{address := Remote}) -> + case poke(Remote) of + ok -> + Pid = proc_lib:spawn_link(?MODULE, heartbeat, [self(), Remote]), + {ok, #{client_pid => Pid, address => Remote}}; + Error -> + Error + end. + +stop(#{client_pid := Pid}) when is_pid(Pid) -> + Ref = erlang:monitor(process, Pid), + unlink(Pid), + Pid ! stop, + receive + {'DOWN', Ref, process, Pid, _Reason} -> + ok + after + 1000 -> + exit(Pid, kill) + end, + ok. + +%% @doc Callback for `emqx_bridge_connect' behaviour +-spec send(node(), batch()) -> {ok, ack_ref()} | {error, any()}. +send(#{address := Remote}, Batch) -> + case ?RPC:call(Remote, ?MODULE, handle_send, [Batch]) of + ok -> + Ref = make_ref(), + self() ! {batch_ack, Ref}, + {ok, Ref}; + {badrpc, Reason} -> {error, Reason} + end. + +%% @doc Handle send on receiver side. +-spec handle_send(batch()) -> ok. +handle_send(Batch) -> + lists:foreach(fun(Msg) -> emqx_broker:publish(Msg) end, Batch). + +%% @hidden Heartbeat loop +heartbeat(Parent, RemoteNode) -> + Interval = ?HEARTBEAT_INTERVAL, + receive + stop -> exit(normal) + after + Interval -> + case poke(RemoteNode) of + ok -> + ?MODULE:heartbeat(Parent, RemoteNode); + {error, Reason} -> + Parent ! {disconnected, self(), Reason}, + exit(normal) + end + end. + +poke(Node) -> + case ?RPC:call(Node, erlang, node, []) of + Node -> ok; + {badrpc, Reason} -> {error, Reason} + end. diff --git a/apps/emqx_bridge_mqtt/src/emqx_bridge_worker.erl b/apps/emqx_bridge_mqtt/src/emqx_bridge_worker.erl new file mode 100644 index 000000000..57bd04d25 --- /dev/null +++ b/apps/emqx_bridge_mqtt/src/emqx_bridge_worker.erl @@ -0,0 +1,595 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +%% @doc Bridge works in two layers (1) batching layer (2) transport layer +%% The `bridge' batching layer collects local messages in batches and sends over +%% to remote MQTT node/cluster via `connetion' transport layer. +%% In case `REMOTE' is also an EMQX node, `connection' is recommended to be +%% the `gen_rpc' based implementation `emqx_bridge_rpc'. Otherwise `connection' +%% has to be `emqx_bridge_mqtt'. +%% +%% ``` +%% +------+ +--------+ +%% | EMQX | | REMOTE | +%% | | | | +%% | (bridge) <==(connection)==> | | +%% | | | | +%% | | | | +%% +------+ +--------+ +%% ''' +%% +%% +%% This module implements 2 kinds of APIs with regards to batching and +%% messaging protocol. (1) A `gen_statem' based local batch collector; +%% (2) APIs for incoming remote batches/messages. +%% +%% Batch collector state diagram +%% +%% [idle] --(0) --> [connecting] --(2)--> [connected] +%% | ^ | +%% | | | +%% '--(1)---'--------(3)------' +%% +%% (0): auto or manual start +%% (1): retry timeout +%% (2): successfuly connected to remote node/cluster +%% (3): received {disconnected, Reason} OR +%% failed to send to remote node/cluster. +%% +%% NOTE: A bridge worker may subscribe to multiple (including wildcard) +%% local topics, and the underlying `emqx_bridge_connect' may subscribe to +%% multiple remote topics, however, worker/connections are not designed +%% to support automatic load-balancing, i.e. in case it can not keep up +%% with the amount of messages comming in, administrator should split and +%% balance topics between worker/connections manually. +%% +%% NOTES: +%% * Local messages are all normalised to QoS-1 when exporting to remote + +-module(emqx_bridge_worker). +-behaviour(gen_statem). + +%% APIs +-export([ start_link/1 + , start_link/2 + , register_metrics/0 + , stop/1 + ]). + +%% gen_statem callbacks +-export([ terminate/3 + , code_change/4 + , init/1 + , callback_mode/0 + ]). + +%% state functions +-export([ idle/3 + , connected/3 + ]). + +%% management APIs +-export([ ensure_started/1 + , ensure_stopped/1 + , ensure_stopped/2 + , status/1 + ]). + +-export([ get_forwards/1 + , ensure_forward_present/2 + , ensure_forward_absent/2 + ]). + +-export([ get_subscriptions/1 + , ensure_subscription_present/3 + , ensure_subscription_absent/2 + ]). + +-export_type([ config/0 + , batch/0 + , ack_ref/0 + ]). + +-type id() :: atom() | string() | pid(). +-type qos() :: emqx_mqtt_types:qos(). +-type config() :: map(). +-type batch() :: [emqx_bridge_msg:exp_msg()]. +-type ack_ref() :: term(). +-type topic() :: emqx_topic:topic(). + +-include_lib("emqx_libs/include/logger.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). + +-logger_header("[Bridge]"). + +%% same as default in-flight limit for emqtt +-define(DEFAULT_BATCH_SIZE, 32). +-define(DEFAULT_RECONNECT_DELAY_MS, timer:seconds(5)). +-define(DEFAULT_SEG_BYTES, (1 bsl 20)). +-define(DEFAULT_MAX_TOTAL_SIZE, (1 bsl 31)). +-define(NO_BRIDGE_HANDLER, undefined). + +%% @doc Start a bridge worker. Supported configs: +%% start_type: 'manual' (default) or 'auto', when manual, bridge will stay +%% at 'idle' state until a manual call to start it. +%% connect_module: The module which implements emqx_bridge_connect behaviour +%% and work as message batch transport layer +%% reconnect_delay_ms: Delay in milli-seconds for the bridge worker to retry +%% in case of transportation failure. +%% max_inflight_batches: Max number of batches allowed to send-ahead before +%% receiving confirmation from remote node/cluster +%% mountpoint: The topic mount point for messages sent to remote node/cluster +%% `undefined', `<<>>' or `""' to disable +%% forwards: Local topics to subscribe. +%% queue.batch_bytes_limit: Max number of bytes to collect in a batch for each +%% send call towards emqx_bridge_connect +%% queue.batch_count_limit: Max number of messages to collect in a batch for +%% each send call towards emqx_bridge_connect +%% queue.replayq_dir: Directory where replayq should persist messages +%% queue.replayq_seg_bytes: Size in bytes for each replayq segment file +%% +%% Find more connection specific configs in the callback modules +%% of emqx_bridge_connect behaviour. +start_link(Config) when is_list(Config) -> + start_link(maps:from_list(Config)); +start_link(Config) -> + gen_statem:start_link(?MODULE, Config, []). + +start_link(Name, Config) when is_list(Config) -> + start_link(Name, maps:from_list(Config)); +start_link(Name, Config) -> + Name1 = name(Name), + gen_statem:start_link({local, Name1}, ?MODULE, Config#{name => Name1}, []). + +ensure_started(Name) -> + gen_statem:call(name(Name), ensure_started). + +%% @doc Manually stop bridge worker. State idempotency ensured. +ensure_stopped(Id) -> + ensure_stopped(Id, 1000). + +ensure_stopped(Id, Timeout) -> + Pid = case id(Id) of + P when is_pid(P) -> P; + N -> whereis(N) + end, + case Pid of + undefined -> + ok; + _ -> + MRef = monitor(process, Pid), + unlink(Pid), + _ = gen_statem:call(id(Id), ensure_stopped, Timeout), + receive + {'DOWN', MRef, _, _, _} -> + ok + after + Timeout -> + exit(Pid, kill) + end + end. + +stop(Pid) -> gen_statem:stop(Pid). + +status(Pid) when is_pid(Pid) -> + gen_statem:call(Pid, status); +status(Id) -> + gen_statem:call(name(Id), status). + +%% @doc Return all forwards (local subscriptions). +-spec get_forwards(id()) -> [topic()]. +get_forwards(Id) -> gen_statem:call(id(Id), get_forwards, timer:seconds(1000)). + +%% @doc Return all subscriptions (subscription over mqtt connection to remote broker). +-spec get_subscriptions(id()) -> [{emqx_topic:topic(), qos()}]. +get_subscriptions(Id) -> gen_statem:call(id(Id), get_subscriptions). + +%% @doc Add a new forward (local topic subscription). +-spec ensure_forward_present(id(), topic()) -> ok. +ensure_forward_present(Id, Topic) -> + gen_statem:call(id(Id), {ensure_present, forwards, topic(Topic)}). + +%% @doc Ensure a forward topic is deleted. +-spec ensure_forward_absent(id(), topic()) -> ok. +ensure_forward_absent(Id, Topic) -> + gen_statem:call(id(Id), {ensure_absent, forwards, topic(Topic)}). + +%% @doc Ensure subscribed to remote topic. +%% NOTE: only applicable when connection module is emqx_bridge_mqtt +%% return `{error, no_remote_subscription_support}' otherwise. +-spec ensure_subscription_present(id(), topic(), qos()) -> ok | {error, any()}. +ensure_subscription_present(Id, Topic, QoS) -> + gen_statem:call(id(Id), {ensure_present, subscriptions, {topic(Topic), QoS}}). + +%% @doc Ensure unsubscribed from remote topic. +%% NOTE: only applicable when connection module is emqx_bridge_mqtt +-spec ensure_subscription_absent(id(), topic()) -> ok. +ensure_subscription_absent(Id, Topic) -> + gen_statem:call(id(Id), {ensure_absent, subscriptions, topic(Topic)}). + +callback_mode() -> [state_functions]. + +%% @doc Config should be a map(). +init(Config) -> + erlang:process_flag(trap_exit, true), + ConnectModule = maps:get(connect_module, Config), + Subscriptions = maps:get(subscriptions, Config, []), + Forwards = maps:get(forwards, Config, []), + Queue = open_replayq(Config), + State = init_opts(Config), + Topics = [iolist_to_binary(T) || T <- Forwards], + Subs = check_subscriptions(Subscriptions), + ConnectConfig = get_conn_cfg(Config), + ConnectFun = fun(SubsX) -> + emqx_bridge_connect:start(ConnectModule, ConnectConfig#{subscriptions => SubsX}) + end, + self() ! idle, + {ok, idle, State#{connect_module => ConnectModule, + connect_fun => ConnectFun, + forwards => Topics, + subscriptions => Subs, + replayq => Queue + }}. + +init_opts(Config) -> + IfRecordMetrics = maps:get(if_record_metrics, Config, true), + ReconnDelayMs = maps:get(reconnect_delay_ms, Config, ?DEFAULT_RECONNECT_DELAY_MS), + StartType = maps:get(start_type, Config, manual), + BridgeHandler = maps:get(bridge_handler, Config, ?NO_BRIDGE_HANDLER), + Mountpoint = maps:get(forward_mountpoint, Config, undefined), + ReceiveMountpoint = maps:get(receive_mountpoint, Config, undefined), + MaxInflightSize = maps:get(max_inflight_batches, Config, ?DEFAULT_BATCH_SIZE), + BatchSize = maps:get(batch_size, Config, ?DEFAULT_BATCH_SIZE), + Name = maps:get(name, Config, undefined), + #{start_type => StartType, + reconnect_delay_ms => ReconnDelayMs, + batch_size => BatchSize, + mountpoint => format_mountpoint(Mountpoint), + receive_mountpoint => ReceiveMountpoint, + inflight => [], + max_inflight => MaxInflightSize, + connection => undefined, + bridge_handler => BridgeHandler, + if_record_metrics => IfRecordMetrics, + name => Name}. + +open_replayq(Config) -> + QCfg = maps:get(queue, Config, #{}), + Dir = maps:get(replayq_dir, QCfg, undefined), + SegBytes = maps:get(replayq_seg_bytes, QCfg, ?DEFAULT_SEG_BYTES), + MaxTotalSize = maps:get(max_total_size, QCfg, ?DEFAULT_MAX_TOTAL_SIZE), + QueueConfig = case Dir =:= undefined orelse Dir =:= "" of + true -> #{mem_only => true}; + false -> #{dir => Dir, seg_bytes => SegBytes, max_total_size => MaxTotalSize} + end, + replayq:open(QueueConfig#{sizer => fun emqx_bridge_msg:estimate_size/1, + marshaller => fun msg_marshaller/1}). + +check_subscriptions(Subscriptions) -> + lists:map(fun({Topic, QoS}) -> + Topic1 = iolist_to_binary(Topic), + true = emqx_topic:validate({filter, Topic1}), + {Topic1, QoS} + end, Subscriptions). + +get_conn_cfg(Config) -> + maps:without([connect_module, + queue, + reconnect_delay_ms, + forwards, + mountpoint, + name + ], Config). + +code_change(_Vsn, State, Data, _Extra) -> + {ok, State, Data}. + +terminate(_Reason, _StateName, #{replayq := Q} = State) -> + _ = disconnect(State), + _ = replayq:close(Q), + ok. + +%% ensure_started will be deprecated in the future +idle({call, From}, ensure_started, State) -> + case do_connect(State) of + {ok, State1} -> + {next_state, connected, State1, [{reply, From, ok}, {state_timeout, 0, connected}]}; + {error, Reason} -> + {keep_state_and_data, [{reply, From, {error, Reason}}]} + end; +%% @doc Standing by for manual start. +idle(info, idle, #{start_type := manual}) -> + keep_state_and_data; +%% @doc Standing by for auto start. +idle(info, idle, #{start_type := auto} = State) -> + connecting(State); +idle(state_timeout, reconnect, State) -> + connecting(State); + +idle(info, {batch_ack, Ref}, State) -> + case do_ack(State, Ref) of + {ok, NewState} -> + {keep_state, NewState}; + _ -> + keep_state_and_data + end; + +idle(Type, Content, State) -> + common(idle, Type, Content, State). + +connecting(#{reconnect_delay_ms := ReconnectDelayMs} = State) -> + case do_connect(State) of + {ok, State1} -> + {next_state, connected, State1, {state_timeout, 0, connected}}; + _ -> + {keep_state_and_data, {state_timeout, ReconnectDelayMs, reconnect}} + end. + +connected(state_timeout, connected, #{inflight := Inflight} = State) -> + case retry_inflight(State, Inflight) of + {ok, NewState} -> + {keep_state, NewState, {next_event, internal, maybe_send}}; + {error, NewState} -> + {keep_state, NewState} + end; +connected(internal, maybe_send, State) -> + {_, NewState} = pop_and_send(State), + {keep_state, NewState}; + +connected(info, {disconnected, Conn, Reason}, + #{connection := Connection, name := Name, reconnect_delay_ms := ReconnectDelayMs} = State) -> + case Conn =:= maps:get(client_pid, Connection, undefined) of + true -> + ?LOG(info, "Bridge ~p diconnected~nreason=~p", [Name, Reason]), + {next_state, idle, State#{connection => undefined}, {state_timeout, ReconnectDelayMs, reconnect}}; + false -> + keep_state_and_data + end; +connected(info, {batch_ack, Ref}, State) -> + case do_ack(State, Ref) of + {ok, NewState} -> + {keep_state, NewState, {next_event, internal, maybe_send}}; + _ -> + keep_state_and_data + end; +connected(Type, Content, State) -> + common(connected, Type, Content, State). + +%% Common handlers +common(StateName, {call, From}, status, _State) -> + {keep_state_and_data, [{reply, From, StateName}]}; +common(_StateName, {call, From}, ensure_started, _State) -> + {keep_state_and_data, [{reply, From, connected}]}; +common(_StateName, {call, From}, ensure_stopped, _State) -> + {stop_and_reply, {shutdown, manual}, [{reply, From, ok}]}; +common(_StateName, {call, From}, get_forwards, #{forwards := Forwards}) -> + {keep_state_and_data, [{reply, From, Forwards}]}; +common(_StateName, {call, From}, get_subscriptions, #{subscriptions := Subs}) -> + {keep_state_and_data, [{reply, From, Subs}]}; +common(_StateName, {call, From}, {ensure_present, What, Topic}, State) -> + {Result, NewState} = ensure_present(What, Topic, State), + {keep_state, NewState, [{reply, From, Result}]}; +common(_StateName, {call, From}, {ensure_absent, What, Topic}, State) -> + {Result, NewState} = ensure_absent(What, Topic, State), + {keep_state, NewState, [{reply, From, Result}]}; +common(_StateName, info, {deliver, _, Msg}, #{replayq := Q, if_record_metrics := IfRecordMetric} = State) -> + bridges_metrics_inc(IfRecordMetric, 'bridge.mqtt.message_received'), + NewQ = replayq:append(Q, collect([Msg])), + {keep_state, State#{replayq => NewQ}, {next_event, internal, maybe_send}}; +common(_StateName, info, {'EXIT', _, _}, State) -> + {keep_state, State}; +common(StateName, Type, Content, #{name := Name} = State) -> + ?LOG(notice, "Bridge ~p discarded ~p type event at state ~p:~p", + [Name, Type, StateName, Content]), + {keep_state, State}. + +eval_bridge_handler(State = #{bridge_handler := ?NO_BRIDGE_HANDLER}, _Msg) -> + State; +eval_bridge_handler(State = #{bridge_handler := Handler}, Msg) -> + Handler(Msg), + State. + +ensure_present(Key, Topic, State) -> + Topics = maps:get(Key, State), + case is_topic_present(Topic, Topics) of + true -> + {ok, State}; + false -> + R = do_ensure_present(Key, Topic, State), + {R, State#{Key := lists:usort([Topic | Topics])}} + end. + +ensure_absent(Key, Topic, State) -> + Topics = maps:get(Key, State), + case is_topic_present(Topic, Topics) of + true -> + R = do_ensure_absent(Key, Topic, State), + {R, State#{Key := ensure_topic_absent(Topic, Topics)}}; + false -> + {ok, State} + end. + +ensure_topic_absent(_Topic, []) -> []; +ensure_topic_absent(Topic, [{_, _} | _] = L) -> lists:keydelete(Topic, 1, L); +ensure_topic_absent(Topic, L) -> lists:delete(Topic, L). + +is_topic_present({Topic, _QoS}, Topics) -> + is_topic_present(Topic, Topics); +is_topic_present(Topic, Topics) -> + lists:member(Topic, Topics) orelse false =/= lists:keyfind(Topic, 1, Topics). + +do_connect(#{forwards := Forwards, + subscriptions := Subs, + connect_fun := ConnectFun, + name := Name} = State) -> + ok = subscribe_local_topics(Forwards, Name), + case ConnectFun(Subs) of + {ok, Conn} -> + ?LOG(info, "Bridge ~p is connecting......", [Name]), + {ok, eval_bridge_handler(State#{connection => Conn}, connected)}; + {error, Reason} -> + {error, Reason, State} + end. + +do_ensure_present(forwards, Topic, #{name := Name}) -> + subscribe_local_topic(Topic, Name); +do_ensure_present(subscriptions, _Topic, #{connection := undefined}) -> + {error, no_connection}; +do_ensure_present(subscriptions, _Topic, #{connect_module := emqx_bridge_rpc}) -> + {error, no_remote_subscription_support}; +do_ensure_present(subscriptions, {Topic, QoS}, #{connect_module := ConnectModule, + connection := Conn}) -> + ConnectModule:ensure_subscribed(Conn, Topic, QoS). + +do_ensure_absent(forwards, Topic, _) -> + do_unsubscribe(Topic); +do_ensure_absent(subscriptions, _Topic, #{connection := undefined}) -> + {error, no_connection}; +do_ensure_absent(subscriptions, _Topic, #{connect_module := emqx_bridge_rpc}) -> + {error, no_remote_subscription_support}; +do_ensure_absent(subscriptions, Topic, #{connect_module := ConnectModule, + connection := Conn}) -> + ConnectModule:ensure_unsubscribed(Conn, Topic). + +collect(Acc) -> + receive + {deliver, _, Msg} -> + collect([Msg | Acc]) + after + 0 -> + lists:reverse(Acc) + end. + +%% Retry all inflight (previously sent but not acked) batches. +retry_inflight(State, []) -> {ok, State}; +retry_inflight(State, [#{q_ack_ref := QAckRef, batch := Batch} | Inflight]) -> + case do_send(State#{inflight := Inflight}, QAckRef, Batch) of + {ok, State1} -> retry_inflight(State1, Inflight); + {error, State1} -> {error, State1} + end. + +pop_and_send(#{inflight := Inflight, max_inflight := Max } = State) when length(Inflight) >= Max -> + {ok, State}; +pop_and_send(#{replayq := Q, connect_module := Module} = State) -> + case replayq:is_empty(Q) of + true -> + {ok, State}; + false -> + BatchSize = case Module of + emqx_bridge_rpc -> maps:get(batch_size, State); + _ -> 1 + end, + Opts = #{count_limit => BatchSize, bytes_limit => 999999999}, + {Q1, QAckRef, Batch} = replayq:pop(Q, Opts), + do_send(State#{replayq := Q1}, QAckRef, Batch) + end. + +%% Assert non-empty batch because we have a is_empty check earlier. +do_send(#{inflight := Inflight, + connect_module := Module, + connection := Connection, + mountpoint := Mountpoint, + if_record_metrics := IfRecordMetrics} = State, QAckRef, Batch) -> + ExportMsg = fun(Message) -> + bridges_metrics_inc(IfRecordMetrics, 'bridge.mqtt.message_sent'), + emqx_bridge_msg:to_export(Module, Mountpoint, Message) + end, + case Module:send(Connection, [ExportMsg(M) || M <- Batch]) of + {ok, Ref} -> + {ok, State#{inflight := Inflight ++ [#{q_ack_ref => QAckRef, + send_ack_ref => Ref, + batch => Batch}]}}; + {error, Reason} -> + ?LOG(info, "Batch produce failed~p", [Reason]), + {error, State} + end. + + +do_ack(#{inflight := []} = State, Ref) -> + ?LOG(error, "Can't be found from the inflight:~p", [Ref]), + {ok, State}; + +do_ack(#{inflight := [#{send_ack_ref := Ref, + q_ack_ref := QAckRef}| Rest], replayq := Q} = State, Ref) -> + ok = replayq:ack(Q, QAckRef), + {ok, State#{inflight => Rest}}; + +do_ack(#{inflight := [#{q_ack_ref := QAckRef, + batch := Batch}| Rest], replayq := Q} = State, Ref) -> + ok = replayq:ack(Q, QAckRef), + NewQ = replayq:append(Q, Batch), + do_ack(State#{replayq => NewQ, inflight => Rest}, Ref). + +subscribe_local_topics(Topics, Name) -> + lists:foreach(fun(Topic) -> subscribe_local_topic(Topic, Name) end, Topics). + +subscribe_local_topic(Topic, Name) -> + do_subscribe(Topic, Name). + +topic(T) -> iolist_to_binary(T). + +validate(RawTopic) -> + Topic = topic(RawTopic), + try emqx_topic:validate(Topic) of + _Success -> Topic + catch + error:Reason -> + error({bad_topic, Topic, Reason}) + end. + +do_subscribe(RawTopic, Name) -> + TopicFilter = validate(RawTopic), + {Topic, SubOpts} = emqx_topic:parse(TopicFilter, #{qos => ?QOS_1}), + emqx_broker:subscribe(Topic, Name, SubOpts). + +do_unsubscribe(RawTopic) -> + TopicFilter = validate(RawTopic), + {Topic, _SubOpts} = emqx_topic:parse(TopicFilter), + emqx_broker:unsubscribe(Topic). + +disconnect(#{connection := Conn, + connect_module := Module + } = State) when Conn =/= undefined -> + Module:stop(Conn), + State0 = State#{connection => undefined}, + eval_bridge_handler(State0, disconnected); +disconnect(State) -> + eval_bridge_handler(State, disconnected). + +%% Called only when replayq needs to dump it to disk. +msg_marshaller(Bin) when is_binary(Bin) -> emqx_bridge_msg:from_binary(Bin); +msg_marshaller(Msg) -> emqx_bridge_msg:to_binary(Msg). + +format_mountpoint(undefined) -> + undefined; +format_mountpoint(Prefix) -> + binary:replace(iolist_to_binary(Prefix), <<"${node}">>, atom_to_binary(node(), utf8)). + +name(Id) -> list_to_atom(lists:concat([?MODULE, "_", Id])). + +id(Pid) when is_pid(Pid) -> Pid; +id(Name) -> name(Name). + +register_metrics() -> + lists:foreach(fun emqx_metrics:ensure/1, + ['bridge.mqtt.message_sent', + 'bridge.mqtt.message_received' + ]). + +bridges_metrics_inc(true, Metric) -> + emqx_metrics:inc(Metric); +bridges_metrics_inc(_IsRecordMetric, _Metric) -> + ok. diff --git a/apps/emqx_bridge_mqtt/test/emqx_bridge_mqtt_tests.erl b/apps/emqx_bridge_mqtt/test/emqx_bridge_mqtt_tests.erl new file mode 100644 index 000000000..37db49e95 --- /dev/null +++ b/apps/emqx_bridge_mqtt/test/emqx_bridge_mqtt_tests.erl @@ -0,0 +1,47 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_bridge_mqtt_tests). + +-include_lib("eunit/include/eunit.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). + +send_and_ack_test() -> + %% delegate from gen_rpc to rpc for unit test + meck:new(emqtt, [passthrough, no_history]), + meck:expect(emqtt, start_link, 1, + fun(_) -> + {ok, spawn_link(fun() -> ok end)} + end), + meck:expect(emqtt, connect, 1, {ok, dummy}), + meck:expect(emqtt, stop, 1, + fun(Pid) -> Pid ! stop end), + meck:expect(emqtt, publish, 2, + fun(Client, Msg) -> + Client ! {publish, Msg}, + {ok, Msg} %% as packet id + end), + try + Max = 1, + Batch = lists:seq(1, Max), + {ok, Conn} = emqx_bridge_mqtt:start(#{address => "127.0.0.1:1883"}), + % %% return last packet id as batch reference + {ok, _AckRef} = emqx_bridge_mqtt:send(Conn, Batch), + + ok = emqx_bridge_mqtt:stop(Conn) + after + meck:unload(emqtt) + end. \ No newline at end of file diff --git a/apps/emqx_bridge_mqtt/test/emqx_bridge_rpc_tests.erl b/apps/emqx_bridge_mqtt/test/emqx_bridge_rpc_tests.erl new file mode 100644 index 000000000..f79d12dfb --- /dev/null +++ b/apps/emqx_bridge_mqtt/test/emqx_bridge_rpc_tests.erl @@ -0,0 +1,42 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_bridge_rpc_tests). +-include_lib("eunit/include/eunit.hrl"). + +send_and_ack_test() -> + %% delegate from emqx_rpc to rpc for unit test + meck:new(emqx_rpc, [passthrough, no_history]), + meck:expect(emqx_rpc, call, 4, + fun(Node, Module, Fun, Args) -> + rpc:call(Node, Module, Fun, Args) + end), + meck:expect(emqx_rpc, cast, 4, + fun(Node, Module, Fun, Args) -> + rpc:cast(Node, Module, Fun, Args) + end), + meck:new(emqx_bridge_worker, [passthrough, no_history]), + try + {ok, #{client_pid := Pid, address := Node}} = emqx_bridge_rpc:start(#{address => node()}), + {ok, Ref} = emqx_bridge_rpc:send(#{address => Node}, []), + receive + {batch_ack, Ref} -> + ok + end, + ok = emqx_bridge_rpc:stop( #{client_pid => Pid}) + after + meck:unload(emqx_rpc) + end. diff --git a/apps/emqx_bridge_mqtt/test/emqx_bridge_worker_SUITE.erl b/apps/emqx_bridge_mqtt/test/emqx_bridge_worker_SUITE.erl new file mode 100644 index 000000000..3a2c541e7 --- /dev/null +++ b/apps/emqx_bridge_mqtt/test/emqx_bridge_worker_SUITE.erl @@ -0,0 +1,176 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_bridge_worker_SUITE). + +-export([ all/0 + , init_per_suite/1 + , end_per_suite/1]). +-export([ t_rpc/1 + , t_mqtt/1 + , t_mngr/1]). + +-include_lib("eunit/include/eunit.hrl"). +-include_lib("common_test/include/ct.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). + +-define(wait(For, Timeout), emqx_ct_helpers:wait_for(?FUNCTION_NAME, ?LINE, fun() -> For end, Timeout)). + +receive_messages(Count) -> + receive_messages(Count, []). + +receive_messages(0, Msgs) -> + Msgs; +receive_messages(Count, Msgs) -> + receive + {publish, Msg} -> + receive_messages(Count-1, [Msg|Msgs]); + _Other -> + receive_messages(Count, Msgs) + after 1000 -> + Msgs + end. + +all() -> [ t_rpc + , t_mqtt + , t_mngr + ]. + +init_per_suite(Config) -> + case node() of + nonode@nohost -> net_kernel:start(['emqx@127.0.0.1', longnames]); + _ -> ok + end, + ok = application:set_env(gen_rpc, tcp_client_num, 1), + emqx_ct_helpers:start_apps([emqx_bridge_mqtt]), + emqx_logger:set_log_level(error), + [{log_level, error} | Config]. + +end_per_suite(_Config) -> + emqx_ct_helpers:stop_apps([emqx_bridge_mqtt]). + +t_mngr(Config) when is_list(Config) -> + Subs = [{<<"a">>, 1}, {<<"b">>, 2}], + Cfg = #{address => node(), + forwards => [<<"mngr">>], + connect_module => emqx_bridge_rpc, + mountpoint => <<"forwarded">>, + subscriptions => Subs, + start_type => auto}, + Name = ?FUNCTION_NAME, + {ok, Pid} = emqx_bridge_worker:start_link(Name, Cfg), + try + ?assertEqual([<<"mngr">>], emqx_bridge_worker:get_forwards(Name)), + ?assertEqual(ok, emqx_bridge_worker:ensure_forward_present(Name, "mngr")), + ?assertEqual(ok, emqx_bridge_worker:ensure_forward_present(Name, "mngr2")), + ?assertEqual([<<"mngr">>, <<"mngr2">>], emqx_bridge_worker:get_forwards(Pid)), + ?assertEqual(ok, emqx_bridge_worker:ensure_forward_absent(Name, "mngr2")), + ?assertEqual(ok, emqx_bridge_worker:ensure_forward_absent(Name, "mngr3")), + ?assertEqual([<<"mngr">>], emqx_bridge_worker:get_forwards(Pid)), + ?assertEqual({error, no_remote_subscription_support}, + emqx_bridge_worker:ensure_subscription_present(Pid, <<"t">>, 0)), + ?assertEqual({error, no_remote_subscription_support}, + emqx_bridge_worker:ensure_subscription_absent(Pid, <<"t">>)), + ?assertEqual(Subs, emqx_bridge_worker:get_subscriptions(Pid)) + after + ok = emqx_bridge_worker:stop(Pid) + end. + +%% A loopback RPC to local node +t_rpc(Config) when is_list(Config) -> + Cfg = #{address => node(), + forwards => [<<"t_rpc/#">>], + connect_module => emqx_bridge_rpc, + forward_mountpoint => <<"forwarded">>, + start_type => auto}, + {ok, Pid} = emqx_bridge_worker:start_link(?FUNCTION_NAME, Cfg), + ClientId = <<"ClientId">>, + try + {ok, ConnPid} = emqtt:start_link([{clientid, ClientId}]), + {ok, _Props} = emqtt:connect(ConnPid), + {ok, _Props, [1]} = emqtt:subscribe(ConnPid, {<<"forwarded/t_rpc/one">>, ?QOS_1}), + timer:sleep(100), + {ok, _PacketId} = emqtt:publish(ConnPid, <<"t_rpc/one">>, <<"hello">>, ?QOS_1), + timer:sleep(100), + ?assertEqual(1, length(receive_messages(1))), + emqtt:disconnect(ConnPid) + after + ok = emqx_bridge_worker:stop(Pid) + end. + +%% Full data loopback flow explained: +%% mqtt-client ----> local-broker ---(local-subscription)---> +%% bridge(export) --- (mqtt-connection)--> local-broker ---(remote-subscription) --> +%% bridge(import) --> mqtt-client +t_mqtt(Config) when is_list(Config) -> + SendToTopic = <<"t_mqtt/one">>, + SendToTopic2 = <<"t_mqtt/two">>, + SendToTopic3 = <<"t_mqtt/three">>, + Mountpoint = <<"forwarded/${node}/">>, + Cfg = #{address => "127.0.0.1:1883", + forwards => [SendToTopic], + connect_module => emqx_bridge_mqtt, + forward_mountpoint => Mountpoint, + username => "user", + clean_start => true, + clientid => "bridge_aws", + keepalive => 60000, + password => "passwd", + proto_ver => mqttv4, + queue => #{replayq_dir => "data/t_mqtt/", + replayq_seg_bytes => 10000, + batch_bytes_limit => 1000, + batch_count_limit => 10 + }, + reconnect_delay_ms => 1000, + ssl => false, + %% Consume back to forwarded message for verification + %% NOTE: this is a indefenite loopback without mocking emqx_bridge_worker:import_batch/1 + subscriptions => [{SendToTopic2, _QoS = 1}], + receive_mountpoint => <<"receive/aws/">>, + start_type => auto}, + {ok, Pid} = emqx_bridge_worker:start_link(?FUNCTION_NAME, Cfg), + ClientId = <<"client-1">>, + try + ?assertEqual([{SendToTopic2, 1}], emqx_bridge_worker:get_subscriptions(Pid)), + ok = emqx_bridge_worker:ensure_subscription_present(Pid, SendToTopic3, _QoS = 1), + ?assertEqual([{SendToTopic3, 1},{SendToTopic2, 1}], + emqx_bridge_worker:get_subscriptions(Pid)), + {ok, ConnPid} = emqtt:start_link([{clientid, ClientId}]), + {ok, _Props} = emqtt:connect(ConnPid), + emqtt:subscribe(ConnPid, <<"forwarded/+/t_mqtt/one">>, 1), + %% message from a different client, to avoid getting terminated by no-local + Max = 10, + Msgs = lists:seq(1, Max), + lists:foreach(fun(I) -> + {ok, _PacketId} = emqtt:publish(ConnPid, SendToTopic, integer_to_binary(I), ?QOS_1) + end, Msgs), + ?assertEqual(10, length(receive_messages(200))), + + emqtt:subscribe(ConnPid, <<"receive/aws/t_mqtt/two">>, 1), + %% message from a different client, to avoid getting terminated by no-local + Max = 10, + Msgs = lists:seq(1, Max), + lists:foreach(fun(I) -> + {ok, _PacketId} = emqtt:publish(ConnPid, SendToTopic2, integer_to_binary(I), ?QOS_1) + end, Msgs), + ?assertEqual(10, length(receive_messages(200))), + + emqtt:disconnect(ConnPid) + after + ok = emqx_bridge_worker:stop(Pid) + end. diff --git a/apps/emqx_bridge_mqtt/test/emqx_bridge_worker_tests.erl b/apps/emqx_bridge_mqtt/test/emqx_bridge_worker_tests.erl new file mode 100644 index 000000000..1bf55d99d --- /dev/null +++ b/apps/emqx_bridge_mqtt/test/emqx_bridge_worker_tests.erl @@ -0,0 +1,172 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_bridge_worker_tests). +-behaviour(emqx_bridge_connect). + +-include_lib("eunit/include/eunit.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). + +-define(BRIDGE_NAME, test). +-define(BRIDGE_REG_NAME, emqx_bridge_worker_test). +-define(WAIT(PATTERN, TIMEOUT), + receive + PATTERN -> + ok + after + TIMEOUT -> + error(timeout) + end). + +%% stub callbacks +-export([start/1, send/2, stop/1]). + +start(#{connect_result := Result, test_pid := Pid, test_ref := Ref}) -> + case is_pid(Pid) of + true -> Pid ! {connection_start_attempt, Ref}; + false -> ok + end, + Result. + +send(SendFun, Batch) when is_function(SendFun, 2) -> + SendFun(Batch). + +stop(_Pid) -> ok. + +%% bridge worker should retry connecting remote node indefinitely +% reconnect_test() -> +% emqx_metrics:start_link(), +% emqx_bridge_worker:register_metrics(), +% Ref = make_ref(), +% Config = make_config(Ref, self(), {error, test}), +% {ok, Pid} = emqx_bridge_worker:start_link(?BRIDGE_NAME, Config), +% %% assert name registered +% ?assertEqual(Pid, whereis(?BRIDGE_REG_NAME)), +% ?WAIT({connection_start_attempt, Ref}, 1000), +% %% expect same message again +% ?WAIT({connection_start_attempt, Ref}, 1000), +% ok = emqx_bridge_worker:stop(?BRIDGE_REG_NAME), +% emqx_metrics:stop(), +% ok. + +%% connect first, disconnect, then connect again +disturbance_test() -> + emqx_metrics:start_link(), + emqx_bridge_worker:register_metrics(), + Ref = make_ref(), + TestPid = self(), + Config = make_config(Ref, TestPid, {ok, #{client_pid => TestPid}}), + {ok, Pid} = emqx_bridge_worker:start_link(?BRIDGE_NAME, Config), + ?assertEqual(Pid, whereis(?BRIDGE_REG_NAME)), + ?WAIT({connection_start_attempt, Ref}, 1000), + Pid ! {disconnected, TestPid, test}, + ?WAIT({connection_start_attempt, Ref}, 1000), + emqx_metrics:stop(), + ok = emqx_bridge_worker:stop(?BRIDGE_REG_NAME). + +% % %% buffer should continue taking in messages when disconnected +% buffer_when_disconnected_test_() -> +% {timeout, 10000, fun test_buffer_when_disconnected/0}. + +% test_buffer_when_disconnected() -> +% Ref = make_ref(), +% Nums = lists:seq(1, 100), +% Sender = spawn_link(fun() -> receive {bridge, Pid} -> sender_loop(Pid, Nums, _Interval = 5) end end), +% SenderMref = monitor(process, Sender), +% Receiver = spawn_link(fun() -> receive {bridge, Pid} -> receiver_loop(Pid, Nums, _Interval = 1) end end), +% ReceiverMref = monitor(process, Receiver), +% SendFun = fun(Batch) -> +% BatchRef = make_ref(), +% Receiver ! {batch, BatchRef, Batch}, +% {ok, BatchRef} +% end, +% Config0 = make_config(Ref, false, {ok, #{client_pid => undefined}}), +% Config = Config0#{reconnect_delay_ms => 100}, +% emqx_metrics:start_link(), +% emqx_bridge_worker:register_metrics(), +% {ok, Pid} = emqx_bridge_worker:start_link(?BRIDGE_NAME, Config), +% Sender ! {bridge, Pid}, +% Receiver ! {bridge, Pid}, +% ?assertEqual(Pid, whereis(?BRIDGE_REG_NAME)), +% Pid ! {disconnected, Ref, test}, +% ?WAIT({'DOWN', SenderMref, process, Sender, normal}, 5000), +% ?WAIT({'DOWN', ReceiverMref, process, Receiver, normal}, 1000), +% ok = emqx_bridge_worker:stop(?BRIDGE_REG_NAME), +% emqx_metrics:stop(). + +manual_start_stop_test() -> + emqx_metrics:start_link(), + emqx_bridge_worker:register_metrics(), + Ref = make_ref(), + TestPid = self(), + Config0 = make_config(Ref, TestPid, {ok, #{client_pid => TestPid}}), + Config = Config0#{start_type := manual}, + {ok, Pid} = emqx_bridge_worker:start_link(?BRIDGE_NAME, Config), + %% call ensure_started again should yeld the same result + ok = emqx_bridge_worker:ensure_started(?BRIDGE_NAME), + ?assertEqual(Pid, whereis(?BRIDGE_REG_NAME)), + emqx_bridge_worker:ensure_stopped(unknown), + emqx_bridge_worker:ensure_stopped(Pid), + emqx_bridge_worker:ensure_stopped(?BRIDGE_REG_NAME), + emqx_metrics:stop(). + +%% Feed messages to bridge +sender_loop(_Pid, [], _) -> exit(normal); +sender_loop(Pid, [Num | Rest], Interval) -> + random_sleep(Interval), + Pid ! {deliver, dummy, make_msg(Num)}, + sender_loop(Pid, Rest, Interval). + +%% Feed acknowledgments to bridge +receiver_loop(_Pid, [], _) -> ok; +receiver_loop(Pid, Nums, Interval) -> + receive + {batch, BatchRef, Batch} -> + Rest = match_nums(Batch, Nums), + random_sleep(Interval), + emqx_bridge_worker:handle_ack(Pid, BatchRef), + receiver_loop(Pid, Rest, Interval) + end. + +random_sleep(MaxInterval) -> + case rand:uniform(MaxInterval) - 1 of + 0 -> ok; + T -> timer:sleep(T) + end. + +match_nums([], Rest) -> Rest; +match_nums([#message{payload = P} | Rest], Nums) -> + I = binary_to_integer(P), + case Nums of + [I | NumsLeft] -> match_nums(Rest, NumsLeft); + [J | _] when J > I -> match_nums(Rest, Nums); %% allow retry + _ -> error([{received, I}, {expecting, Nums}]) + end. + +make_config(Ref, TestPid, Result) -> + #{test_pid => TestPid, + test_ref => Ref, + connect_module => ?MODULE, + reconnect_delay_ms => 50, + connect_result => Result, + start_type => auto + }. + +make_msg(I) -> + Payload = integer_to_binary(I), + emqx_message:make(<<"test/topic">>, Payload). + diff --git a/apps/emqx_coap/README.md b/apps/emqx_coap/README.md new file mode 100644 index 000000000..2da7b9fca --- /dev/null +++ b/apps/emqx_coap/README.md @@ -0,0 +1,254 @@ + +# emqx-coap + +emqx-coap is a CoAP Gateway for EMQ X Broker. It translates CoAP messages into MQTT messages and make it possible to communiate between CoAP clients and MQTT clients. + +### Client Usage Example +libcoap is an excellent coap library which has a simple client tool. It is recommended to use libcoap as a coap client. + +To compile libcoap, do following steps: + +``` +git clone http://github.com/obgm/libcoap +cd libcoap +./autogen.sh +./configure --enable-documentation=no --enable-tests=no +make +``` + +### Publish example: +``` +libcoap/examples/coap-client -m put -e 1234 "coap://127.0.0.1/mqtt/topic1?c=client1&u=tom&p=secret" +``` +- topic name is "topic1", NOT "/topic1" +- client id is client1 +- username is tom +- password is secret +- payload is a text string "1234" + +A mqtt message with topic="topic1", payload="1234" has been published. Any mqtt client or coap client, who has subscribed this topic could receive this message immediately. + +### Subscribe example: + +``` +libcoap/examples/coap-client -m get -s 10 "coap://127.0.0.1/mqtt/topic1?c=client1&u=tom&p=secret" +``` +- topic name is "topic1", NOT "/topic1" +- client id is client1 +- username is tom +- password is secret +- subscribe time is 10 seconds + +And you will get following result if any mqtt client or coap client sent message with text "1234567" to "topic1": + +``` +v:1 t:CON c:GET i:31ae {} [ ] +1234567v:1 t:CON c:GET i:31af {} [ Observe:1, Uri-Path:mqtt, Uri-Path:topic1, Uri-Query:c=client1, Uri-Query:u=tom, Uri-Query:p=secret ] +``` +The output message is not well formatted which hide "1234567" at the head of the 2nd line. + +### Configure + +#### Common + +File: etc/emqx_coap.conf + +```properties + +## The UDP port that CoAP is listening on. +## +## Value: Port +coap.port = 5683 + +## Interval for keepalive, specified in seconds. +## +## Value: Duration +## -s: seconds +## -m: minutes +## -h: hours +coap.keepalive = 120s + +## Whether to enable statistics for CoAP clients. +## +## Value: on | off +coap.enable_stats = off + +``` + +#### DTLS + +emqx_coap enable one-way authentication by default. + +If you want to disable it, comment these lines. + +File: etc/emqx_coap.conf + +```properties + +## The DTLS port that CoAP is listening on. +## +## Value: Port +coap.dtls.port = 5684 + +## Private key file for DTLS +## +## Value: File +coap.dtls.keyfile = {{ platform_etc_dir }}/certs/key.pem + +## Server certificate for DTLS. +## +## Value: File +coap.dtls.certfile = {{ platform_etc_dir }}/certs/cert.pem + +``` + +##### Enable two-way autentication + +For two-way autentication: + +```properties + +## A server only does x509-path validation in mode verify_peer, +## as it then sends a certificate request to the client (this +## message is not sent if the verify option is verify_none). +## You can then also want to specify option fail_if_no_peer_cert. +## More information at: http://erlang.org/doc/man/ssl.html +## +## Value: verify_peer | verify_none +## coap.dtls.verify = verify_peer + +## PEM-encoded CA certificates for DTLS +## +## Value: File +## coap.dtls.cacertfile = {{ platform_etc_dir }}/certs/cacert.pem + +## Used together with {verify, verify_peer} by an SSL server. If set to true, +## the server fails if the client does not have a certificate to send, that is, +## sends an empty certificate. +## +## Value: true | false +## coap.dtls.fail_if_no_peer_cert = false + +``` + +### Load emqx-coap + +```bash +./bin/emqx_ctl plugins load emqx_coap +``` + +CoAP Client Observe Operation (subscribe topic) +----------------------------------------------- +To subscribe any topic, issue following command: + +``` + GET coap://localhost/mqtt/{topicname}?c={clientid}&u={username}&p={password} with OBSERVE=0 +``` + +- "mqtt" in the path is mandatory. +- replace {topicname}, {clientid}, {username} and {password} with your true values. +- {topicname} and {clientid} is mandatory. +- if clientid is absent, a "bad_request" will be returned. +- {topicname} in URI should be percent-encoded to prevent special characters, such as + and #. +- {username} and {password} are optional. +- if {username} and {password} are not correct, an uauthorized error will be returned. +- topic is subscribed with qos1. + +CoAP Client Unobserve Operation (unsubscribe topic) +--------------------------------------------------- +To cancel observation, issue following command: + +``` + GET coap://localhost/mqtt/{topicname}?c={clientid}&u={username}&p={password} with OBSERVE=1 +``` + +- "mqtt" in the path is mandatory. +- replace {topicname}, {clientid}, {username} and {password} with your true values. +- {topicname} and {clientid} is mandatory. +- if clientid is absent, a "bad_request" will be returned. +- {topicname} in URI should be percent-encoded to prevent special characters, such as + and #. +- {username} and {password} are optional. +- if {username} and {password} are not correct, an uauthorized error will be returned. + +CoAP Client Notification Operation (subscribed Message) +------------------------------------------------------- +Server will issue an observe-notification as a subscribed message. + +- Its payload is exactly the mqtt payload. +- payload data type is "application/octet-stream". + +CoAP Client Publish Operation +----------------------------- +Issue a coap put command to do publishment. For example: + +``` + PUT coap://localhost/mqtt/{topicname}?c={clientid}&u={username}&p={password} +``` + +- "mqtt" in the path is mandatory. +- replace {topicname}, {clientid}, {username} and {password} with your true values. +- {topicname} and {clientid} is mandatory. +- if clientid is absent, a "bad_request" will be returned. +- {topicname} in URI should be percent-encoded to prevent special characters, such as + and #. +- {username} and {password} are optional. +- if {username} and {password} are not correct, an uauthorized error will be returned. +- payload could be any binary data. +- payload data type is "application/octet-stream". +- publish message will be sent with qos0. + +CoAP Client Keep Alive +---------------------- +Device should issue a get command periodically, serve as a ping to keep mqtt session online. + +``` + GET coap://localhost/mqtt/{any_topicname}?c={clientid}&u={username}&p={password} +``` + +- "mqtt" in the path is mandatory. +- replace {any_topicname}, {clientid}, {username} and {password} with your true values. +- {any_topicname} is optional, and should be percent-encoded to prevent special characters. +- {clientid} is mandatory. If clientid is absent, a "bad_request" will be returned. +- {username} and {password} are optional. +- if {username} and {password} are not correct, an uauthorized error will be returned. +- coap client should do keepalive work periodically to keep mqtt session online, especially those devices in a NAT network. + + +CoAP Client NOTES +----------------- +emqx-coap gateway does not accept POST and DELETE requests. + +Topics in URI should be percent-encoded, but corresponding uri_path option has percent-encoding converted. Please refer to RFC 7252 section 6.4, "Decomposing URIs into Options": + +> Note that these rules completely resolve any percent-encoding. + +That implies coap client is responsible to convert any percert-encoding into true character while assembling coap packet. + + +ClientId, Username, Password and Topic +-------------------------------------- +ClientId/username/password/topic in the coap URI are the concepts in mqtt. That is to say, emqx-coap is trying to fit coap message into mqtt system, by borrowing the client/username/password/topic from mqtt. + +The Auth/ACL/Hook features in mqtt also applies on coap stuff. For example: +- If username/password is not authorized, coap client will get an uauthorized error. +- If username or clientid is not allowed to published specific topic, coap message will be dropped in fact, although coap client will get an acknoledgement from emqx-coap. +- If a coap message is published, a 'message.publish' hook is able to capture this message as well. + +well-known locations +-------------------- +Discovery always return "," + +For example +``` +libcoap/examples/coap-client -m get "coap://127.0.0.1/.well-known/core" +``` + +License +------- + +Apache License Version 2.0 + +Author +------ + +EMQ X Team. + diff --git a/apps/emqx_coap/TODO b/apps/emqx_coap/TODO new file mode 100644 index 000000000..2af129d6c --- /dev/null +++ b/apps/emqx_coap/TODO @@ -0,0 +1,13 @@ +1. Remove the test/test_mqtt_broker and use emqx-ct-helpers -> Done! + - Enhance all test case + +2. Remove the mqtt adaptor +3. Remove the emqx_coap_ps_topics.erl + + +### Problems + +1. The coap-client of libcoap does not support Fragment DTLS handshake frame + * So, the connection will be established failed, if the 'Server Hello' frame is too big + * Why is the 'Server Hello' too big when enable the 'coap.dtls.cacertfile' option? +2. diff --git a/apps/emqx_coap/docs/rfc7049.pdf b/apps/emqx_coap/docs/rfc7049.pdf new file mode 100644 index 000000000..a16db36ef Binary files /dev/null and b/apps/emqx_coap/docs/rfc7049.pdf differ diff --git a/apps/emqx_coap/docs/rfc7228.pdf b/apps/emqx_coap/docs/rfc7228.pdf new file mode 100644 index 000000000..c9dc1b59f Binary files /dev/null and b/apps/emqx_coap/docs/rfc7228.pdf differ diff --git a/apps/emqx_coap/docs/rfc7252.pdf b/apps/emqx_coap/docs/rfc7252.pdf new file mode 100644 index 000000000..6876fad3e Binary files /dev/null and b/apps/emqx_coap/docs/rfc7252.pdf differ diff --git a/apps/emqx_coap/include/emqx_coap.hrl b/apps/emqx_coap/include/emqx_coap.hrl new file mode 100644 index 000000000..8204dc98c --- /dev/null +++ b/apps/emqx_coap/include/emqx_coap.hrl @@ -0,0 +1,20 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-define(APP, emqx_coap). + +-record(coap_mqtt_auth, {clientid, username, password}). + diff --git a/apps/emqx_coap/intergration_test/README.md b/apps/emqx_coap/intergration_test/README.md new file mode 100644 index 000000000..eb3507923 --- /dev/null +++ b/apps/emqx_coap/intergration_test/README.md @@ -0,0 +1,8 @@ +Integration test for emq-coap +====== + +execute following command +``` +make +``` + diff --git a/apps/emqx_coap/intergration_test/check_result.py b/apps/emqx_coap/intergration_test/check_result.py new file mode 100644 index 000000000..f9baaefae --- /dev/null +++ b/apps/emqx_coap/intergration_test/check_result.py @@ -0,0 +1,52 @@ +import sys + + +def have_string(filename, text): + data = open(filename, "rb").read() + if data.find(text) > 0: + return True + else: + return False + + +def mark(case_number, result, description): + if result: + f = open(case_number+"_PASS.txt", "wb") + f.close() + print("\n\n"+case_number+" PASS\n\n") + else: + f = open(case_number+"_FAIL.txt", "wb") + f.write(description) + f.close() + print("\n\n"+case_number+" FAIL\n\n") + +def parse_condition(condition): + if condition.find("==") > 0: + r = condition.split("==") + return r[0], r[1], True + elif condition.find("!=") > 0: + r = condition.split("!=") + return r[0], r[1], False + else: + print("\ncondition syntax error\n\n\n") + sys.exit("condition syntax error") + + +def main(): + case_number = sys.argv[1] + description = "" + conclustion = True + for condition in sys.argv[2:]: + filename, text, result = parse_condition(condition) + if have_string(filename, text) == result: + pass + else: + conclustion = False + description = description + "\n" + condition + " failed\n" + + mark(case_number, conclustion, description) + + +if __name__ == "__main__": + main() + diff --git a/apps/emqx_coap/priv/emqx_coap.schema b/apps/emqx_coap/priv/emqx_coap.schema new file mode 100644 index 000000000..465979964 --- /dev/null +++ b/apps/emqx_coap/priv/emqx_coap.schema @@ -0,0 +1,93 @@ +%%-*- mode: erlang -*- +%% emqx_coap config mapping +{mapping, "coap.bind.udp.$number", "emqx_coap.bind_udp", [ + {datatype, ip}, + {default, "0.0.0.0:5683"} +]}. + +{mapping, "coap.enable_stats", "emqx_coap.enable_stats", [ + {datatype, flag} +]}. + +{mapping, "coap.bind.dtls.$number", "emqx_coap.bind_dtls", [ + {datatype, ip}, + {default, "0.0.0.0:5684"} +]}. + +{mapping, "coap.dtls.keyfile", "emqx_coap.dtls_opts", [ + {datatype, string} +]}. + +{mapping, "coap.dtls.certfile", "emqx_coap.dtls_opts", [ + {datatype, string} +]}. + +{mapping, "coap.dtls.verify", "emqx_coap.dtls_opts", [ + {default, verify_none}, + {datatype, {enum, [verify_none, verify_peer]}} +]}. + +{mapping, "coap.dtls.cacertfile", "emqx_coap.dtls_opts", [ + {datatype, string} +]}. + +{mapping, "coap.dtls.fail_if_no_peer_cert", "emqx_coap.dtls_opts", [ + {datatype, {enum, [true, false]}} +]}. + +{mapping, "coap.dtls.ciphers", "emqx_coap.dtls_opts", [ + {datatype, string} +]}. + +{translation, "emqx_coap.bind_udp", fun(Conf) -> + Options = cuttlefish_variable:filter_by_prefix("coap.bind.udp", Conf), + lists:map(fun({_, Bind}) -> + {Ip, Port} = cuttlefish_datatypes:from_string(Bind, ip), + Opts = case inet:parse_address(Ip) of + {ok, {_,_,_,_} = Address} -> + [inet, {ip, Address}]; + {ok, {_,_,_,_,_,_,_,_} = Address} -> + [inet6, {ip, Address}] + end, + {Port, Opts} + end, Options) +end}. + +{translation, "emqx_coap.bind_dtls", fun(Conf) -> + Options = cuttlefish_variable:filter_by_prefix("coap.bind.dtls", Conf), + lists:map(fun({_, Bind}) -> + {Ip, Port} = cuttlefish_datatypes:from_string(Bind, ip), + Opts = case inet:parse_address(Ip) of + {ok, {_,_,_,_} = Address} -> + [inet, {ip, Address}]; + {ok, {_,_,_,_,_,_,_,_} = Address} -> + [inet6, {ip, Address}] + end, + {Port, Opts} + end, Options) +end}. + +{translation, "emqx_coap.dtls_opts", fun(Conf) -> + Filter = fun(Opts) -> [{K, V} || {K, V} <- Opts, V =/= undefined] end, + + %% Ciphers + SplitFun = fun(undefined) -> undefined; (S) -> string:tokens(S, ",") end, + Ciphers = + case cuttlefish:conf_get("coap.dtls.ciphers", Conf, undefined) of + undefined -> + lists:foldl( + fun(TlsVer, Ciphers) -> + Ciphers ++ ssl:cipher_suites(all, TlsVer) + end, [], ['dtlsv1', 'dtlsv1.2']); + C -> + SplitFun(C) + end, + + Filter([{verify, cuttlefish:conf_get("coap.dtls.verify", Conf, undefined)}, + {keyfile, cuttlefish:conf_get("coap.dtls.keyfile", Conf, undefined)}, + {certfile, cuttlefish:conf_get("coap.dtls.certfile", Conf, undefined)}, + {cacertfile, cuttlefish:conf_get("coap.dtls.cacertfile", Conf, undefined)}, + {fail_if_no_peer_cert, cuttlefish:conf_get("coap.dtls.fail_if_no_peer_cert", Conf, undefined)}, + {ciphers, Ciphers}]) +end}. + diff --git a/apps/emqx_coap/rebar.config b/apps/emqx_coap/rebar.config new file mode 100644 index 000000000..655e3b14f --- /dev/null +++ b/apps/emqx_coap/rebar.config @@ -0,0 +1,4 @@ +{deps, + [ + {gen_coap, {git, "https://github.com/emqx/gen_coap", {tag, "v0.3.0"}}} + ]}. \ No newline at end of file diff --git a/apps/emqx_coap/src/emqx_coap.app.src b/apps/emqx_coap/src/emqx_coap.app.src new file mode 100644 index 000000000..a47d62980 --- /dev/null +++ b/apps/emqx_coap/src/emqx_coap.app.src @@ -0,0 +1,14 @@ +{application, emqx_coap, + [{description, "EMQ X CoAP Gateway"}, + {vsn, "5.0.0"}, % strict semver, bump manually! + {modules, []}, + {registered, []}, + {applications, [kernel,stdlib,gen_coap,emqx_libs]}, + {mod, {emqx_coap_app, []}}, + {env, []}, + {licenses, ["Apache-2.0"]}, + {maintainers, ["EMQ X Team "]}, + {links, [{"Homepage", "https://emqx.io/"}, + {"Github", "https://github.com/emqx/emqx-coap"} + ]} + ]}. diff --git a/apps/emqx_coap/src/emqx_coap_app.erl b/apps/emqx_coap/src/emqx_coap_app.erl new file mode 100644 index 000000000..eaabd356b --- /dev/null +++ b/apps/emqx_coap/src/emqx_coap_app.erl @@ -0,0 +1,40 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_coap_app). + +-behaviour(application). + +-emqx_plugin(protocol). + +-include("emqx_coap.hrl"). + +-export([ start/2 + , stop/1 + ]). + +start(_Type, _Args) -> + {ok, Sup} = emqx_coap_sup:start_link(), + coap_server_registry:add_handler([<<"mqtt">>], emqx_coap_resource, undefined), + coap_server_registry:add_handler([<<"ps">>], emqx_coap_ps_resource, undefined), + emqx_coap_ps_topics:start_link(), + emqx_coap_server:start(application:get_all_env(?APP)), + {ok,Sup}. + +stop(_State) -> + coap_server_registry:remove_handler([<<"mqtt">>], emqx_coap_resource, undefined), + coap_server_registry:remove_handler([<<"ps">>], emqx_coap_ps_resource, undefined), + emqx_coap_server:stop(application:get_all_env(?APP)). diff --git a/apps/emqx_coap/src/emqx_coap_mqtt_adapter.erl b/apps/emqx_coap/src/emqx_coap_mqtt_adapter.erl new file mode 100644 index 000000000..6580f8677 --- /dev/null +++ b/apps/emqx_coap/src/emqx_coap_mqtt_adapter.erl @@ -0,0 +1,357 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_coap_mqtt_adapter). + +-behaviour(gen_server). + +-include("emqx_coap.hrl"). + +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). + +-logger_header("[CoAP-Adpter]"). + +%% API. +-export([ subscribe/2 + , unsubscribe/2 + , publish/3 + ]). + +-export([ client_pid/4 + , stop/1 + ]). + +-export([call/2]). + +%% gen_server. +-export([ init/1 + , handle_call/3 + , handle_cast/2 + , handle_info/2 + , terminate/2 + , code_change/3 + ]). + +-record(state, {peername, clientid, username, password, sub_topics = [], connected_at}). + +-define(ALIVE_INTERVAL, 20000). + +-define(CONN_STATS, [recv_pkt, recv_msg, send_pkt, send_msg]). + +-define(SUBOPTS, #{rh => 0, rap => 0, nl => 0, qos => ?QOS_0, is_new => false}). + +%%-------------------------------------------------------------------- +%% API +%%-------------------------------------------------------------------- + +client_pid(undefined, _Username, _Password, _Channel) -> + {error, bad_request}; +client_pid(ClientId, Username, Password, Channel) -> + % check authority + case start(ClientId, Username, Password, Channel) of + {ok, Pid1} -> {ok, Pid1}; + {error, {already_started, Pid2}} -> {ok, Pid2}; + {error, auth_failure} -> {error, auth_failure}; + Other -> {error, Other} + end. + +start(ClientId, Username, Password, Channel) -> + % DO NOT use start_link, since multiple coap_reponsder may have relation with one mqtt adapter, + % one coap_responder crashes should not make mqtt adapter crash too + % And coap_responder is not a system process, it is dangerous to link mqtt adapter to coap_responder + gen_server:start({via, emqx_coap_registry, {ClientId, Username, Password}}, ?MODULE, {ClientId, Username, Password, Channel}, []). + +stop(Pid) -> + gen_server:stop(Pid). + +subscribe(Pid, Topic) -> + gen_server:call(Pid, {subscribe, Topic, self()}). + +unsubscribe(Pid, Topic) -> + gen_server:call(Pid, {unsubscribe, Topic, self()}). + +publish(Pid, Topic, Payload) -> + gen_server:call(Pid, {publish, Topic, Payload}). + +%% For emqx_management plugin +call(Pid, Msg) -> + Pid ! Msg, ok. + +%%-------------------------------------------------------------------- +%% gen_server Callbacks +%%-------------------------------------------------------------------- + +init({ClientId, Username, Password, Channel}) -> + ?LOG(debug, "try to start adapter ClientId=~p, Username=~p, Password=~p, Channel=~p", + [ClientId, Username, Password, Channel]), + State0 = #state{peername = Channel, + clientid = ClientId, + username = Username, + password = Password}, + _ = run_hooks('client.connect', [conninfo(State0)], undefined), + case emqx_access_control:authenticate(clientinfo(State0)) of + {ok, _AuthResult} -> + _ = run_hooks('client.connack', [conninfo(State0), success], undefined), + + State = State0#state{connected_at = erlang:system_time(millisecond)}, + + %% TODO: Evict same clientid on other node?? + + run_hooks('client.connected', [clientinfo(State), conninfo(State)]), + + erlang:send_after(?ALIVE_INTERVAL, self(), check_alive), + emqx_cm:register_channel(ClientId, info(State), stats(State)), + {ok, State}; + {error, Reason} -> + ?LOG(debug, "authentication faild: ~p", [Reason]), + _ = run_hooks('client.connack', [conninfo(State0), not_authorized], undefined), + {stop, {shutdown, Reason}} + end. + +handle_call({subscribe, Topic, CoapPid}, _From, State=#state{sub_topics = TopicList}) -> + NewTopics = proplists:delete(Topic, TopicList), + IsWild = emqx_topic:wildcard(Topic), + chann_subscribe(Topic, State), + {reply, ok, State#state{sub_topics = [{Topic, {IsWild, CoapPid}}|NewTopics]}, hibernate}; + +handle_call({unsubscribe, Topic, _CoapPid}, _From, State=#state{sub_topics = TopicList}) -> + NewTopics = proplists:delete(Topic, TopicList), + chann_unsubscribe(Topic, State), + {reply, ok, State#state{sub_topics = NewTopics}, hibernate}; + +handle_call({publish, Topic, Payload}, _From, State) -> + chann_publish(Topic, Payload, State), + {reply, ok, State}; + +handle_call(info, _From, State) -> + {reply, info(State), State}; + +handle_call(stats, _From, State) -> + {reply, stats(State), State, hibernate}; + +handle_call(kick, _From, State) -> + {stop, {shutdown, kick}, ok, State}; + +handle_call({set_rate_limit, _Rl}, _From, State) -> + ?LOG(error, "set_rate_limit is not support", []), + {reply, ok, State}; + +handle_call(get_rate_limit, _From, State) -> + ?LOG(error, "get_rate_limit is not support", []), + {reply, ok, State}; + +handle_call(Request, _From, State) -> + ?LOG(error, "adapter unexpected call ~p", [Request]), + {reply, ignored, State, hibernate}. + +handle_cast(Msg, State) -> + ?LOG(error, "broker_api unexpected cast ~p", [Msg]), + {noreply, State, hibernate}. + +handle_info({deliver, _Topic, #message{topic = Topic, payload = Payload}}, State = #state{sub_topics = Subscribers}) -> + deliver([{Topic, Payload}], Subscribers), + {noreply, State, hibernate}; + +handle_info(check_alive, State = #state{sub_topics = []}) -> + {stop, {shutdown, check_alive}, State}; +handle_info(check_alive, State) -> + erlang:send_after(?ALIVE_INTERVAL, self(), check_alive), + {noreply, State, hibernate}; + +handle_info({shutdown, Error}, State) -> + {stop, {shutdown, Error}, State}; + +handle_info({shutdown, conflict, {ClientId, NewPid}}, State) -> + ?LOG(warning, "clientid '~s' conflict with ~p", [ClientId, NewPid]), + {stop, {shutdown, conflict}, State}; + +handle_info(kick, State) -> + ?LOG(info, "Kicked", []), + {stop, {shutdown, kick}, State}; + +handle_info(Info, State) -> + ?LOG(error, "adapter unexpected info ~p", [Info]), + {noreply, State, hibernate}. + +terminate(Reason, State = #state{clientid = ClientId, sub_topics = SubTopics}) -> + ?LOG(debug, "unsubscribe ~p while exiting for ~p", [SubTopics, Reason]), + [chann_unsubscribe(Topic, State) || {Topic, _} <- SubTopics], + emqx_cm:unregister_channel(ClientId), + + ConnInfo0 = conninfo(State), + ConnInfo = ConnInfo0#{disconnected_at => erlang:system_time(millisecond)}, + run_hooks('client.disconnected', [clientinfo(State), Reason, ConnInfo]). + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +%%-------------------------------------------------------------------- +%% Channel adapter functions + +chann_subscribe(Topic, State = #state{clientid = ClientId}) -> + ?LOG(debug, "subscribe Topic=~p", [Topic]), + emqx_broker:subscribe(Topic, ClientId, ?SUBOPTS), + emqx_hooks:run('session.subscribed', [clientinfo(State), Topic, ?SUBOPTS]). + +chann_unsubscribe(Topic, State) -> + ?LOG(debug, "unsubscribe Topic=~p", [Topic]), + Opts = #{rh => 0, rap => 0, nl => 0, qos => 0}, + emqx_broker:unsubscribe(Topic), + emqx_hooks:run('session.unsubscribed', [clientinfo(State), Topic, Opts]). + +chann_publish(Topic, Payload, #state{clientid = ClientId}) -> + ?LOG(debug, "publish Topic=~p, Payload=~p", [Topic, Payload]), + emqx_broker:publish( + emqx_message:set_flag(retain, false, + emqx_message:make(ClientId, ?QOS_0, Topic, Payload))). + +%%-------------------------------------------------------------------- +%% Deliver + +deliver([], _) -> ok; +deliver([Pub | More], Subscribers) -> + ok = do_deliver(Pub, Subscribers), + deliver(More, Subscribers). + +do_deliver({Topic, Payload}, Subscribers) -> + %% handle PUBLISH packet from broker + ?LOG(debug, "deliver message from broker Topic=~p, Payload=~p", [Topic, Payload]), + deliver_to_coap(Topic, Payload, Subscribers), + ok; + +do_deliver(Pkt, _Subscribers) -> + ?LOG(warning, "unknown packet type to deliver, pkt=~p,", [Pkt]), + ok. + +deliver_to_coap(_TopicName, _Payload, []) -> + ok; +deliver_to_coap(TopicName, Payload, [{TopicFilter, {IsWild, CoapPid}}|T]) -> + Matched = case IsWild of + true -> emqx_topic:match(TopicName, TopicFilter); + false -> TopicName =:= TopicFilter + end, + %?LOG(debug, "deliver_to_coap Matched=~p, CoapPid=~p, TopicName=~p, Payload=~p, T=~p", [Matched, CoapPid, TopicName, Payload, T]), + Matched andalso (CoapPid ! {dispatch, TopicName, Payload}), + deliver_to_coap(TopicName, Payload, T). + +%%-------------------------------------------------------------------- +%% Helper funcs + +-compile({inline, [run_hooks/2, run_hooks/3]}). +run_hooks(Name, Args) -> + ok = emqx_metrics:inc(Name), emqx_hooks:run(Name, Args). + +run_hooks(Name, Args, Acc) -> + ok = emqx_metrics:inc(Name), emqx_hooks:run_fold(Name, Args, Acc). + +%%-------------------------------------------------------------------- +%% Info & Stats + +info(State) -> + ChannInfo = chann_info(State), + ChannInfo#{sockinfo => sockinfo(State)}. + +%% copies from emqx_connection:info/1 +sockinfo(#state{peername = Peername}) -> + #{socktype => udp, + peername => Peername, + sockname => {{127,0,0,1}, 5683}, %% FIXME: Sock? + sockstate => running, + active_n => 1 + }. + +%% copies from emqx_channel:info/1 +chann_info(State) -> + #{conninfo => conninfo(State), + conn_state => connected, + clientinfo => clientinfo(State), + session => maps:from_list(session_info(State)), + will_msg => undefined + }. + +conninfo(#state{peername = Peername, + clientid = ClientId, + connected_at = ConnectedAt}) -> + #{socktype => udp, + sockname => {{127,0,0,1}, 5683}, + peername => Peername, + peercert => nossl, %% TODO: dtls + conn_mod => ?MODULE, + proto_name => <<"CoAP">>, + proto_ver => 1, + clean_start => true, + clientid => ClientId, + username => undefined, + conn_props => undefined, + connected => true, + connected_at => ConnectedAt, + keepalive => 0, + receive_maximum => 0, + expiry_interval => 0 + }. + +%% copies from emqx_session:info/1 +session_info(#state{sub_topics = SubTopics, connected_at = ConnectedAt}) -> + Subs = lists:foldl( + fun({Topic, _}, Acc) -> + Acc#{Topic => ?SUBOPTS} + end, #{}, SubTopics), + [{subscriptions, Subs}, + {upgrade_qos, false}, + {retry_interval, 0}, + {await_rel_timeout, 0}, + {created_at, ConnectedAt} + ]. + +%% The stats keys copied from emqx_connection:stats/1 +stats(#state{sub_topics = SubTopics}) -> + SockStats = [{recv_oct,0}, {recv_cnt,0}, {send_oct,0}, {send_cnt,0}, {send_pend,0}], + ConnStats = emqx_pd:get_counters(?CONN_STATS), + ChanStats = [{subscriptions_cnt, length(SubTopics)}, + {subscriptions_max, length(SubTopics)}, + {inflight_cnt, 0}, + {inflight_max, 0}, + {mqueue_len, 0}, + {mqueue_max, 0}, + {mqueue_dropped, 0}, + {next_pkt_id, 0}, + {awaiting_rel_cnt, 0}, + {awaiting_rel_max, 0} + ], + ProcStats = emqx_misc:proc_stats(), + lists:append([SockStats, ConnStats, ChanStats, ProcStats]). + +clientinfo(#state{peername = {PeerHost, _}, + clientid = ClientId, + username = Username, + password = Password}) -> + #{zone => undefined, + protocol => coap, + peerhost => PeerHost, + sockport => 5683, %% FIXME: + clientid => ClientId, + username => Username, + password => Password, + peercert => nossl, + is_bridge => false, + is_superuser => false, + mountpoint => undefined, + ws_cookie => undefined + }. + diff --git a/apps/emqx_coap/src/emqx_coap_ps_resource.erl b/apps/emqx_coap/src/emqx_coap_ps_resource.erl new file mode 100644 index 000000000..781477ac2 --- /dev/null +++ b/apps/emqx_coap/src/emqx_coap_ps_resource.erl @@ -0,0 +1,318 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_coap_ps_resource). + +-behaviour(coap_resource). + +-include("emqx_coap.hrl"). +-include_lib("gen_coap/include/coap.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). + +-logger_header("[CoAP-PS-RES]"). + +-export([ coap_discover/2 + , coap_get/5 + , coap_post/4 + , coap_put/4 + , coap_delete/3 + , coap_observe/5 + , coap_unobserve/1 + , handle_info/2 + , coap_ack/2 + ]). + +-ifdef(TEST). +-export([topic/1]). +-endif. + +-define(PS_PREFIX, [<<"ps">>]). + +%%-------------------------------------------------------------------- +%% Resource Callbacks +%%-------------------------------------------------------------------- +coap_discover(_Prefix, _Args) -> + [{absolute, [<<"ps">>], []}]. + +coap_get(ChId, ?PS_PREFIX, TopicPath, Query, Content=#coap_content{format = Format}) when TopicPath =/= [] -> + Topic = topic(TopicPath), + ?LOG(debug, "coap_get() Topic=~p, Query=~p~n", [Topic, Query]), + #coap_mqtt_auth{clientid = Clientid, username = Usr, password = Passwd} = get_auth(Query), + case emqx_coap_mqtt_adapter:client_pid(Clientid, Usr, Passwd, ChId) of + {ok, Pid} -> + put(mqtt_client_pid, Pid), + case Format of + <<"application/link-format">> -> + Content; + _Other -> + %% READ the topic info + read_last_publish_message(emqx_topic:wildcard(Topic), Topic, Content) + end; + {error, auth_failure} -> + put(mqtt_client_pid, undefined), + {error, uauthorized}; + {error, bad_request} -> + put(mqtt_client_pid, undefined), + {error, bad_request}; + {error, _Other} -> + put(mqtt_client_pid, undefined), + {error, internal_server_error} + end; +coap_get(ChId, Prefix, TopicPath, Query, _Content) -> + ?LOG(error, "ignore bad get request ChId=~p, Prefix=~p, TopicPath=~p, Query=~p", [ChId, Prefix, TopicPath, Query]), + {error, bad_request}. + +coap_post(_ChId, ?PS_PREFIX, TopicPath, #coap_content{format = Format, payload = Payload, max_age = MaxAge}) when TopicPath =/= [] -> + Topic = topic(TopicPath), + ?LOG(debug, "coap_post() Topic=~p, MaxAge=~p, Format=~p~n", [Topic, MaxAge, Format]), + case Format of + %% We treat ct of "application/link-format" as CREATE message + <<"application/link-format">> -> + handle_received_create(Topic, MaxAge, Payload); + %% We treat ct of other values as PUBLISH message + Other -> + ?LOG(debug, "coap_post() receive payload format=~p, will process as PUBLISH~n", [Format]), + handle_received_publish(Topic, MaxAge, Other, Payload) + end; + +coap_post(_ChId, _Prefix, _TopicPath, _Content) -> + {error, method_not_allowed}. + +coap_put(_ChId, ?PS_PREFIX, TopicPath, #coap_content{max_age = MaxAge, format = Format, payload = Payload}) when TopicPath =/= [] -> + Topic = topic(TopicPath), + ?LOG(debug, "put message, Topic=~p, Payload=~p~n", [Topic, Payload]), + handle_received_publish(Topic, MaxAge, Format, Payload); + +coap_put(_ChId, Prefix, TopicPath, Content) -> + ?LOG(error, "put has error, Prefix=~p, TopicPath=~p, Content=~p", [Prefix, TopicPath, Content]), + {error, bad_request}. + +coap_delete(_ChId, ?PS_PREFIX, TopicPath) -> + delete_topic_info(topic(TopicPath)); + +coap_delete(_ChId, _Prefix, _TopicPath) -> + {error, method_not_allowed}. + +coap_observe(ChId, ?PS_PREFIX, TopicPath, Ack, Content) when TopicPath =/= [] -> + Topic = topic(TopicPath), + ?LOG(debug, "observe Topic=~p, Ack=~p,Content=~p", [Topic, Ack, Content]), + Pid = get(mqtt_client_pid), + emqx_coap_mqtt_adapter:subscribe(Pid, Topic), + Code = case emqx_coap_ps_topics:is_topic_timeout(Topic) of + true -> + nocontent; + false-> + content + end, + {ok, {state, ChId, ?PS_PREFIX, [Topic]}, Code, Content}; + +coap_observe(ChId, Prefix, TopicPath, Ack, _Content) -> + ?LOG(error, "unknown observe request ChId=~p, Prefix=~p, TopicPath=~p, Ack=~p", [ChId, Prefix, TopicPath, Ack]), + {error, bad_request}. + +coap_unobserve({state, _ChId, ?PS_PREFIX, TopicPath}) when TopicPath =/= [] -> + Topic = topic(TopicPath), + ?LOG(debug, "unobserve ~p", [Topic]), + Pid = get(mqtt_client_pid), + emqx_coap_mqtt_adapter:unsubscribe(Pid, Topic), + ok; +coap_unobserve({state, ChId, Prefix, TopicPath}) -> + ?LOG(error, "ignore unknown unobserve request ChId=~p, Prefix=~p, TopicPath=~p", [ChId, Prefix, TopicPath]), + ok. + +handle_info({dispatch, Topic, Payload}, State) -> + ?LOG(debug, "dispatch Topic=~p, Payload=~p", [Topic, Payload]), + {ok, Ret} = emqx_coap_ps_topics:reset_topic_info(Topic, Payload), + ?LOG(debug, "Updated publish info of topic=~p, the Ret is ~p", [Topic, Ret]), + {notify, [], #coap_content{format = <<"application/octet-stream">>, payload = Payload}, State}; +handle_info(Message, State) -> + ?LOG(error, "Unknown Message ~p", [Message]), + {noreply, State}. + +coap_ack(_Ref, State) -> {ok, State}. + + +%%-------------------------------------------------------------------- +%% Internal Functions +%%-------------------------------------------------------------------- +get_auth(Query) -> + get_auth(Query, #coap_mqtt_auth{}). + +get_auth([], Auth=#coap_mqtt_auth{}) -> + Auth; +get_auth([<<$c, $=, Rest/binary>>|T], Auth=#coap_mqtt_auth{}) -> + get_auth(T, Auth#coap_mqtt_auth{clientid = Rest}); +get_auth([<<$u, $=, Rest/binary>>|T], Auth=#coap_mqtt_auth{}) -> + get_auth(T, Auth#coap_mqtt_auth{username = Rest}); +get_auth([<<$p, $=, Rest/binary>>|T], Auth=#coap_mqtt_auth{}) -> + get_auth(T, Auth#coap_mqtt_auth{password = Rest}); +get_auth([Param|T], Auth=#coap_mqtt_auth{}) -> + ?LOG(error, "ignore unknown parameter ~p", [Param]), + get_auth(T, Auth). + +add_topic_info(publish, Topic, MaxAge, Format, Payload) when is_binary(Topic), Topic =/= <<>> -> + case emqx_coap_ps_topics:lookup_topic_info(Topic) of + [{_, StoredMaxAge, StoredCT, _, _}] -> + ?LOG(debug, "publish topic=~p already exists, need reset the topic info", [Topic]), + %% check whether the ct value stored matches the ct option in this POST message + case Format =:= StoredCT of + true -> + {ok, Ret} = + case StoredMaxAge =:= MaxAge of + true -> + emqx_coap_ps_topics:reset_topic_info(Topic, Payload); + false -> + emqx_coap_ps_topics:reset_topic_info(Topic, MaxAge, Payload) + end, + {changed, Ret}; + false -> + ?LOG(debug, "ct values of topic=~p do not match, stored ct=~p, new ct=~p, ignore the PUBLISH", [Topic, StoredCT, Format]), + {changed, false} + end; + [] -> + ?LOG(debug, "publish topic=~p will be created", [Topic]), + {ok, Ret} = emqx_coap_ps_topics:add_topic_info(Topic, MaxAge, Format, Payload), + {created, Ret} + end; + +add_topic_info(create, Topic, MaxAge, Format, _Payload) when is_binary(Topic), Topic =/= <<>> -> + case emqx_coap_ps_topics:is_topic_existed(Topic) of + true -> + %% Whether we should support CREATE to an existed topic is TBD!! + ?LOG(debug, "create topic=~p already exists, need reset the topic info", [Topic]), + {ok, Ret} = emqx_coap_ps_topics:reset_topic_info(Topic, MaxAge, Format, <<>>); + false -> + ?LOG(debug, "create topic=~p will be created", [Topic]), + {ok, Ret} = emqx_coap_ps_topics:add_topic_info(Topic, MaxAge, Format, <<>>) + end, + {created, Ret}; + +add_topic_info(_, Topic, _MaxAge, _Format, _Payload) -> + ?LOG(debug, "create topic=~p info failed", [Topic]), + {badarg, false}. + +concatenate_location_path(List = [TopicPart1, TopicPart2, TopicPart3]) when is_binary(TopicPart1), is_binary(TopicPart2), is_binary(TopicPart3) -> + list_to_binary(lists:foldl( fun (Element, AccIn) when Element =/= <<>> -> + AccIn ++ "/" ++ binary_to_list(Element); + (_Element, AccIn) -> + AccIn + end, [], List)). + +format_string_to_int(<<"application/octet-stream">>) -> + <<"42">>; +format_string_to_int(<<"application/exi">>) -> + <<"47">>; +format_string_to_int(<<"application/json">>) -> + <<"50">>. + +handle_received_publish(Topic, MaxAge, Format, Payload) -> + case add_topic_info(publish, Topic, MaxAge, format_string_to_int(Format), Payload) of + {Ret ,true} -> + Pid = get(mqtt_client_pid), + emqx_coap_mqtt_adapter:publish(Pid, topic(Topic), Payload), + Content = case Ret of + changed -> + #coap_content{}; + created -> + LocPath = concatenate_location_path([<<"ps">>, Topic, <<>>]), + #coap_content{location_path = [LocPath]} + end, + {ok, Ret, Content}; + {_, false} -> + ?LOG(debug, "add_topic_info failed, will return bad_request", []), + {error, bad_request} + end. + +handle_received_create(TopicPrefix, MaxAge, Payload) -> + case core_link:decode(Payload) of + [{rootless, [Topic], [{ct, CT}]}] when is_binary(Topic), Topic =/= <<>> -> + TrueTopic = http_uri:decode(Topic), + ?LOG(debug, "decoded link-format payload, the Topic=~p, CT=~p~n", [TrueTopic, CT]), + LocPath = concatenate_location_path([<<"ps">>, TopicPrefix, TrueTopic]), + FullTopic = binary:part(LocPath, 4, byte_size(LocPath)-4), + ?LOG(debug, "the location path is ~p, the full topic is ~p~n", [LocPath, FullTopic]), + case add_topic_info(create, FullTopic, MaxAge, CT, <<>>) of + {_, true} -> + ?LOG(debug, "create topic info successfully, will return LocPath=~p", [LocPath]), + {ok, created, #coap_content{location_path = [LocPath]}}; + {_, false} -> + ?LOG(debug, "create topic info failed, will return bad_request", []), + {error, bad_request} + end; + Other -> + ?LOG(debug, "post with bad payload of link-format ~p, will return bad_request", [Other]), + {error, bad_request} + end. + +%% When topic is timeout, server should return nocontent here, +%% but gen_coap only receive return value of #coap_content from coap_get, so temporarily we can't give the Code 2.07 {ok, nocontent} out.TBC!!! +return_resource(Topic, Payload, MaxAge, TimeStamp, Content) -> + TimeElapsed = trunc((erlang:system_time(millisecond) - TimeStamp) / 1000), + case TimeElapsed < MaxAge of + true -> + LeftTime = (MaxAge - TimeElapsed), + ?LOG(debug, "topic=~p has max age left time is ~p", [Topic, LeftTime]), + Content#coap_content{max_age = LeftTime, payload = Payload}; + false -> + ?LOG(debug, "topic=~p has been timeout, will return empty content", [Topic]), + #coap_content{} + end. + +read_last_publish_message(false, Topic, Content=#coap_content{format = QueryFormat}) when is_binary(QueryFormat)-> + ?LOG(debug, "the QueryFormat=~p", [QueryFormat]), + case emqx_coap_ps_topics:lookup_topic_info(Topic) of + [] -> + {error, not_found}; + [{_, MaxAge, CT, Payload, TimeStamp}] -> + case CT =:= format_string_to_int(QueryFormat) of + true -> + return_resource(Topic, Payload, MaxAge, TimeStamp, Content); + false -> + ?LOG(debug, "format value does not match, the queried format=~p, the stored format=~p", [QueryFormat, CT]), + {error, bad_request} + end + end; + +read_last_publish_message(false, Topic, Content) -> + case emqx_coap_ps_topics:lookup_topic_info(Topic) of + [] -> + {error, not_found}; + [{_, MaxAge, _, Payload, TimeStamp}] -> + return_resource(Topic, Payload, MaxAge, TimeStamp, Content) + end; + +read_last_publish_message(true, Topic, _Content) -> + ?LOG(debug, "the topic=~p is illegal wildcard topic", [Topic]), + {error, bad_request}. + +delete_topic_info(Topic) -> + case emqx_coap_ps_topics:lookup_topic_info(Topic) of + [] -> + {error, not_found}; + [{_, _, _, _, _}] -> + emqx_coap_ps_topics:delete_sub_topics(Topic) + end. + +topic(Topic) when is_binary(Topic) -> Topic; +topic([]) -> <<>>; +topic([Path | TopicPath]) -> + case topic(TopicPath) of + <<>> -> Path; + RemTopic -> + <> + end. diff --git a/apps/emqx_coap/src/emqx_coap_ps_topics.erl b/apps/emqx_coap/src/emqx_coap_ps_topics.erl new file mode 100644 index 000000000..ebe9c3b28 --- /dev/null +++ b/apps/emqx_coap/src/emqx_coap_ps_topics.erl @@ -0,0 +1,185 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_coap_ps_topics). + +-behaviour(gen_server). + +-include("emqx_coap.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). + +-logger_header("[CoAP-PS-TOPICS]"). + +-export([ start_link/0 + , stop/1 + ]). + +-export([ add_topic_info/4 + , delete_topic_info/1 + , delete_sub_topics/1 + , is_topic_existed/1 + , is_topic_timeout/1 + , reset_topic_info/2 + , reset_topic_info/3 + , reset_topic_info/4 + , lookup_topic_info/1 + , lookup_topic_payload/1 + ]). + +%% gen_server. +-export([ init/1 + , handle_call/3 + , handle_cast/2 + , handle_info/2 + , terminate/2 + , code_change/3 + ]). + +-record(state, {}). + +-define(COAP_TOPIC_TABLE, coap_topic). + +%%-------------------------------------------------------------------- +%% API +%%-------------------------------------------------------------------- + +start_link() -> + gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). + +stop(Pid) -> + gen_server:stop(Pid). + +add_topic_info(Topic, MaxAge, CT, Payload) when is_binary(Topic), is_integer(MaxAge), is_binary(CT), is_binary(Payload) -> + gen_server:call(?MODULE, {add_topic, {Topic, MaxAge, CT, Payload}}). + +delete_topic_info(Topic) when is_binary(Topic) -> + gen_server:call(?MODULE, {remove_topic, Topic}). + +delete_sub_topics(Topic) when is_binary(Topic) -> + gen_server:cast(?MODULE, {remove_sub_topics, Topic}). + +reset_topic_info(Topic, Payload) -> + gen_server:call(?MODULE, {reset_topic, {Topic, Payload}}). + +reset_topic_info(Topic, MaxAge, Payload) -> + gen_server:call(?MODULE, {reset_topic, {Topic, MaxAge, Payload}}). + +reset_topic_info(Topic, MaxAge, CT, Payload) -> + gen_server:call(?MODULE, {reset_topic, {Topic, MaxAge, CT, Payload}}). + +is_topic_existed(Topic) -> + ets:member(?COAP_TOPIC_TABLE, Topic). + +is_topic_timeout(Topic) when is_binary(Topic) -> + [{Topic, MaxAge, _, _, TimeStamp}] = ets:lookup(?COAP_TOPIC_TABLE, Topic), + %% MaxAge: x seconds + MaxAge < ((erlang:system_time(millisecond) - TimeStamp) / 1000). + +lookup_topic_info(Topic) -> + ets:lookup(?COAP_TOPIC_TABLE, Topic). + +lookup_topic_payload(Topic) -> + try ets:lookup_element(?COAP_TOPIC_TABLE, Topic, 4) + catch + error:badarg -> undefined + end. + +%%-------------------------------------------------------------------- +%% gen_server callbacks +%%-------------------------------------------------------------------- + +init([]) -> + ets:new(?COAP_TOPIC_TABLE, [set, named_table, protected]), + ?LOG(debug, "Create the coap_topic table", []), + {ok, #state{}}. + +handle_call({add_topic, {Topic, MaxAge, CT, Payload}}, _From, State) -> + Ret = create_table_element(Topic, MaxAge, CT, Payload), + {reply, {ok, Ret}, State, hibernate}; + +handle_call({reset_topic, {Topic, Payload}}, _From, State) -> + Ret = update_table_element(Topic, Payload), + {reply, {ok, Ret}, State, hibernate}; + +handle_call({reset_topic, {Topic, MaxAge, Payload}}, _From, State) -> + Ret = update_table_element(Topic, MaxAge, Payload), + {reply, {ok, Ret}, State, hibernate}; + +handle_call({reset_topic, {Topic, MaxAge, CT, Payload}}, _From, State) -> + Ret = update_table_element(Topic, MaxAge, CT, Payload), + {reply, {ok, Ret}, State, hibernate}; + +handle_call({remove_topic, {Topic, _Content}}, _From, State) -> + ets:delete(?COAP_TOPIC_TABLE, Topic), + ?LOG(debug, "Remove topic ~p in the coap_topic table", [Topic]), + {reply, ok, State, hibernate}; + +handle_call(Request, _From, State) -> + ?LOG(error, "adapter unexpected call ~p", [Request]), + {reply, ignored, State, hibernate}. + +handle_cast({remove_sub_topics, TopicPrefix}, State) -> + DeletedTopicNum = ets:foldl(fun ({Topic, _, _, _, _}, AccIn) -> + case binary:match(Topic, TopicPrefix) =/= nomatch of + true -> + ?LOG(debug, "Remove topic ~p in the coap_topic table", [Topic]), + ets:delete(?COAP_TOPIC_TABLE, Topic), + AccIn + 1; + false -> + AccIn + end + end, 0, ?COAP_TOPIC_TABLE), + ?LOG(debug, "Remove number of ~p topics with prefix=~p in the coap_topic table", [DeletedTopicNum, TopicPrefix]), + {noreply, State, hibernate}; + +handle_cast(Msg, State) -> + ?LOG(error, "broker_api unexpected cast ~p", [Msg]), + {noreply, State, hibernate}. + +handle_info(Info, State) -> + ?LOG(error, "adapter unexpected info ~p", [Info]), + {noreply, State, hibernate}. + +terminate(Reason, #state{}) -> + ets:delete(?COAP_TOPIC_TABLE), + ?LOG(error, "the ~p terminate for reason ~p", [?MODULE, Reason]), + ok. + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + + +%%-------------------------------------------------------------------- +%% Internal Functions +%%-------------------------------------------------------------------- +create_table_element(Topic, MaxAge, CT, Payload) -> + TopicInfo = {Topic, MaxAge, CT, Payload, erlang:system_time(millisecond)}, + ?LOG(debug, "Insert ~p in the coap_topic table", [TopicInfo]), + ets:insert_new(?COAP_TOPIC_TABLE, TopicInfo). + +update_table_element(Topic, Payload) -> + ?LOG(debug, "Update the topic=~p only with Payload", [Topic]), + ets:update_element(?COAP_TOPIC_TABLE, Topic, [{4, Payload}, {5, erlang:system_time(millisecond)}]). + +update_table_element(Topic, MaxAge, Payload) -> + ?LOG(debug, "Update the topic=~p info of MaxAge=~p and Payload", [Topic, MaxAge]), + ets:update_element(?COAP_TOPIC_TABLE, Topic, [{2, MaxAge}, {4, Payload}, {5, erlang:system_time(millisecond)}]). + +update_table_element(Topic, MaxAge, CT, <<>>) -> + ?LOG(debug, "Update the topic=~p info of MaxAge=~p, CT=~p, payload=<<>>", [Topic, MaxAge, CT]), + ets:update_element(?COAP_TOPIC_TABLE, Topic, [{2, MaxAge}, {3, CT}, {5, erlang:system_time(millisecond)}]). diff --git a/apps/emqx_coap/src/emqx_coap_registry.erl b/apps/emqx_coap/src/emqx_coap_registry.erl new file mode 100644 index 000000000..428dcf2a5 --- /dev/null +++ b/apps/emqx_coap/src/emqx_coap_registry.erl @@ -0,0 +1,154 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_coap_registry). + +-author("Feng Lee "). + +-include("emqx_coap.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). + +-logger_header("[CoAP-Registry]"). + +-behaviour(gen_server). + +%% API. +-export([ start_link/0 + , register_name/2 + , unregister_name/1 + , whereis_name/1 + , send/2 + , stop/0 + ]). + +%% gen_server. +-export([ init/1 + , handle_call/3 + , handle_cast/2 + , handle_info/2 + , terminate/2 + , code_change/3 + ]). + +-record(state, {}). + +-define(RESPONSE_TAB, coap_response_process). +-define(RESPONSE_REF_TAB, coap_response_process_ref). + +%% ------------------------------------------------------------------ +%% API Function Definitions +%% ------------------------------------------------------------------ + + +start_link() -> + gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). + +register_name(Name, Pid) -> + gen_server:call(?MODULE, {register_name, Name, Pid}). + +unregister_name(Name) -> + gen_server:call(?MODULE, {unregister_name, Name}). + +whereis_name(Name) -> + case ets:lookup(?RESPONSE_TAB, Name) of + [] -> undefined; + [{Name, Pid, _MRef}] -> Pid + end. + +send(Name, Msg) -> + case whereis_name(Name) of + undefined -> + exit({badarg, {Name, Msg}}); + Pid when is_pid(Pid) -> + Pid ! Msg, + Pid + end. + +stop() -> + gen_server:stop(?MODULE). + + +%% ------------------------------------------------------------------ +%% gen_server Function Definitions +%% ------------------------------------------------------------------ + +init([]) -> + ets:new(?RESPONSE_TAB, [set, named_table, protected]), + ets:new(?RESPONSE_REF_TAB, [set, named_table, protected]), + {ok, #state{}}. + +handle_call({register_name, Name, Pid}, _From, State) -> + case ets:member(?RESPONSE_TAB, Name) of + false -> + MRef = monitor_client(Pid), + ets:insert(?RESPONSE_TAB, {Name, Pid, MRef}), + ets:insert(?RESPONSE_REF_TAB, {MRef, Name, Pid}), + {reply, yes, State}; + true -> {reply, no, State} + end; + +handle_call({unregister_name, Name}, _From, State) -> + case ets:lookup(?RESPONSE_TAB, Name) of + [] -> + ok; + [{Name, _Pid, MRef}] -> + erase_monitor(MRef), + ets:delete(?RESPONSE_TAB, Name), + ets:delete(?RESPONSE_REF_TAB, MRef) + end, + {reply, ok, State}; + +handle_call(_Request, _From, State) -> + {reply, ignored, State}. + +handle_cast(_Msg, State) -> + {noreply, State}. + + +handle_info({'DOWN', MRef, process, DownPid, _Reason}, State) -> + case ets:lookup(?RESPONSE_REF_TAB, MRef) of + [{MRef, Name, _Pid}] -> + ets:delete(?RESPONSE_TAB, Name), + ets:delete(?RESPONSE_REF_TAB, MRef), + erase_monitor(MRef); + [] -> + ?LOG(error, "MRef of client ~p not found", [DownPid]) + end, + {noreply, State}; + + +handle_info(_Info, State) -> + {noreply, State}. + +terminate(_Reason, _State) -> + ets:delete(?RESPONSE_TAB), + ets:delete(?RESPONSE_REF_TAB), + ok. + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + + + +%%-------------------------------------------------------------------- +%% Internal functions +%%-------------------------------------------------------------------- + +monitor_client(Pid) -> + erlang:monitor(process, Pid). + +erase_monitor(MRef) -> + catch erlang:demonitor(MRef, [flush]). diff --git a/apps/emqx_coap/src/emqx_coap_resource.erl b/apps/emqx_coap/src/emqx_coap_resource.erl new file mode 100644 index 000000000..fab7f2c20 --- /dev/null +++ b/apps/emqx_coap/src/emqx_coap_resource.erl @@ -0,0 +1,136 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_coap_resource). + +-behaviour(coap_resource). + +-include("emqx_coap.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). +-include_lib("emqx_libs/include/logger.hrl"). +-include_lib("emqx_libs/include/emqx_mqtt.hrl"). +-include_lib("gen_coap/include/coap.hrl"). + +-logger_header("[CoAP-RES]"). + +-export([ coap_discover/2 + , coap_get/5 + , coap_post/4 + , coap_put/4 + , coap_delete/3 + , coap_observe/5 + , coap_unobserve/1 + , handle_info/2 + , coap_ack/2 + ]). + +-ifdef(TEST). +-export([topic/1]). +-endif. + +-define(MQTT_PREFIX, [<<"mqtt">>]). + +% resource operations +coap_discover(_Prefix, _Args) -> + [{absolute, [<<"mqtt">>], []}]. + +coap_get(ChId, ?MQTT_PREFIX, Path, Query, _Content) -> + ?LOG(debug, "coap_get() Path=~p, Query=~p~n", [Path, Query]), + #coap_mqtt_auth{clientid = Clientid, username = Usr, password = Passwd} = get_auth(Query), + case emqx_coap_mqtt_adapter:client_pid(Clientid, Usr, Passwd, ChId) of + {ok, Pid} -> + put(mqtt_client_pid, Pid), + #coap_content{}; + {error, auth_failure} -> + put(mqtt_client_pid, undefined), + {error, unauthorized}; + {error, bad_request} -> + put(mqtt_client_pid, undefined), + {error, bad_request}; + {error, _Other} -> + put(mqtt_client_pid, undefined), + {error, internal_server_error} + end; +coap_get(ChId, Prefix, Path, Query, _Content) -> + ?LOG(error, "ignore bad get request ChId=~p, Prefix=~p, Path=~p, Query=~p", [ChId, Prefix, Path, Query]), + {error, bad_request}. + +coap_post(_ChId, _Prefix, _Topic, _Content) -> + {error, method_not_allowed}. + +coap_put(_ChId, ?MQTT_PREFIX, Topic, #coap_content{payload = Payload}) when Topic =/= [] -> + ?LOG(debug, "put message, Topic=~p, Payload=~p~n", [Topic, Payload]), + Pid = get(mqtt_client_pid), + emqx_coap_mqtt_adapter:publish(Pid, topic(Topic), Payload), + ok; +coap_put(_ChId, Prefix, Topic, Content) -> + ?LOG(error, "put has error, Prefix=~p, Topic=~p, Content=~p", [Prefix, Topic, Content]), + {error, bad_request}. + +coap_delete(_ChId, _Prefix, _Topic) -> + {error, method_not_allowed}. + +coap_observe(ChId, ?MQTT_PREFIX, Topic, Ack, Content) when Topic =/= [] -> + TrueTopic = topic(Topic), + ?LOG(debug, "observe Topic=~p, Ack=~p", [TrueTopic, Ack]), + Pid = get(mqtt_client_pid), + emqx_coap_mqtt_adapter:subscribe(Pid, TrueTopic), + {ok, {state, ChId, ?MQTT_PREFIX, [TrueTopic]}, content, Content}; +coap_observe(ChId, Prefix, Topic, Ack, _Content) -> + ?LOG(error, "unknown observe request ChId=~p, Prefix=~p, Topic=~p, Ack=~p", [ChId, Prefix, Topic, Ack]), + {error, bad_request}. + +coap_unobserve({state, _ChId, ?MQTT_PREFIX, Topic}) when Topic =/= [] -> + ?LOG(debug, "unobserve ~p", [Topic]), + Pid = get(mqtt_client_pid), + emqx_coap_mqtt_adapter:unsubscribe(Pid, topic(Topic)), + ok; +coap_unobserve({state, ChId, Prefix, Topic}) -> + ?LOG(error, "ignore unknown unobserve request ChId=~p, Prefix=~p, Topic=~p", [ChId, Prefix, Topic]), + ok. + +handle_info({dispatch, Topic, Payload}, State) -> + ?LOG(debug, "dispatch Topic=~p, Payload=~p", [Topic, Payload]), + {notify, [], #coap_content{format = <<"application/octet-stream">>, payload = Payload}, State}; +handle_info(Message, State) -> + emqx_coap_mqtt_adapter:handle_info(Message, State). + +coap_ack(_Ref, State) -> {ok, State}. + +get_auth(Query) -> + get_auth(Query, #coap_mqtt_auth{}). + +get_auth([], Auth=#coap_mqtt_auth{}) -> + Auth; +get_auth([<<$c, $=, Rest/binary>>|T], Auth=#coap_mqtt_auth{}) -> + get_auth(T, Auth#coap_mqtt_auth{clientid = Rest}); +get_auth([<<$u, $=, Rest/binary>>|T], Auth=#coap_mqtt_auth{}) -> + get_auth(T, Auth#coap_mqtt_auth{username = Rest}); +get_auth([<<$p, $=, Rest/binary>>|T], Auth=#coap_mqtt_auth{}) -> + get_auth(T, Auth#coap_mqtt_auth{password = Rest}); +get_auth([Param|T], Auth=#coap_mqtt_auth{}) -> + ?LOG(error, "ignore unknown parameter ~p", [Param]), + get_auth(T, Auth). + +topic(Topic) when is_binary(Topic) -> Topic; +topic([]) -> <<>>; +topic([Path | TopicPath]) -> + case topic(TopicPath) of + <<>> -> Path; + RemTopic -> + <> + end. + diff --git a/apps/emqx_coap/src/emqx_coap_server.erl b/apps/emqx_coap/src/emqx_coap_server.erl new file mode 100644 index 000000000..d3ed1a96e --- /dev/null +++ b/apps/emqx_coap/src/emqx_coap_server.erl @@ -0,0 +1,100 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_coap_server). + +-include("emqx_coap.hrl"). + +-export([ start/1 + , stop/1 + ]). + +%%-------------------------------------------------------------------- +%% APIs +%%-------------------------------------------------------------------- + +start(Envs) -> + {ok, _} = application:ensure_all_started(gen_coap), + start_listeners(Envs). + +stop(Envs) -> + stop_listeners(Envs). + +%%-------------------------------------------------------------------- +%% Internal funcs +%%-------------------------------------------------------------------- + +start_listeners(Envs) -> + lists:foreach(fun start_listener/1, listeners_confs(Envs)). + +stop_listeners(Envs) -> + lists:foreach(fun stop_listener/1, listeners_confs(Envs)). + +start_listener({Proto, ListenOn, Opts}) -> + case start_listener(Proto, ListenOn, Opts) of + {ok, _Pid} -> + io:format("Start coap:~s listener on ~s successfully.~n", + [Proto, format(ListenOn)]); + {error, Reason} -> + io:format(standard_error, "Failed to start coap:~s listener on ~s - ~0p~n!", + [Proto, format(ListenOn), Reason]), + error(Reason) + end. + +start_listener(udp, ListenOn, Opts) -> + coap_server:start_udp('coap:udp', ListenOn, Opts); +start_listener(dtls, ListenOn, Opts) -> + coap_server:start_dtls('coap:dtls', ListenOn, Opts). + +stop_listener({Proto, ListenOn, _Opts}) -> + Ret = stop_listener(Proto, ListenOn), + case Ret of + ok -> io:format("Stop coap:~s listener on ~s successfully.~n", + [Proto, format(ListenOn)]); + {error, Reason} -> + io:format(standard_error, "Failed to stop coap:~s listener on ~s - ~p~n.", + [Proto, format(ListenOn), Reason]) + end, + Ret. + +stop_listener(udp, ListenOn) -> + coap_server:stop_udp('coap:udp', ListenOn); +stop_listener(dtls, ListenOn) -> + coap_server:stop_dtls('coap:dtls', ListenOn). + +%% XXX: It is a temporary func to convert conf format for esockd +listeners_confs(Envs) -> + listeners_confs(udp, Envs) ++ listeners_confs(dtls, Envs). + +listeners_confs(udp, Envs) -> + Udps = proplists:get_value(bind_udp, Envs, []), + [{udp, Port, [{udp_options, InetOpts}]} || {Port, InetOpts} <- Udps]; + +listeners_confs(dtls, Envs) -> + case proplists:get_value(dtls_opts, Envs, []) of + [] -> []; + DtlsOpts -> + BindDtls = proplists:get_value(bind_dtls, Envs, []), + [{dtls, Port, [{dtls_options, InetOpts ++ DtlsOpts}]} || {Port, InetOpts} <- BindDtls] + end. + +format(Port) when is_integer(Port) -> + io_lib:format("0.0.0.0:~w", [Port]); +format({Addr, Port}) when is_list(Addr) -> + io_lib:format("~s:~w", [Addr, Port]); +format({Addr, Port}) when is_tuple(Addr) -> + io_lib:format("~s:~w", [inet:ntoa(Addr), Port]). + diff --git a/apps/emqx_coap/src/emqx_coap_sup.erl b/apps/emqx_coap/src/emqx_coap_sup.erl new file mode 100644 index 000000000..a3a0fdc53 --- /dev/null +++ b/apps/emqx_coap/src/emqx_coap_sup.erl @@ -0,0 +1,42 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_coap_sup). + +-behaviour(supervisor). + +-export([ start_link/0 + , init/1 + ]). + +start_link() -> + supervisor:start_link({local, ?MODULE}, ?MODULE, []). + +init(_Args) -> + Registry = #{id => emqx_coap_registry, + start => {emqx_coap_registry, start_link, []}, + restart => permanent, + shutdown => 5000, + type => worker, + modules => [emqx_coap_registry]}, + PsTopics = #{id => emqx_coap_ps_topics, + start => {emqx_coap_ps_topics, start_link, []}, + restart => permanent, + shutdown => 5000, + type => worker, + modules => [emqx_coap_ps_topics]}, + {ok, {{one_for_all, 10, 3600}, [Registry, PsTopics]}}. + diff --git a/apps/emqx_coap/src/emqx_coap_timer.erl b/apps/emqx_coap/src/emqx_coap_timer.erl new file mode 100644 index 000000000..3924ba239 --- /dev/null +++ b/apps/emqx_coap/src/emqx_coap_timer.erl @@ -0,0 +1,59 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_coap_timer). + +-include("emqx_coap.hrl"). + +-export([ cancel_timer/1 + , start_timer/2 + , restart_timer/1 + , kick_timer/1 + , is_timeout/1 + , get_timer_length/1 + ]). + +-record(timer_state, {interval, kickme, tref, message}). + +-define(LOG(Level, Format, Args), + emqx_logger:Level("CoAP-Timer: " ++ Format, Args)). + +cancel_timer(#timer_state{tref = TRef}) when is_reference(TRef) -> + catch erlang:cancel_timer(TRef), + ok; +cancel_timer(_) -> + ok. + +kick_timer(State=#timer_state{kickme = false}) -> + State#timer_state{kickme = true}; +kick_timer(State=#timer_state{kickme = true}) -> + State. + +start_timer(Sec, Msg) -> + ?LOG(debug, "emqx_coap_timer:start_timer ~p", [Sec]), + TRef = erlang:send_after(timer:seconds(Sec), self(), Msg), + #timer_state{interval = Sec, kickme = false, tref = TRef, message = Msg}. + +restart_timer(State=#timer_state{interval = Sec, message = Msg}) -> + ?LOG(debug, "emqx_coap_timer:restart_timer ~p", [Sec]), + TRef = erlang:send_after(timer:seconds(Sec), self(), Msg), + State#timer_state{kickme = false, tref = TRef}. + +is_timeout(#timer_state{kickme = Bool}) -> + not Bool. + +get_timer_length(#timer_state{interval = Interval}) -> + Interval. diff --git a/apps/emqx_coap/test/emqx_coap_SUITE.erl b/apps/emqx_coap/test/emqx_coap_SUITE.erl new file mode 100644 index 000000000..33f74c39a --- /dev/null +++ b/apps/emqx_coap/test/emqx_coap_SUITE.erl @@ -0,0 +1,240 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_coap_SUITE). + +-compile(export_all). +-compile(nowarn_export_all). + +-include_lib("gen_coap/include/coap.hrl"). +-include_lib("eunit/include/eunit.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). + +-define(LOGT(Format, Args), ct:pal(Format, Args)). + +all() -> emqx_ct:all(?MODULE). + +init_per_suite(Config) -> + emqx_ct_helpers:start_apps([emqx_coap], fun set_sepecial_cfg/1), + Config. + +set_sepecial_cfg(emqx_coap) -> + Opts = application:get_env(emqx_coap, dtls_opts,[]), + Opts2 = [{keyfile, emqx_ct_helpers:deps_path(emqx, "etc/certs/key.pem")}, + {certfile, emqx_ct_helpers:deps_path(emqx, "etc/certs/cert.pem")}], + application:set_env(emqx_coap, dtls_opts, emqx_misc:merge_opts(Opts, Opts2)), + application:set_env(emqx_coap, enable_stats, true); +set_sepecial_cfg(_) -> + ok. + +end_per_suite(Config) -> + emqx_ct_helpers:stop_apps([emqx_coap]), + Config. + +%%-------------------------------------------------------------------- +%% Test Cases +%%-------------------------------------------------------------------- + +t_publish(_Config) -> + Topic = <<"abc">>, Payload = <<"123">>, + TopicStr = binary_to_list(Topic), + URI = "coap://127.0.0.1/mqtt/"++TopicStr++"?c=client1&u=tom&p=secret", + + %% Sub topic first + emqx:subscribe(Topic), + + Reply = er_coap_client:request(put, URI, #coap_content{format = <<"application/octet-stream">>, payload = Payload}), + {ok, changed, _} = Reply, + + receive + {deliver, Topic, Msg} -> + ?assertEqual(Topic, Msg#message.topic), + ?assertEqual(Payload, Msg#message.payload) + after + 500 -> + ?assert(false) + end. + +t_observe(_Config) -> + Topic = <<"abc">>, TopicStr = binary_to_list(Topic), + Payload = <<"123">>, + Uri = "coap://127.0.0.1/mqtt/"++TopicStr++"?c=client1&u=tom&p=secret", + {ok, Pid, N, Code, Content} = er_coap_observer:observe(Uri), + ?LOGT("observer Pid=~p, N=~p, Code=~p, Content=~p", [Pid, N, Code, Content]), + + [SubPid] = emqx:subscribers(Topic), + ?assert(is_pid(SubPid)), + + %% Publish a message + emqx:publish(emqx_message:make(Topic, Payload)), + + Notif = receive_notification(), + ?LOGT("observer get Notif=~p", [Notif]), + {coap_notify, _, _, {ok,content}, #coap_content{payload = PayloadRecv}} = Notif, + ?_assertEqual(Payload, PayloadRecv), + + er_coap_observer:stop(Pid), + timer:sleep(100), + + [] = emqx:subscribers(Topic). + +t_observe_wildcard(_Config) -> + Topic = <<"+/b">>, TopicStr = http_uri:encode(binary_to_list(Topic)), + Payload = <<"123">>, + Uri = "coap://127.0.0.1/mqtt/"++TopicStr++"?c=client1&u=tom&p=secret", + {ok, Pid, N, Code, Content} = er_coap_observer:observe(Uri), + ?LOGT("observer Uri=~p, Pid=~p, N=~p, Code=~p, Content=~p", [Uri, Pid, N, Code, Content]), + + [SubPid] = emqx:subscribers(Topic), + ?assert(is_pid(SubPid)), + + %% Publish a message + emqx:publish(emqx_message:make(Topic, Payload)), + + Notif = receive_notification(), + ?LOGT("observer get Notif=~p", [Notif]), + {coap_notify, _, _, {ok,content}, #coap_content{payload = PayloadRecv}} = Notif, + ?_assertEqual(Payload, PayloadRecv), + + er_coap_observer:stop(Pid), + timer:sleep(100), + + [] = emqx:subscribers(Topic). + +t_observe_pub(_Config) -> + Topic = <<"+/b">>, TopicStr = http_uri:encode(binary_to_list(Topic)), + Uri = "coap://127.0.0.1/mqtt/"++TopicStr++"?c=client1&u=tom&p=secret", + {ok, Pid, N, Code, Content} = er_coap_observer:observe(Uri), + ?LOGT("observer Pid=~p, N=~p, Code=~p, Content=~p", [Pid, N, Code, Content]), + + [SubPid] = emqx:subscribers(Topic), + ?assert(is_pid(SubPid)), + + Topic2 = <<"a/b">>, Payload2 = <<"UFO">>, + TopicStr2 = http_uri:encode(binary_to_list(Topic2)), + URI2 = "coap://127.0.0.1/mqtt/"++TopicStr2++"?c=client1&u=tom&p=secret", + + Reply2 = er_coap_client:request(put, URI2, #coap_content{format = <<"application/octet-stream">>, payload = Payload2}), + {ok,changed, _} = Reply2, + + Notif2 = receive_notification(), + ?LOGT("observer get Notif2=~p", [Notif2]), + {coap_notify, _, _, {ok,content}, #coap_content{payload = PayloadRecv2}} = Notif2, + ?_assertEqual(Payload2, PayloadRecv2), + + Topic3 = <<"j/b">>, Payload3 = <<"ET629">>, + TopicStr3 = http_uri:encode(binary_to_list(Topic3)), + URI3 = "coap://127.0.0.1/mqtt/"++TopicStr3++"?c=client2&u=mike&p=guess", + Reply3 = er_coap_client:request(put, URI3, #coap_content{format = <<"application/octet-stream">>, payload = Payload3}), + {ok,changed, _} = Reply3, + + Notif3 = receive_notification(), + ?LOGT("observer get Notif3=~p", [Notif3]), + {coap_notify, _, _, {ok,content}, #coap_content{payload = PayloadRecv3}} = Notif3, + ?_assertEqual(Payload3, PayloadRecv3), + + er_coap_observer:stop(Pid). + +t_one_clientid_sub_2_topics(_Config) -> + Topic1 = <<"abc">>, TopicStr1 = binary_to_list(Topic1), + Payload1 = <<"123">>, + Uri1 = "coap://127.0.0.1/mqtt/"++TopicStr1++"?c=client1&u=tom&p=secret", + {ok, Pid1, N1, Code1, Content1} = er_coap_observer:observe(Uri1), + ?LOGT("observer 1 Pid=~p, N=~p, Code=~p, Content=~p", [Pid1, N1, Code1, Content1]), + + [SubPid] = emqx:subscribers(Topic1), + ?assert(is_pid(SubPid)), + + Topic2 = <<"x/y">>, TopicStr2 = http_uri:encode(binary_to_list(Topic2)), + Payload2 = <<"456">>, + Uri2 = "coap://127.0.0.1/mqtt/"++TopicStr2++"?c=client1&u=tom&p=secret", + {ok, Pid2, N2, Code2, Content2} = er_coap_observer:observe(Uri2), + ?LOGT("observer 2 Pid=~p, N=~p, Code=~p, Content=~p", [Pid2, N2, Code2, Content2]), + + [SubPid] = emqx:subscribers(Topic2), + ?assert(is_pid(SubPid)), + + emqx:publish(emqx_message:make(Topic1, Payload1)), + + Notif1 = receive_notification(), + ?LOGT("observer 1 get Notif=~p", [Notif1]), + {coap_notify, _, _, {ok,content}, #coap_content{payload = PayloadRecv1}} = Notif1, + ?_assertEqual(Payload1, PayloadRecv1), + + emqx:publish(emqx_message:make(Topic2, Payload2)), + + Notif2 = receive_notification(), + ?LOGT("observer 2 get Notif=~p", [Notif2]), + {coap_notify, _, _, {ok,content}, #coap_content{payload = PayloadRecv2}} = Notif2, + ?_assertEqual(Payload2, PayloadRecv2), + + er_coap_observer:stop(Pid1), + er_coap_observer:stop(Pid2). + +t_invalid_parameter(_Config) -> + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %% "cid=client2" is invaid + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + Topic3 = <<"a/b">>, Payload3 = <<"ET629">>, + TopicStr3 = http_uri:encode(binary_to_list(Topic3)), + URI3 = "coap://127.0.0.1/mqtt/"++TopicStr3++"?cid=client2&u=tom&p=simple", + Reply3 = er_coap_client:request(put, URI3, #coap_content{format = <<"application/octet-stream">>, payload = Payload3}), + ?assertMatch({error,bad_request}, Reply3), + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %% "what=hello" is invaid + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + URI4 = "coap://127.0.0.1/mqtt/"++TopicStr3++"?what=hello", + Reply4 = er_coap_client:request(put, URI4, #coap_content{format = <<"application/octet-stream">>, payload = Payload3}), + ?assertMatch({error, bad_request}, Reply4). + +t_invalid_topic(_Config) -> + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %% "a/b" is a valid topic string + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + Topic3 = <<"a/b">>, Payload3 = <<"ET629">>, + TopicStr3 = binary_to_list(Topic3), + URI3 = "coap://127.0.0.1/mqtt/"++TopicStr3++"?c=client2&u=tom&p=simple", + Reply3 = er_coap_client:request(put, URI3, #coap_content{format = <<"application/octet-stream">>, payload = Payload3}), + ?assertMatch({ok,changed,_Content}, Reply3), + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %% "+?#" is invaid topic string + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + URI4 = "coap://127.0.0.1/mqtt/"++"+?#"++"?what=hello", + Reply4 = er_coap_client:request(put, URI4, #coap_content{format = <<"application/octet-stream">>, payload = Payload3}), + ?assertMatch({error,bad_request}, Reply4). + +t_stats(_) -> + ok. + +t_auth_failure(_) -> + ok. + +t_qos_supprot(_) -> + ok. + +%%-------------------------------------------------------------------- +%% Helpers + +receive_notification() -> + receive + {coap_notify, Pid, N2, Code2, Content2} -> + {coap_notify, Pid, N2, Code2, Content2} + after 2000 -> + receive_notification_timeout + end. + diff --git a/apps/emqx_coap/test/emqx_coap_ps_SUITE.erl b/apps/emqx_coap/test/emqx_coap_ps_SUITE.erl new file mode 100644 index 000000000..930a027d8 --- /dev/null +++ b/apps/emqx_coap/test/emqx_coap_ps_SUITE.erl @@ -0,0 +1,677 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_coap_ps_SUITE). + +-compile(export_all). +-compile(nowarn_export_all). + +-include_lib("gen_coap/include/coap.hrl"). +-include_lib("eunit/include/eunit.hrl"). +-include_lib("emqx_libs/include/emqx.hrl"). + +-define(LOGT(Format, Args), ct:pal(Format, Args)). + +all() -> emqx_ct:all(?MODULE). + +init_per_suite(Config) -> + emqx_ct_helpers:start_apps([emqx_coap], fun set_sepecial_cfg/1), + Config. + +set_sepecial_cfg(emqx_coap) -> + application:set_env(emqx_coap, enable_stats, true); +set_sepecial_cfg(_) -> + ok. + +end_per_suite(Config) -> + emqx_ct_helpers:stop_apps([emqx_coap]), + Config. + +%%-------------------------------------------------------------------- +%% Test Cases +%%-------------------------------------------------------------------- + +t_update_max_age(_Config) -> + TopicInPayload = <<"topic1">>, + Payload = <<";ct=42">>, + Payload1 = <<";ct=50">>, + URI = "coap://127.0.0.1/ps/"++"?c=client1&u=tom&p=secret", + URI2 = "coap://127.0.0.1/ps/topic1"++"?c=client1&u=tom&p=secret", + Reply = er_coap_client:request(post, URI, #coap_content{format = <<"application/link-format">>, payload = Payload}), + ?LOGT("Reply =~p", [Reply]), + {ok,created, #coap_content{location_path = LocPath}} = Reply, + ?assertEqual([<<"/ps/topic1">>] ,LocPath), + TopicInfo = [{TopicInPayload, MaxAge1, CT1, _ResPayload, _TimeStamp}] = emqx_coap_ps_topics:lookup_topic_info(TopicInPayload), + ?LOGT("lookup topic info=~p", [TopicInfo]), + ?assertEqual(60, MaxAge1), + ?assertEqual(<<"42">>, CT1), + + timer:sleep(50), + + %% post to create the same topic but with different max age and ct value in payload + Reply1 = er_coap_client:request(post, URI, #coap_content{max_age = 70, format = <<"application/link-format">>, payload = Payload1}), + {ok,created, #coap_content{location_path = LocPath}} = Reply1, + ?assertEqual([<<"/ps/topic1">>] ,LocPath), + [{TopicInPayload, MaxAge2, CT2, _ResPayload, _TimeStamp1}] = emqx_coap_ps_topics:lookup_topic_info(TopicInPayload), + ?assertEqual(70, MaxAge2), + ?assertEqual(<<"50">>, CT2), + + {ok, deleted, #coap_content{}} = er_coap_client:request(delete, URI2). + +t_create_subtopic(_Config) -> + TopicInPayload = <<"topic1">>, + TopicInPayloadStr = "topic1", + Payload = <<";ct=42">>, + URI = "coap://127.0.0.1/ps/"++"?c=client1&u=tom&p=secret", + RealURI = "coap://127.0.0.1/ps/topic1"++"?c=client1&u=tom&p=secret", + + Reply = er_coap_client:request(post, URI, #coap_content{format = <<"application/link-format">>, payload = Payload}), + ?LOGT("Reply =~p", [Reply]), + {ok,created, #coap_content{location_path = LocPath}} = Reply, + ?assertEqual([<<"/ps/topic1">>] ,LocPath), + TopicInfo = [{TopicInPayload, MaxAge1, CT1, _ResPayload, _TimeStamp}] = emqx_coap_ps_topics:lookup_topic_info(TopicInPayload), + ?LOGT("lookup topic info=~p", [TopicInfo]), + ?assertEqual(60, MaxAge1), + ?assertEqual(<<"42">>, CT1), + + timer:sleep(50), + + %% post to create the a sub topic + SubPayload = <<";ct=42">>, + SubTopicInPayloadStr = "subtopic", + SubURI = "coap://127.0.0.1/ps/"++TopicInPayloadStr++"?c=client1&u=tom&p=secret", + SubRealURI = "coap://127.0.0.1/ps/"++TopicInPayloadStr++"/"++SubTopicInPayloadStr++"?c=client1&u=tom&p=secret", + FullTopic = list_to_binary(TopicInPayloadStr++"/"++SubTopicInPayloadStr), + Reply1 = er_coap_client:request(post, SubURI, #coap_content{format = <<"application/link-format">>, payload = SubPayload}), + ?LOGT("Reply =~p", [Reply1]), + {ok,created, #coap_content{location_path = LocPath1}} = Reply1, + ?assertEqual([<<"/ps/topic1/subtopic">>] ,LocPath1), + [{FullTopic, MaxAge2, CT2, _ResPayload, _}] = emqx_coap_ps_topics:lookup_topic_info(FullTopic), + ?assertEqual(60, MaxAge2), + ?assertEqual(<<"42">>, CT2), + + {ok, deleted, #coap_content{}} = er_coap_client:request(delete, SubRealURI), + {ok, deleted, #coap_content{}} = er_coap_client:request(delete, RealURI). + +t_over_max_age(_Config) -> + TopicInPayload = <<"topic1">>, + Payload = <<";ct=42">>, + URI = "coap://127.0.0.1/ps/"++"?c=client1&u=tom&p=secret", + Reply = er_coap_client:request(post, URI, #coap_content{max_age = 2, format = <<"application/link-format">>, payload = Payload}), + ?LOGT("Reply =~p", [Reply]), + {ok,created, #coap_content{location_path = LocPath}} = Reply, + ?assertEqual([<<"/ps/topic1">>] ,LocPath), + TopicInfo = [{TopicInPayload, MaxAge1, CT1, _ResPayload, _TimeStamp}] = emqx_coap_ps_topics:lookup_topic_info(TopicInPayload), + ?LOGT("lookup topic info=~p", [TopicInfo]), + ?assertEqual(2, MaxAge1), + ?assertEqual(<<"42">>, CT1), + + timer:sleep(3000), + ?assertEqual(true, emqx_coap_ps_topics:is_topic_timeout(TopicInPayload)). + +t_refreash_max_age(_Config) -> + TopicInPayload = <<"topic1">>, + Payload = <<";ct=42">>, + Payload1 = <<";ct=50">>, + URI = "coap://127.0.0.1/ps/"++"?c=client1&u=tom&p=secret", + RealURI = "coap://127.0.0.1/ps/topic1"++"?c=client1&u=tom&p=secret", + Reply = er_coap_client:request(post, URI, #coap_content{max_age = 5, format = <<"application/link-format">>, payload = Payload}), + ?LOGT("Reply =~p", [Reply]), + {ok,created, #coap_content{location_path = LocPath}} = Reply, + ?assertEqual([<<"/ps/topic1">>] ,LocPath), + TopicInfo = [{TopicInPayload, MaxAge1, CT1, _ResPayload, TimeStamp}] = emqx_coap_ps_topics:lookup_topic_info(TopicInPayload), + ?LOGT("lookup topic info=~p", [TopicInfo]), + ?LOGT("TimeStamp=~p", [TimeStamp]), + ?assertEqual(5, MaxAge1), + ?assertEqual(<<"42">>, CT1), + + timer:sleep(3000), + + %% post to create the same topic, the max age timer will be restarted with the new max age value + Reply1 = er_coap_client:request(post, URI, #coap_content{max_age = 5, format = <<"application/link-format">>, payload = Payload1}), + {ok,created, #coap_content{location_path = LocPath}} = Reply1, + ?assertEqual([<<"/ps/topic1">>] ,LocPath), + [{TopicInPayload, MaxAge2, CT2, _ResPayload, TimeStamp1}] = emqx_coap_ps_topics:lookup_topic_info(TopicInPayload), + ?LOGT("TimeStamp1=~p", [TimeStamp1]), + ?assertEqual(5, MaxAge2), + ?assertEqual(<<"50">>, CT2), + + timer:sleep(3000), + ?assertEqual(false, emqx_coap_ps_topics:is_topic_timeout(TopicInPayload)), + + {ok, deleted, #coap_content{}} = er_coap_client:request(delete, RealURI). + +t_case01_publish_post(_Config) -> + timer:sleep(100), + MainTopic = <<"maintopic">>, + TopicInPayload = <<"topic1">>, + Payload = <<";ct=42">>, + MainTopicStr = binary_to_list(MainTopic), + + %% post to create topic maintopic/topic1 + URI1 = "coap://127.0.0.1/ps/"++MainTopicStr++"?c=client1&u=tom&p=secret", + FullTopic = list_to_binary(MainTopicStr++"/"++binary_to_list(TopicInPayload)), + Reply1 = er_coap_client:request(post, URI1, #coap_content{format = <<"application/link-format">>, payload = Payload}), + ?LOGT("Reply =~p", [Reply1]), + {ok,created, #coap_content{location_path = LocPath1}} = Reply1, + ?assertEqual([<<"/ps/maintopic/topic1">>] ,LocPath1), + [{FullTopic, MaxAge, CT2, <<>>, _TimeStamp}] = emqx_coap_ps_topics:lookup_topic_info(FullTopic), + ?assertEqual(60, MaxAge), + ?assertEqual(<<"42">>, CT2), + + %% post to publish message to topic maintopic/topic1 + FullTopicStr = http_uri:encode(binary_to_list(FullTopic)), + URI2 = "coap://127.0.0.1/ps/"++FullTopicStr++"?c=client1&u=tom&p=secret", + PubPayload = <<"PUBLISH">>, + + %% Sub topic first + emqx:subscribe(FullTopic), + + Reply2 = er_coap_client:request(post, URI2, #coap_content{format = <<"application/octet-stream">>, payload = PubPayload}), + ?LOGT("Reply =~p", [Reply2]), + {ok,changed, _} = Reply2, + TopicInfo = [{FullTopic, MaxAge, CT2, PubPayload, _TimeStamp1}] = emqx_coap_ps_topics:lookup_topic_info(FullTopic), + ?LOGT("the topic info =~p", [TopicInfo]), + + assert_recv(FullTopic, PubPayload), + {ok, deleted, #coap_content{}} = er_coap_client:request(delete, URI2). + +t_case02_publish_post(_Config) -> + Topic = <<"topic1">>, + TopicStr = binary_to_list(Topic), + Payload = <<"payload">>, + + %% Sub topic first + emqx:subscribe(Topic), + + %% post to publish a new topic "topic1", and the topic is created + URI = "coap://127.0.0.1/ps/"++TopicStr++"?c=client1&u=tom&p=secret", + Reply = er_coap_client:request(post, URI, #coap_content{format = <<"application/octet-stream">>, payload = Payload}), + ?LOGT("Reply =~p", [Reply]), + {ok,created, #coap_content{location_path = LocPath}} = Reply, + ?assertEqual([<<"/ps/topic1">>] ,LocPath), + [{Topic, MaxAge, CT, Payload, _TimeStamp}] = emqx_coap_ps_topics:lookup_topic_info(Topic), + ?assertEqual(60, MaxAge), + ?assertEqual(<<"42">>, CT), + + assert_recv(Topic, Payload), + + %% post to publish a new message to the same topic "topic1" with different payload + NewPayload = <<"newpayload">>, + Reply1 = er_coap_client:request(post, URI, #coap_content{format = <<"application/octet-stream">>, payload = NewPayload}), + ?LOGT("Reply =~p", [Reply1]), + {ok,changed, _} = Reply1, + [{Topic, MaxAge, CT, NewPayload, _TimeStamp1}] = emqx_coap_ps_topics:lookup_topic_info(Topic), + + assert_recv(Topic, NewPayload), + {ok, deleted, #coap_content{}} = er_coap_client:request(delete, URI). + +t_case03_publish_post(_Config) -> + Topic = <<"topic1">>, + TopicStr = binary_to_list(Topic), + Payload = <<"payload">>, + + %% Sub topic first + emqx:subscribe(Topic), + + %% post to publish a new topic "topic1", and the topic is created + URI = "coap://127.0.0.1/ps/"++TopicStr++"?c=client1&u=tom&p=secret", + Reply = er_coap_client:request(post, URI, #coap_content{format = <<"application/octet-stream">>, payload = Payload}), + ?LOGT("Reply =~p", [Reply]), + {ok,created, #coap_content{location_path = LocPath}} = Reply, + ?assertEqual([<<"/ps/topic1">>] ,LocPath), + [{Topic, MaxAge, CT, Payload, _TimeStamp}] = emqx_coap_ps_topics:lookup_topic_info(Topic), + ?assertEqual(60, MaxAge), + ?assertEqual(<<"42">>, CT), + + assert_recv(Topic, Payload), + + %% post to publish a new message to the same topic "topic1", but the ct is not same as created + NewPayload = <<"newpayload">>, + Reply1 = er_coap_client:request(post, URI, #coap_content{format = <<"application/exi">>, payload = NewPayload}), + ?LOGT("Reply =~p", [Reply1]), + ?assertEqual({error,bad_request}, Reply1), + + {ok, deleted, #coap_content{}} = er_coap_client:request(delete, URI). + +t_case04_publish_post(_Config) -> + Topic = <<"topic1">>, + TopicStr = binary_to_list(Topic), + Payload = <<"payload">>, + + %% post to publish a new topic "topic1", and the topic is created + URI = "coap://127.0.0.1/ps/"++TopicStr++"?c=client1&u=tom&p=secret", + Reply = er_coap_client:request(post, URI, #coap_content{max_age = 5, format = <<"application/octet-stream">>, payload = Payload}), + ?LOGT("Reply =~p", [Reply]), + {ok,created, #coap_content{location_path = LocPath}} = Reply, + ?assertEqual([<<"/ps/topic1">>] ,LocPath), + [{Topic, MaxAge, CT, Payload, _TimeStamp}] = emqx_coap_ps_topics:lookup_topic_info(Topic), + ?assertEqual(5, MaxAge), + ?assertEqual(<<"42">>, CT), + + %% after max age timeout, the topic still exists but the status is timeout + timer:sleep(6000), + ?assertEqual(true, emqx_coap_ps_topics:is_topic_timeout(Topic)), + + {ok, deleted, #coap_content{}} = er_coap_client:request(delete, URI). + +t_case01_publish_put(_Config) -> + MainTopic = <<"maintopic">>, + TopicInPayload = <<"topic1">>, + Payload = <<";ct=42">>, + MainTopicStr = binary_to_list(MainTopic), + + %% post to create topic maintopic/topic1 + URI1 = "coap://127.0.0.1/ps/"++MainTopicStr++"?c=client1&u=tom&p=secret", + FullTopic = list_to_binary(MainTopicStr++"/"++binary_to_list(TopicInPayload)), + Reply1 = er_coap_client:request(post, URI1, #coap_content{format = <<"application/link-format">>, payload = Payload}), + ?LOGT("Reply =~p", [Reply1]), + {ok,created, #coap_content{location_path = LocPath1}} = Reply1, + ?assertEqual([<<"/ps/maintopic/topic1">>] ,LocPath1), + [{FullTopic, MaxAge, CT2, <<>>, _TimeStamp}] = emqx_coap_ps_topics:lookup_topic_info(FullTopic), + ?assertEqual(60, MaxAge), + ?assertEqual(<<"42">>, CT2), + + %% put to publish message to topic maintopic/topic1 + FullTopicStr = http_uri:encode(binary_to_list(FullTopic)), + URI2 = "coap://127.0.0.1/ps/"++FullTopicStr++"?c=client1&u=tom&p=secret", + PubPayload = <<"PUBLISH">>, + + %% Sub topic first + emqx:subscribe(FullTopic), + + Reply2 = er_coap_client:request(put, URI2, #coap_content{format = <<"application/octet-stream">>, payload = PubPayload}), + ?LOGT("Reply =~p", [Reply2]), + {ok,changed, _} = Reply2, + [{FullTopic, MaxAge, CT2, PubPayload, _TimeStamp1}] = emqx_coap_ps_topics:lookup_topic_info(FullTopic), + + assert_recv(FullTopic, PubPayload), + + {ok, deleted, #coap_content{}} = er_coap_client:request(delete, URI2). + +t_case02_publish_put(_Config) -> + Topic = <<"topic1">>, + TopicStr = binary_to_list(Topic), + Payload = <<"payload">>, + + %% Sub topic first + emqx:subscribe(Topic), + + %% put to publish a new topic "topic1", and the topic is created + URI = "coap://127.0.0.1/ps/"++TopicStr++"?c=client1&u=tom&p=secret", + Reply = er_coap_client:request(put, URI, #coap_content{format = <<"application/octet-stream">>, payload = Payload}), + ?LOGT("Reply =~p", [Reply]), + {ok,created, #coap_content{location_path = LocPath}} = Reply, + ?assertEqual([<<"/ps/topic1">>] ,LocPath), + [{Topic, MaxAge, CT, Payload, _TimeStamp}] = emqx_coap_ps_topics:lookup_topic_info(Topic), + ?assertEqual(60, MaxAge), + ?assertEqual(<<"42">>, CT), + + assert_recv(Topic, Payload), + + %% put to publish a new message to the same topic "topic1" with different payload + NewPayload = <<"newpayload">>, + Reply1 = er_coap_client:request(put, URI, #coap_content{format = <<"application/octet-stream">>, payload = NewPayload}), + ?LOGT("Reply =~p", [Reply1]), + {ok,changed, _} = Reply1, + [{Topic, MaxAge, CT, NewPayload, _TimeStamp1}] = emqx_coap_ps_topics:lookup_topic_info(Topic), + + assert_recv(Topic, NewPayload), + + {ok, deleted, #coap_content{}} = er_coap_client:request(delete, URI). + +t_case03_publish_put(_Config) -> + Topic = <<"topic1">>, + TopicStr = binary_to_list(Topic), + Payload = <<"payload">>, + + %% Sub topic first + emqx:subscribe(Topic), + + %% put to publish a new topic "topic1", and the topic is created + URI = "coap://127.0.0.1/ps/"++TopicStr++"?c=client1&u=tom&p=secret", + Reply = er_coap_client:request(put, URI, #coap_content{format = <<"application/octet-stream">>, payload = Payload}), + ?LOGT("Reply =~p", [Reply]), + {ok,created, #coap_content{location_path = LocPath}} = Reply, + ?assertEqual([<<"/ps/topic1">>] ,LocPath), + [{Topic, MaxAge, CT, Payload, _TimeStamp}] = emqx_coap_ps_topics:lookup_topic_info(Topic), + ?assertEqual(60, MaxAge), + ?assertEqual(<<"42">>, CT), + + assert_recv(Topic, Payload), + + %% put to publish a new message to the same topic "topic1", but the ct is not same as created + NewPayload = <<"newpayload">>, + Reply1 = er_coap_client:request(put, URI, #coap_content{format = <<"application/exi">>, payload = NewPayload}), + ?LOGT("Reply =~p", [Reply1]), + ?assertEqual({error,bad_request}, Reply1), + + {ok, deleted, #coap_content{}} = er_coap_client:request(delete, URI). + +t_case04_publish_put(_Config) -> + Topic = <<"topic1">>, + TopicStr = binary_to_list(Topic), + Payload = <<"payload">>, + + %% put to publish a new topic "topic1", and the topic is created + URI = "coap://127.0.0.1/ps/"++TopicStr++"?c=client1&u=tom&p=secret", + Reply = er_coap_client:request(put, URI, #coap_content{max_age = 5, format = <<"application/octet-stream">>, payload = Payload}), + ?LOGT("Reply =~p", [Reply]), + {ok,created, #coap_content{location_path = LocPath}} = Reply, + ?assertEqual([<<"/ps/topic1">>] ,LocPath), + [{Topic, MaxAge, CT, Payload, _TimeStamp}] = emqx_coap_ps_topics:lookup_topic_info(Topic), + ?assertEqual(5, MaxAge), + ?assertEqual(<<"42">>, CT), + + %% after max age timeout, no publish message to the same topic, the topic info will be deleted + %%%%%%%%%%%%%%%%%%%%%%%%%% + % but there is one thing to do is we don't count in the publish message received from emqx(from other node).TBD!!!!!!!!!!!!! + %%%%%%%%%%%%%%%%%%%%%%%%%% + timer:sleep(6000), + ?assertEqual(true, emqx_coap_ps_topics:is_topic_timeout(Topic)), + + {ok, deleted, #coap_content{}} = er_coap_client:request(delete, URI). + +t_case01_subscribe(_Config) -> + Topic = <<"topic1">>, + Payload1 = <<";ct=42">>, + timer:sleep(100), + + %% First post to create a topic "topic1" + Uri = "coap://127.0.0.1/ps/"++"?c=client1&u=tom&p=secret", + Reply = er_coap_client:request(post, Uri, #coap_content{format = <<"application/link-format">>, payload = Payload1}), + ?LOGT("Reply =~p", [Reply]), + {ok,created, #coap_content{location_path = [LocPath]}} = Reply, + ?assertEqual(<<"/ps/topic1">> ,LocPath), + TopicInfo = [{Topic, MaxAge1, CT1, _ResPayload, _TimeStamp}] = emqx_coap_ps_topics:lookup_topic_info(Topic), + ?LOGT("lookup topic info=~p", [TopicInfo]), + ?assertEqual(60, MaxAge1), + ?assertEqual(<<"42">>, CT1), + + %% Subscribe the topic + Uri1 = "coap://127.0.0.1"++binary_to_list(LocPath)++"?c=client1&u=tom&p=secret", + {ok, Pid, N, Code, Content} = er_coap_observer:observe(Uri1), + ?LOGT("observer Pid=~p, N=~p, Code=~p, Content=~p", [Pid, N, Code, Content]), + + [SubPid] = emqx:subscribers(Topic), + ?assert(is_pid(SubPid)), + + %% Publish a message + Payload = <<"123">>, + emqx:publish(emqx_message:make(Topic, Payload)), + + Notif = receive_notification(), + ?LOGT("observer get Notif=~p", [Notif]), + {coap_notify, _, _, {ok,content}, #coap_content{payload = PayloadRecv}} = Notif, + + ?_assertEqual(Payload, PayloadRecv), + + %% GET to read the publish message of the topic + Reply1 = er_coap_client:request(get, Uri1), + ?LOGT("Reply=~p", [Reply1]), + {ok,content, #coap_content{max_age = MaxAgeLeft,payload = <<"123">>}} = Reply1, + ?_assertEqual(true, MaxAgeLeft<60), + + er_coap_observer:stop(Pid), + {ok, deleted, #coap_content{}} = er_coap_client:request(delete, Uri1). + +t_case02_subscribe(_Config) -> + Topic = <<"a/b">>, + TopicStr = binary_to_list(Topic), + PercentEncodedTopic = http_uri:encode(TopicStr), + Payload = <<"payload">>, + + %% post to publish a new topic "a/b", and the topic is created + URI = "coap://127.0.0.1/ps/"++PercentEncodedTopic++"?c=client1&u=tom&p=secret", + Reply = er_coap_client:request(post, URI, #coap_content{max_age = 5, format = <<"application/octet-stream">>, payload = Payload}), + ?LOGT("Reply =~p", [Reply]), + {ok,created, #coap_content{location_path = LocPath}} = Reply, + ?assertEqual([<<"/ps/a/b">>] ,LocPath), + [{Topic, MaxAge, CT, Payload, _TimeStamp}] = emqx_coap_ps_topics:lookup_topic_info(Topic), + ?assertEqual(5, MaxAge), + ?assertEqual(<<"42">>, CT), + + %% Wait for the max age of the timer expires + timer:sleep(6000), + ?assertEqual(true, emqx_coap_ps_topics:is_topic_timeout(Topic)), + + %% Subscribe to the timeout topic "a/b", still successfully,got {ok, nocontent} Method + Uri = "coap://127.0.0.1/ps/"++PercentEncodedTopic++"?c=client1&u=tom&p=secret", + Reply1 = {ok, Pid, _N, nocontent, _} = er_coap_observer:observe(Uri), + ?LOGT("Subscribe Reply=~p", [Reply1]), + + [SubPid] = emqx:subscribers(Topic), + ?assert(is_pid(SubPid)), + + %% put to publish to topic "a/b" + Reply2 = er_coap_client:request(put, URI, #coap_content{format = <<"application/octet-stream">>, payload = Payload}), + {ok,changed, #coap_content{}} = Reply2, + [{Topic, MaxAge1, CT, Payload, TimeStamp}] = emqx_coap_ps_topics:lookup_topic_info(Topic), + ?assertEqual(60, MaxAge1), + ?assertEqual(<<"42">>, CT), + ?assertEqual(false, TimeStamp =:= timeout), + + %% Publish a message + emqx:publish(emqx_message:make(Topic, Payload)), + + Notif = receive_notification(), + ?LOGT("observer get Notif=~p", [Notif]), + {coap_notify, _, _, {ok,content}, #coap_content{payload = Payload}} = Notif, + + er_coap_observer:stop(Pid), + {ok, deleted, #coap_content{}} = er_coap_client:request(delete, URI). + +t_case03_subscribe(_Config) -> + %% Subscribe to the unexisted topic "a/b", got not_found + Topic = <<"a/b">>, + TopicStr = binary_to_list(Topic), + PercentEncodedTopic = http_uri:encode(TopicStr), + Uri = "coap://127.0.0.1/ps/"++PercentEncodedTopic++"?c=client1&u=tom&p=secret", + {error, not_found} = er_coap_observer:observe(Uri), + + [] = emqx:subscribers(Topic). + +t_case04_subscribe(_Config) -> + %% Subscribe to the wildcad topic "+/b", got bad_request + Topic = <<"+/b">>, + TopicStr = binary_to_list(Topic), + PercentEncodedTopic = http_uri:encode(TopicStr), + Uri = "coap://127.0.0.1/ps/"++PercentEncodedTopic++"?c=client1&u=tom&p=secret", + {error, bad_request} = er_coap_observer:observe(Uri), + + [] = emqx:subscribers(Topic). + +t_case01_read(_Config) -> + Topic = <<"topic1">>, + TopicStr = binary_to_list(Topic), + Payload = <<"PubPayload">>, + timer:sleep(100), + + %% First post to create a topic "topic1" + Uri = "coap://127.0.0.1/ps/"++TopicStr++"?c=client1&u=tom&p=secret", + Reply = er_coap_client:request(post, Uri, #coap_content{format = <<"application/octet-stream">>, payload = Payload}), + ?LOGT("Reply =~p", [Reply]), + {ok,created, #coap_content{location_path = [LocPath]}} = Reply, + ?assertEqual(<<"/ps/topic1">> ,LocPath), + TopicInfo = [{Topic, MaxAge1, CT1, _ResPayload, _TimeStamp}] = emqx_coap_ps_topics:lookup_topic_info(Topic), + ?LOGT("lookup topic info=~p", [TopicInfo]), + ?assertEqual(60, MaxAge1), + ?assertEqual(<<"42">>, CT1), + + %% GET to read the publish message of the topic + Reply1 = er_coap_client:request(get, Uri), + ?LOGT("Reply=~p", [Reply1]), + {ok,content, #coap_content{max_age = MaxAgeLeft,payload = Payload}} = Reply1, + ?_assertEqual(true, MaxAgeLeft<60), + + {ok, deleted, #coap_content{}} = er_coap_client:request(delete, Uri). + +t_case02_read(_Config) -> + Topic = <<"topic1">>, + TopicStr = binary_to_list(Topic), + Payload = <<"PubPayload">>, + timer:sleep(100), + + %% First post to publish a topic "topic1" + Uri = "coap://127.0.0.1/ps/"++TopicStr++"?c=client1&u=tom&p=secret", + Reply = er_coap_client:request(post, Uri, #coap_content{format = <<"application/octet-stream">>, payload = Payload}), + ?LOGT("Reply =~p", [Reply]), + {ok,created, #coap_content{location_path = [LocPath]}} = Reply, + ?assertEqual(<<"/ps/topic1">> ,LocPath), + TopicInfo = [{Topic, MaxAge1, CT1, _ResPayload, _TimeStamp}] = emqx_coap_ps_topics:lookup_topic_info(Topic), + ?LOGT("lookup topic info=~p", [TopicInfo]), + ?assertEqual(60, MaxAge1), + ?assertEqual(<<"42">>, CT1), + + %% GET to read the publish message of unmatched format, got bad_request + Reply1 = er_coap_client:request(get, Uri, #coap_content{format = <<"application/json">>}), + ?LOGT("Reply=~p", [Reply1]), + {error, bad_request} = Reply1, + + {ok, deleted, #coap_content{}} = er_coap_client:request(delete, Uri). + +t_case03_read(_Config) -> + Topic = <<"topic1">>, + TopicStr = binary_to_list(Topic), + Uri = "coap://127.0.0.1/ps/"++TopicStr++"?c=client1&u=tom&p=secret", + timer:sleep(100), + + %% GET to read the nexisted topic "topic1", got not_found + Reply = er_coap_client:request(get, Uri), + ?LOGT("Reply=~p", [Reply]), + {error, not_found} = Reply. + +t_case04_read(_Config) -> + Topic = <<"topic1">>, + TopicStr = binary_to_list(Topic), + Payload = <<"PubPayload">>, + timer:sleep(100), + + %% First post to publish a topic "topic1" + Uri = "coap://127.0.0.1/ps/"++TopicStr++"?c=client1&u=tom&p=secret", + Reply = er_coap_client:request(post, Uri, #coap_content{format = <<"application/octet-stream">>, payload = Payload}), + ?LOGT("Reply =~p", [Reply]), + {ok,created, #coap_content{location_path = [LocPath]}} = Reply, + ?assertEqual(<<"/ps/topic1">> ,LocPath), + TopicInfo = [{Topic, MaxAge1, CT1, _ResPayload, _TimeStamp}] = emqx_coap_ps_topics:lookup_topic_info(Topic), + ?LOGT("lookup topic info=~p", [TopicInfo]), + ?assertEqual(60, MaxAge1), + ?assertEqual(<<"42">>, CT1), + + %% GET to read the publish message of wildcard topic, got bad_request + WildTopic = binary_to_list(<<"+/topic1">>), + Uri1 = "coap://127.0.0.1/ps/"++WildTopic++"?c=client1&u=tom&p=secret", + Reply1 = er_coap_client:request(get, Uri1, #coap_content{format = <<"application/json">>}), + ?LOGT("Reply=~p", [Reply1]), + {error, bad_request} = Reply1, + + {ok, deleted, #coap_content{}} = er_coap_client:request(delete, Uri). + +t_case05_read(_Config) -> + Topic = <<"a/b">>, + TopicStr = binary_to_list(Topic), + PercentEncodedTopic = http_uri:encode(TopicStr), + Payload = <<"payload">>, + + %% post to publish a new topic "a/b", and the topic is created + URI = "coap://127.0.0.1/ps/"++PercentEncodedTopic++"?c=client1&u=tom&p=secret", + Reply = er_coap_client:request(post, URI, #coap_content{max_age = 5, format = <<"application/octet-stream">>, payload = Payload}), + ?LOGT("Reply =~p", [Reply]), + {ok,created, #coap_content{location_path = LocPath}} = Reply, + ?assertEqual([<<"/ps/a/b">>] ,LocPath), + [{Topic, MaxAge, CT, Payload, _TimeStamp}] = emqx_coap_ps_topics:lookup_topic_info(Topic), + ?assertEqual(5, MaxAge), + ?assertEqual(<<"42">>, CT), + + %% Wait for the max age of the timer expires + timer:sleep(6000), + ?assertEqual(true, emqx_coap_ps_topics:is_topic_timeout(Topic)), + + %% GET to read the expired publish message, supposed to get {ok, nocontent}, but now got {ok, content} + Reply1 = er_coap_client:request(get, URI), + ?LOGT("Reply=~p", [Reply1]), + {ok, content, #coap_content{payload = <<>>}}= Reply1, + + {ok, deleted, #coap_content{}} = er_coap_client:request(delete, URI). + +t_case01_delete(_Config) -> + TopicInPayload = <<"a/b">>, + TopicStr = binary_to_list(TopicInPayload), + PercentEncodedTopic = http_uri:encode(TopicStr), + Payload = list_to_binary("<"++PercentEncodedTopic++">;ct=42"), + URI = "coap://127.0.0.1/ps/"++"?c=client1&u=tom&p=secret", + + %% Client post to CREATE topic "a/b" + Reply = er_coap_client:request(post, URI, #coap_content{format = <<"application/link-format">>, payload = Payload}), + ?LOGT("Reply =~p", [Reply]), + {ok,created, #coap_content{location_path = LocPath}} = Reply, + ?assertEqual([<<"/ps/a/b">>] ,LocPath), + + %% Client post to CREATE topic "a/b/c" + TopicInPayload1 = <<"a/b/c">>, + PercentEncodedTopic1 = http_uri:encode(binary_to_list(TopicInPayload1)), + Payload1 = list_to_binary("<"++PercentEncodedTopic1++">;ct=42"), + Reply1 = er_coap_client:request(post, URI, #coap_content{format = <<"application/link-format">>, payload = Payload1}), + ?LOGT("Reply =~p", [Reply1]), + {ok,created, #coap_content{location_path = LocPath1}} = Reply1, + ?assertEqual([<<"/ps/a/b/c">>] ,LocPath1), + + timer:sleep(50), + + %% DELETE the topic "a/b" + UriD = "coap://127.0.0.1/ps/"++PercentEncodedTopic++"?c=client1&u=tom&p=secret", + ReplyD = er_coap_client:request(delete, UriD), + ?LOGT("Reply=~p", [Reply1]), + {ok, deleted, #coap_content{}}= ReplyD, + + ?assertEqual(false, emqx_coap_ps_topics:is_topic_existed(TopicInPayload)), + ?assertEqual(false, emqx_coap_ps_topics:is_topic_existed(TopicInPayload1)). + +t_case02_delete(_Config) -> + TopicInPayload = <<"a/b">>, + TopicStr = binary_to_list(TopicInPayload), + PercentEncodedTopic = http_uri:encode(TopicStr), + + %% DELETE the unexisted topic "a/b" + Uri1 = "coap://127.0.0.1/ps/"++PercentEncodedTopic++"?c=client1&u=tom&p=secret", + Reply1 = er_coap_client:request(delete, Uri1), + ?LOGT("Reply=~p", [Reply1]), + {error, not_found} = Reply1. + +t_case13_emit_stats_test(_Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Internal functions + +receive_notification() -> + receive + {coap_notify, Pid, N2, Code2, Content2} -> + {coap_notify, Pid, N2, Code2, Content2} + after 2000 -> + receive_notification_timeout + end. + +assert_recv(Topic, Payload) -> + receive + {deliver, _, Msg} -> + ?assertEqual(Topic, Msg#message.topic), + ?assertEqual(Payload, Msg#message.payload) + after + 500 -> + ?assert(false) + end. + diff --git a/apps/emqx_dashboard/README.md b/apps/emqx_dashboard/README.md new file mode 100644 index 000000000..e9e50a7c9 --- /dev/null +++ b/apps/emqx_dashboard/README.md @@ -0,0 +1,88 @@ + +emqx-dashboard +============== + +Dashboard for the EMQ X Broker. + +REST API +-------- + +The prefix of REST API is '/api/v4/'. + +Method | Path | Description +-------|---------------------------------------|------------------------------------ +GET | /nodes/ | A list of nodes in the cluster +GET | /nodes/:node | Lookup a node in the cluster +GET | /brokers/ | A list of brokers in the cluster +GET | /brokers/:node | Get broker info of a node +GET | /metrics/ | A list of metrics of all nodes in the cluster +GET | /nodes/:node/metrics/ | A list of metrics of a node +GET | /stats/ | A list of stats of all nodes in the cluster +GET | /nodes/:node/stats/ | A list of stats of a node +GET | /nodes/:node/clients/ | A list of clients on a node +GET | /listeners/ | A list of listeners in the cluster +GET | /nodes/:node/listeners | A list of listeners on the node +GET | /nodes/:node/sessions/ | A list of sessions on a node +GET | /subscriptions/:clientid | A list of subscriptions of a client +GET | /nodes/:node/subscriptions/:clientid | A list of subscriptions of a client on the node +GET | /nodes/:node/subscriptions/ | A list of subscriptions on a node +PUT | /clients/:clientid/clean_acl_cache | Clean ACL cache of a client +GET | /configs/ | Get all configs +GET | /nodes/:node/configs/ | Get all configs of a node +GET | /nodes/:node/plugin_configs/:plugin | Get configurations of a plugin on the node +DELETE | /clients/:clientid | Kick out a client +GET | /alarms/:node | List alarms of a node +GET | /alarms/ | List all alarms +GET | /plugins/ | List all plugins in the cluster +GET | /nodes/:node/plugins/ | List all plugins on a node +GET | /routes/ | List routes +POST | /nodes/:node/plugins/:plugin/load | Load a plugin +GET | /clients/:clientid | Lookup a client in the cluster +GET | nodes/:node/clients/:clientid | Lookup a client on node +GET | nodes/:node/sessions/:clientid | Lookup a session in the cluster +GET | nodes/:node/sessions/:clientid | Lookup a session on the node +POST | /mqtt/publish | Publish a MQTT message +POST | /mqtt/subscribe | Subscribe a topic +POST | /nodes/:node/plugins/:plugin/unload | Unload a plugin +POST | /mqtt/unsubscribe | Unsubscribe a topic +PUT | /configs/:app | Update config of an application in the cluster +PUT | /nodes/:node/configs/:app | Update config of an application on a node +PUT | /nodes/:node/plugin_configs/:plugin | Update configurations of a plugin on the node + +Build +----- + +make && make ct + +Configurtion +------------ + +``` +dashboard.listener = 18083 + +dashboard.listener.acceptors = 2 + +dashboard.listener.max_clients = 512 +``` + +Load Plugin +----------- + +``` +./bin/emqx_ctl plugins load emqx_dashboard +``` + +Login +----- + +URL: http://host:18083 + +Username: admin + +Password: public + +License +------- + +Apache License Version 2.0 + diff --git a/apps/emqx_dashboard/include/emqx_dashboard.hrl b/apps/emqx_dashboard/include/emqx_dashboard.hrl new file mode 100644 index 000000000..73b64de77 --- /dev/null +++ b/apps/emqx_dashboard/include/emqx_dashboard.hrl @@ -0,0 +1,21 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-record(mqtt_admin, {username, password, tags}). + +-type(mqtt_admin() :: #mqtt_admin{}). + +-define(EMPTY_KEY(Key), ((Key == undefined) orelse (Key == <<>>))). diff --git a/apps/emqx_dashboard/priv/emqx_dashboard.schema b/apps/emqx_dashboard/priv/emqx_dashboard.schema new file mode 100644 index 000000000..fcc8f3489 --- /dev/null +++ b/apps/emqx_dashboard/priv/emqx_dashboard.schema @@ -0,0 +1,151 @@ +%%-*- mode: erlang -*- +%% emqx_dashboard config mapping + +{mapping, "dashboard.default_user.login", "emqx_dashboard.default_user_username", [ + {datatype, string} +]}. + +{mapping, "dashboard.default_user.password", "emqx_dashboard.default_user_passwd", [ + {datatype, string} +]}. + +{mapping, "dashboard.listener.http", "emqx_dashboard.listeners", [ + {datatype, integer} +]}. + +{mapping, "dashboard.listener.http.acceptors", "emqx_dashboard.listeners", [ + {default, 4}, + {datatype, integer} +]}. + +{mapping, "dashboard.listener.http.max_clients", "emqx_dashboard.listeners", [ + {default, 512}, + {datatype, integer} +]}. + +{mapping, "dashboard.listener.http.access.$id", "emqx_dashboard.listeners", [ + {datatype, string} +]}. + +{mapping, "dashboard.listener.http.inet6", "emqx_dashboard.listeners", [ + {default, false}, + {datatype, {enum, [true, false]}} +]}. + +{mapping, "dashboard.listener.http.ipv6_v6only", "emqx_dashboard.listeners", [ + {default, false}, + {datatype, {enum, [true, false]}} +]}. + +{mapping, "dashboard.listener.https", "emqx_dashboard.listeners", [ + {datatype, integer} +]}. + +{mapping, "dashboard.listener.https.acceptors", "emqx_dashboard.listeners", [ + {default, 8}, + {datatype, integer} +]}. + +{mapping, "dashboard.listener.https.max_clients", "emqx_dashboard.listeners", [ + {default, 64}, + {datatype, integer} +]}. + +{mapping, "dashboard.listener.https.inet6", "emqx_dashboard.listeners", [ + {default, false}, + {datatype, {enum, [true, false]}} +]}. + +{mapping, "dashboard.listener.https.ipv6_v6only", "emqx_dashboard.listeners", [ + {default, false}, + {datatype, {enum, [true, false]}} +]}. + +{mapping, "dashboard.listener.https.tls_versions", "emqx_dashboard.listeners", [ + {datatype, string} +]}. + +{mapping, "dashboard.listener.https.dhfile", "emqx_dashboard.listeners", [ + {datatype, string} +]}. + +{mapping, "dashboard.listener.https.keyfile", "emqx_dashboard.listeners", [ + {datatype, string} +]}. + +{mapping, "dashboard.listener.https.certfile", "emqx_dashboard.listeners", [ + {datatype, string} +]}. + +{mapping, "dashboard.listener.https.cacertfile", "emqx_dashboard.listeners", [ + {datatype, string} +]}. + +{mapping, "dashboard.listener.https.verify", "emqx_dashboard.listeners", [ + {datatype, string} +]}. + +{mapping, "dashboard.listener.https.fail_if_no_peer_cert", "emqx_dashboard.listeners", [ + {datatype, {enum, [true, false]}} +]}. + +{mapping, "dashboard.listener.https.ciphers", "emqx_dashboard.listeners", [ + {datatype, string} +]}. + +{mapping, "dashboard.listener.https.secure_renegotiate", "emqx_dashboard.listeners", [ + {datatype, flag} +]}. + +{mapping, "dashboard.listener.https.reuse_sessions", "emqx_dashboard.listeners", [ + {default, on}, + {datatype, flag} +]}. + +{mapping, "dashboard.listener.https.honor_cipher_order", "emqx_dashboard.listeners", [ + {datatype, flag} +]}. + +{translation, "emqx_dashboard.listeners", fun(Conf) -> + Filter = fun(Opts) -> [{K, V} || {K, V} <- Opts, V =/= undefined] end, + LisOpts = fun(Prefix) -> + Filter([{num_acceptors, cuttlefish:conf_get(Prefix ++ ".acceptors", Conf)}, + {max_connections, cuttlefish:conf_get(Prefix ++ ".max_clients", Conf)}, + {inet6, cuttlefish:conf_get(Prefix ++ ".inet6", Conf)}, + {ipv6_v6only, cuttlefish:conf_get(Prefix ++ ".ipv6_v6only", Conf)}]) + end, + + SplitFun = fun(undefined) -> undefined; (S) -> string:tokens(S, ",") end, + + SslOpts = fun(Prefix) -> + Versions = case SplitFun(cuttlefish:conf_get(Prefix ++ ".tls_versions", Conf, undefined)) of + undefined -> undefined; + L -> [list_to_atom(V) || V <- L] + end, + Filter([{versions, Versions}, + {ciphers, SplitFun(cuttlefish:conf_get(Prefix ++ ".ciphers", Conf, undefined))}, + {dhfile, cuttlefish:conf_get(Prefix ++ ".dhfile", Conf, undefined)}, + {keyfile, cuttlefish:conf_get(Prefix ++ ".keyfile", Conf, undefined)}, + {certfile, cuttlefish:conf_get(Prefix ++ ".certfile", Conf, undefined)}, + {cacertfile, cuttlefish:conf_get(Prefix ++ ".cacertfile", Conf, undefined)}, + {verify, cuttlefish:conf_get(Prefix ++ ".verify", Conf, undefined)}, + {fail_if_no_peer_cert, cuttlefish:conf_get(Prefix ++ ".fail_if_no_peer_cert", Conf, undefined)}, + {secure_renegotiate, cuttlefish:conf_get(Prefix ++ ".secure_renegotiate", Conf, undefined)}, + {reuse_sessions, cuttlefish:conf_get(Prefix ++ ".reuse_sessions", Conf, undefined)}, + {honor_cipher_order, cuttlefish:conf_get(Prefix ++ ".honor_cipher_order", Conf, undefined)}]) + end, + lists:append( + lists:map( + fun(Proto) -> + Prefix = "dashboard.listener." ++ atom_to_list(Proto), + case cuttlefish:conf_get(Prefix, Conf, undefined) of + undefined -> []; + Port -> + [{Proto, Port, case Proto of + http -> LisOpts(Prefix); + https -> LisOpts(Prefix) ++ SslOpts(Prefix) + end}] + end + end, [http, https])) +end}. + diff --git a/apps/emqx_dashboard/priv/www/index.html b/apps/emqx_dashboard/priv/www/index.html new file mode 100644 index 000000000..4f43f0708 --- /dev/null +++ b/apps/emqx_dashboard/priv/www/index.html @@ -0,0 +1,3 @@ +Dashboard
\ No newline at end of file diff --git a/apps/emqx_dashboard/priv/www/static/css/app.1495f134b9420661c25a03fc6be1c155.css b/apps/emqx_dashboard/priv/www/static/css/app.1495f134b9420661c25a03fc6be1c155.css new file mode 100644 index 000000000..ab753d5bb --- /dev/null +++ b/apps/emqx_dashboard/priv/www/static/css/app.1495f134b9420661c25a03fc6be1c155.css @@ -0,0 +1 @@ +.login-view{width:100%;height:100%;background-color:#181818}.login-view .el-card{width:420px;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}.login-view .el-card .el-card__header{font-size:16px}.login-view .error input{border:2px solid #e0b4b4}.login-view .login-footer{margin-top:40px;display:-ms-flexbox;display:flex;-ms-flex-pack:justify;justify-content:space-between;-ms-flex-align:center;align-items:center}.home-view{box-sizing:border-box;min-height:100%}.home-view .home-content{margin:0 32px 0 232px;padding:60px 0 20px}.left-bar{position:fixed;top:0;bottom:0;width:200px;z-index:1002;overflow-y:auto;overflow-x:hidden;padding-top:140px;padding-bottom:45px;background-color:#242327;box-shadow:0 0 15px #0b0b0b}.left-bar .iconfont{margin-right:8px;font-size:18px}.left-bar .bar-title{position:fixed;top:0;z-index:1003;width:200px;border-bottom:1px solid #2b2c30;color:#fff!important;background-color:#242327;text-align:center;padding:24px 0}.left-bar .bar-title h3{font-size:18px;margin:0;color:#fff}.left-bar .bar-title img{width:60px;height:60px;margin-bottom:8px}.left-bar .bar-footer{position:fixed;bottom:0;width:180px;z-index:1003;padding-left:20px;height:47px;line-height:47px;background:inherit;border-top:1px solid #2b2c30;color:#fff!important}.left-bar .bar-footer span{font-size:16px;font-weight:bolder;margin-right:12px;vertical-align:middle}.left-bar .bar-footer a{font-weight:700}.left-bar .bar-footer a img{width:20px;height:20px;border:none;vertical-align:middle}.left-bar .el-menu{width:200px;min-height:100%;border-right:none!important}.left-bar .el-submenu__title{padding-left:27px!important;height:40px;line-height:40px}.left-bar .el-submenu .el-menu-item{width:157px!important;min-width:0;margin-left:11px}.left-bar .el-menu-item{height:36px!important;line-height:36px!important;background-color:#8f8e8e;color:#929299!important;border-radius:4px;width:185px;margin-left:7px;margin-bottom:4px;margin-top:4px;transition:border-color .3s,background-color .3s,color .3s,box-shadow .3s}.left-bar .el-menu-item:hover{color:#fff!important;background-color:#393a3e!important}.left-bar .el-menu-item:hover i{color:#fff!important}.left-bar .el-menu-item.is-active{color:#fff!important;background-color:#00b173!important;box-shadow:0 0 5px 0 #02d48a}.left-bar .el-menu-item.is-active i{color:#fff!important}.left-bar .last-item{margin-bottom:72px}.left-bar .menu-dot .el-badge__content.is-fixed.is-dot{top:17px;right:0}.left-bar .submenu-dot .el-badge__content.is-fixed.is-dot{right:3px;top:14px}.topbar{height:60px;line-height:60px;padding-left:110px;position:fixed;top:0;left:0;right:0;z-index:4}.topbar .top-area{background-color:#242327;height:100%;padding:0 32px;text-align:right}.topbar .top-area .topbar-right .help-link{display:inline;line-height:32px}.topbar .top-area .topbar-right .help-link .link{display:inline-block;color:#82858f;padding:0 20px;border-right:1px solid #2b2c30;position:relative;top:3px}.topbar .top-area .topbar-right .help-link .link .icon-bangzhu{font-size:20px}.topbar .top-area .topbar-right .help-link a.active{color:#34c388}.topbar .top-area .topbar-right .el-button{border-radius:40px;border-width:2px;margin-left:20px;font-size:14px;font-weight:400;line-height:15px;background:transparent}.topbar .top-area .topbar-right .el-button.enterprise-btn{color:#34c388;border-color:#34c388}.topbar .top-area .topbar-right .el-button.enterprise-btn .icon-arrow{position:relative;top:1px}.topbar .top-area .topbar-right .el-button.github-btn{color:#adafb4;border-color:#adafb4}.topbar .top-area .topbar-right .el-button .iconfont{margin-left:5px}.topbar .top-area .topbar-right .el-button--medium{padding:9px 20px}.overview-view *{padding:0;margin:0;box-sizing:border-box}.overview-view .el-select .el-input__inner{padding-left:10px}.overview-view .card-box{position:relative;margin-top:74px}.overview-view .card-box .card-title{position:absolute;height:24px;line-height:24px;width:100%;top:-34px;left:0;font-size:16px}.overview-view .card-box .el-table{margin-top:0}.overview-view .card-box .el-table .caret-wrapper{left:-8px}.overview-view .card-box .el-table--medium td,.overview-view .card-box .stats-table.el-table--medium th{padding:4px 0}@media screen and (max-width:1280px){.overview-view .card-box .el-col-6{width:50%!important;margin-top:10px!important}}@media screen and (max-width:740px){.overview-view .card-box .el-col-6{width:100%!important;margin-top:10px!important}}.overview-view .card-box .broker-card.el-row{overflow-x:auto}.overview-view .card-box .broker-card .el-col .card-item{height:90px;min-width:250px;line-height:90px;padding:18px 20px 0;border-radius:4px}.overview-view .card-box .broker-card .el-col .card-item .icon{float:left;width:54px;height:54px;line-height:50px;text-align:center;border:2px solid;border-radius:50%}.overview-view .card-box .broker-card .el-col .card-item .icon i{font-size:26px}.overview-view .card-box .broker-card .el-col .card-item .desc{line-height:normal;float:right;text-align:right;height:70px}.overview-view .card-box .broker-card .el-col .card-item .desc h3{font-size:14px;font-weight:700}.overview-view .card-box .broker-card .el-col .card-item .desc p{margin-top:12px;max-width:150px}.overview-view span{line-height:10px}.overview-view .box-card,.overview-view .el-row{margin-top:20px}.overview-view .iconfont{position:relative}.data-view .el-table{margin-top:24px}.data-view .el-row{margin-top:20px}.data-view .el-input{width:240px}.data-view .search-btn{margin-left:8px}.data-view .el-breadcrumb{margin-top:10px;margin-bottom:20px}.data-view .el-pagination .el-select .el-input .el-input__inner{height:22px}.data-view .el-select .el-input .el-select__caret{line-height:12px}.data-view .search-card{margin-top:24px;border:none}.data-view .search-card .el-card__body{padding:5px 12px}.data-view .search-card .el-input,.data-view .search-card .el-select{width:100%}.data-view .search-card .el-input--medium .el-input__inner{height:32px!important}.data-view .search-card .col-share{position:absolute;bottom:-13px}.data-view .search-card .col-oper{float:right;position:relative;top:1px;margin-bottom:10px}.data-view .search-card .col-oper .show-more{margin:0 10px;font-size:12px}.data-view .search-card .form-item-row{margin-top:0}.data-view .search-card .form-item-row .el-select.comparator .el-input--medium .el-input__inner,.data-view .search-card .form-item-row .el-select.match .el-input--medium .el-input__inner{border-radius:4px 0 0 4px}.data-view .search-card .form-item-row .el-input__inner{border-radius:0 4px 4px 0}.data-view .search-card .el-select .el-input .el-select__caret{line-height:36px}.data-view .custom-pagination{margin-top:10px}.data-view .custom-pagination a{transition:all .3s ease;color:#fff;margin-right:10px;background:#42d885;display:inline-block;border-radius:4px;padding:5px 8px}.data-view .custom-pagination a:hover{color:#fff}.data-view .custom-pagination a.disabled{transition:all .3s ease;color:#606266;background:transparent;cursor:not-allowed}.clients-view .client-oper{float:right;margin-top:-32px;color:#adafb4}.clients-view .client-oper .connect-btn{border:1px solid;background:transparent;margin-left:20px;min-width:80px;font-size:14px;font-weight:400}.clients-view .client-oper .connect-btn.disconnected{border-color:#ff6d6d;color:#ff6d6d}.clients-view .client-oper .connect-btn.connected{border-color:#adafb4;color:#adafb4}.clients-view .client-oper .connect-btn:hover{background:transparent!important}.clients-view .el-card.tabs-card{border-radius:0 0 4px 4px}.clients-view .el-card .el-card__body{padding:10px 36px}.clients-view .card-subtitle{font-size:16px;margin:24px 0}.clients-basic .clients-basic-form .form-item-desc{color:#5f6067;margin-left:20px;font-size:14px}.clients-basic .clients-basic-form .el-form-item__content{color:#f8f8f8}.clients-basic .clients-basic-form .el-form-item{margin-bottom:12px}.clients-basic .view-more{margin:24px 0;font-size:14px}.clients-subscriptions .oper-btn-group{text-align:right;margin:24px 0}.clients-subscriptions .client-sub-table{margin-bottom:24px}.clients-subscriptions .el-select--public{width:100%}.clients-subscriptions .el-select--public .el-input__inner{height:32px!important;line-height:32px!important}.rules-view .el-table{margin-top:24px}.rules-view .status-wrapper{padding:0;list-style-type:none}.rules-view .status-wrapper .status-item{padding:2px 6px}.rules-view .status-wrapper .status-item>span{margin-right:12px}.rules-view span[type=info]{padding-right:20px}.rules-view span[type=info]>span{margin-left:6px;color:#333;font-weight:600;border-bottom:1px dashed #d8d8d8}.rules-view span[type=info]>span:hover{font-weight:800}.rule-actions .status-wrapper .status-item,.rule-actions .status-wrapper .title{margin-bottom:10px}.rule-actions .status-wrapper .key{width:120px;display:inline-block}.rule-actions .action-item{margin:2px auto}.rule-actions .action-card{font-size:14px;margin-bottom:24px}.rule-actions .action-card .action-body,.rule-actions .action-card .action-footer{padding:20px}.rule-actions .action-card .filed-item{margin-bottom:16px}.rule-actions .action-card .filed-item:last-child{margin-bottom:0}.rule-actions .action-card .filed-item .title{margin-right:10px}.rule-actions .action-card .action-oper{text-align:right;position:relative}.rule-actions .action-card .action-oper .delete-btn{margin-bottom:40px}.rule-actions .action-card .action-oper .fallbacks{position:absolute;right:0;bottom:0}.rule-actions .action-card .action-oper .fallbacks .el-button [class*=el-icon-]+span{margin-left:0}.rule-actions .action-card:last-child{margin-bottom:0}.rule-actions .el-table__expanded-cell{padding:6px;font-size:12px}.action-dialog .action-tips{padding:20px auto;font-size:13px}.action-dialog .resource-item .el-form-item__label{width:100%;text-align:left;padding-right:0}.action-dialog .el-form-item__content{clear:both}.action-dialog .el-select{width:100%}.resource-dialog .el-form{padding:20px}.resource-dialog .el-input--medium .el-input__inner{height:35px;line-height:35px}.resource-dialog .block__title{padding-left:10px;margin-left:10px;border-left:4px solid #34c388;margin-bottom:20px}.resource-dialog .el-select{width:100%}.resource-dialog .divide{margin:25px auto;border-bottom:1px solid #d8d8d8;clear:both}.resource-dialog .el-form-item__content{clear:both}.rule-create .page-title .el-breadcrumb{text-transform:none}.rule-create .el-card{margin-top:24px;min-height:150px;padding:20px;overflow:visible}.rule-create .el-card .config-null{text-align:center;margin:20px auto}.rule-create .toggle-btn{cursor:pointer;margin-top:4px;width:auto}.rule-create .show-guess{line-height:1.4}.rule-create .show-guess p{font-size:13px;margin-bottom:4px}.rule-create .show-guess p .notice{color:#ff6d6d}.rule-create .form-block--wrapper{margin-bottom:50px;padding-bottom:24px}.rule-create .form-block--wrapper .form-block__title{margin-bottom:30px;padding-left:10px;border-left:4px solid #34c388}.rule-create .form-block--wrapper .form-block__title .form-block__title-tips{font-size:12px;display:inline-block;margin-left:4px}.rule-create .form-block--wrapper .form-block__body{padding-left:20px}.rule-create .sql-tips{padding:20px 0;border-radius:4px;font-size:15px;max-height:480px}.rule-create .sql-tips .title{padding:0 20px 12px}.rule-create .sql-tips .el-scrollbar__wrap{overflow-x:hidden}.rule-create .sql-tips .doc-wrapper{max-height:400px;padding:0 20px}.rule-create .sql-tips p{font-size:13px;margin-bottom:4px}.rule-create .sql-tips li{font-size:13px;margin:8px 12px}.rule-create .sql-tips code,.rule-create .sql-tips span{font-size:12px;margin-bottom:12px}.rule-create .code{line-height:1.4;padding:6px;border-radius:4px;margin-bottom:12px}.rule-create .code.text{line-height:1.8}.rule-create .test-btn{margin-top:12px}.code-sql{line-height:18px!important;margin-bottom:44px}.code-sql.rawsql .el-form-item__content{height:420px}.code-sql.payload .el-form-item__content{height:200px}.code-sql .el-form-item__content{line-height:18px!important}.code-sql .payload-type{width:100%;text-align:right;padding:2px 4px;margin-bottom:12px}.code-sql .payload-type .el-radio__label{font-size:13px}.code-sql.is-error .code-sql__editor,.code-sql.is-error .monaco-container{border-color:#ff6d6d}#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.monaco-view{height:100%;position:relative}.monaco-editor .accessibilityHelpWidget{padding:10px;vertical-align:middle;overflow:scroll}.monaco-aria-container{position:absolute;left:-999em}.monaco-editor .bracket-match{box-sizing:border-box}.monaco-menu .monaco-action-bar.vertical .action-label.hover{background-color:#eee}.monaco-editor .monaco-editor-overlaymessage{padding-bottom:8px}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.monaco-editor .monaco-editor-overlaymessage.fadeIn{animation:fadeIn .15s ease-out}@keyframes fadeOut{0%{opacity:1}to{opacity:0}}.monaco-editor .monaco-editor-overlaymessage.fadeOut{animation:fadeOut .1s ease-out}.monaco-editor .monaco-editor-overlaymessage .message{padding:1px 4px}.monaco-editor .monaco-editor-overlaymessage .anchor{width:0!important;height:0!important;border:8px solid transparent;z-index:1000;position:absolute}.monaco-editor .lightbulb-glyph{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;height:16px;width:20px;padding-left:2px}.monaco-editor .lightbulb-glyph:hover{cursor:pointer}.monaco-editor.vs .lightbulb-glyph{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMS42NzA4IDguNjU4MDZDMTEuMzMxOSA4Ljk5MTYgMTEuMDcxNiA5LjM2Mjc4IDEwLjg4ODYgOS43NzE3MkMxMC43MTA1IDEwLjE3OTIgMTAuNjIxIDEwLjYyMTkgMTAuNjIxIDExLjEwMDlWMTIuNzAxMkMxMC42MjEgMTIuODgwNyAxMC41ODcyIDEzLjA1MDMgMTAuNTE4OSAxMy4yMDkxQzEwLjQ1MTMgMTMuMzY2MSAxMC4zNTg2IDEzLjUwMzggMTAuMjQwNyAxMy42MjEzQzEwLjEyMjggMTMuNzM4OCA5Ljk4NDY0IDEzLjgzMTEgOS44MjcyMyAxMy44OTg0QzkuNjY4MDYgMTMuOTY2MyA5LjQ5ODA2IDE0IDkuMzE4MjMgMTRINy43MTIwNUM3LjUzMjIzIDE0IDcuMzYyMjMgMTMuOTY2MyA3LjIwMzA2IDEzLjg5ODRDNy4wNDU2NCAxMy44MzExIDYuOTA3NTMgMTMuNzM4OCA2Ljc4OTYxIDEzLjYyMTNDNi42NzE2OCAxMy41MDM4IDYuNTc4OTUgMTMuMzY2MSA2LjUxMTQxIDEzLjIwOTFDNi40NDMxMSAxMy4wNTAzIDYuNDA5MjcgMTIuODgwNyA2LjQwOTI3IDEyLjcwMTJWMTEuMTAwOUM2LjQwOTI3IDEwLjYyMiA2LjMxNzcyIDEwLjE3OTUgNi4xMzU1MyA5Ljc3MjA5QzUuOTU2ODMgOS4zNjMzNiA1LjY5ODMyIDguOTkxNTYgNS4zNTk1MyA4LjY1ODA2QzQuOTI0NjggOC4yMjkwMyA0LjU4ODk2IDcuNzUwMDMgNC4zNTM2MSA3LjIyMTM0QzQuMTE3NTYgNi42OTEwNyA0IDYuMTE2NzIgNCA1LjQ5OTUzQzQgNS4wODY2NCA0LjA1MzQyIDQuNjg4MDIgNC4xNjA0OCA0LjMwMzk3QzQuMjY3MjggMy45MjA4OSA0LjQxOTA3IDMuNTYyODYgNC42MTU5NSAzLjIzMDE4QzQuODEyNTcgMi44OTM3NyA1LjA0Nzc3IDIuNTg5MTEgNS4zMjE0NiAyLjMxNjQxQzUuNTk1MDMgMi4wNDM4MyA1Ljg5ODU4IDEuODA5NTMgNi4yMzE5NSAxLjYxMzY0QzYuNTY5NzkgMS40MTc2NCA2LjkzMTQ2IDEuMjY2MiA3LjMxNTc4IDEuMTU5ODNDNy43MDEwNiAxLjA1MzIgOC4xMDA5NCAxIDguNTE1MTQgMUM4LjkyOTM0IDEgOS4zMjkyMyAxLjA1MzIgOS43MTQ1MSAxLjE1OTgzQzEwLjA5ODggMS4yNjYyIDEwLjQ1OCAxLjQxNzM5IDEwLjc5MTggMS42MTM1MUMxMS4xMjk0IDEuODA5MzggMTEuNDM1MSAyLjA0MzcgMTEuNzA4OCAyLjMxNjQxQzExLjk4MjUgMi41ODkxIDEyLjIxNzcgMi44OTM3NiAxMi40MTQzIDMuMjMwMTZDMTIuNjExMiAzLjU2Mjg1IDEyLjc2MyAzLjkyMDg4IDEyLjg2OTggNC4zMDM5N0MxMi45NzY5IDQuNjg4MDIgMTMuMDMwMyA1LjA4NjY0IDEzLjAzMDMgNS40OTk1M0MxMy4wMzAzIDYuMTE2NzIgMTIuOTEyNyA2LjY5MTA3IDEyLjY3NjcgNy4yMjEzNEMxMi40NDEzIDcuNzUwMDMgMTIuMTA1NiA4LjIyOTAzIDExLjY3MDggOC42NTgwNlpNOS42MjE2MiAxMC41SDcuNDA4NjdWMTIuNzAxMkM3LjQwODY3IDEyLjc4MjMgNy40MzcyIDEyLjg1MTIgNy40OTg4OCAxMi45MTI3QzcuNTYwNTggMTIuOTc0MSA3LjYzMDA3IDEzLjAwMjggNy43MTIwNSAxMy4wMDI4SDkuMzE4MjNDOS40MDAyMiAxMy4wMDI4IDkuNDY5NzEgMTIuOTc0MSA5LjUzMTQgMTIuOTEyN0M5LjU5MzA5IDEyLjg1MTIgOS42MjE2MiAxMi43ODIzIDkuNjIxNjIgMTIuNzAxMlYxMC41WiIgZmlsbD0iI0ZGQ0MwMCIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTExLjY3MDggOC42NTgwNkMxMS4zMzE5IDguOTkxNiAxMS4wNzE2IDkuMzYyNzggMTAuODg4NiA5Ljc3MTcyQzEwLjcxMDUgMTAuMTc5MiAxMC42MjEgMTAuNjIxOSAxMC42MjEgMTEuMTAwOVYxMi43MDEyQzEwLjYyMSAxMi44ODA3IDEwLjU4NzIgMTMuMDUwMyAxMC41MTg5IDEzLjIwOTFDMTAuNDUxMyAxMy4zNjYxIDEwLjM1ODYgMTMuNTAzOCAxMC4yNDA3IDEzLjYyMTNDMTAuMTIyOCAxMy43Mzg4IDkuOTg0NjQgMTMuODMxMSA5LjgyNzIzIDEzLjg5ODRDOS42NjgwNiAxMy45NjYzIDkuNDk4MDYgMTQgOS4zMTgyMyAxNEg3LjcxMjA1QzcuNTMyMjMgMTQgNy4zNjIyMyAxMy45NjYzIDcuMjAzMDYgMTMuODk4NEM3LjA0NTY0IDEzLjgzMTEgNi45MDc1MyAxMy43Mzg4IDYuNzg5NjEgMTMuNjIxM0M2LjY3MTY4IDEzLjUwMzggNi41Nzg5NSAxMy4zNjYxIDYuNTExNDEgMTMuMjA5MUM2LjQ0MzExIDEzLjA1MDMgNi40MDkyNyAxMi44ODA3IDYuNDA5MjcgMTIuNzAxMlYxMS4xMDA5QzYuNDA5MjcgMTAuNjIyIDYuMzE3NzIgMTAuMTc5NSA2LjEzNTUzIDkuNzcyMDlDNS45NTY4MyA5LjM2MzM2IDUuNjk4MzIgOC45OTE1NiA1LjM1OTUzIDguNjU4MDZDNC45MjQ2OCA4LjIyOTAzIDQuNTg4OTYgNy43NTAwMyA0LjM1MzYxIDcuMjIxMzRDNC4xMTc1NiA2LjY5MTA3IDQgNi4xMTY3MiA0IDUuNDk5NTNDNCA1LjA4NjY0IDQuMDUzNDIgNC42ODgwMiA0LjE2MDQ4IDQuMzAzOTdDNC4yNjcyOCAzLjkyMDg5IDQuNDE5MDcgMy41NjI4NiA0LjYxNTk1IDMuMjMwMThDNC44MTI1NyAyLjg5Mzc3IDUuMDQ3NzcgMi41ODkxMSA1LjMyMTQ2IDIuMzE2NDFDNS41OTUwMyAyLjA0MzgzIDUuODk4NTggMS44MDk1MyA2LjIzMTk1IDEuNjEzNjRDNi41Njk3OSAxLjQxNzY0IDYuOTMxNDYgMS4yNjYyIDcuMzE1NzggMS4xNTk4M0M3LjcwMTA2IDEuMDUzMiA4LjEwMDk0IDEgOC41MTUxNCAxQzguOTI5MzQgMSA5LjMyOTIzIDEuMDUzMiA5LjcxNDUxIDEuMTU5ODNDMTAuMDk4OCAxLjI2NjIgMTAuNDU4IDEuNDE3MzkgMTAuNzkxOCAxLjYxMzUxQzExLjEyOTQgMS44MDkzOCAxMS40MzUxIDIuMDQzNyAxMS43MDg4IDIuMzE2NDFDMTEuOTgyNSAyLjU4OTEgMTIuMjE3NyAyLjg5Mzc2IDEyLjQxNDMgMy4yMzAxNkMxMi42MTEyIDMuNTYyODUgMTIuNzYzIDMuOTIwODggMTIuODY5OCA0LjMwMzk3QzEyLjk3NjkgNC42ODgwMiAxMy4wMzAzIDUuMDg2NjQgMTMuMDMwMyA1LjQ5OTUzQzEzLjAzMDMgNi4xMTY3MiAxMi45MTI3IDYuNjkxMDcgMTIuNjc2NyA3LjIyMTM0QzEyLjQ0MTMgNy43NTAwMyAxMi4xMDU2IDguMjI5MDMgMTEuNjcwOCA4LjY1ODA2Wk05LjYyMTYyIDEwLjVINy40MDg2N1YxMi43MDEyQzcuNDA4NjcgMTIuNzgyMyA3LjQzNzIgMTIuODUxMiA3LjQ5ODg4IDEyLjkxMjdDNy41NjA1OCAxMi45NzQxIDcuNjMwMDcgMTMuMDAyOCA3LjcxMjA1IDEzLjAwMjhIOS4zMTgyM0M5LjQwMDIyIDEzLjAwMjggOS40Njk3MSAxMi45NzQxIDkuNTMxNCAxMi45MTI3QzkuNTkzMDkgMTIuODUxMiA5LjYyMTYyIDEyLjc4MjMgOS42MjE2MiAxMi43MDEyVjEwLjVaIiBmaWxsPSIjRERCMTAwIi8+Cjwvc3ZnPgo=") 50% no-repeat}.monaco-editor.vs .lightbulb-glyph.autofixable{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMiA5QzEwLjMzMDQgOSA5IDEwLjMzMDQgOSAxMkM5IDEzLjY2OTYgMTAuMzMwNCAxNSAxMiAxNUMxMy42Njk2IDE1IDE1IDEzLjY2OTYgMTUgMTJDMTUgMTAuMzMwNCAxMy42Njk2IDkgMTIgOVpNMTEuMjAyOCAxMi40NzEyTDEwLjcwNCAxNEwxMiAxMy4wMjRMMTMuMzA1NCAxNEwxMi43OTcyIDEyLjQ3MTJMMTQgMTEuNjM5NEgxMi41MzYxTDEyIDEwTDExLjQ3MzIgMTEuNjM5NEgxMEwxMS4yMDI4IDEyLjQ3MTJaIiBmaWxsPSIjMDA3QUNDIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTEuMTcwOCA4LjA4NDc0QzkuODUwODEgOC4zNTkxMSA4Ljc3Njg3IDkuMjc2ODQgOC4yODY5NiAxMC41SDYuNDA4NjdWMTIuNzAxMkM2LjQwODY3IDEyLjc4MjMgNi40MzcyIDEyLjg1MTIgNi40OTg4OCAxMi45MTI3QzYuNTYwNTggMTIuOTc0MSA2LjYzMDA3IDEzLjAwMjggNi43MTIwNSAxMy4wMDI4SDguMTI0ODdDOC4yMTM2NCAxMy4zNTEzIDguMzQ3NzMgMTMuNjgwOSA4LjUyMDU5IDEzLjk4NTFDOC40NTQ2MiAxMy45OTUxIDguMzg3MTUgMTQgOC4zMTgyMyAxNEg2LjcxMjA1QzYuNTMyMjMgMTQgNi4zNjIyMyAxMy45NjYzIDYuMjAzMDYgMTMuODk4NEM2LjA0NTY0IDEzLjgzMTEgNS45MDc1MyAxMy43Mzg4IDUuNzg5NjEgMTMuNjIxM0M1LjY3MTY4IDEzLjUwMzggNS41Nzg5NSAxMy4zNjYxIDUuNTExNDEgMTMuMjA5MUM1LjQ0MzExIDEzLjA1MDMgNS40MDkyNyAxMi44ODA3IDUuNDA5MjcgMTIuNzAxMlYxMS4xMDA5QzUuNDA5MjcgMTAuNjIyIDUuMzE3NzIgMTAuMTc5NSA1LjEzNTUzIDkuNzcyMDlDNC45NTY4MyA5LjM2MzM2IDQuNjk4MzIgOC45OTE1NiA0LjM1OTUzIDguNjU4MDZDMy45MjQ2OCA4LjIyOTAzIDMuNTg4OTYgNy43NTAwMyAzLjM1MzYxIDcuMjIxMzRDMy4xMTc1NiA2LjY5MTA3IDMgNi4xMTY3MiAzIDUuNDk5NTNDMyA1LjA4NjY0IDMuMDUzNDIgNC42ODgwMiAzLjE2MDQ4IDQuMzAzOTdDMy4yNjcyOCAzLjkyMDg5IDMuNDE5MDcgMy41NjI4NiAzLjYxNTk1IDMuMjMwMThDMy44MTI1NyAyLjg5Mzc3IDQuMDQ3NzcgMi41ODkxMSA0LjMyMTQ2IDIuMzE2NDFDNC41OTUwMyAyLjA0MzgzIDQuODk4NTggMS44MDk1MyA1LjIzMTk1IDEuNjEzNjRDNS41Njk3OSAxLjQxNzY0IDUuOTMxNDYgMS4yNjYyIDYuMzE1NzggMS4xNTk4M0M2LjcwMTA2IDEuMDUzMiA3LjEwMDk0IDEgNy41MTUxNCAxQzcuOTI5MzQgMSA4LjMyOTIzIDEuMDUzMiA4LjcxNDUxIDEuMTU5ODNDOS4wOTg4MyAxLjI2NjIgOS40NTgwMyAxLjQxNzM5IDkuNzkxODMgMS42MTM1MUMxMC4xMjk0IDEuODA5MzggMTAuNDM1MSAyLjA0MzcgMTAuNzA4OCAyLjMxNjQxQzEwLjk4MjUgMi41ODkxIDExLjIxNzcgMi44OTM3NiAxMS40MTQzIDMuMjMwMTZDMTEuNjExMiAzLjU2Mjg1IDExLjc2MyAzLjkyMDg4IDExLjg2OTggNC4zMDM5N0MxMS45NzY5IDQuNjg4MDIgMTIuMDMwMyA1LjA4NjY0IDEyLjAzMDMgNS40OTk1M0MxMi4wMzAzIDYuMTE2NzIgMTEuOTEyNyA2LjY5MTA3IDExLjY3NjcgNy4yMjEzNEMxMS41NDEyIDcuNTI1NjIgMTEuMzcyNSA3LjgxMzQ0IDExLjE3MDggOC4wODQ3NFoiIGZpbGw9IiMwMDdBQ0MiLz4KPC9zdmc+Cg==") 50% no-repeat}.monaco-editor.hc-black .lightbulb-glyph,.monaco-editor.vs-dark .lightbulb-glyph{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMS42NzA4IDguNjU4MDZDMTEuMzMxOSA4Ljk5MTYgMTEuMDcxNiA5LjM2Mjc4IDEwLjg4ODYgOS43NzE3MkMxMC43MTA1IDEwLjE3OTIgMTAuNjIxIDEwLjYyMTkgMTAuNjIxIDExLjEwMDlWMTIuNzAxMkMxMC42MjEgMTIuODgwNyAxMC41ODcyIDEzLjA1MDMgMTAuNTE4OSAxMy4yMDkxQzEwLjQ1MTMgMTMuMzY2MSAxMC4zNTg2IDEzLjUwMzggMTAuMjQwNyAxMy42MjEzQzEwLjEyMjggMTMuNzM4OCA5Ljk4NDY0IDEzLjgzMTEgOS44MjcyMyAxMy44OTg0QzkuNjY4MDYgMTMuOTY2MyA5LjQ5ODA2IDE0IDkuMzE4MjMgMTRINy43MTIwNUM3LjUzMjIzIDE0IDcuMzYyMjMgMTMuOTY2MyA3LjIwMzA2IDEzLjg5ODRDNy4wNDU2NCAxMy44MzExIDYuOTA3NTMgMTMuNzM4OCA2Ljc4OTYxIDEzLjYyMTNDNi42NzE2OCAxMy41MDM4IDYuNTc4OTUgMTMuMzY2MSA2LjUxMTQxIDEzLjIwOTFDNi40NDMxMSAxMy4wNTAzIDYuNDA5MjcgMTIuODgwNyA2LjQwOTI3IDEyLjcwMTJWMTEuMTAwOUM2LjQwOTI3IDEwLjYyMiA2LjMxNzcyIDEwLjE3OTUgNi4xMzU1MyA5Ljc3MjA5QzUuOTU2ODMgOS4zNjMzNiA1LjY5ODMyIDguOTkxNTYgNS4zNTk1MyA4LjY1ODA2QzQuOTI0NjggOC4yMjkwMyA0LjU4ODk2IDcuNzUwMDMgNC4zNTM2MSA3LjIyMTM0QzQuMTE3NTYgNi42OTEwNyA0IDYuMTE2NzIgNCA1LjQ5OTUzQzQgNS4wODY2NCA0LjA1MzQyIDQuNjg4MDIgNC4xNjA0OCA0LjMwMzk3QzQuMjY3MjggMy45MjA4OSA0LjQxOTA3IDMuNTYyODYgNC42MTU5NSAzLjIzMDE4QzQuODEyNTcgMi44OTM3NyA1LjA0Nzc3IDIuNTg5MTEgNS4zMjE0NiAyLjMxNjQxQzUuNTk1MDMgMi4wNDM4MyA1Ljg5ODU4IDEuODA5NTMgNi4yMzE5NSAxLjYxMzY0QzYuNTY5NzkgMS40MTc2NCA2LjkzMTQ2IDEuMjY2MiA3LjMxNTc4IDEuMTU5ODNDNy43MDEwNiAxLjA1MzIgOC4xMDA5NCAxIDguNTE1MTQgMUM4LjkyOTM0IDEgOS4zMjkyMyAxLjA1MzIgOS43MTQ1MSAxLjE1OTgzQzEwLjA5ODggMS4yNjYyIDEwLjQ1OCAxLjQxNzM5IDEwLjc5MTggMS42MTM1MUMxMS4xMjk0IDEuODA5MzggMTEuNDM1MSAyLjA0MzcgMTEuNzA4OCAyLjMxNjQxQzExLjk4MjUgMi41ODkxIDEyLjIxNzcgMi44OTM3NiAxMi40MTQzIDMuMjMwMTZDMTIuNjExMiAzLjU2Mjg1IDEyLjc2MyAzLjkyMDg4IDEyLjg2OTggNC4zMDM5N0MxMi45NzY5IDQuNjg4MDIgMTMuMDMwMyA1LjA4NjY0IDEzLjAzMDMgNS40OTk1M0MxMy4wMzAzIDYuMTE2NzIgMTIuOTEyNyA2LjY5MTA3IDEyLjY3NjcgNy4yMjEzNEMxMi40NDEzIDcuNzUwMDMgMTIuMTA1NiA4LjIyOTAzIDExLjY3MDggOC42NTgwNlpNOS42MjE2MiAxMC41SDcuNDA4NjdWMTIuNzAxMkM3LjQwODY3IDEyLjc4MjMgNy40MzcyIDEyLjg1MTIgNy40OTg4OCAxMi45MTI3QzcuNTYwNTggMTIuOTc0MSA3LjYzMDA3IDEzLjAwMjggNy43MTIwNSAxMy4wMDI4SDkuMzE4MjNDOS40MDAyMiAxMy4wMDI4IDkuNDY5NzEgMTIuOTc0MSA5LjUzMTQgMTIuOTEyN0M5LjU5MzA5IDEyLjg1MTIgOS42MjE2MiAxMi43ODIzIDkuNjIxNjIgMTIuNzAxMlYxMC41WiIgZmlsbD0iI0ZGQ0MwMCIvPgo8L3N2Zz4K") 50% no-repeat}.monaco-editor.hc-black .lightbulb-glyph.autofixable,.monaco-editor.vs-dark .lightbulb-glyph.autofixable{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMiA5QzEwLjMzMDQgOSA5IDEwLjMzMDQgOSAxMkM5IDEzLjY2OTYgMTAuMzMwNCAxNSAxMiAxNUMxMy42Njk2IDE1IDE1IDEzLjY2OTYgMTUgMTJDMTUgMTAuMzMwNCAxMy42Njk2IDkgMTIgOVpNMTEuMjAyOCAxMi40NzEyTDEwLjcwNCAxNEwxMiAxMy4wMjRMMTMuMzA1NCAxNEwxMi43OTcyIDEyLjQ3MTJMMTQgMTEuNjM5NEgxMi41MzYxTDEyIDEwTDExLjQ3MzIgMTEuNjM5NEgxMEwxMS4yMDI4IDEyLjQ3MTJaIiBmaWxsPSIjNzVCRUZGIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTEuMTcwOCA4LjA4NDc0QzkuODUwODEgOC4zNTkxMSA4Ljc3Njg3IDkuMjc2ODQgOC4yODY5NiAxMC41SDYuNDA4NjdWMTIuNzAxMkM2LjQwODY3IDEyLjc4MjMgNi40MzcyIDEyLjg1MTIgNi40OTg4OCAxMi45MTI3QzYuNTYwNTggMTIuOTc0MSA2LjYzMDA3IDEzLjAwMjggNi43MTIwNSAxMy4wMDI4SDguMTI0ODdDOC4yMTM2NCAxMy4zNTEzIDguMzQ3NzMgMTMuNjgwOSA4LjUyMDU5IDEzLjk4NTFDOC40NTQ2MiAxMy45OTUxIDguMzg3MTUgMTQgOC4zMTgyMyAxNEg2LjcxMjA1QzYuNTMyMjMgMTQgNi4zNjIyMyAxMy45NjYzIDYuMjAzMDYgMTMuODk4NEM2LjA0NTY0IDEzLjgzMTEgNS45MDc1MyAxMy43Mzg4IDUuNzg5NjEgMTMuNjIxM0M1LjY3MTY4IDEzLjUwMzggNS41Nzg5NSAxMy4zNjYxIDUuNTExNDEgMTMuMjA5MUM1LjQ0MzExIDEzLjA1MDMgNS40MDkyNyAxMi44ODA3IDUuNDA5MjcgMTIuNzAxMlYxMS4xMDA5QzUuNDA5MjcgMTAuNjIyIDUuMzE3NzIgMTAuMTc5NSA1LjEzNTUzIDkuNzcyMDlDNC45NTY4MyA5LjM2MzM2IDQuNjk4MzIgOC45OTE1NiA0LjM1OTUzIDguNjU4MDZDMy45MjQ2OCA4LjIyOTAzIDMuNTg4OTYgNy43NTAwMyAzLjM1MzYxIDcuMjIxMzRDMy4xMTc1NiA2LjY5MTA3IDMgNi4xMTY3MiAzIDUuNDk5NTNDMyA1LjA4NjY0IDMuMDUzNDIgNC42ODgwMiAzLjE2MDQ4IDQuMzAzOTdDMy4yNjcyOCAzLjkyMDg5IDMuNDE5MDcgMy41NjI4NiAzLjYxNTk1IDMuMjMwMThDMy44MTI1NyAyLjg5Mzc3IDQuMDQ3NzcgMi41ODkxMSA0LjMyMTQ2IDIuMzE2NDFDNC41OTUwMyAyLjA0MzgzIDQuODk4NTggMS44MDk1MyA1LjIzMTk1IDEuNjEzNjRDNS41Njk3OSAxLjQxNzY0IDUuOTMxNDYgMS4yNjYyIDYuMzE1NzggMS4xNTk4M0M2LjcwMTA2IDEuMDUzMiA3LjEwMDk0IDEgNy41MTUxNCAxQzcuOTI5MzQgMSA4LjMyOTIzIDEuMDUzMiA4LjcxNDUxIDEuMTU5ODNDOS4wOTg4MyAxLjI2NjIgOS40NTgwMyAxLjQxNzM5IDkuNzkxODMgMS42MTM1MUMxMC4xMjk0IDEuODA5MzggMTAuNDM1MSAyLjA0MzcgMTAuNzA4OCAyLjMxNjQxQzEwLjk4MjUgMi41ODkxIDExLjIxNzcgMi44OTM3NiAxMS40MTQzIDMuMjMwMTZDMTEuNjExMiAzLjU2Mjg1IDExLjc2MyAzLjkyMDg4IDExLjg2OTggNC4zMDM5N0MxMS45NzY5IDQuNjg4MDIgMTIuMDMwMyA1LjA4NjY0IDEyLjAzMDMgNS40OTk1M0MxMi4wMzAzIDYuMTE2NzIgMTEuOTEyNyA2LjY5MTA3IDExLjY3NjcgNy4yMjEzNEMxMS41NDEyIDcuNTI1NjIgMTEuMzcyNSA3LjgxMzQ0IDExLjE3MDggOC4wODQ3NFoiIGZpbGw9IiM3NUJFRkYiLz4KPC9zdmc+Cg==") 50% no-repeat}.monaco-editor .codelens-decoration{overflow:hidden;display:inline-block;text-overflow:ellipsis}.monaco-editor .codelens-decoration>a,.monaco-editor .codelens-decoration>span{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none;white-space:nowrap;vertical-align:sub}.monaco-editor .codelens-decoration>a{text-decoration:none}.monaco-editor .codelens-decoration>a:hover{text-decoration:underline;cursor:pointer}.monaco-editor .codelens-decoration.invisible-cl{opacity:0}@keyframes fadein{0%{opacity:0;visibility:visible}to{opacity:1}}.monaco-editor .codelens-decoration.fadein{animation:fadein .1s linear}.monaco-action-bar{text-align:right;overflow:hidden;white-space:nowrap}.monaco-action-bar .actions-container{display:-ms-flexbox;display:flex;margin:0 auto;padding:0;width:100%;-ms-flex-pack:end;justify-content:flex-end}.monaco-action-bar.vertical .actions-container{display:inline-block}.monaco-action-bar.reverse .actions-container{-ms-flex-direction:row-reverse;flex-direction:row-reverse}.monaco-action-bar .action-item{cursor:pointer;display:inline-block;transition:transform 50ms ease;position:relative}.monaco-action-bar .action-item.disabled{cursor:default}.monaco-action-bar.animated .action-item.active{transform:scale(1.272019649)}.monaco-action-bar .action-item .icon{display:inline-block}.monaco-action-bar .action-label{font-size:11px;margin-right:4px}.monaco-action-bar .action-label.octicon{font-size:15px;line-height:35px;text-align:center}.monaco-action-bar .action-item.disabled .action-label,.monaco-action-bar .action-item.disabled .action-label:hover{opacity:.4}.monaco-action-bar.vertical{text-align:left}.monaco-action-bar.vertical .action-item{display:block}.monaco-action-bar.vertical .action-label.separator{display:block;border-bottom:1px solid #bbb;padding-top:1px;margin-left:.8em;margin-right:.8em}.monaco-action-bar.animated.vertical .action-item.active{transform:translate(5px)}.secondary-actions .monaco-action-bar .action-label{margin-left:6px}.monaco-action-bar .action-item.select-container{overflow:hidden;-ms-flex:1;flex:1;max-width:170px;min-width:60px;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center}.monaco-editor.vs .dnd-target{border-right:2px dotted #000;color:#fff}.monaco-editor.vs-dark .dnd-target{border-right:2px dotted #aeafad;color:#51504f}.monaco-editor.hc-black .dnd-target{border-right:2px dotted #fff;color:#000}.monaco-editor.hc-black.mac.mouse-default .view-lines,.monaco-editor.mouse-default .view-lines,.monaco-editor.vs-dark.mac.mouse-default .view-lines{cursor:default}.monaco-editor.hc-black.mac.mouse-copy .view-lines,.monaco-editor.mouse-copy .view-lines,.monaco-editor.vs-dark.mac.mouse-copy .view-lines{cursor:copy}.monaco-custom-checkbox{margin-left:2px;float:left;cursor:pointer;overflow:hidden;opacity:.7;width:20px;height:20px;border:1px solid transparent;padding:1px;-o-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;-webkit-user-select:none;-moz-user-select:none;-o-user-select:none;-ms-user-select:none;user-select:none}.monaco-custom-checkbox.checked,.monaco-custom-checkbox:hover{opacity:1}.hc-black .monaco-custom-checkbox,.hc-black .monaco-custom-checkbox:hover{background:none}.monaco-custom-checkbox.monaco-simple-checkbox{height:18px;width:18px;border:1px solid transparent;border-radius:3px;margin-right:9px;margin-left:0;padding:0;opacity:1;background-size:16px!important}.monaco-custom-checkbox.monaco-simple-checkbox.checked{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xNSAzLjc2MzQ1TDUuODA2ODcgMTEuOTM1MUw1LjA4NTg0IDExLjg5MjdMMSA3LjI5NjE0TDEuNzYzNDUgNi42MTc1Mkw1LjUwOTk3IDEwLjgzMjRMMTQuMzIxNCAzTDE1IDMuNzYzNDVaIiBmaWxsPSIjNDI0MjQyIi8+Cjwvc3ZnPgo=") 50% no-repeat;background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xNSAzLjc2MzQ1TDUuODA2ODcgMTEuOTM1MUw1LjA4NTg0IDExLjg5MjdMMSA3LjI5NjE0TDEuNzYzNDUgNi42MTc1Mkw1LjUwOTk3IDEwLjgzMjRMMTQuMzIxNCAzTDE1IDMuNzYzNDVaIiBmaWxsPSIjQzVDNUM1Ii8+Cjwvc3ZnPgo=") 50% no-repeat}.vs .monaco-custom-checkbox.monaco-case-sensitive{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03LjQ5NSA5LjA1Mkw4LjM4NiAxMS40MDJIOS40NzdMNi4yMzcgM0g1LjIxN0wyIDExLjQwMkgzLjA5NUwzLjkzMyA5LjA1Mkg3LjQ5NVpNNS44MTEgNC40NTNMNS44NTUgNC41ODhMNy4xNzMgOC4xNjJINC4yNTVMNS41NjIgNC41ODhMNS42MDYgNC40NTNMNS42NDQgNC4yOTdMNS42NzYgNC4xNDVMNS42OTcgNC4wMTlINS43Mkw1Ljc0NCA0LjE0NUw1Ljc3MyA0LjI5N0w1LjgxMSA0LjQ1M1pNMTMuNzk1IDEwLjQ2NFYxMS40SDE0Ljc1NVY3LjQ5OEMxNC43NTUgNi43NzkgMTQuNTc1IDYuMjI2IDE0LjIxNiA1LjgzN0MxMy44NTcgNS40NDggMTMuMzI3IDUuMjU0IDEyLjYyOCA1LjI1NEMxMi40MjkgNS4yNTQgMTIuMjI3IDUuMjczIDEyLjAyMiA1LjMxQzExLjgxNyA1LjM0NyAxMS42MjIgNS4zOTQgMTEuNDM5IDUuNDUxQzExLjI1NiA1LjUwOCAxMS4wOTEgNS41NjkgMTAuOTQ0IDUuNjM2QzEwLjc5NyA1LjcwMyAxMC42ODMgNS43NjUgMTAuNjAxIDUuODI0VjYuODA4QzEwLjg2NyA2LjU3OCAxMS4xNjcgNi4zOTcgMTEuNTA1IDYuMjY4QzExLjg0MyA2LjEzOSAxMi4xOTQgNi4wNzUgMTIuNTU3IDYuMDc1QzEyLjc0NSA2LjA3NSAxMi45MTUgNi4xMDMgMTMuMDcgNi4xNkMxMy4yMjUgNi4yMTcgMTMuMzU3IDYuMzA2IDEzLjQ2NiA2LjQyN0MxMy41NzUgNi41NDggMTMuNjU5IDYuNzA2IDEzLjcxOCA2Ljg5OUMxMy43NzcgNy4wOTIgMTMuODA2IDcuMzI2IDEzLjgwNiA3LjU5OUwxMS45OTUgNy44NTFDMTEuNjUxIDcuODk4IDExLjM1NSA3Ljk3NyAxMS4xMDcgOC4wODhDMTAuODU5IDguMTk5IDEwLjY1NCA4LjMzOSAxMC40OTIgOC41MDdDMTAuMzMgOC42NzUgMTAuMjEgOC44NjggMTAuMTMyIDkuMDg3QzEwLjA1NCA5LjMwNiAxMC4wMTUgOS41NDYgMTAuMDE1IDkuODA4QzEwLjAxNSAxMC4wNTQgMTAuMDU3IDEwLjI4MyAxMC4xMzkgMTAuNDk2QzEwLjIyMSAxMC43MDkgMTAuMzQyIDEwLjg5MyAxMC41MDIgMTEuMDQ3QzEwLjY2MiAxMS4yMDEgMTAuODYyIDExLjMyMyAxMS4xIDExLjQxM0MxMS4zMzggMTEuNTAzIDExLjYxMyAxMS41NDggMTEuOTI2IDExLjU0OEMxMi4zMjggMTEuNTQ4IDEyLjY4NiAxMS40NTYgMTMuMDAxIDExLjI3QzEzLjMxNiAxMS4wODQgMTMuNTczIDEwLjgxNiAxMy43NzIgMTAuNDY0SDEzLjc5NVpNMTEuNjY3IDguNzIxQzExLjg0MyA4LjY1NyAxMi4wNjggOC42MDcgMTIuMzQxIDguNTcyTDEzLjgwNiA4LjM2N1Y4Ljk3NkMxMy44MDYgOS4yMjIgMTMuNzY1IDkuNDUxIDEzLjY4MyA5LjY2NEMxMy42MDEgOS44NzcgMTMuNDg2IDEwLjA2MyAxMy4zNCAxMC4yMjFDMTMuMTk0IDEwLjM3OSAxMy4wMTkgMTAuNTAzIDEyLjgxNiAxMC41OTNDMTIuNjEzIDEwLjY4MyAxMi4zOSAxMC43MjggMTIuMTQ4IDEwLjcyOEMxMS45NjEgMTAuNzI4IDExLjc5NSAxMC43MDMgMTEuNjUzIDEwLjY1MkMxMS41MTEgMTAuNjAxIDExLjM5MiAxMC41MyAxMS4yOTYgMTAuNDQxQzExLjIgMTAuMzUyIDExLjEyNyAxMC4yNDcgMTEuMDc2IDEwLjEyNUMxMS4wMjUgMTAuMDAzIDExIDkuODczIDExIDkuNzMyQzExIDkuNTY4IDExLjAxOCA5LjQyMSAxMS4wNTUgOS4yOTJDMTEuMDkyIDkuMTYzIDExLjE2IDkuMDUxIDExLjI1NyA4Ljk1OEMxMS4zNTQgOC44NjUgMTEuNDkxIDguNzg1IDExLjY2NyA4LjcyMVoiIGZpbGw9IiM0MjQyNDIiLz4KPC9zdmc+Cg==") 50% no-repeat}.vs-dark .monaco-custom-checkbox.monaco-case-sensitive{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03LjQ5NSA5LjA1Mkw4LjM4NiAxMS40MDJIOS40NzdMNi4yMzcgM0g1LjIxN0wyIDExLjQwMkgzLjA5NUwzLjkzMyA5LjA1Mkg3LjQ5NVpNNS44MTEgNC40NTNMNS44NTUgNC41ODhMNy4xNzMgOC4xNjJINC4yNTVMNS41NjIgNC41ODhMNS42MDYgNC40NTNMNS42NDQgNC4yOTdMNS42NzYgNC4xNDVMNS42OTcgNC4wMTlINS43Mkw1Ljc0NCA0LjE0NUw1Ljc3MyA0LjI5N0w1LjgxMSA0LjQ1M1pNMTMuNzk1IDEwLjQ2NFYxMS40SDE0Ljc1NVY3LjQ5OEMxNC43NTUgNi43NzkgMTQuNTc1IDYuMjI2IDE0LjIxNiA1LjgzN0MxMy44NTcgNS40NDggMTMuMzI3IDUuMjU0IDEyLjYyOCA1LjI1NEMxMi40MjkgNS4yNTQgMTIuMjI3IDUuMjczIDEyLjAyMiA1LjMxQzExLjgxNyA1LjM0NyAxMS42MjIgNS4zOTQgMTEuNDM5IDUuNDUxQzExLjI1NiA1LjUwOCAxMS4wOTEgNS41NjkgMTAuOTQ0IDUuNjM2QzEwLjc5NyA1LjcwMyAxMC42ODMgNS43NjUgMTAuNjAxIDUuODI0VjYuODA4QzEwLjg2NyA2LjU3OCAxMS4xNjcgNi4zOTcgMTEuNTA1IDYuMjY4QzExLjg0MyA2LjEzOSAxMi4xOTQgNi4wNzUgMTIuNTU3IDYuMDc1QzEyLjc0NSA2LjA3NSAxMi45MTUgNi4xMDMgMTMuMDcgNi4xNkMxMy4yMjUgNi4yMTcgMTMuMzU3IDYuMzA2IDEzLjQ2NiA2LjQyN0MxMy41NzUgNi41NDggMTMuNjU5IDYuNzA2IDEzLjcxOCA2Ljg5OUMxMy43NzcgNy4wOTIgMTMuODA2IDcuMzI2IDEzLjgwNiA3LjU5OUwxMS45OTUgNy44NTFDMTEuNjUxIDcuODk4IDExLjM1NSA3Ljk3NyAxMS4xMDcgOC4wODhDMTAuODU5IDguMTk5IDEwLjY1NCA4LjMzOSAxMC40OTIgOC41MDdDMTAuMzMgOC42NzUgMTAuMjEgOC44NjggMTAuMTMyIDkuMDg3QzEwLjA1NCA5LjMwNiAxMC4wMTUgOS41NDYgMTAuMDE1IDkuODA4QzEwLjAxNSAxMC4wNTQgMTAuMDU3IDEwLjI4MyAxMC4xMzkgMTAuNDk2QzEwLjIyMSAxMC43MDkgMTAuMzQyIDEwLjg5MyAxMC41MDIgMTEuMDQ3QzEwLjY2MiAxMS4yMDEgMTAuODYyIDExLjMyMyAxMS4xIDExLjQxM0MxMS4zMzggMTEuNTAzIDExLjYxMyAxMS41NDggMTEuOTI2IDExLjU0OEMxMi4zMjggMTEuNTQ4IDEyLjY4NiAxMS40NTYgMTMuMDAxIDExLjI3QzEzLjMxNiAxMS4wODQgMTMuNTczIDEwLjgxNiAxMy43NzIgMTAuNDY0SDEzLjc5NVpNMTEuNjY3IDguNzIxQzExLjg0MyA4LjY1NyAxMi4wNjggOC42MDcgMTIuMzQxIDguNTcyTDEzLjgwNiA4LjM2N1Y4Ljk3NkMxMy44MDYgOS4yMjIgMTMuNzY1IDkuNDUxIDEzLjY4MyA5LjY2NEMxMy42MDEgOS44NzcgMTMuNDg2IDEwLjA2MyAxMy4zNCAxMC4yMjFDMTMuMTk0IDEwLjM3OSAxMy4wMTkgMTAuNTAzIDEyLjgxNiAxMC41OTNDMTIuNjEzIDEwLjY4MyAxMi4zOSAxMC43MjggMTIuMTQ4IDEwLjcyOEMxMS45NjEgMTAuNzI4IDExLjc5NSAxMC43MDMgMTEuNjUzIDEwLjY1MkMxMS41MTEgMTAuNjAxIDExLjM5MiAxMC41MyAxMS4yOTYgMTAuNDQxQzExLjIgMTAuMzUyIDExLjEyNyAxMC4yNDcgMTEuMDc2IDEwLjEyNUMxMS4wMjUgMTAuMDAzIDExIDkuODczIDExIDkuNzMyQzExIDkuNTY4IDExLjAxOCA5LjQyMSAxMS4wNTUgOS4yOTJDMTEuMDkyIDkuMTYzIDExLjE2IDkuMDUxIDExLjI1NyA4Ljk1OEMxMS4zNTQgOC44NjUgMTEuNDkxIDguNzg1IDExLjY2NyA4LjcyMVoiIGZpbGw9IiNDNUM1QzUiLz4KPC9zdmc+Cg==") 50% no-repeat}.hc-black .monaco-custom-checkbox.monaco-case-sensitive,.hc-black .monaco-custom-checkbox.monaco-case-sensitive:hover{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03LjQ5NSA5LjA1Mkw4LjM4NiAxMS40MDJIOS40NzdMNi4yMzcgM0g1LjIxN0wyIDExLjQwMkgzLjA5NUwzLjkzMyA5LjA1Mkg3LjQ5NVpNNS44MTEgNC40NTNMNS44NTUgNC41ODhMNy4xNzMgOC4xNjJINC4yNTVMNS41NjIgNC41ODhMNS42MDYgNC40NTNMNS42NDQgNC4yOTdMNS42NzYgNC4xNDVMNS42OTcgNC4wMTlINS43Mkw1Ljc0NCA0LjE0NUw1Ljc3MyA0LjI5N0w1LjgxMSA0LjQ1M1pNMTMuNzk1IDEwLjQ2NFYxMS40SDE0Ljc1NVY3LjQ5OEMxNC43NTUgNi43NzkgMTQuNTc1IDYuMjI2IDE0LjIxNiA1LjgzN0MxMy44NTcgNS40NDggMTMuMzI3IDUuMjU0IDEyLjYyOCA1LjI1NEMxMi40MjkgNS4yNTQgMTIuMjI3IDUuMjczIDEyLjAyMiA1LjMxQzExLjgxNyA1LjM0NyAxMS42MjIgNS4zOTQgMTEuNDM5IDUuNDUxQzExLjI1NiA1LjUwOCAxMS4wOTEgNS41NjkgMTAuOTQ0IDUuNjM2QzEwLjc5NyA1LjcwMyAxMC42ODMgNS43NjUgMTAuNjAxIDUuODI0VjYuODA4QzEwLjg2NyA2LjU3OCAxMS4xNjcgNi4zOTcgMTEuNTA1IDYuMjY4QzExLjg0MyA2LjEzOSAxMi4xOTQgNi4wNzUgMTIuNTU3IDYuMDc1QzEyLjc0NSA2LjA3NSAxMi45MTUgNi4xMDMgMTMuMDcgNi4xNkMxMy4yMjUgNi4yMTcgMTMuMzU3IDYuMzA2IDEzLjQ2NiA2LjQyN0MxMy41NzUgNi41NDggMTMuNjU5IDYuNzA2IDEzLjcxOCA2Ljg5OUMxMy43NzcgNy4wOTIgMTMuODA2IDcuMzI2IDEzLjgwNiA3LjU5OUwxMS45OTUgNy44NTFDMTEuNjUxIDcuODk4IDExLjM1NSA3Ljk3NyAxMS4xMDcgOC4wODhDMTAuODU5IDguMTk5IDEwLjY1NCA4LjMzOSAxMC40OTIgOC41MDdDMTAuMzMgOC42NzUgMTAuMjEgOC44NjggMTAuMTMyIDkuMDg3QzEwLjA1NCA5LjMwNiAxMC4wMTUgOS41NDYgMTAuMDE1IDkuODA4QzEwLjAxNSAxMC4wNTQgMTAuMDU3IDEwLjI4MyAxMC4xMzkgMTAuNDk2QzEwLjIyMSAxMC43MDkgMTAuMzQyIDEwLjg5MyAxMC41MDIgMTEuMDQ3QzEwLjY2MiAxMS4yMDEgMTAuODYyIDExLjMyMyAxMS4xIDExLjQxM0MxMS4zMzggMTEuNTAzIDExLjYxMyAxMS41NDggMTEuOTI2IDExLjU0OEMxMi4zMjggMTEuNTQ4IDEyLjY4NiAxMS40NTYgMTMuMDAxIDExLjI3QzEzLjMxNiAxMS4wODQgMTMuNTczIDEwLjgxNiAxMy43NzIgMTAuNDY0SDEzLjc5NVpNMTEuNjY3IDguNzIxQzExLjg0MyA4LjY1NyAxMi4wNjggOC42MDcgMTIuMzQxIDguNTcyTDEzLjgwNiA4LjM2N1Y4Ljk3NkMxMy44MDYgOS4yMjIgMTMuNzY1IDkuNDUxIDEzLjY4MyA5LjY2NEMxMy42MDEgOS44NzcgMTMuNDg2IDEwLjA2MyAxMy4zNCAxMC4yMjFDMTMuMTk0IDEwLjM3OSAxMy4wMTkgMTAuNTAzIDEyLjgxNiAxMC41OTNDMTIuNjEzIDEwLjY4MyAxMi4zOSAxMC43MjggMTIuMTQ4IDEwLjcyOEMxMS45NjEgMTAuNzI4IDExLjc5NSAxMC43MDMgMTEuNjUzIDEwLjY1MkMxMS41MTEgMTAuNjAxIDExLjM5MiAxMC41MyAxMS4yOTYgMTAuNDQxQzExLjIgMTAuMzUyIDExLjEyNyAxMC4yNDcgMTEuMDc2IDEwLjEyNUMxMS4wMjUgMTAuMDAzIDExIDkuODczIDExIDkuNzMyQzExIDkuNTY4IDExLjAxOCA5LjQyMSAxMS4wNTUgOS4yOTJDMTEuMDkyIDkuMTYzIDExLjE2IDkuMDUxIDExLjI1NyA4Ljk1OEMxMS4zNTQgOC44NjUgMTEuNDkxIDguNzg1IDExLjY2NyA4LjcyMVoiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPgo=") 50% no-repeat}.vs .monaco-custom-checkbox.monaco-preserve-case{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTguNTM0MzcgMTIuNDY3M0g3LjQzNjFMNi41Mzg1OSAxMC4wOTM2SDIuOTQ4NTRMMi4xMDQxOCAxMi40NjczSDFMNC4yNDc1NyA0SDUuMjc0OTlMOC41MzQzNyAxMi40NjczWk02LjIxMzgzIDkuMjAyMDJMNC44ODUyOCA1LjU5NDI2QzQuODQxOTggNS40NzYxNyA0Ljc5ODY4IDUuMjg3MjIgNC43NTUzOCA1LjAyNzQxSDQuNzMxNzZDNC42OTIzOSA1LjI2NzU0IDQuNjQ3MTMgNS40NTY0OSA0LjU5NTk1IDUuNTk0MjZMMy4yNzkyMSA5LjIwMjAySDYuMjEzODNaIiBmaWxsPSIjNDI0MjQyIi8+CjxwYXRoIGQ9Ik05Ljc4NjE3IDEyLjQ2NzNWNEgxMi4xOTUzQzEyLjkyNzUgNCAxMy41MDgxIDQuMTc5MTEgMTMuOTM3MiA0LjUzNzMzQzE0LjM2NjIgNC44OTU1NCAxNC41ODA4IDUuMzYyMDEgMTQuNTgwOCA1LjkzNjc0QzE0LjU4MDggNi40MTY5OCAxNC40NTA5IDYuODM0MjUgMTQuMTkxMSA3LjE4ODUzQzEzLjkzMTMgNy41NDI4MSAxMy41NzMgNy43OTQ3NCAxMy4xMTY0IDcuOTQ0MzNWNy45Njc5NUMxMy42ODcyIDguMDM0ODcgMTQuMTQzOCA4LjI1MTM3IDE0LjQ4NjMgOC42MTc0NkMxNC44Mjg4IDguOTc5NjEgMTUgOS40NTE5OSAxNSAxMC4wMzQ2QzE1IDEwLjc1ODkgMTQuNzQwMiAxMS4zNDU0IDE0LjIyMDYgMTEuNzk0MkMxMy43MDEgMTIuMjQyOSAxMy4wNDU2IDEyLjQ2NzMgMTIuMjU0MyAxMi40NjczSDkuNzg2MTdaTTEwLjc3ODIgNC44OTc1MVY3LjYzMTM4SDExLjc5MzhDMTIuMzM3IDcuNjMxMzggMTIuNzY0MSA3LjUwMTQ4IDEzLjA3NTEgNy4yNDE2N0MxMy4zODYxIDYuOTc3OTMgMTMuNTQxNSA2LjYwNzkgMTMuNTQxNSA2LjEzMTU5QzEzLjU0MTUgNS4zMDg4NyAxMy4wMDAzIDQuODk3NTEgMTEuOTE3OCA0Ljg5NzUxSDEwLjc3ODJaTTEwLjc3ODIgOC41MjI5OVYxMS41Njk4SDEyLjEyNDRDMTIuNzA3IDExLjU2OTggMTMuMTU3NyAxMS40MzIgMTMuNDc2NiAxMS4xNTY1QzEzLjc5OTQgMTAuODgwOSAxMy45NjA4IDEwLjUwMyAxMy45NjA4IDEwLjAyMjhDMTMuOTYwOCA5LjAyMjkyIDEzLjI3OTggOC41MjI5OSAxMS45MTc4IDguNTIyOTlIMTAuNzc4MloiIGZpbGw9IiM0MjQyNDIiLz4KPC9zdmc+Cg==") 50% no-repeat}.vs-dark .monaco-custom-checkbox.monaco-preserve-case{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTguNTM0MzcgMTIuNDY3M0g3LjQzNjFMNi41Mzg1OSAxMC4wOTM2SDIuOTQ4NTRMMi4xMDQxOCAxMi40NjczSDFMNC4yNDc1NyA0SDUuMjc0OTlMOC41MzQzNyAxMi40NjczWk02LjIxMzgzIDkuMjAyMDJMNC44ODUyOCA1LjU5NDI2QzQuODQxOTggNS40NzYxNyA0Ljc5ODY4IDUuMjg3MjIgNC43NTUzOCA1LjAyNzQxSDQuNzMxNzZDNC42OTIzOSA1LjI2NzU0IDQuNjQ3MTMgNS40NTY0OSA0LjU5NTk1IDUuNTk0MjZMMy4yNzkyMSA5LjIwMjAySDYuMjEzODNaIiBmaWxsPSIjQzVDNUM1Ii8+CjxwYXRoIGQ9Ik05Ljc4NjE3IDEyLjQ2NzNWNEgxMi4xOTUzQzEyLjkyNzUgNCAxMy41MDgxIDQuMTc5MTEgMTMuOTM3MiA0LjUzNzMzQzE0LjM2NjIgNC44OTU1NCAxNC41ODA4IDUuMzYyMDEgMTQuNTgwOCA1LjkzNjc0QzE0LjU4MDggNi40MTY5OCAxNC40NTA5IDYuODM0MjUgMTQuMTkxMSA3LjE4ODUzQzEzLjkzMTMgNy41NDI4MSAxMy41NzMgNy43OTQ3NCAxMy4xMTY0IDcuOTQ0MzNWNy45Njc5NUMxMy42ODcyIDguMDM0ODcgMTQuMTQzOCA4LjI1MTM3IDE0LjQ4NjMgOC42MTc0NkMxNC44Mjg4IDguOTc5NjEgMTUgOS40NTE5OSAxNSAxMC4wMzQ2QzE1IDEwLjc1ODkgMTQuNzQwMiAxMS4zNDU0IDE0LjIyMDYgMTEuNzk0MkMxMy43MDEgMTIuMjQyOSAxMy4wNDU2IDEyLjQ2NzMgMTIuMjU0MyAxMi40NjczSDkuNzg2MTdaTTEwLjc3ODIgNC44OTc1MVY3LjYzMTM4SDExLjc5MzhDMTIuMzM3IDcuNjMxMzggMTIuNzY0MSA3LjUwMTQ4IDEzLjA3NTEgNy4yNDE2N0MxMy4zODYxIDYuOTc3OTMgMTMuNTQxNSA2LjYwNzkgMTMuNTQxNSA2LjEzMTU5QzEzLjU0MTUgNS4zMDg4NyAxMy4wMDAzIDQuODk3NTEgMTEuOTE3OCA0Ljg5NzUxSDEwLjc3ODJaTTEwLjc3ODIgOC41MjI5OVYxMS41Njk4SDEyLjEyNDRDMTIuNzA3IDExLjU2OTggMTMuMTU3NyAxMS40MzIgMTMuNDc2NiAxMS4xNTY1QzEzLjc5OTQgMTAuODgwOSAxMy45NjA4IDEwLjUwMyAxMy45NjA4IDEwLjAyMjhDMTMuOTYwOCA5LjAyMjkyIDEzLjI3OTggOC41MjI5OSAxMS45MTc4IDguNTIyOTlIMTAuNzc4MloiIGZpbGw9IiNDNUM1QzUiLz4KPC9zdmc+Cg==") 50% no-repeat}.hc-black .monaco-custom-checkbox.monaco-preserve-case,.hc-black .monaco-custom-checkbox.monaco-preserve-case:hover{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTguNTM0MzcgMTIuNDY3M0g3LjQzNjFMNi41Mzg1OSAxMC4wOTM2SDIuOTQ4NTRMMi4xMDQxOCAxMi40NjczSDFMNC4yNDc1NyA0SDUuMjc0OTlMOC41MzQzNyAxMi40NjczWk02LjIxMzgzIDkuMjAyMDJMNC44ODUyOCA1LjU5NDI2QzQuODQxOTggNS40NzYxNyA0Ljc5ODY4IDUuMjg3MjIgNC43NTUzOCA1LjAyNzQxSDQuNzMxNzZDNC42OTIzOSA1LjI2NzU0IDQuNjQ3MTMgNS40NTY0OSA0LjU5NTk1IDUuNTk0MjZMMy4yNzkyMSA5LjIwMjAySDYuMjEzODNaIiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBkPSJNOS43ODYxNyAxMi40NjczVjRIMTIuMTk1M0MxMi45Mjc1IDQgMTMuNTA4MSA0LjE3OTExIDEzLjkzNzIgNC41MzczM0MxNC4zNjYyIDQuODk1NTQgMTQuNTgwOCA1LjM2MjAxIDE0LjU4MDggNS45MzY3NEMxNC41ODA4IDYuNDE2OTggMTQuNDUwOSA2LjgzNDI1IDE0LjE5MTEgNy4xODg1M0MxMy45MzEzIDcuNTQyODEgMTMuNTczIDcuNzk0NzQgMTMuMTE2NCA3Ljk0NDMzVjcuOTY3OTVDMTMuNjg3MiA4LjAzNDg3IDE0LjE0MzggOC4yNTEzNyAxNC40ODYzIDguNjE3NDZDMTQuODI4OCA4Ljk3OTYxIDE1IDkuNDUxOTkgMTUgMTAuMDM0NkMxNSAxMC43NTg5IDE0Ljc0MDIgMTEuMzQ1NCAxNC4yMjA2IDExLjc5NDJDMTMuNzAxIDEyLjI0MjkgMTMuMDQ1NiAxMi40NjczIDEyLjI1NDMgMTIuNDY3M0g5Ljc4NjE3Wk0xMC43NzgyIDQuODk3NTFWNy42MzEzOEgxMS43OTM4QzEyLjMzNyA3LjYzMTM4IDEyLjc2NDEgNy41MDE0OCAxMy4wNzUxIDcuMjQxNjdDMTMuMzg2MSA2Ljk3NzkzIDEzLjU0MTUgNi42MDc5IDEzLjU0MTUgNi4xMzE1OUMxMy41NDE1IDUuMzA4ODcgMTMuMDAwMyA0Ljg5NzUxIDExLjkxNzggNC44OTc1MUgxMC43NzgyWk0xMC43NzgyIDguNTIyOTlWMTEuNTY5OEgxMi4xMjQ0QzEyLjcwNyAxMS41Njk4IDEzLjE1NzcgMTEuNDMyIDEzLjQ3NjYgMTEuMTU2NUMxMy43OTk0IDEwLjg4MDkgMTMuOTYwOCAxMC41MDMgMTMuOTYwOCAxMC4wMjI4QzEzLjk2MDggOS4wMjI5MiAxMy4yNzk4IDguNTIyOTkgMTEuOTE3OCA4LjUyMjk5SDEwLjc3ODJaIiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4K") 50% no-repeat}.vs .monaco-custom-checkbox.monaco-whole-word{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xIDJIMTVWM0gxVjJaTTE0IDRIMTNWMTJIMTRWNFpNMTEuMjcyIDguMzg3QzExLjE5NCA4LjA4OCAxMS4wNzMgNy44MjUgMTAuOTEyIDcuNjAxQzEwLjc1MSA3LjM3NyAxMC41NDcgNy4yIDEwLjMwMyA3LjA3MUMxMC4wNTkgNi45NDIgOS43NjkgNi44NzggOS40MzcgNi44NzhDOS4yMzkgNi44NzggOS4wNTcgNi45MDIgOC44OSA2Ljk1MUM4LjcyNSA3IDguNTc0IDcuMDY4IDguNDM3IDcuMTU2QzguMzAxIDcuMjQ0IDguMTggNy4zNSA4LjA3MiA3LjQ3NEw3Ljg5MyA3LjczMlY0LjU3OEg3VjEySDcuODkzVjExLjQyNUw4LjAxOSAxMS42QzguMTA2IDExLjcwMiA4LjIwOCAxMS43OSA4LjMyMyAxMS44NjlDOC40NCAxMS45NDcgOC41NzIgMTIuMDA5IDguNzIxIDEyLjA1NUM4Ljg3IDEyLjEwMSA5LjAzNSAxMi4xMjMgOS4yMTkgMTIuMTIzQzkuNTcyIDEyLjEyMyA5Ljg4NSAxMi4wNTIgMTAuMTU2IDExLjkxMUMxMC40MjggMTEuNzY4IDEwLjY1NSAxMS41NzMgMTAuODM4IDExLjMyNUMxMS4wMjEgMTEuMDc1IDExLjE1OSAxMC43ODIgMTEuMjUyIDEwLjQ0NkMxMS4zNDUgMTAuMTA4IDExLjM5MiA5Ljc0MyAxMS4zOTIgOS4zNDlDMTEuMzkxIDkuMDA3IDExLjM1MiA4LjY4NiAxMS4yNzIgOC4zODdaTTkuNzkzIDcuNzhDOS45NDQgNy44NTEgMTAuMDc1IDcuOTU2IDEwLjE4MyA4LjA5NEMxMC4yOTIgOC4yMzQgMTAuMzc3IDguNDA3IDEwLjQzOCA4LjYxMUMxMC40ODkgOC43ODUgMTAuNTIgOC45ODIgMTAuNTI3IDkuMTk4TDEwLjUyIDkuMzIzQzEwLjUyIDkuNjUgMTAuNDg3IDkuOTQzIDEwLjQyIDEwLjE5MkMxMC4zNTMgMTAuNDM4IDEwLjI1OSAxMC42NDUgMTAuMTQyIDEwLjgwNkMxMC4wMjUgMTAuOTY4IDkuODgyIDExLjA5MSA5LjcyMSAxMS4xNzJDOS4zOTkgMTEuMzM0IDguOTYxIDExLjMzOCA4LjY1MiAxMS4xODdDOC40OTkgMTEuMTEyIDguMzY2IDExLjAxMiA4LjI1OSAxMC44OTFDOC4xNzQgMTAuNzk1IDguMTAzIDEwLjY3NSA4LjA0MSAxMC41MjRDOC4wNDEgMTAuNTI0IDcuODYyIDEwLjA3NyA3Ljg2MiA5LjU3N0M3Ljg2MiA5LjA3NyA4LjA0MSA4LjU3NSA4LjA0MSA4LjU3NUM4LjEwMyA4LjM5OCA4LjE3NyA4LjI1NyA4LjI2NSA4LjE0NUM4LjM3OSA4LjAwMiA4LjUyMSA3Ljg4NiA4LjY4OSA3LjhDOC44NTcgNy43MTQgOS4wNTQgNy42NzEgOS4yNzYgNy42NzFDOS40NjYgNy42NzEgOS42NCA3LjcwOCA5Ljc5MyA3Ljc4Wk0xNSAxM0gxVjE0SDE1VjEzWk0yLjgxMyAxMEwyLjA4NSAxMi4wMzFIMUwxLjAyNSAxMS45NTlMMy40NjYgNC44NzMwNUg0LjQwN0w2Ljg5MiAxMi4wMzFINS44MUw1LjAzMiAxMEgyLjgxM1pNMy45MzQgNi40MjIwNUgzLjkxMkwzLjAwNyA5LjE3NTA1SDQuODQ4TDMuOTM0IDYuNDIyMDVaIiBmaWxsPSIjNDI0MjQyIi8+Cjwvc3ZnPgo=") 50% no-repeat}.vs-dark .monaco-custom-checkbox.monaco-whole-word{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xIDJIMTVWM0gxVjJaTTE0IDRIMTNWMTJIMTRWNFpNMTEuMjcyIDguMzg3QzExLjE5NCA4LjA4OCAxMS4wNzMgNy44MjUgMTAuOTEyIDcuNjAxQzEwLjc1MSA3LjM3NyAxMC41NDcgNy4yIDEwLjMwMyA3LjA3MUMxMC4wNTkgNi45NDIgOS43NjkgNi44NzggOS40MzcgNi44NzhDOS4yMzkgNi44NzggOS4wNTcgNi45MDIgOC44OSA2Ljk1MUM4LjcyNSA3IDguNTc0IDcuMDY4IDguNDM3IDcuMTU2QzguMzAxIDcuMjQ0IDguMTggNy4zNSA4LjA3MiA3LjQ3NEw3Ljg5MyA3LjczMlY0LjU3OEg3VjEySDcuODkzVjExLjQyNUw4LjAxOSAxMS42QzguMTA2IDExLjcwMiA4LjIwOCAxMS43OSA4LjMyMyAxMS44NjlDOC40NCAxMS45NDcgOC41NzIgMTIuMDA5IDguNzIxIDEyLjA1NUM4Ljg3IDEyLjEwMSA5LjAzNSAxMi4xMjMgOS4yMTkgMTIuMTIzQzkuNTcyIDEyLjEyMyA5Ljg4NSAxMi4wNTIgMTAuMTU2IDExLjkxMUMxMC40MjggMTEuNzY4IDEwLjY1NSAxMS41NzMgMTAuODM4IDExLjMyNUMxMS4wMjEgMTEuMDc1IDExLjE1OSAxMC43ODIgMTEuMjUyIDEwLjQ0NkMxMS4zNDUgMTAuMTA4IDExLjM5MiA5Ljc0MyAxMS4zOTIgOS4zNDlDMTEuMzkxIDkuMDA3IDExLjM1MiA4LjY4NiAxMS4yNzIgOC4zODdaTTkuNzkzIDcuNzhDOS45NDQgNy44NTEgMTAuMDc1IDcuOTU2IDEwLjE4MyA4LjA5NEMxMC4yOTIgOC4yMzQgMTAuMzc3IDguNDA3IDEwLjQzOCA4LjYxMUMxMC40ODkgOC43ODUgMTAuNTIgOC45ODIgMTAuNTI3IDkuMTk4TDEwLjUyIDkuMzIzQzEwLjUyIDkuNjUgMTAuNDg3IDkuOTQzIDEwLjQyIDEwLjE5MkMxMC4zNTMgMTAuNDM4IDEwLjI1OSAxMC42NDUgMTAuMTQyIDEwLjgwNkMxMC4wMjUgMTAuOTY4IDkuODgyIDExLjA5MSA5LjcyMSAxMS4xNzJDOS4zOTkgMTEuMzM0IDguOTYxIDExLjMzOCA4LjY1MiAxMS4xODdDOC40OTkgMTEuMTEyIDguMzY2IDExLjAxMiA4LjI1OSAxMC44OTFDOC4xNzQgMTAuNzk1IDguMTAzIDEwLjY3NSA4LjA0MSAxMC41MjRDOC4wNDEgMTAuNTI0IDcuODYyIDEwLjA3NyA3Ljg2MiA5LjU3N0M3Ljg2MiA5LjA3NyA4LjA0MSA4LjU3NSA4LjA0MSA4LjU3NUM4LjEwMyA4LjM5OCA4LjE3NyA4LjI1NyA4LjI2NSA4LjE0NUM4LjM3OSA4LjAwMiA4LjUyMSA3Ljg4NiA4LjY4OSA3LjhDOC44NTcgNy43MTQgOS4wNTQgNy42NzEgOS4yNzYgNy42NzFDOS40NjYgNy42NzEgOS42NCA3LjcwOCA5Ljc5MyA3Ljc4Wk0xNSAxM0gxVjE0SDE1VjEzWk0yLjgxMyAxMEwyLjA4NSAxMi4wMzFIMUwxLjAyNSAxMS45NTlMMy40NjYgNC44NzMwNUg0LjQwN0w2Ljg5MiAxMi4wMzFINS44MUw1LjAzMiAxMEgyLjgxM1pNMy45MzQgNi40MjIwNUgzLjkxMkwzLjAwNyA5LjE3NTA1SDQuODQ4TDMuOTM0IDYuNDIyMDVaIiBmaWxsPSIjQzVDNUM1Ii8+Cjwvc3ZnPgo=") 50% no-repeat}.hc-black .monaco-custom-checkbox.monaco-whole-word,.hc-black .monaco-custom-checkbox.monaco-whole-word:hover{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xIDJIMTVWM0gxVjJaTTE0IDRIMTNWMTJIMTRWNFpNMTEuMjcyIDguMzg3QzExLjE5NCA4LjA4OCAxMS4wNzMgNy44MjUgMTAuOTEyIDcuNjAxQzEwLjc1MSA3LjM3NyAxMC41NDcgNy4yIDEwLjMwMyA3LjA3MUMxMC4wNTkgNi45NDIgOS43NjkgNi44NzggOS40MzcgNi44NzhDOS4yMzkgNi44NzggOS4wNTcgNi45MDIgOC44OSA2Ljk1MUM4LjcyNSA3IDguNTc0IDcuMDY4IDguNDM3IDcuMTU2QzguMzAxIDcuMjQ0IDguMTggNy4zNSA4LjA3MiA3LjQ3NEw3Ljg5MyA3LjczMlY0LjU3OEg3VjEySDcuODkzVjExLjQyNUw4LjAxOSAxMS42QzguMTA2IDExLjcwMiA4LjIwOCAxMS43OSA4LjMyMyAxMS44NjlDOC40NCAxMS45NDcgOC41NzIgMTIuMDA5IDguNzIxIDEyLjA1NUM4Ljg3IDEyLjEwMSA5LjAzNSAxMi4xMjMgOS4yMTkgMTIuMTIzQzkuNTcyIDEyLjEyMyA5Ljg4NSAxMi4wNTIgMTAuMTU2IDExLjkxMUMxMC40MjggMTEuNzY4IDEwLjY1NSAxMS41NzMgMTAuODM4IDExLjMyNUMxMS4wMjEgMTEuMDc1IDExLjE1OSAxMC43ODIgMTEuMjUyIDEwLjQ0NkMxMS4zNDUgMTAuMTA4IDExLjM5MiA5Ljc0MyAxMS4zOTIgOS4zNDlDMTEuMzkxIDkuMDA3IDExLjM1MiA4LjY4NiAxMS4yNzIgOC4zODdaTTkuNzkzIDcuNzhDOS45NDQgNy44NTEgMTAuMDc1IDcuOTU2IDEwLjE4MyA4LjA5NEMxMC4yOTIgOC4yMzQgMTAuMzc3IDguNDA3IDEwLjQzOCA4LjYxMUMxMC40ODkgOC43ODUgMTAuNTIgOC45ODIgMTAuNTI3IDkuMTk4TDEwLjUyIDkuMzIzQzEwLjUyIDkuNjUgMTAuNDg3IDkuOTQzIDEwLjQyIDEwLjE5MkMxMC4zNTMgMTAuNDM4IDEwLjI1OSAxMC42NDUgMTAuMTQyIDEwLjgwNkMxMC4wMjUgMTAuOTY4IDkuODgyIDExLjA5MSA5LjcyMSAxMS4xNzJDOS4zOTkgMTEuMzM0IDguOTYxIDExLjMzOCA4LjY1MiAxMS4xODdDOC40OTkgMTEuMTEyIDguMzY2IDExLjAxMiA4LjI1OSAxMC44OTFDOC4xNzQgMTAuNzk1IDguMTAzIDEwLjY3NSA4LjA0MSAxMC41MjRDOC4wNDEgMTAuNTI0IDcuODYyIDEwLjA3NyA3Ljg2MiA5LjU3N0M3Ljg2MiA5LjA3NyA4LjA0MSA4LjU3NSA4LjA0MSA4LjU3NUM4LjEwMyA4LjM5OCA4LjE3NyA4LjI1NyA4LjI2NSA4LjE0NUM4LjM3OSA4LjAwMiA4LjUyMSA3Ljg4NiA4LjY4OSA3LjhDOC44NTcgNy43MTQgOS4wNTQgNy42NzEgOS4yNzYgNy42NzFDOS40NjYgNy42NzEgOS42NCA3LjcwOCA5Ljc5MyA3Ljc4Wk0xNSAxM0gxVjE0SDE1VjEzWk0yLjgxMyAxMEwyLjA4NSAxMi4wMzFIMUwxLjAyNSAxMS45NTlMMy40NjYgNC44NzMwNUg0LjQwN0w2Ljg5MiAxMi4wMzFINS44MUw1LjAzMiAxMEgyLjgxM1pNMy45MzQgNi40MjIwNUgzLjkxMkwzLjAwNyA5LjE3NTA1SDQuODQ4TDMuOTM0IDYuNDIyMDVaIiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4K") 50% no-repeat}.vs .monaco-custom-checkbox.monaco-regex{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMC4wMTIyIDJIMTAuOTg3OVY1LjExMzQ2TDEzLjU0ODkgMy41NTYwOUwxNC4wMzQgNC40NDA5NUwxMS40NzAyIDZMMTQuMDM0IDcuNTU5MDVMMTMuNTQ4OSA4LjQ0MzkxTDEwLjk4NzkgNi44ODY1NFYxMEgxMC4wMTIyVjYuODg2NTRMNy40NTExNCA4LjQ0MzkxTDYuOTY2MDYgNy41NTkwNUw5LjUyOTkgNkw2Ljk2NjA2IDQuNDQwOTVMNy40NTExNCAzLjU1NjA5TDEwLjAxMjIgNS4xMTM0NlYyWk0yIDEwSDZWMTRIMlYxMFoiIGZpbGw9IiM0MjQyNDIiLz4KPC9zdmc+Cg==") 50% no-repeat}.vs-dark .monaco-custom-checkbox.monaco-regex{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMC4wMTIyIDJIMTAuOTg3OVY1LjExMzQ2TDEzLjU0ODkgMy41NTYwOUwxNC4wMzQgNC40NDA5NUwxMS40NzAyIDZMMTQuMDM0IDcuNTU5MDVMMTMuNTQ4OSA4LjQ0MzkxTDEwLjk4NzkgNi44ODY1NFYxMEgxMC4wMTIyVjYuODg2NTRMNy40NTExNCA4LjQ0MzkxTDYuOTY2MDYgNy41NTkwNUw5LjUyOTkgNkw2Ljk2NjA2IDQuNDQwOTVMNy40NTExNCAzLjU1NjA5TDEwLjAxMjIgNS4xMTM0NlYyWk0yIDEwSDZWMTRIMlYxMFoiIGZpbGw9IiNDNUM1QzUiLz4KPC9zdmc+Cg==") 50% no-repeat}.hc-black .monaco-custom-checkbox.monaco-regex,.hc-black .monaco-custom-checkbox.monaco-regex:hover{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMC4wMTIyIDJIMTAuOTg3OVY1LjExMzQ2TDEzLjU0ODkgMy41NTYwOUwxNC4wMzQgNC40NDA5NUwxMS40NzAyIDZMMTQuMDM0IDcuNTU5MDVMMTMuNTQ4OSA4LjQ0MzkxTDEwLjk4NzkgNi44ODY1NFYxMEgxMC4wMTIyVjYuODg2NTRMNy40NTExNCA4LjQ0MzkxTDYuOTY2MDYgNy41NTkwNUw5LjUyOTkgNkw2Ljk2NjA2IDQuNDQwOTVMNy40NTExNCAzLjU1NjA5TDEwLjAxMjIgNS4xMTM0NlYyWk0yIDEwSDZWMTRIMlYxMFoiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPgo=") 50% no-repeat}.monaco-checkbox .label{width:12px;height:12px;border:1px solid #000;background-color:transparent;display:inline-block}.monaco-checkbox .checkbox{position:absolute;overflow:hidden;clip:rect(0 0 0 0);height:1px;width:1px;margin:-1px;padding:0;border:0}.monaco-checkbox .checkbox:checked+.label{background-color:#000}.monaco-editor .find-widget{position:absolute;z-index:10;top:-44px;height:33px;overflow:hidden;line-height:19px;transition:top .2s linear;padding:0 4px;box-sizing:border-box}.monaco-editor .find-widget.hiddenEditor{display:none}.monaco-editor .find-widget.replaceToggled{top:-74px}.monaco-editor .find-widget.replaceToggled>.replace-part{display:-ms-flexbox;display:flex;display:-webkit-flex}.monaco-editor .find-widget.replaceToggled.visible,.monaco-editor .find-widget.visible{top:0}.monaco-editor .find-widget.multipleline{top:unset;bottom:10px}.monaco-editor .find-widget.multipleline.replaceToggled.visible,.monaco-editor .find-widget.multipleline.visible{top:0;bottom:unset}.monaco-editor .find-widget .monaco-inputbox.synthetic-focus{outline:1px solid -webkit-focus-ring-color;outline-offset:-1px}.monaco-editor .find-widget .monaco-inputbox .input{background-color:transparent;min-height:0}.monaco-editor .find-widget .monaco-findInput .input{font-size:13px}.monaco-editor .find-widget>.find-part,.monaco-editor .find-widget>.replace-part{margin:4px 0 0 17px;font-size:12px;display:-ms-flexbox;display:flex;display:-webkit-flex}.monaco-editor .find-widget>.find-part .monaco-inputbox,.monaco-editor .find-widget>.replace-part .monaco-inputbox{min-height:25px}.monaco-editor .find-widget>.replace-part .monaco-inputbox>.wrapper>.mirror{padding-right:22px}.monaco-editor .find-widget>.find-part .monaco-inputbox>.wrapper>.input,.monaco-editor .find-widget>.find-part .monaco-inputbox>.wrapper>.mirror,.monaco-editor .find-widget>.replace-part .monaco-inputbox>.wrapper>.input,.monaco-editor .find-widget>.replace-part .monaco-inputbox>.wrapper>.mirror{padding-top:2px;padding-bottom:2px}.monaco-editor .find-widget>.find-part .find-actions,.monaco-editor .find-widget>.replace-part .replace-actions{height:25px;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}.monaco-editor .find-widget .monaco-findInput{vertical-align:middle;display:-ms-flexbox;display:flex;display:-webkit-flex;-ms-flex:1;flex:1}.monaco-editor .find-widget .monaco-findInput .monaco-scrollable-element{width:100%}.monaco-editor .find-widget .monaco-findInput .monaco-scrollable-element .scrollbar.vertical{opacity:0}.monaco-editor .find-widget .matchesCount{margin:0 0 0 3px;padding:2px 0 0 2px;height:25px;vertical-align:middle;box-sizing:border-box;text-align:center;line-height:23px}.monaco-editor .find-widget .button,.monaco-editor .find-widget .matchesCount{display:-ms-flexbox;display:flex;display:-webkit-flex;-ms-flex:initial;flex:initial}.monaco-editor .find-widget .button{min-width:20px;width:20px;height:20px;margin-left:3px;background-position:50%;background-repeat:no-repeat;cursor:pointer}.monaco-editor .find-widget .button:not(.disabled):hover{background-color:rgba(0,0,0,.1)}.monaco-editor .find-widget .button.left{margin-left:0;margin-right:3px}.monaco-editor .find-widget .button.wide{width:auto;padding:1px 6px;top:-1px}.monaco-editor .find-widget .button.toggle{position:absolute;top:0;left:0;width:18px;height:100%;-o-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.monaco-editor .find-widget .button.toggle.disabled{display:none}.monaco-editor .find-widget .previous{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMy44NTM1IDYuMjkyODRMOC44NTM1NiAxLjI5Mjg1SDguMTQ2NDVMMy4xNDY0NSA2LjI5Mjg0TDMuODUzNTYgNi45OTk5NUw4IDIuODUzNTFWMTUuMDYwNkg5VjIuODUzNTFMMTMuMTQ2NCA2Ljk5OTk1TDEzLjg1MzUgNi4yOTI4NFoiIGZpbGw9IiM0MjQyNDIiLz4KPC9zdmc+Cg==")}.monaco-editor .find-widget .next{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0zLjE0NjQ2IDkuNzY3ODNMOC4xNDY0NCAxNC43Njc4TDguODUzNTUgMTQuNzY3OEwxMy44NTM1IDkuNzY3ODNMMTMuMTQ2NCA5LjA2MDcyTDkgMTMuMjA3Mkw5IDEuMDAwMDZMOCAxLjAwMDA2TDggMTMuMjA3MkwzLjg1MzU2IDkuMDYwNzJMMy4xNDY0NiA5Ljc2NzgzWiIgZmlsbD0iIzQyNDI0MiIvPgo8L3N2Zz4K")}.monaco-editor .find-widget .disabled{opacity:.3;cursor:default}.monaco-editor .find-widget .monaco-checkbox{width:20px;height:20px;display:inline-block;vertical-align:middle;margin-left:3px}.monaco-editor .find-widget .monaco-checkbox .label{content:"";display:inline-block;background-repeat:no-repeat;background-position:50%;background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTEgMTJMMSAxMUgxMFYxMkgxWk0xIDdIMTVWOEgxTDEgN1pNMTIgM1Y0SDFMMSAzSDEyWiIgZmlsbD0iIzQyNDI0MiIvPgo8L3N2Zz4K");width:20px;height:20px;border:none}.monaco-editor .find-widget .monaco-checkbox .checkbox:disabled+.label{opacity:.3;cursor:default}.monaco-editor .find-widget .monaco-checkbox .checkbox:not(:disabled)+.label{cursor:pointer}.monaco-editor .find-widget .monaco-checkbox .checkbox:not(:disabled):hover:before+.label{background-color:#ddd}.monaco-editor .find-widget .monaco-checkbox .checkbox:checked+.label{background-color:hsla(0,0%,39%,.2)}.monaco-editor .find-widget .close-fw{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik04IDguNzA3MTRMMTEuNjQ2NCAxMi4zNTM2TDEyLjM1MzYgMTEuNjQ2NUw4LjcwNzExIDguMDAwMDRMMTIuMzUzNiA0LjM1MzU5TDExLjY0NjQgMy42NDY0OEw4IDcuMjkyOTNMNC4zNTM1NSAzLjY0NjQ4TDMuNjQ2NDUgNC4zNTM1OUw3LjI5Mjg5IDguMDAwMDRMMy42NDY0NSAxMS42NDY1TDQuMzUzNTUgMTIuMzUzNkw4IDguNzA3MTRaIiBmaWxsPSIjNDI0MjQyIi8+Cjwvc3ZnPgo=")}.monaco-editor .find-widget .expand{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03Ljk3NjAzIDEwLjA3MTlMMTIuMzMzMyA1LjcxNDZMMTIuOTUyMSA2LjMzMzMyTDguMjg1MzkgMTFMNy42NjY2NyAxMUwzIDYuMzMzMzJMMy42MTg3MiA1LjcxNDZMNy45NzYwMyAxMC4wNzE5WiIgZmlsbD0iIzQyNDI0MiIvPgo8L3N2Zz4K")}.monaco-editor .find-widget .collapse{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMC4wNzE5IDguMDAwMDVMNS43MTQ2MSAxMi4zNTc0TDYuMzMzMzMgMTIuOTc2MUwxMSA4LjMwOTQxVjcuNjkwNjlMNi4zMzMzMyAzLjAyNDAyTDUuNzE0NjEgMy42NDI3NEwxMC4wNzE5IDguMDAwMDVaIiBmaWxsPSIjNDI0MjQyIi8+Cjwvc3ZnPgo=")}.monaco-editor .find-widget .replace{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0zLjIyMSAzLjczOUw1LjQ4MiA2LjAwOEw3LjcgMy43ODRMNyAzLjA4NEw1Ljk4OCA0LjA5MUw1Ljk4IDIuNDkxQzUuOTc5MDkgMi4zNTU2NyA2LjAzMDY4IDIuMjI1MjUgNi4xMjM5MiAyLjEyNzE2QzYuMjE3MTYgMi4wMjkwOCA2LjM0NDggMS45NzA5NSA2LjQ4IDEuOTY1SDhWMUg2LjQ4QzYuMjg0OTYgMS4wMDAyNiA2LjA5MTg5IDEuMDM5MDIgNS45MTE4NiAxLjExNDA1QzUuNzMxODMgMS4xODkwOCA1LjU2ODM4IDEuMjk4OTIgNS40MzA4OCAxLjQzNzI1QzUuMjkzMzggMS41NzU1OCA1LjE4NDU1IDEuNzM5NjkgNS4xMTA2MSAxLjkyMDE4QzUuMDM2NjcgMi4xMDA2NiA0Ljk5OTA4IDIuMjkzOTYgNSAyLjQ4OVY0LjFMMy45MjcgMy4wMzNMMy4yMjEgMy43MzlaTTkuODkwMTQgNS41MzI3N0g5LjkwMTQxQzEwLjA4MzYgNS44NDQyNiAxMC4zNTIxIDYgMTAuNzA3IDZDMTEuMDk5NSA2IDExLjQxMzEgNS44MzIzNiAxMS42NDc5IDUuNDk3MDhDMTEuODgyNiA1LjE2MTggMTIgNC43MTcyOCAxMiA0LjE2MzUzQzEyIDMuNjUzMDQgMTEuODk5NSAzLjI1MDcgMTEuNjk4NiAyLjk1NjUyQzExLjQ5NzcgMi42NjIzNCAxMS4yMTEzIDIuNTE1MjUgMTAuODM5NCAyLjUxNTI1QzEwLjQzMzggMi41MTUyNSAxMC4xMjExIDIuNzA4ODUgOS45MDE0MSAzLjA5NjA0SDkuODkwMTRWMUg5VjUuOTE4ODhIOS44OTAxNFY1LjUzMjc3Wk05Ljg3NjA2IDQuNDcxNzdWNC4xMzEwOEM5Ljg3NjA2IDMuODg0NDkgOS45MzQyNyAzLjY4NDQgMTAuMDUwNyAzLjUzMDgyQzEwLjE2OSAzLjM3NzI0IDEwLjMxNzQgMy4zMDA0NSAxMC40OTU4IDMuMzAwNDVDMTAuNjg1NCAzLjMwMDQ1IDEwLjgzMSAzLjM3ODMzIDEwLjkzMjQgMy41MzQwN0MxMS4wMzU3IDMuNjg3NjUgMTEuMDg3MyAzLjkwMTggMTEuMDg3MyA0LjE3NjUxQzExLjA4NzMgNC41MDc0NiAxMS4wMzEgNC43NjM3OSAxMC45MTgzIDQuOTQ1NDlDMTAuODA3NSA1LjEyNTAzIDEwLjY1MDcgNS4yMTQ4IDEwLjQ0NzkgNS4yMTQ4QzEwLjI4MDggNS4yMTQ4IDEwLjE0MzcgNS4xNDQ0OSAxMC4wMzY2IDUuMDAzODlDOS45Mjk1OCA0Ljg2MzI5IDkuODc2MDYgNC42ODU5MiA5Ljg3NjA2IDQuNDcxNzdaTTkgMTIuNzY5MUM4Ljc0NDMyIDEyLjkyMyA4LjM3NTE1IDEzIDcuODkyNDcgMTNDNy4zMjg1NSAxMyA2Ljg3MjE2IDEyLjgyMjUgNi41MjMzIDEyLjQ2NzRDNi4xNzQ0MyAxMi4xMTI0IDYgMTEuNjU0MyA2IDExLjA5MzFDNiAxMC40NDUxIDYuMTg2MzggOS45MzQ4NCA2LjU1OTE0IDkuNTYyNEM2LjkzNDI5IDkuMTg3NDcgNy40MzQ4OSA5LjAwMDAxIDguMDYwOTMgOS4wMDAwMUM4LjQ5MzQzIDkuMDAwMDEgOC44MDY0NSA5LjA1OTYgOSA5LjE3ODc4VjEwLjE3NjlDOC43NjM0NCA5Ljk5MzE5IDguNDk5NCA5LjkwMTMyIDguMjA3ODkgOS45MDEzMkM3Ljg4MjkyIDkuOTAxMzIgNy42MjQ4NSAxMC4wMDA2IDcuNDMzNjkgMTAuMTk5M0M3LjI0NDkyIDEwLjM5NTQgNy4xNTA1NCAxMC42NjczIDcuMTUwNTQgMTEuMDE0OUM3LjE1MDU0IDExLjM1MjYgNy4yNDEzNCAxMS42MTgzIDcuNDIyOTQgMTEuODExOUM3LjYwNDU0IDEyLjAwMzEgNy44NTQyNCAxMi4wOTg3IDguMTcyMDQgMTIuMDk4N0M4LjQ1NCAxMi4wOTg3IDguNzI5OTkgMTIuMDA2OCA5IDExLjgyMzFWMTIuNzY5MVpNNCA3TDMgOFYxNEw0IDE1SDExTDEyIDE0VjhMMTEgN0g0Wk00IDhINUgxMEgxMVY5VjEzVjE0SDEwSDVINFYxM1Y5VjhaIiBmaWxsPSIjNDI0MjQyIi8+Cjwvc3ZnPgo=")}.monaco-editor .find-widget .replace-all{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMS42MDA5IDIuNjc2ODNDMTEuNzQ3NCAyLjM2NzA4IDExLjk1NTkgMi4yMTIyIDEyLjIyNjMgMi4yMTIyQzEyLjQ3NDIgMi4yMTIyIDEyLjY2NTEgMi4zMjk4NyAxMi43OTkxIDIuNTY1MjJDMTIuOTMzIDIuODAwNTYgMTMgMy4xMjI0MyAxMyAzLjUzMDgyQzEzIDMuOTczODMgMTIuOTIxOCA0LjMyOTQ0IDEyLjc2NTMgNC41OTc2NkMxMi42MDg4IDQuODY1ODkgMTIuMzk5NyA1IDEyLjEzOCA1QzExLjkwMTQgNSAxMS43MjI0IDQuODc1NDEgMTEuNjAwOSA0LjYyNjIySDExLjU5MzRWNC45MzUxMUgxMVYxSDExLjU5MzRWMi42NzY4M0gxMS42MDA5Wk0xMS41ODQgMy43Nzc0MkMxMS41ODQgMy45NDg3MyAxMS42MTk3IDQuMDkwNjMgMTEuNjkxMSA0LjIwMzExQzExLjc2MjQgNC4zMTU2IDExLjg1MzggNC4zNzE4NCAxMS45NjUzIDQuMzcxODRDMTIuMTAwNSA0LjM3MTg0IDEyLjIwNSA0LjMwMDAyIDEyLjI3ODkgNC4xNTYzOUMxMi4zNTQgNC4wMTEwMyAxMi4zOTE1IDMuODA1OTcgMTIuMzkxNSAzLjU0MTIxQzEyLjM5MTUgMy4zMjE0NCAxMi4zNTcxIDMuMTUwMTIgMTIuMjg4MyAzLjAyNzI2QzEyLjIyMDcgMi45MDI2NiAxMi4xMjM2IDIuODQwMzYgMTEuOTk3MiAyLjg0MDM2QzExLjg3ODIgMi44NDAzNiAxMS43NzkzIDIuOTAxOCAxMS43MDA1IDMuMDI0NjZDMTEuNjIyOCAzLjE0NzUyIDExLjU4NCAzLjMwNzU5IDExLjU4NCAzLjUwNDg3VjMuNzc3NDJaTTQuMTE5NjkgNy42OTVMMiA1LjU2NzgxTDIuNjYxODggNC45MDU5NEwzLjY2NzgxIDUuOTA2MjVWNC4zOTU5NEMzLjY2Njk1IDQuMjEzMDkgMy43MDIxOSA0LjAzMTg3IDMuNzcxNSAzLjg2MjY2QzMuODQwODIgMy42OTM0NiAzLjk0Mjg2IDMuNTM5NjEgNC4wNzE3NiAzLjQwOTkyQzQuMjAwNjYgMy4yODAyMyA0LjM1MzkgMy4xNzcyNyA0LjUyMjY4IDMuMTA2OTJDNC42OTE0NiAzLjAzNjU4IDQuODcyNDYgMy4wMDAyNCA1LjA1NTMxIDNINy4zOTkwNlYzLjkwNDY5SDUuMDU1MzFDNC45Mjg1NiAzLjkxMDI2IDQuODA4OSAzLjk2NDc2IDQuNzIxNDkgNC4wNTY3MkM0LjYzNDA4IDQuMTQ4NjggNC41ODU3MSA0LjI3MDk0IDQuNTg2NTYgNC4zOTc4MUw0LjU5NDA2IDUuODk3ODFMNS41NDI4MSA0Ljk1Mzc1TDYuMTk5MDYgNS42MUw0LjExOTY5IDcuNjk1Wk05LjM1NTYgNC45MzAxN0gxMFYzLjIyMDY3QzEwIDIuNDA2ODkgOS42ODUzNCAyIDkuMDU2MDMgMkM4LjkyMDk4IDIgOC43NzA4MyAyLjAyNDIxIDguNjA1NiAyLjA3MjYzQzguNDQxODEgMi4xMjEwNCA4LjMxMjUgMi4xNzY5MSA4LjIxNzY3IDIuMjQwMjJWMi45MDUwM0M4LjQ1NDc0IDIuNzAyMDUgOC43MDQ3NCAyLjYwMDU2IDguOTY3NjcgMi42MDA1NkM5LjIyOTE3IDIuNjAwNTYgOS4zNTk5MSAyLjc1Njk4IDkuMzU5OTEgMy4wNjk4M0w4Ljc2MDc4IDMuMTczMThDOC4yNTM1OSAzLjI1ODg1IDggMy41NzkxNCA4IDQuMTM0MDhDOCA0LjM5NjY1IDguMDYxMDYgNC42MDcwOCA4LjE4MzE5IDQuNzY1MzZDOC4zMDY3NSA0LjkyMTc5IDguNDc1NTcgNSA4LjY4OTY2IDVDOC45Nzk4OSA1IDkuMTk4OTkgNC44Mzk4NSA5LjM0Njk4IDQuNTE5NTVIOS4zNTU2VjQuOTMwMTdaTTkuMzU5OTEgMy41NzU0MlYzLjc2ODE2QzkuMzU5OTEgMy45NDMyIDkuMzE5NjggNC4wODg0NSA5LjIzOTIyIDQuMjAzOTFDOS4xNTg3NiA0LjMxNzUgOS4wNTQ2IDQuMzc0MyA4LjkyNjcyIDQuMzc0M0M4LjgzNDc3IDQuMzc0MyA4Ljc2MTQ5IDQuMzQyNjQgOC43MDY5IDQuMjc5MzNDOC42NTM3NCA0LjIxNDE1IDguNjI3MTYgNC4xMzEyOCA4LjYyNzE2IDQuMDMwNzNDOC42MjcxNiAzLjgwOTEyIDguNzM3NzkgMy42Nzk3IDguOTU5MDUgMy42NDI0Nkw5LjM1OTkxIDMuNTc1NDJaTTcgMTIuOTMwMkg2LjM1NTZWMTIuNTE5Nkg2LjM0Njk4QzYuMTk4OTkgMTIuODM5OSA1Ljk3OTg5IDEzIDUuNjg5NjYgMTNDNS40NzU1NyAxMyA1LjMwNjc1IDEyLjkyMTggNS4xODMxOSAxMi43NjU0QzUuMDYxMDYgMTIuNjA3MSA1IDEyLjM5NjYgNSAxMi4xMzQxQzUgMTEuNTc5MSA1LjI1MzU5IDExLjI1ODggNS43NjA3OCAxMS4xNzMyTDYuMzU5OTEgMTEuMDY5OEM2LjM1OTkxIDEwLjc1NyA2LjIyOTE3IDEwLjYwMDYgNS45Njc2NyAxMC42MDA2QzUuNzA0NzQgMTAuNjAwNiA1LjQ1NDc0IDEwLjcwMiA1LjIxNzY3IDEwLjkwNVYxMC4yNDAyQzUuMzEyNSAxMC4xNzY5IDUuNDQxODEgMTAuMTIxIDUuNjA1NiAxMC4wNzI2QzUuNzcwODMgMTAuMDI0MiA1LjkyMDk4IDEwIDYuMDU2MDMgMTBDNi42ODUzNCAxMCA3IDEwLjQwNjkgNyAxMS4yMjA3VjEyLjkzMDJaTTYuMzU5OTEgMTEuNzY4MlYxMS41NzU0TDUuOTU5MDUgMTEuNjQyNUM1LjczNzc5IDExLjY3OTcgNS42MjcxNiAxMS44MDkxIDUuNjI3MTYgMTIuMDMwN0M1LjYyNzE2IDEyLjEzMTMgNS42NTM3NCAxMi4yMTQyIDUuNzA2OSAxMi4yNzkzQzUuNzYxNDkgMTIuMzQyNiA1LjgzNDc3IDEyLjM3NDMgNS45MjY3MiAxMi4zNzQzQzYuMDU0NiAxMi4zNzQzIDYuMTU4NzYgMTIuMzE3NSA2LjIzOTIyIDEyLjIwMzlDNi4zMTk2OCAxMi4wODg1IDYuMzU5OTEgMTEuOTQzMiA2LjM1OTkxIDExLjc2ODJaTTkuMjYxNjUgMTNDOS41ODM0MyAxMyA5LjgyOTU1IDEyLjk0MjMgMTAgMTIuODI2OFYxMi4xMTczQzkuODE5OTkgMTIuMjU1MSA5LjYzNiAxMi4zMjQgOS40NDgwMyAxMi4zMjRDOS4yMzYxNiAxMi4zMjQgOS4wNjk2OSAxMi4yNTIzIDguOTQ4NjMgMTIuMTA4OUM4LjgyNzU2IDExLjk2MzcgOC43NjcwMiAxMS43NjQ0IDguNzY3MDIgMTEuNTExMkM4Ljc2NzAyIDExLjI1MDUgOC44Mjk5NSAxMS4wNDY2IDguOTU1NzkgMTAuODk5NEM5LjA4MzIzIDEwLjc1MDUgOS4yNTUyOCAxMC42NzYgOS40NzE5MiAxMC42NzZDOS42NjYyNyAxMC42NzYgOS44NDIyOSAxMC43NDQ5IDEwIDEwLjg4MjdWMTAuMTM0MUM5Ljg3MDk3IDEwLjA0NDcgOS42NjIyOSAxMCA5LjM3Mzk1IDEwQzguOTU2NTkgMTAgOC42MjI4NiAxMC4xNDA2IDguMzcyNzYgMTAuNDIxOEM4LjEyNDI1IDEwLjcwMTEgOCAxMS4wODM4IDggMTEuNTY5OEM4IDExLjk5MDcgOC4xMTYyOSAxMi4zMzQzIDguMzQ4ODcgMTIuNjAwNkM4LjU4MTQ0IDEyLjg2NjkgOC44ODU3IDEzIDkuMjYxNjUgMTNaTTIgOUwzIDhIMTJMMTMgOVYxNEwxMiAxNUgzTDIgMTRWOVpNMyA5VjE0SDEyVjlIM1pNNiA3TDcgNkgxNEwxNSA3VjEyTDE0IDEzVjEyVjdIN0g2WiIgZmlsbD0iIzQyNDI0MiIvPgo8L3N2Zz4K")}.monaco-editor .find-widget>.replace-part{display:none}.monaco-editor .find-widget>.replace-part>.monaco-findInput{position:relative;display:-ms-flexbox;display:flex;display:-webkit-flex;vertical-align:middle;-ms-flex:auto;flex:auto;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.monaco-editor .find-widget>.replace-part>.monaco-findInput>.controls{position:absolute;top:3px;right:2px}.monaco-editor .find-widget.reduced-find-widget .matchesCount,.monaco-editor .find-widget.reduced-find-widget .monaco-checkbox{display:none}.monaco-editor .find-widget.narrow-find-widget{max-width:257px!important}.monaco-editor .find-widget.collapsed-find-widget{max-width:170px!important}.monaco-editor .find-widget.collapsed-find-widget .button.next,.monaco-editor .find-widget.collapsed-find-widget .button.previous,.monaco-editor .find-widget.collapsed-find-widget .button.replace,.monaco-editor .find-widget.collapsed-find-widget .button.replace-all,.monaco-editor .find-widget.collapsed-find-widget>.find-part .monaco-findInput .controls{display:none}.monaco-editor .findMatch{-webkit-animation-duration:0;-webkit-animation-name:inherit!important;-moz-animation-duration:0;-moz-animation-name:inherit!important;-ms-animation-duration:0;-ms-animation-name:inherit!important;animation-duration:0;animation-name:inherit!important}.monaco-editor .find-widget .monaco-sash{width:2px!important;margin-left:-4px}.monaco-editor.hc-black .find-widget .previous,.monaco-editor.vs-dark .find-widget .previous{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMy44NTM1IDYuMjkyODRMOC44NTM1NiAxLjI5Mjg1SDguMTQ2NDVMMy4xNDY0NSA2LjI5Mjg0TDMuODUzNTYgNi45OTk5NUw4IDIuODUzNTFWMTUuMDYwNkg5VjIuODUzNTFMMTMuMTQ2NCA2Ljk5OTk1TDEzLjg1MzUgNi4yOTI4NFoiIGZpbGw9IiNDNUM1QzUiLz4KPC9zdmc+Cg==")}.monaco-editor.hc-black .find-widget .next,.monaco-editor.vs-dark .find-widget .next{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0zLjE0NjQ2IDkuNzY3ODNMOC4xNDY0NCAxNC43Njc4TDguODUzNTUgMTQuNzY3OEwxMy44NTM1IDkuNzY3ODNMMTMuMTQ2NCA5LjA2MDcyTDkgMTMuMjA3Mkw5IDEuMDAwMDZMOCAxLjAwMDA2TDggMTMuMjA3MkwzLjg1MzU2IDkuMDYwNzJMMy4xNDY0NiA5Ljc2NzgzWiIgZmlsbD0iI0M1QzVDNSIvPgo8L3N2Zz4K")}.monaco-editor.hc-black .find-widget .monaco-checkbox .label,.monaco-editor.vs-dark .find-widget .monaco-checkbox .label{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTEgMTJMMSAxMUgxMFYxMkgxWk0xIDdIMTVWOEgxTDEgN1pNMTIgM1Y0SDFMMSAzSDEyWiIgZmlsbD0iI0M1QzVDNSIvPgo8L3N2Zz4K")}.monaco-editor.vs-dark .find-widget .monaco-checkbox .checkbox:not(:disabled):hover:before+.label{background-color:hsla(0,0%,100%,.1)}.monaco-editor.hc-black .find-widget .close-fw,.monaco-editor.vs-dark .find-widget .close-fw{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik04IDguNzA3MTRMMTEuNjQ2NCAxMi4zNTM2TDEyLjM1MzYgMTEuNjQ2NUw4LjcwNzExIDguMDAwMDRMMTIuMzUzNiA0LjM1MzU5TDExLjY0NjQgMy42NDY0OEw4IDcuMjkyOTNMNC4zNTM1NSAzLjY0NjQ4TDMuNjQ2NDUgNC4zNTM1OUw3LjI5Mjg5IDguMDAwMDRMMy42NDY0NSAxMS42NDY1TDQuMzUzNTUgMTIuMzUzNkw4IDguNzA3MTRaIiBmaWxsPSIjQzVDNUM1Ii8+Cjwvc3ZnPgo=")}.monaco-editor.hc-black .find-widget .replace,.monaco-editor.vs-dark .find-widget .replace{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0zLjIyMSAzLjczOUw1LjQ4MiA2LjAwOEw3LjcgMy43ODRMNyAzLjA4NEw1Ljk4OCA0LjA5MUw1Ljk4IDIuNDkxQzUuOTc5MDkgMi4zNTU2NyA2LjAzMDY4IDIuMjI1MjUgNi4xMjM5MiAyLjEyNzE2QzYuMjE3MTYgMi4wMjkwOCA2LjM0NDggMS45NzA5NSA2LjQ4IDEuOTY1SDhWMUg2LjQ4QzYuMjg0OTYgMS4wMDAyNiA2LjA5MTg5IDEuMDM5MDIgNS45MTE4NiAxLjExNDA1QzUuNzMxODMgMS4xODkwOCA1LjU2ODM4IDEuMjk4OTIgNS40MzA4OCAxLjQzNzI1QzUuMjkzMzggMS41NzU1OCA1LjE4NDU1IDEuNzM5NjkgNS4xMTA2MSAxLjkyMDE4QzUuMDM2NjcgMi4xMDA2NiA0Ljk5OTA4IDIuMjkzOTYgNSAyLjQ4OVY0LjFMMy45MjcgMy4wMzNMMy4yMjEgMy43MzlaTTkuODkwMTQgNS41MzI3N0g5LjkwMTQxQzEwLjA4MzYgNS44NDQyNiAxMC4zNTIxIDYgMTAuNzA3IDZDMTEuMDk5NSA2IDExLjQxMzEgNS44MzIzNiAxMS42NDc5IDUuNDk3MDhDMTEuODgyNiA1LjE2MTggMTIgNC43MTcyOCAxMiA0LjE2MzUzQzEyIDMuNjUzMDQgMTEuODk5NSAzLjI1MDcgMTEuNjk4NiAyLjk1NjUyQzExLjQ5NzcgMi42NjIzNCAxMS4yMTEzIDIuNTE1MjUgMTAuODM5NCAyLjUxNTI1QzEwLjQzMzggMi41MTUyNSAxMC4xMjExIDIuNzA4ODUgOS45MDE0MSAzLjA5NjA0SDkuODkwMTRWMUg5VjUuOTE4ODhIOS44OTAxNFY1LjUzMjc3Wk05Ljg3NjA2IDQuNDcxNzdWNC4xMzEwOEM5Ljg3NjA2IDMuODg0NDkgOS45MzQyNyAzLjY4NDQgMTAuMDUwNyAzLjUzMDgyQzEwLjE2OSAzLjM3NzI0IDEwLjMxNzQgMy4zMDA0NSAxMC40OTU4IDMuMzAwNDVDMTAuNjg1NCAzLjMwMDQ1IDEwLjgzMSAzLjM3ODMzIDEwLjkzMjQgMy41MzQwN0MxMS4wMzU3IDMuNjg3NjUgMTEuMDg3MyAzLjkwMTggMTEuMDg3MyA0LjE3NjUxQzExLjA4NzMgNC41MDc0NiAxMS4wMzEgNC43NjM3OSAxMC45MTgzIDQuOTQ1NDlDMTAuODA3NSA1LjEyNTAzIDEwLjY1MDcgNS4yMTQ4IDEwLjQ0NzkgNS4yMTQ4QzEwLjI4MDggNS4yMTQ4IDEwLjE0MzcgNS4xNDQ0OSAxMC4wMzY2IDUuMDAzODlDOS45Mjk1OCA0Ljg2MzI5IDkuODc2MDYgNC42ODU5MiA5Ljg3NjA2IDQuNDcxNzdaTTkgMTIuNzY5MUM4Ljc0NDMzIDEyLjkyMyA4LjM3NTE1IDEzIDcuODkyNDcgMTNDNy4zMjg1NSAxMyA2Ljg3MjE2IDEyLjgyMjUgNi41MjMzIDEyLjQ2NzRDNi4xNzQ0MyAxMi4xMTI0IDYgMTEuNjU0MyA2IDExLjA5MzFDNiAxMC40NDUxIDYuMTg2MzggOS45MzQ4NCA2LjU1OTE0IDkuNTYyNEM2LjkzNDI5IDkuMTg3NDcgNy40MzQ4OSA5LjAwMDAxIDguMDYwOTMgOS4wMDAwMUM4LjQ5MzQzIDkuMDAwMDEgOC44MDY0NSA5LjA1OTYgOSA5LjE3ODc4VjEwLjE3NjlDOC43NjM0NCA5Ljk5MzE5IDguNDk5NCA5LjkwMTMyIDguMjA3ODkgOS45MDEzMkM3Ljg4MjkyIDkuOTAxMzIgNy42MjQ4NSAxMC4wMDA2IDcuNDMzNjkgMTAuMTk5M0M3LjI0NDkyIDEwLjM5NTQgNy4xNTA1NCAxMC42NjczIDcuMTUwNTQgMTEuMDE0OUM3LjE1MDU0IDExLjM1MjYgNy4yNDEzNCAxMS42MTgzIDcuNDIyOTQgMTEuODExOUM3LjYwNDU0IDEyLjAwMzEgNy44NTQyNCAxMi4wOTg3IDguMTcyMDQgMTIuMDk4N0M4LjQ1NCAxMi4wOTg3IDguNzI5OTkgMTIuMDA2OCA5IDExLjgyMzFWMTIuNzY5MVpNNCA3TDMgOFYxNEw0IDE1SDExTDEyIDE0VjhMMTEgN0g0Wk00IDhINUgxMEgxMVY5VjEzVjE0SDEwSDVINFYxM1Y5VjhaIiBmaWxsPSIjQzVDNUM1Ii8+Cjwvc3ZnPgo=")}.monaco-editor.hc-black .find-widget .replace-all,.monaco-editor.vs-dark .find-widget .replace-all{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMS42MDA5IDIuNjc2ODNDMTEuNzQ3NCAyLjM2NzA4IDExLjk1NTkgMi4yMTIyIDEyLjIyNjMgMi4yMTIyQzEyLjQ3NDIgMi4yMTIyIDEyLjY2NTEgMi4zMjk4NyAxMi43OTkxIDIuNTY1MjJDMTIuOTMzIDIuODAwNTYgMTMgMy4xMjI0MyAxMyAzLjUzMDgyQzEzIDMuOTczODMgMTIuOTIxOCA0LjMyOTQ0IDEyLjc2NTMgNC41OTc2NkMxMi42MDg4IDQuODY1ODkgMTIuMzk5NyA1IDEyLjEzOCA1QzExLjkwMTQgNSAxMS43MjI0IDQuODc1NDEgMTEuNjAwOSA0LjYyNjIySDExLjU5MzRWNC45MzUxMUgxMVYxSDExLjU5MzRWMi42NzY4M0gxMS42MDA5Wk0xMS41ODQgMy43Nzc0MkMxMS41ODQgMy45NDg3MyAxMS42MTk3IDQuMDkwNjMgMTEuNjkxMSA0LjIwMzExQzExLjc2MjQgNC4zMTU2IDExLjg1MzggNC4zNzE4NCAxMS45NjUzIDQuMzcxODRDMTIuMTAwNSA0LjM3MTg0IDEyLjIwNSA0LjMwMDAyIDEyLjI3ODkgNC4xNTYzOUMxMi4zNTQgNC4wMTEwMyAxMi4zOTE1IDMuODA1OTcgMTIuMzkxNSAzLjU0MTIxQzEyLjM5MTUgMy4zMjE0NCAxMi4zNTcxIDMuMTUwMTIgMTIuMjg4MyAzLjAyNzI2QzEyLjIyMDcgMi45MDI2NiAxMi4xMjM2IDIuODQwMzYgMTEuOTk3MiAyLjg0MDM2QzExLjg3ODIgMi44NDAzNiAxMS43NzkzIDIuOTAxOCAxMS43MDA1IDMuMDI0NjZDMTEuNjIyOCAzLjE0NzUyIDExLjU4NCAzLjMwNzU5IDExLjU4NCAzLjUwNDg3VjMuNzc3NDJaTTQuMTE5NjkgNy42OTVMMiA1LjU2NzgxTDIuNjYxODggNC45MDU5NEwzLjY2NzgxIDUuOTA2MjVWNC4zOTU5NEMzLjY2Njk1IDQuMjEzMDkgMy43MDIxOSA0LjAzMTg3IDMuNzcxNSAzLjg2MjY2QzMuODQwODIgMy42OTM0NiAzLjk0Mjg2IDMuNTM5NjEgNC4wNzE3NiAzLjQwOTkyQzQuMjAwNjYgMy4yODAyMyA0LjM1MzkgMy4xNzcyNyA0LjUyMjY4IDMuMTA2OTJDNC42OTE0NiAzLjAzNjU4IDQuODcyNDYgMy4wMDAyNCA1LjA1NTMxIDNINy4zOTkwNlYzLjkwNDY5SDUuMDU1MzFDNC45Mjg1NiAzLjkxMDI2IDQuODA4OSAzLjk2NDc2IDQuNzIxNDkgNC4wNTY3MkM0LjYzNDA4IDQuMTQ4NjggNC41ODU3MSA0LjI3MDk0IDQuNTg2NTYgNC4zOTc4MUw0LjU5NDA2IDUuODk3ODFMNS41NDI4MSA0Ljk1Mzc1TDYuMTk5MDYgNS42MUw0LjExOTY5IDcuNjk1Wk05LjM1NTYgNC45MzAxN0gxMFYzLjIyMDY3QzEwIDIuNDA2ODkgOS42ODUzNCAyIDkuMDU2MDMgMkM4LjkyMDk4IDIgOC43NzA4MyAyLjAyNDIxIDguNjA1NiAyLjA3MjYzQzguNDQxODEgMi4xMjEwNCA4LjMxMjUgMi4xNzY5MSA4LjIxNzY3IDIuMjQwMjJWMi45MDUwM0M4LjQ1NDc0IDIuNzAyMDUgOC43MDQ3NCAyLjYwMDU2IDguOTY3NjcgMi42MDA1NkM5LjIyOTE3IDIuNjAwNTYgOS4zNTk5MSAyLjc1Njk4IDkuMzU5OTEgMy4wNjk4M0w4Ljc2MDc4IDMuMTczMThDOC4yNTM1OSAzLjI1ODg1IDggMy41NzkxNCA4IDQuMTM0MDhDOCA0LjM5NjY1IDguMDYxMDYgNC42MDcwOCA4LjE4MzE5IDQuNzY1MzZDOC4zMDY3NSA0LjkyMTc5IDguNDc1NTcgNSA4LjY4OTY2IDVDOC45Nzk4OSA1IDkuMTk4OTkgNC44Mzk4NSA5LjM0Njk4IDQuNTE5NTVIOS4zNTU2VjQuOTMwMTdaTTkuMzU5OTEgMy41NzU0MlYzLjc2ODE2QzkuMzU5OTEgMy45NDMyIDkuMzE5NjggNC4wODg0NSA5LjIzOTIyIDQuMjAzOTFDOS4xNTg3NiA0LjMxNzUgOS4wNTQ2IDQuMzc0MyA4LjkyNjcyIDQuMzc0M0M4LjgzNDc3IDQuMzc0MyA4Ljc2MTQ5IDQuMzQyNjQgOC43MDY5IDQuMjc5MzNDOC42NTM3NCA0LjIxNDE1IDguNjI3MTYgNC4xMzEyOCA4LjYyNzE2IDQuMDMwNzNDOC42MjcxNiAzLjgwOTEyIDguNzM3NzkgMy42Nzk3IDguOTU5MDUgMy42NDI0Nkw5LjM1OTkxIDMuNTc1NDJaTTcgMTIuOTMwMkg2LjM1NTZWMTIuNTE5Nkg2LjM0Njk4QzYuMTk4OTkgMTIuODM5OSA1Ljk3OTg5IDEzIDUuNjg5NjYgMTNDNS40NzU1NyAxMyA1LjMwNjc1IDEyLjkyMTggNS4xODMxOSAxMi43NjU0QzUuMDYxMDYgMTIuNjA3MSA1IDEyLjM5NjYgNSAxMi4xMzQxQzUgMTEuNTc5MSA1LjI1MzU5IDExLjI1ODggNS43NjA3OCAxMS4xNzMyTDYuMzU5OTEgMTEuMDY5OEM2LjM1OTkxIDEwLjc1NyA2LjIyOTE3IDEwLjYwMDYgNS45Njc2NyAxMC42MDA2QzUuNzA0NzQgMTAuNjAwNiA1LjQ1NDc0IDEwLjcwMiA1LjIxNzY3IDEwLjkwNVYxMC4yNDAyQzUuMzEyNSAxMC4xNzY5IDUuNDQxODEgMTAuMTIxIDUuNjA1NiAxMC4wNzI2QzUuNzcwODMgMTAuMDI0MiA1LjkyMDk4IDEwIDYuMDU2MDMgMTBDNi42ODUzNCAxMCA3IDEwLjQwNjkgNyAxMS4yMjA3VjEyLjkzMDJaTTYuMzU5OTEgMTEuNzY4MlYxMS41NzU0TDUuOTU5MDUgMTEuNjQyNUM1LjczNzc5IDExLjY3OTcgNS42MjcxNiAxMS44MDkxIDUuNjI3MTYgMTIuMDMwN0M1LjYyNzE2IDEyLjEzMTMgNS42NTM3NCAxMi4yMTQyIDUuNzA2OSAxMi4yNzkzQzUuNzYxNDkgMTIuMzQyNiA1LjgzNDc3IDEyLjM3NDMgNS45MjY3MiAxMi4zNzQzQzYuMDU0NiAxMi4zNzQzIDYuMTU4NzYgMTIuMzE3NSA2LjIzOTIyIDEyLjIwMzlDNi4zMTk2OCAxMi4wODg1IDYuMzU5OTEgMTEuOTQzMiA2LjM1OTkxIDExLjc2ODJaTTkuMjYxNjUgMTNDOS41ODM0MyAxMyA5LjgyOTU1IDEyLjk0MjMgMTAgMTIuODI2OFYxMi4xMTczQzkuODE5OTkgMTIuMjU1MSA5LjYzNiAxMi4zMjQgOS40NDgwMyAxMi4zMjRDOS4yMzYxNiAxMi4zMjQgOS4wNjk2OSAxMi4yNTIzIDguOTQ4NjMgMTIuMTA4OUM4LjgyNzU2IDExLjk2MzcgOC43NjcwMiAxMS43NjQ0IDguNzY3MDIgMTEuNTExMkM4Ljc2NzAyIDExLjI1MDUgOC44Mjk5NSAxMS4wNDY2IDguOTU1NzkgMTAuODk5NEM5LjA4MzIzIDEwLjc1MDUgOS4yNTUyOCAxMC42NzYgOS40NzE5MiAxMC42NzZDOS42NjYyNyAxMC42NzYgOS44NDIyOSAxMC43NDQ5IDEwIDEwLjg4MjdWMTAuMTM0MUM5Ljg3MDk3IDEwLjA0NDcgOS42NjIyOSAxMCA5LjM3Mzk1IDEwQzguOTU2NTkgMTAgOC42MjI4NiAxMC4xNDA2IDguMzcyNzYgMTAuNDIxOEM4LjEyNDI1IDEwLjcwMTEgOCAxMS4wODM4IDggMTEuNTY5OEM4IDExLjk5MDcgOC4xMTYyOSAxMi4zMzQzIDguMzQ4ODcgMTIuNjAwNkM4LjU4MTQ0IDEyLjg2NjkgOC44ODU3IDEzIDkuMjYxNjUgMTNaTTIgOUwzIDhIMTJMMTMgOVYxNEwxMiAxNUgzTDIgMTRWOVpNMyA5VjE0SDEyVjlIM1pNNiA3TDcgNkgxNEwxNSA3VjEyTDE0IDEzVjEyVjdIN0g2WiIgZmlsbD0iI0M1QzVDNSIvPgo8L3N2Zz4K")}.monaco-editor.hc-black .find-widget .expand,.monaco-editor.vs-dark .find-widget .expand{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03Ljk3NjAzIDEwLjA3MTlMMTIuMzMzMyA1LjcxNDZMMTIuOTUyMSA2LjMzMzMyTDguMjg1MzkgMTFMNy42NjY2NyAxMUwzIDYuMzMzMzJMMy42MTg3MiA1LjcxNDZMNy45NzYwMyAxMC4wNzE5WiIgZmlsbD0iI0M1QzVDNSIvPgo8L3N2Zz4K")}.monaco-editor.hc-black .find-widget .collapse,.monaco-editor.vs-dark .find-widget .collapse{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMC4wNzE5IDguMDAwMDVMNS43MTQ2MSAxMi4zNTc0TDYuMzMzMzMgMTIuOTc2MUwxMSA4LjMwOTQxVjcuNjkwNjlMNi4zMzMzMyAzLjAyNDAyTDUuNzE0NjEgMy42NDI3NEwxMC4wNzE5IDguMDAwMDVaIiBmaWxsPSIjQzVDNUM1Ii8+Cjwvc3ZnPgo=")}.monaco-editor.hc-black .find-widget .button:not(.disabled):hover,.monaco-editor.vs-dark .find-widget .button:not(.disabled):hover{background-color:hsla(0,0%,100%,.1)}.monaco-editor.hc-black .find-widget .button:before{position:relative;top:1px;left:2px}.monaco-editor.hc-black .find-widget .monaco-checkbox .checkbox:checked+.label{background-color:hsla(0,0%,100%,.1)}.monaco-sash{position:absolute;z-index:35;-ms-touch-action:none;touch-action:none}.monaco-sash.disabled{pointer-events:none}.monaco-sash.vertical{cursor:ew-resize;top:0;width:4px;height:100%}.monaco-sash.mac.vertical{cursor:col-resize}.monaco-sash.vertical.minimum{cursor:e-resize}.monaco-sash.vertical.maximum{cursor:w-resize}.monaco-sash.horizontal{cursor:ns-resize;left:0;width:100%;height:4px}.monaco-sash.mac.horizontal{cursor:row-resize}.monaco-sash.horizontal.minimum{cursor:s-resize}.monaco-sash.horizontal.maximum{cursor:n-resize}.monaco-sash:not(.disabled).orthogonal-end:after,.monaco-sash:not(.disabled).orthogonal-start:before{content:" ";height:8px;width:8px;z-index:100;display:block;cursor:all-scroll;position:absolute}.monaco-sash.orthogonal-start.vertical:before{left:-2px;top:-4px}.monaco-sash.orthogonal-end.vertical:after{left:-2px;bottom:-4px}.monaco-sash.orthogonal-start.horizontal:before{top:-2px;left:-4px}.monaco-sash.orthogonal-end.horizontal:after{top:-2px;right:-4px}.monaco-sash.disabled{cursor:default!important;pointer-events:none!important}.monaco-sash.touch.vertical{width:20px}.monaco-sash.touch.horizontal{height:20px}.monaco-sash.debug{background:cyan}.monaco-sash.debug.disabled{background:rgba(0,255,255,.2)}.monaco-sash.debug:not(.disabled).orthogonal-end:after,.monaco-sash.debug:not(.disabled).orthogonal-start:before{background:red}.monaco-findInput{position:relative}.monaco-findInput .monaco-inputbox{font-size:13px;width:100%}.monaco-findInput>.controls{position:absolute;top:3px;right:2px}.vs .monaco-findInput.disabled{background-color:#e1e1e1}.vs-dark .monaco-findInput.disabled{background-color:#333}.monaco-findInput.highlight-0 .controls{animation:monaco-findInput-highlight-0 .1s linear 0s}.monaco-findInput.highlight-1 .controls{animation:monaco-findInput-highlight-1 .1s linear 0s}.hc-black .monaco-findInput.highlight-0 .controls,.vs-dark .monaco-findInput.highlight-0 .controls{animation:monaco-findInput-highlight-dark-0 .1s linear 0s}.hc-black .monaco-findInput.highlight-1 .controls,.vs-dark .monaco-findInput.highlight-1 .controls{animation:monaco-findInput-highlight-dark-1 .1s linear 0s}@keyframes monaco-findInput-highlight-0{0%{background:rgba(253,255,0,.8)}to{background:transparent}}@keyframes monaco-findInput-highlight-1{0%{background:rgba(253,255,0,.8)}99%{background:transparent}}@keyframes monaco-findInput-highlight-dark-0{0%{background:hsla(0,0%,100%,.44)}to{background:transparent}}@keyframes monaco-findInput-highlight-dark-1{0%{background:hsla(0,0%,100%,.44)}99%{background:transparent}}.monaco-inputbox{position:relative;display:block;padding:0;-o-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;line-height:auto!important;font-size:inherit}.monaco-inputbox.idle{border:1px solid transparent}.monaco-inputbox>.wrapper>.input,.monaco-inputbox>.wrapper>.mirror{padding:4px}.monaco-inputbox>.wrapper{position:relative;width:100%;height:100%}.monaco-inputbox>.wrapper>.input{display:inline-block;-o-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;width:100%;height:100%;line-height:inherit;border:none;font-family:inherit;font-size:inherit;resize:none;color:inherit}.monaco-inputbox>.wrapper>input{text-overflow:ellipsis}.monaco-inputbox>.wrapper>textarea.input{display:block;-ms-overflow-style:none;overflow:-moz-scrollbars-none;scrollbar-width:none;outline:none}.monaco-inputbox>.wrapper>textarea.input::-webkit-scrollbar{display:none}.monaco-inputbox>.wrapper>.mirror{position:absolute;display:inline-block;width:100%;top:0;left:0;-o-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;white-space:pre-wrap;visibility:hidden;word-wrap:break-word}.monaco-inputbox-container{text-align:right}.monaco-inputbox-container .monaco-inputbox-message{display:inline-block;overflow:hidden;text-align:left;width:100%;-o-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;padding:.4em;font-size:12px;line-height:17px;min-height:34px;margin-top:-1px;word-wrap:break-word}.monaco-inputbox .monaco-action-bar{position:absolute;right:2px;top:4px}.monaco-inputbox .monaco-action-bar .action-item{margin-left:2px}.monaco-inputbox .monaco-action-bar .action-item .icon{background-repeat:no-repeat;width:16px;height:16px}.monaco-scrollable-element>.scrollbar>.up-arrow{background:url("data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTEgMTEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0ibTkuNDgwNDYsOC45NjE1bDEuMjYsLTEuMjZsLTUuMDQsLTUuMDRsLTUuNDYsNS4wNGwxLjI2LDEuMjZsNC4yLC0zLjc4bDMuNzgsMy43OHoiIGZpbGw9IiM0MjQyNDIiLz48L3N2Zz4=");cursor:pointer}.monaco-scrollable-element>.scrollbar>.down-arrow{background:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMSAxMSI+PHBhdGggdHJhbnNmb3JtPSJyb3RhdGUoLTE4MCA1LjQ5MDQ1OTkxODk3NTgzLDUuODExNTAwMDcyNDc5MjQ4KSIgZmlsbD0iIzQyNDI0MiIgZD0ibTkuNDgwNDYsOC45NjE1bDEuMjYsLTEuMjZsLTUuMDQsLTUuMDRsLTUuNDYsNS4wNGwxLjI2LDEuMjZsNC4yLC0zLjc4bDMuNzgsMy43OHoiLz48L3N2Zz4=");cursor:pointer}.monaco-scrollable-element>.scrollbar>.left-arrow{background:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMSAxMSI+PHBhdGggdHJhbnNmb3JtPSJyb3RhdGUoLTkwIDUuNDkwNDU5OTE4OTc1ODMxLDUuNDMxMzgyMTc5MjYwMjU0KSIgZmlsbD0iIzQyNDI0MiIgZD0ibTkuNDgwNDYsOC41ODEzOGwxLjI2LC0xLjI2bC01LjA0LC01LjA0bC01LjQ2LDUuMDRsMS4yNiwxLjI2bDQuMiwtMy43OGwzLjc4LDMuNzh6Ii8+PC9zdmc+");cursor:pointer}.monaco-scrollable-element>.scrollbar>.right-arrow{background:url("data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTEgMTEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggdHJhbnNmb3JtPSJyb3RhdGUoOTAgNS42MTcxNjUwODg2NTM1NjQ1LDUuNTU4MDg5NzMzMTIzNzgpICIgZmlsbD0iIzQyNDI0MiIgZD0ibTkuNjA3MTcsOC43MDgwOWwxLjI2LC0xLjI2bC01LjA0LC01LjA0bC01LjQ2LDUuMDRsMS4yNiwxLjI2bDQuMiwtMy43OGwzLjc4LDMuNzh6Ii8+PC9zdmc+");cursor:pointer}.hc-black .monaco-scrollable-element>.scrollbar>.up-arrow,.vs-dark .monaco-scrollable-element>.scrollbar>.up-arrow{background:url("data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTEgMTEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0ibTkuNDgwNDYsOC45NjE1bDEuMjYsLTEuMjZsLTUuMDQsLTUuMDRsLTUuNDYsNS4wNGwxLjI2LDEuMjZsNC4yLC0zLjc4bDMuNzgsMy43OHoiIGZpbGw9IiNFOEU4RTgiLz48L3N2Zz4=")}.hc-black .monaco-scrollable-element>.scrollbar>.down-arrow,.vs-dark .monaco-scrollable-element>.scrollbar>.down-arrow{background:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMSAxMSI+PHBhdGggdHJhbnNmb3JtPSJyb3RhdGUoLTE4MCA1LjQ5MDQ1OTkxODk3NTgzLDUuODExNTAwMDcyNDc5MjQ4KSIgZmlsbD0iI0U4RThFOCIgZD0ibTkuNDgwNDYsOC45NjE1bDEuMjYsLTEuMjZsLTUuMDQsLTUuMDRsLTUuNDYsNS4wNGwxLjI2LDEuMjZsNC4yLC0zLjc4bDMuNzgsMy43OHoiLz48L3N2Zz4=")}.hc-black .monaco-scrollable-element>.scrollbar>.left-arrow,.vs-dark .monaco-scrollable-element>.scrollbar>.left-arrow{background:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMSAxMSI+PHBhdGggdHJhbnNmb3JtPSJyb3RhdGUoLTkwIDUuNDkwNDU5OTE4OTc1ODMxLDUuNDMxMzgyMTc5MjYwMjU0KSIgZmlsbD0iI0U4RThFOCIgZD0ibTkuNDgwNDYsOC41ODEzOGwxLjI2LC0xLjI2bC01LjA0LC01LjA0bC01LjQ2LDUuMDRsMS4yNiwxLjI2bDQuMiwtMy43OGwzLjc4LDMuNzh6Ii8+PC9zdmc+")}.hc-black .monaco-scrollable-element>.scrollbar>.right-arrow,.vs-dark .monaco-scrollable-element>.scrollbar>.right-arrow{background:url("data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTEgMTEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggdHJhbnNmb3JtPSJyb3RhdGUoOTAgNS42MTcxNjUwODg2NTM1NjQ1LDUuNTU4MDg5NzMzMTIzNzgpICIgZmlsbD0iI0U4RThFOCIgZD0ibTkuNjA3MTcsOC43MDgwOWwxLjI2LC0xLjI2bC01LjA0LC01LjA0bC01LjQ2LDUuMDRsMS4yNiwxLjI2bDQuMiwtMy43OGwzLjc4LDMuNzh6Ii8+PC9zdmc+")}.monaco-scrollable-element>.visible{opacity:1;background:transparent;transition:opacity .1s linear}.monaco-scrollable-element>.invisible{opacity:0;pointer-events:none}.monaco-scrollable-element>.invisible.fade{transition:opacity .8s linear}.monaco-scrollable-element>.shadow{position:absolute;display:none}.monaco-scrollable-element>.shadow.top{display:block;top:0;left:3px;height:3px;width:100%;box-shadow:inset 0 6px 6px -6px #ddd}.monaco-scrollable-element>.shadow.left{display:block;top:3px;left:0;height:100%;width:3px;box-shadow:inset 6px 0 6px -6px #ddd}.monaco-scrollable-element>.shadow.top-left-corner{display:block;top:0;left:0;height:3px;width:3px}.monaco-scrollable-element>.shadow.top.left{box-shadow:inset 6px 6px 6px -6px #ddd}.vs .monaco-scrollable-element>.scrollbar>.slider{background:hsla(0,0%,39%,.4)}.vs-dark .monaco-scrollable-element>.scrollbar>.slider{background:hsla(0,0%,47%,.4)}.hc-black .monaco-scrollable-element>.scrollbar>.slider{background:rgba(111,195,223,.6)}.monaco-scrollable-element>.scrollbar>.slider:hover{background:hsla(0,0%,39%,.7)}.hc-black .monaco-scrollable-element>.scrollbar>.slider:hover{background:rgba(111,195,223,.8)}.monaco-scrollable-element>.scrollbar>.slider.active{background:rgba(0,0,0,.6)}.vs-dark .monaco-scrollable-element>.scrollbar>.slider.active{background:hsla(0,0%,75%,.4)}.hc-black .monaco-scrollable-element>.scrollbar>.slider.active{background:#6fc3df}.vs-dark .monaco-scrollable-element .shadow.top{box-shadow:none}.vs-dark .monaco-scrollable-element .shadow.left{box-shadow:inset 6px 0 6px -6px #000}.vs-dark .monaco-scrollable-element .shadow.top.left{box-shadow:inset 6px 6px 6px -6px #000}.hc-black .monaco-scrollable-element .shadow.left,.hc-black .monaco-scrollable-element .shadow.top,.hc-black .monaco-scrollable-element .shadow.top.left{box-shadow:none}.monaco-editor .margin-view-overlays .folding{cursor:pointer;background-repeat:no-repeat;background-origin:border-box;background-position:calc(50% + 2px) 50%;background-size:auto calc(100% - 3px);opacity:0;transition:opacity .5s;background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03Ljk3NjAzIDEwLjA3MTlMMTIuMzMzMyA1LjcxNDYxTDEyLjk1MjEgNi4zMzMzM0w4LjI4NTM5IDExTDcuNjY2NjcgMTFMMyA2LjMzMzMzTDMuNjE4NzIgNS43MTQ2MUw3Ljk3NjAzIDEwLjA3MTlaIiBmaWxsPSIjNDI0MjQyIi8+Cjwvc3ZnPgo=")}.monaco-editor.hc-black .margin-view-overlays .folding,.monaco-editor.vs-dark .margin-view-overlays .folding{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03Ljk3NjAzIDEwLjA3MTlMMTIuMzMzMyA1LjcxNDYxTDEyLjk1MjEgNi4zMzMzM0w4LjI4NTM5IDExTDcuNjY2NjcgMTFMMyA2LjMzMzMzTDMuNjE4NzIgNS43MTQ2MUw3Ljk3NjAzIDEwLjA3MTlaIiBmaWxsPSIjQzVDNUM1Ii8+Cjwvc3ZnPgo=")}.monaco-editor.hc-black .margin-view-overlays .folding{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03Ljk3NjAzIDEwLjA3MTlMMTIuMzMzMyA1LjcxNDYxTDEyLjk1MjEgNi4zMzMzM0w4LjI4NTM5IDExTDcuNjY2NjcgMTFMMyA2LjMzMzMzTDMuNjE4NzIgNS43MTQ2MUw3Ljk3NjAzIDEwLjA3MTlaIiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4K")}.monaco-editor .margin-view-overlays .folding.alwaysShowFoldIcons,.monaco-editor .margin-view-overlays:hover .folding{opacity:1}.monaco-editor .margin-view-overlays .folding.collapsed{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMC4wNzE5IDcuOTk5OTlMNS43MTQ2IDEyLjM1NzNMNi4zMzMzMiAxMi45NzZMMTEgOC4zMDkzNVY3LjY5MDYzTDYuMzMzMzIgMy4wMjM5Nkw1LjcxNDYgMy42NDI2OEwxMC4wNzE5IDcuOTk5OTlaIiBmaWxsPSIjNDI0MjQyIi8+Cjwvc3ZnPgo=");opacity:1}.monaco-editor.vs-dark .margin-view-overlays .folding.collapsed{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMC4wNzE5IDcuOTk5OTlMNS43MTQ2IDEyLjM1NzNMNi4zMzMzMiAxMi45NzZMMTEgOC4zMDkzNVY3LjY5MDY0TDYuMzMzMzIgMy4wMjM5N0w1LjcxNDYgMy42NDI2OUwxMC4wNzE5IDcuOTk5OTlaIiBmaWxsPSIjQzVDNUM1Ii8+Cjwvc3ZnPgo=")}.monaco-editor.hc-black .margin-view-overlays .folding.collapsed{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMC4wNzE5IDcuOTk5OTlMNS43MTQ2IDEyLjM1NzNMNi4zMzMzMiAxMi45NzZMMTEgOC4zMDkzNVY3LjY5MDYzTDYuMzMzMzIgMy4wMjM5Nkw1LjcxNDYgMy42NDI2OEwxMC4wNzE5IDcuOTk5OTlaIiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4K")}.monaco-editor .inline-folded:after{color:grey;margin:.1em .2em 0;content:"\22EF";display:inline;line-height:1em;cursor:pointer}.monaco-editor .peekview-widget .head{-o-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;display:-ms-flexbox;display:flex}.monaco-editor .peekview-widget .head .peekview-title{display:inline-block;font-size:13px;margin-left:20px;cursor:pointer}.monaco-editor .peekview-widget .head .peekview-title .dirname:not(:empty){font-size:.9em;margin-left:.5em}.monaco-editor .peekview-widget .head .peekview-actions{-ms-flex:1;flex:1;text-align:right;padding-right:2px}.monaco-editor .peekview-widget .head .peekview-actions>.monaco-action-bar{display:inline-block}.monaco-editor .peekview-widget .head .peekview-actions>.monaco-action-bar,.monaco-editor .peekview-widget .head .peekview-actions>.monaco-action-bar>.actions-container{height:100%}.monaco-editor .peekview-widget .head .peekview-actions>.monaco-action-bar .action-item{margin-left:4px}.monaco-editor .peekview-widget .head .peekview-actions>.monaco-action-bar .action-label{width:16px;height:100%;margin:0;line-height:inherit;background-repeat:no-repeat;background-position:50%}.monaco-editor .peekview-widget .head .peekview-actions>.monaco-action-bar .action-label.octicon{margin:0}.monaco-editor .peekview-widget .head .peekview-actions .action-label.icon.close-peekview-action{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik04LjAwMDAxIDguNzA3MDhMMTEuNjQ2NSAxMi4zNTM1TDEyLjM1MzYgMTEuNjQ2NEw4LjcwNzExIDcuOTk5OThMMTIuMzUzNiA0LjM1MzUzTDExLjY0NjUgMy42NDY0Mkw4LjAwMDAxIDcuMjkyODdMNC4zNTM1NiAzLjY0NjQyTDMuNjQ2NDUgNC4zNTM1M0w3LjI5MjkgNy45OTk5OEwzLjY0NjQ1IDExLjY0NjRMNC4zNTM1NiAxMi4zNTM1TDguMDAwMDEgOC43MDcwOFoiIGZpbGw9IiM0MjQyNDIiLz4KPC9zdmc+Cg==") 50% no-repeat}.monaco-editor .peekview-widget>.body{border-top:1px solid;position:relative}.monaco-editor.hc-black .peekview-widget .head .peekview-actions .action-label.icon.close-peekview-action,.monaco-editor.vs-dark .peekview-widget .head .peekview-actions .action-label.icon.close-peekview-action{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik04LjAwMDAxIDguNzA3MDhMMTEuNjQ2NSAxMi4zNTM1TDEyLjM1MzYgMTEuNjQ2NEw4LjcwNzExIDcuOTk5OThMMTIuMzUzNiA0LjM1MzUzTDExLjY0NjUgMy42NDY0Mkw4LjAwMDAxIDcuMjkyODdMNC4zNTM1NiAzLjY0NjQyTDMuNjQ2NDUgNC4zNTM1M0w3LjI5MjkgNy45OTk5OEwzLjY0NjQ1IDExLjY0NjRMNC4zNTM1NiAxMi4zNTM1TDguMDAwMDEgOC43MDcwOFoiIGZpbGw9IiNDNUM1QzUiLz4KPC9zdmc+Cg==") 50% no-repeat}.monaco-editor .peekview-widget .peekview-actions .icon.chevron-up{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMy44NTM1IDYuMjkyOUw4Ljg1MzU2IDEuMjkyOTFIOC4xNDY0NUwzLjE0NjQ1IDYuMjkyOUwzLjg1MzU2IDcuMDAwMDFMOCAyLjg1MzU3VjE1LjA2MDdIOVYyLjg1MzU3TDEzLjE0NjQgNy4wMDAwMUwxMy44NTM1IDYuMjkyOVoiIGZpbGw9IiM0MjQyNDIiLz4KPC9zdmc+Cg==") 50% no-repeat}.hc-black .monaco-editor .peekview-widget .peekview-actions .icon.chevron-up,.vs-dark .monaco-editor .peekview-widget .peekview-actions .icon.chevron-up{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMy44NTM1IDYuMjkyOUw4Ljg1MzU2IDEuMjkyOTFIOC4xNDY0NUwzLjE0NjQ1IDYuMjkyOUwzLjg1MzU2IDcuMDAwMDFMOCAyLjg1MzU3VjE1LjA2MDdIOVYyLjg1MzU3TDEzLjE0NjQgNy4wMDAwMUwxMy44NTM1IDYuMjkyOVoiIGZpbGw9IiNDNUM1QzUiLz4KPC9zdmc+Cg==") 50% no-repeat}.monaco-editor .peekview-widget .peekview-actions .icon.chevron-down{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0zLjE0NjQ2IDkuNzY3NzdMOC4xNDY0NCAxNC43Njc4TDguODUzNTUgMTQuNzY3OEwxMy44NTM1IDkuNzY3NzdMMTMuMTQ2NCA5LjA2MDY2TDkgMTMuMjA3MUw5IDFMOCAwLjk5OTk5OUw4IDEzLjIwNzFMMy44NTM1NiA5LjA2MDY2TDMuMTQ2NDYgOS43Njc3N1oiIGZpbGw9IiM0MjQyNDIiLz4KPC9zdmc+Cg==") 50% no-repeat}.hc-black .monaco-editor .peekview-widget .peekview-actions .icon.chevron-down,.vs-dark .monaco-editor .peekview-widget .peekview-actions .icon.chevron-down{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0zLjE0NjQ2IDkuNzY3NzdMOC4xNDY0NCAxNC43Njc4TDguODUzNTUgMTQuNzY3OEwxMy44NTM1IDkuNzY3NzdMMTMuMTQ2NCA5LjA2MDY2TDkgMTMuMjA3MUw5IDFMOCAwLjk5OTk5OUw4IDEzLjIwNzFMMy44NTM1NiA5LjA2MDY2TDMuMTQ2NDYgOS43Njc3N1oiIGZpbGw9IiNDNUM1QzUiLz4KPC9zdmc+Cg==") 50% no-repeat}::-ms-clear{display:none}.monaco-editor .editor-widget input{color:inherit}.monaco-editor{position:relative;overflow:visible;-webkit-text-size-adjust:100%;-webkit-font-feature-settings:"liga" off,"calt" off;font-feature-settings:"liga" off,"calt" off}.monaco-editor.enable-ligatures{-webkit-font-feature-settings:"liga" on,"calt" on;font-feature-settings:"liga" on,"calt" on}.monaco-editor .overflow-guard{position:relative;overflow:hidden}.monaco-editor .view-overlays{position:absolute;top:0}.monaco-editor .vs-whitespace{display:inline-block}.monaco-editor .inputarea{min-width:0;min-height:0;margin:0;padding:0;position:absolute;outline:none!important;resize:none;border:none;overflow:hidden;color:transparent;background-color:transparent}.monaco-editor .inputarea.ime-input{z-index:10}.monaco-editor .margin-view-overlays .line-numbers{position:absolute;text-align:right;display:inline-block;vertical-align:middle;box-sizing:border-box;cursor:default;height:100%}.monaco-editor .relative-current-line-number{text-align:left;display:inline-block;width:100%}.monaco-editor .margin-view-overlays .line-numbers{cursor:-webkit-image-set(url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNSIgaGVpZ2h0PSIyNSIgeD0iMHB4IiB5PSIwcHgiIHZpZXdCb3g9IjAgMCAxNSAyNSIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMTUgMjU7Ij48cG9seWdvbiBzdHlsZT0iZmlsbDojRkZGRkZGO3N0cm9rZTojMDAwMDAwIiBwb2ludHM9IjE0LjUsMS4yIDEuOSwxMy44IDcsMTMuOCAzLjIsMjEuNSA2LjMsMjIuNSAxMC4xLDE0LjkgMTQuNSwxOCIvPjwvc3ZnPg==") 1x,url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjBweCIgeT0iMHB4IiB3aWR0aD0iMzAiIGhlaWdodD0iNTAiIHZpZXdCb3g9IjAgMCAzMCA1MCIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMzAgNTA7Ij48cG9seWdvbiBzdHlsZT0iZmlsbDojRkZGRkZGO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDoyOyIgcG9pbnRzPSIyOSwyLjQgMy44LDI3LjYgMTQsMjcuNiA2LjQsNDMgMTIuNiw0NSAyMC4yLDI5LjggMjksMzYiLz48L3N2Zz4K") 2x) 30 0,default}.monaco-editor.mac .margin-view-overlays .line-numbers{cursor:-webkit-image-set(url("data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMTMgMTkiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDEzIDE5OyIgd2lkdGg9IjEzIiBoZWlnaHQ9IjE5Ij48c3R5bGUgdHlwZT0idGV4dC9jc3MiPi5zdDB7c3Ryb2tlOiNGRkZGRkY7c3Ryb2tlLW1pdGVybGltaXQ6MTA7fTwvc3R5bGU+PHRpdGxlPmZsaXBwZWQtY3Vyc29yLW1hYzwvdGl0bGU+PHBhdGggY2xhc3M9InN0MCIgZD0iTTUuMywxNi42bDEuNi00LjdIMi4xTDEyLjUsMS4ydjE0LjRMOS43LDEzbC0xLjYsNC42Yy0wLjIsMC41LTAuOCwwLjgtMS4zLDAuNkw2LDE3LjkgQzUuNCwxNy43LDUuMSwxNy4yLDUuMywxNi42eiIvPjwvc3ZnPgo=") 1x,url("data:image/svg+xml;base64,CjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmlld0JveD0iMCAwIDI2IDM4IiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCAyNiAzODsiIHdpZHRoPSIyNiIgaGVpZ2h0PSIzOCI+PHN0eWxlIHR5cGU9InRleHQvY3NzIj4uc3Qwe3N0cm9rZTojRkZGRkZGO3N0cm9rZS1taXRlcmxpbWl0OjEwO308L3N0eWxlPgk8dGl0bGU+ZmxpcHBlZC1jdXJzb3ItbWFjPC90aXRsZT48cGF0aCBjbGFzcz0ic3QwIiBkPSJNMTAuNiwzMy4ybDMuMi05LjRINC4yTDI1LDIuNHYyOC44TDE5LjQsMjZsLTMuMiw5LjJjLTAuNCwxLTEuNiwxLjYtMi42LDEuMkwxMiwzNS44IEMxMC44LDM1LjQsMTAuMiwzNC40LDEwLjYsMzMuMnoiLz48L3N2Zz4K") 2x) 24 3,default}.monaco-editor .margin-view-overlays .line-numbers.lh-odd{margin-top:1px}.monaco-editor .margin-view-overlays .current-line,.monaco-editor .view-overlays .current-line{display:block;position:absolute;left:0;top:0;box-sizing:border-box}.monaco-editor .margin-view-overlays .current-line.current-line-margin.current-line-margin-both{border-right:0}.monaco-editor .lines-content .cdr{position:absolute}.monaco-editor .glyph-margin{position:absolute;top:0}.monaco-editor .lines-content .cigr,.monaco-editor .lines-content .cigra,.monaco-editor .margin-view-overlays .cgmr{position:absolute}.monaco-editor.no-user-select .lines-content,.monaco-editor.no-user-select .view-line,.monaco-editor.no-user-select .view-lines{-webkit-user-select:none;-ms-user-select:none;-moz-user-select:none;-o-user-select:none;user-select:none}.monaco-editor .view-lines{cursor:text;white-space:nowrap}.monaco-editor.hc-black.mac .view-lines,.monaco-editor.vs-dark.mac .view-lines{cursor:-webkit-image-set(url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAL0lEQVQoz2NgCD3x//9/BhBYBWdhgFVAiVW4JBFKGIa4AqD0//9D3pt4I4tAdAMAHTQ/j5Zom30AAAAASUVORK5CYII=) 1x,url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAQAAADZc7J/AAAAz0lEQVRIx2NgYGBY/R8I/vx5eelX3n82IJ9FxGf6tksvf/8FiTMQAcAGQMDvSwu09abffY8QYSAScNk45G198eX//yev73/4///701eh//kZSARckrNBRvz//+8+6ZohwCzjGNjdgQxkAg7B9WADeBjIBqtJCbhRA0YNoIkBSNmaPEMoNmA0FkYNoFKhapJ6FGyAH3nauaSmPfwI0v/3OukVi0CIZ+F25KrtYcx/CTIy0e+rC7R1Z4KMICVTQQ14feVXIbR695u14+Ir4gwAAD49E54wc1kWAAAAAElFTkSuQmCC) 2x) 5 8,text}.monaco-editor .view-line{position:absolute;width:100%}.monaco-editor .lines-decorations{position:absolute;top:0;background:#fff}.monaco-editor .margin-view-overlays .cldr{position:absolute;height:100%}.monaco-editor .margin-view-overlays .cmdr{position:absolute;left:0;width:100%;height:100%}.monaco-editor .minimap.slider-mouseover .minimap-slider{opacity:0;transition:opacity .1s linear}.monaco-editor .minimap.slider-mouseover .minimap-slider.active,.monaco-editor .minimap.slider-mouseover:hover .minimap-slider{opacity:1}.monaco-editor .minimap-shadow-hidden{position:absolute;width:0}.monaco-editor .minimap-shadow-visible{position:absolute;left:-6px;width:6px}.monaco-editor .overlayWidgets{position:absolute;top:0;left:0}.monaco-editor .view-ruler{position:absolute;top:0}.monaco-editor .scroll-decoration{position:absolute;top:0;left:0;height:6px}.monaco-editor .lines-content .cslr{position:absolute}.monaco-editor .top-left-radius{border-top-left-radius:3px}.monaco-editor .bottom-left-radius{border-bottom-left-radius:3px}.monaco-editor .top-right-radius{border-top-right-radius:3px}.monaco-editor .bottom-right-radius{border-bottom-right-radius:3px}.monaco-editor.hc-black .top-left-radius{border-top-left-radius:0}.monaco-editor.hc-black .bottom-left-radius{border-bottom-left-radius:0}.monaco-editor.hc-black .top-right-radius{border-top-right-radius:0}.monaco-editor.hc-black .bottom-right-radius{border-bottom-right-radius:0}.monaco-editor .cursors-layer{position:absolute;top:0}.monaco-editor .cursors-layer>.cursor{position:absolute;cursor:text;overflow:hidden}.monaco-editor .cursors-layer.cursor-smooth-caret-animation>.cursor{transition:80ms}.monaco-editor .cursors-layer.cursor-block-outline-style>.cursor{box-sizing:border-box;background:transparent!important;border-style:solid;border-width:1px}.monaco-editor .cursors-layer.cursor-underline-style>.cursor{border-bottom-width:2px;border-bottom-style:solid;background:transparent!important;box-sizing:border-box}.monaco-editor .cursors-layer.cursor-underline-thin-style>.cursor{border-bottom-width:1px;border-bottom-style:solid;background:transparent!important;box-sizing:border-box}@keyframes monaco-cursor-smooth{0%,20%{opacity:1}60%,to{opacity:0}}@keyframes monaco-cursor-phase{0%,20%{opacity:1}90%,to{opacity:0}}@keyframes monaco-cursor-expand{0%,20%{transform:scaleY(1)}80%,to{transform:scaleY(0)}}.cursor-smooth{animation:monaco-cursor-smooth .5s ease-in-out 0s 20 alternate}.cursor-phase{animation:monaco-cursor-phase .5s ease-in-out 0s 20 alternate}.cursor-expand>.cursor{animation:monaco-cursor-expand .5s ease-in-out 0s 20 alternate}.monaco-editor .zone-widget{position:absolute;z-index:10}.monaco-editor .zone-widget .zone-widget-container{border-top-style:solid;border-bottom-style:solid;border-top-width:0;border-bottom-width:0;position:relative}.monaco-editor .zone-widget .zone-widget-container.reference-zone-widget{border-top-width:1px;border-bottom-width:1px}.monaco-editor .reference-zone-widget .inline{display:inline-block;vertical-align:top}.monaco-editor .reference-zone-widget .messages{height:100%;width:100%;text-align:center;padding:3em 0}.monaco-editor .reference-zone-widget .ref-tree{line-height:23px}.monaco-editor .reference-zone-widget .ref-tree .reference{text-overflow:ellipsis;overflow:hidden}.monaco-editor .reference-zone-widget .ref-tree .reference-file{display:-ms-inline-flexbox;display:inline-flex;width:100%;height:100%}.monaco-editor .reference-zone-widget .ref-tree .monaco-list:focus .selected .reference-file{color:inherit!important}.monaco-editor .reference-zone-widget .ref-tree .reference-file .count{margin-right:12px;margin-left:auto}.monaco-editor.hc-black .reference-zone-widget .ref-tree .reference-file{font-weight:700}.monaco-icon-label{display:-ms-flexbox;display:flex;overflow:hidden;text-overflow:ellipsis}.monaco-icon-label:before{background-size:16px;background-position:0;background-repeat:no-repeat;padding-right:6px;width:16px;height:22px;display:inline-block;-webkit-font-smoothing:antialiased;vertical-align:top;-ms-flex-negative:0;flex-shrink:0}.monaco-icon-label>.monaco-icon-label-description-container{overflow:hidden;text-overflow:ellipsis}.monaco-icon-label>.monaco-icon-label-description-container>.label-name{color:inherit;white-space:pre}.monaco-icon-label>.monaco-icon-label-description-container>.label-description{opacity:.7;margin-left:.5em;font-size:.9em;white-space:pre}.monaco-icon-label.italic>.monaco-icon-label-description-container>.label-description,.monaco-icon-label.italic>.monaco-icon-label-description-container>.label-name{font-style:italic}.monaco-icon-label:after{opacity:.75;font-size:90%;font-weight:600;padding:0 12px 0 5px;margin-left:auto;text-align:center}.monaco-list:focus .selected .monaco-icon-label,.monaco-list:focus .selected .monaco-icon-label:after,.monaco-tree.focused .selected .monaco-icon-label,.monaco-tree.focused .selected .monaco-icon-label:after{color:inherit!important}.monaco-list-row.focused.selected .label-description,.monaco-list-row.selected .label-description,.monaco-tree-row.focused.selected .label-description,.monaco-tree-row.selected .label-description{opacity:.8}.monaco-count-badge{padding:3px 5px;border-radius:11px;font-size:11px;min-width:18px;min-height:18px;line-height:11px;font-weight:400;text-align:center;display:inline-block;box-sizing:border-box}.monaco-list{position:relative;height:100%;width:100%;white-space:nowrap}.monaco-list.mouse-support{-webkit-user-select:none;-moz-user-select:-moz-none;-ms-user-select:none;-o-user-select:none;user-select:none}.monaco-list>.monaco-scrollable-element{height:100%}.monaco-list-rows{position:relative;width:100%;height:100%}.monaco-list.horizontal-scrolling .monaco-list-rows{width:auto;min-width:100%}.monaco-list-row{position:absolute;-o-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;overflow:hidden;width:100%}.monaco-list.mouse-support .monaco-list-row{cursor:pointer;-ms-touch-action:none;touch-action:none}.monaco-list-row.scrolling{display:none!important}.monaco-list.element-focused,.monaco-list.selection-multiple,.monaco-list.selection-single{outline:0!important}.monaco-drag-image{display:inline-block;padding:1px 7px;border-radius:10px;font-size:12px;position:absolute}.monaco-list-type-filter{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;position:absolute;border-radius:2px;padding:0 3px;max-width:calc(100% - 10px);text-overflow:ellipsis;overflow:hidden;text-align:right;box-sizing:border-box;cursor:all-scroll;font-size:13px;line-height:18px;height:20px;z-index:1;top:4px}.monaco-list-type-filter.dragging{transition:top .2s,left .2s}.monaco-list-type-filter.ne{right:4px}.monaco-list-type-filter.nw{left:4px}.monaco-list-type-filter>.controls{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;box-sizing:border-box;transition:width .2s;width:0}.monaco-list-type-filter.dragging>.controls,.monaco-list-type-filter:hover>.controls{width:36px}.monaco-list-type-filter>.controls>*{box-sizing:border-box;width:16px;height:16px;margin:0 0 0 2px;-ms-flex-negative:0;flex-shrink:0}.monaco-list-type-filter>.controls>.filter{-webkit-appearance:none;width:16px;height:16px;background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTEgMTJMMSAxMUgxMFYxMkgxWk0xIDdIMTVWOEgxTDEgN1pNMTIgM1Y0SDFMMSAzSDEyWiIgZmlsbD0iIzQyNDI0MiIvPgo8L3N2Zz4K");background-position:50% 50%;cursor:pointer}.monaco-list-type-filter>.controls>.filter:checked{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTYgMTJWMTFIMTBWMTJINlpNNCA3SDEyVjhINFY3Wk0xNCAzVjRIMlYzSDE0WiIgZmlsbD0iIzQyNDI0MiIvPgo8L3N2Zz4K")}.vs-dark .monaco-list-type-filter>.controls>.filter{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTEgMTJMMSAxMUgxMFYxMkgxWk0xIDdIMTVWOEgxTDEgN1pNMTIgM1Y0SDFMMSAzSDEyWiIgZmlsbD0iI0M1QzVDNSIvPgo8L3N2Zz4K")}.vs-dark .monaco-list-type-filter>.controls>.filter:checked{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTYgMTJWMTFIMTBWMTJINlpNNCA3SDEyVjhINFY3Wk0xNCAzVjRIMlYzSDE0WiIgZmlsbD0iI0M1QzVDNSIvPgo8L3N2Zz4K")}.hc-black .monaco-list-type-filter>.controls>.filter{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTEgMTJMMSAxMUgxMFYxMkgxWk0xIDdIMTVWOEgxTDEgN1pNMTIgM1Y0SDFMMSAzSDEyWiIgZmlsbD0iI0M1QzVDNSIvPgo8L3N2Zz4K")}.hc-black .monaco-list-type-filter>.controls>.filter:checked{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTYgMTJWMTFIMTBWMTJINlpNNCA3SDEyVjhINFY3Wk0xNCAzVjRIMlYzSDE0WiIgZmlsbD0id2hpdGUiLz4KPC9zdmc+Cg==")}.monaco-list-type-filter>.controls>.clear{border:none;background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik04LjAwMDAxIDguNzA3MTRMMTEuNjQ2NSAxMi4zNTM2TDEyLjM1MzYgMTEuNjQ2NUw4LjcwNzExIDguMDAwMDRMMTIuMzUzNiA0LjM1MzU5TDExLjY0NjUgMy42NDY0OEw4LjAwMDAxIDcuMjkyOTNMNC4zNTM1NiAzLjY0NjQ4TDMuNjQ2NDUgNC4zNTM1OUw3LjI5MjkgOC4wMDAwNEwzLjY0NjQ1IDExLjY0NjVMNC4zNTM1NiAxMi4zNTM2TDguMDAwMDEgOC43MDcxNFoiIGZpbGw9IiM0MjQyNDIiLz4KPC9zdmc+Cg==");cursor:pointer}.hc-black .monaco-list-type-filter>.controls>.clear,.vs-dark .monaco-list-type-filter>.controls>.clear{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik04LjAwMDAxIDguNzA3MTRMMTEuNjQ2NSAxMi4zNTM2TDEyLjM1MzYgMTEuNjQ2NUw4LjcwNzExIDguMDAwMDRMMTIuMzUzNiA0LjM1MzU5TDExLjY0NjUgMy42NDY0OEw4LjAwMDAxIDcuMjkyOTNMNC4zNTM1NiAzLjY0NjQ4TDMuNjQ2NDUgNC4zNTM1OUw3LjI5MjkgOC4wMDAwNEwzLjY0NjQ1IDExLjY0NjVMNC4zNTM1NiAxMi4zNTM2TDguMDAwMDEgOC43MDcxNFoiIGZpbGw9IiNDNUM1QzUiLz4KPC9zdmc+Cg==")}.monaco-list-type-filter-message{position:absolute;box-sizing:border-box;width:100%;height:100%;top:0;left:0;padding:40px 1em 1em;text-align:center;white-space:normal;opacity:.7;pointer-events:none}.monaco-list-type-filter-message:empty{display:none}.monaco-list-type-filter{cursor:grab}.monaco-list-type-filter.dragging{cursor:grabbing}.monaco-tl-row{display:-ms-flexbox;display:flex;height:100%;-ms-flex-align:center;align-items:center;position:relative}.monaco-tl-indent{height:100%;position:absolute;top:0;left:18px;pointer-events:none}.hide-arrows .monaco-tl-indent{left:12px}.monaco-tl-indent>.indent-guide{display:inline-block;box-sizing:border-box;height:100%;border-left:1px solid transparent;transition:border-color .1s linear}.monaco-tl-contents,.monaco-tl-twistie{height:100%}.monaco-tl-twistie{font-size:10px;text-align:right;margin-right:6px;-ms-flex-negative:0;flex-shrink:0;width:16px}.monaco-tl-contents{-ms-flex:1;flex:1;overflow:hidden}.monaco-tl-twistie.collapsible{background-size:16px;background-position:3px 50%;background-repeat:no-repeat;background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03Ljk3NjAzIDEwLjA3MTlMMTIuMzMzMyA1LjcxNDYxTDEyLjk1MjEgNi4zMzMzM0w4LjI4NTM5IDExTDcuNjY2NjcgMTFMMyA2LjMzMzMzTDMuNjE4NzIgNS43MTQ2MUw3Ljk3NjAzIDEwLjA3MTlaIiBmaWxsPSIjNDI0MjQyIi8+Cjwvc3ZnPgo=")}.monaco-tl-twistie.collapsible.collapsed:not(.loading){display:inline-block;background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMC4wNzE5IDcuOTk5OTlMNS43MTQ2MSAxMi4zNTczTDYuMzMzMzMgMTIuOTc2TDExIDguMzA5MzVWNy42OTA2M0w2LjMzMzMzIDMuMDIzOTZMNS43MTQ2MSAzLjY0MjY4TDEwLjA3MTkgNy45OTk5OVoiIGZpbGw9IiM0MjQyNDIiLz4KPC9zdmc+Cg==")}.vs-dark .monaco-tl-twistie.collapsible:not(.loading){background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03Ljk3NjAzIDEwLjA3MTlMMTIuMzMzMyA1LjcxNDYxTDEyLjk1MjEgNi4zMzMzM0w4LjI4NTM5IDExTDcuNjY2NjcgMTFMMyA2LjMzMzMzTDMuNjE4NzIgNS43MTQ2MUw3Ljk3NjAzIDEwLjA3MTlaIiBmaWxsPSIjQzVDNUM1Ii8+Cjwvc3ZnPgo=")}.vs-dark .monaco-tl-twistie.collapsible.collapsed:not(.loading){background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMC4wNzE5IDcuOTk5OTlMNS43MTQ2MSAxMi4zNTczTDYuMzMzMzMgMTIuOTc2TDExIDguMzA5MzVWNy42OTA2NEw2LjMzMzMzIDMuMDIzOTdMNS43MTQ2MSAzLjY0MjY5TDEwLjA3MTkgNy45OTk5OVoiIGZpbGw9IiNDNUM1QzUiLz4KPC9zdmc+Cg==")}.hc-black .monaco-tl-twistie.collapsible:not(.loading){background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03Ljk3NjAzIDEwLjA3MTlMMTIuMzMzMyA1LjcxNDYxTDEyLjk1MjEgNi4zMzMzM0w4LjI4NTM5IDExTDcuNjY2NjcgMTFMMyA2LjMzMzMzTDMuNjE4NzIgNS43MTQ2MUw3Ljk3NjAzIDEwLjA3MTlaIiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4K")}.hc-black .monaco-tl-twistie.collapsible.collapsed:not(.loading){background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMC4wNzE5IDcuOTk5OTlMNS43MTQ2MSAxMi4zNTczTDYuMzMzMzMgMTIuOTc2TDExIDguMzA5MzVWNy42OTA2M0w2LjMzMzMzIDMuMDIzOTZMNS43MTQ2MSAzLjY0MjY4TDEwLjA3MTkgNy45OTk5OVoiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPgo=")}.monaco-tl-twistie.loading{background-image:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0nMS4wJyBzdGFuZGFsb25lPSdubycgPz4KPHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZlcnNpb249JzEuMScgd2lkdGg9JzEwcHgnIGhlaWdodD0nMTBweCc+Cgk8c3R5bGU+CiAgICBjaXJjbGUgewogICAgICBhbmltYXRpb246IGJhbGwgMC42cyBsaW5lYXIgaW5maW5pdGU7CiAgICB9CgogICAgY2lyY2xlOm50aC1jaGlsZCgyKSB7IGFuaW1hdGlvbi1kZWxheTogMC4wNzVzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDMpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjE1czsgfQogICAgY2lyY2xlOm50aC1jaGlsZCg0KSB7IGFuaW1hdGlvbi1kZWxheTogMC4yMjVzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDUpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjNzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDYpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjM3NXM7IH0KICAgIGNpcmNsZTpudGgtY2hpbGQoNykgeyBhbmltYXRpb24tZGVsYXk6IDAuNDVzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDgpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjUyNXM7IH0KCiAgICBAa2V5ZnJhbWVzIGJhbGwgewogICAgICBmcm9tIHsgb3BhY2l0eTogMTsgfQogICAgICB0byB7IG9wYWNpdHk6IDAuMzsgfQogICAgfQoJPC9zdHlsZT4KCTxnPgoJCTxjaXJjbGUgY3g9JzUnIGN5PScxJyByPScxJyBzdHlsZT0nb3BhY2l0eTowLjM7JyAvPgoJCTxjaXJjbGUgY3g9JzcuODI4NCcgY3k9JzIuMTcxNicgcj0nMScgc3R5bGU9J29wYWNpdHk6MC4zOycgLz4KCQk8Y2lyY2xlIGN4PSc5JyBjeT0nNScgcj0nMScgc3R5bGU9J29wYWNpdHk6MC4zOycgLz4KCQk8Y2lyY2xlIGN4PSc3LjgyODQnIGN5PSc3LjgyODQnIHI9JzEnIHN0eWxlPSdvcGFjaXR5OjAuMzsnIC8+CgkJPGNpcmNsZSBjeD0nNScgY3k9JzknIHI9JzEnIHN0eWxlPSdvcGFjaXR5OjAuMzsnIC8+CgkJPGNpcmNsZSBjeD0nMi4xNzE2JyBjeT0nNy44Mjg0JyByPScxJyBzdHlsZT0nb3BhY2l0eTowLjM7JyAvPgoJCTxjaXJjbGUgY3g9JzEnIGN5PSc1JyByPScxJyBzdHlsZT0nb3BhY2l0eTowLjM7JyAvPgoJCTxjaXJjbGUgY3g9JzIuMTcxNicgY3k9JzIuMTcxNicgcj0nMScgc3R5bGU9J29wYWNpdHk6MC4zOycgLz4KCTwvZz4KPC9zdmc+Cg==");background-position:0}.vs-dark .monaco-tl-twistie.loading{background-image:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0nMS4wJyBzdGFuZGFsb25lPSdubycgPz4KPHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZlcnNpb249JzEuMScgd2lkdGg9JzEwcHgnIGhlaWdodD0nMTBweCc+Cgk8c3R5bGU+CiAgICBjaXJjbGUgewogICAgICBhbmltYXRpb246IGJhbGwgMC42cyBsaW5lYXIgaW5maW5pdGU7CiAgICB9CgogICAgY2lyY2xlOm50aC1jaGlsZCgyKSB7IGFuaW1hdGlvbi1kZWxheTogMC4wNzVzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDMpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjE1czsgfQogICAgY2lyY2xlOm50aC1jaGlsZCg0KSB7IGFuaW1hdGlvbi1kZWxheTogMC4yMjVzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDUpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjNzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDYpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjM3NXM7IH0KICAgIGNpcmNsZTpudGgtY2hpbGQoNykgeyBhbmltYXRpb24tZGVsYXk6IDAuNDVzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDgpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjUyNXM7IH0KCiAgICBAa2V5ZnJhbWVzIGJhbGwgewogICAgICBmcm9tIHsgb3BhY2l0eTogMTsgfQogICAgICB0byB7IG9wYWNpdHk6IDAuMzsgfQogICAgfQoJPC9zdHlsZT4KCTxnIHN0eWxlPSJmaWxsOmdyZXk7Ij4KCQk8Y2lyY2xlIGN4PSc1JyBjeT0nMScgcj0nMScgc3R5bGU9J29wYWNpdHk6MC4zOycgLz4KCQk8Y2lyY2xlIGN4PSc3LjgyODQnIGN5PScyLjE3MTYnIHI9JzEnIHN0eWxlPSdvcGFjaXR5OjAuMzsnIC8+CgkJPGNpcmNsZSBjeD0nOScgY3k9JzUnIHI9JzEnIHN0eWxlPSdvcGFjaXR5OjAuMzsnIC8+CgkJPGNpcmNsZSBjeD0nNy44Mjg0JyBjeT0nNy44Mjg0JyByPScxJyBzdHlsZT0nb3BhY2l0eTowLjM7JyAvPgoJCTxjaXJjbGUgY3g9JzUnIGN5PSc5JyByPScxJyBzdHlsZT0nb3BhY2l0eTowLjM7JyAvPgoJCTxjaXJjbGUgY3g9JzIuMTcxNicgY3k9JzcuODI4NCcgcj0nMScgc3R5bGU9J29wYWNpdHk6MC4zOycgLz4KCQk8Y2lyY2xlIGN4PScxJyBjeT0nNScgcj0nMScgc3R5bGU9J29wYWNpdHk6MC4zOycgLz4KCQk8Y2lyY2xlIGN4PScyLjE3MTYnIGN5PScyLjE3MTYnIHI9JzEnIHN0eWxlPSdvcGFjaXR5OjAuMzsnIC8+Cgk8L2c+Cjwvc3ZnPgo=")}.hc-black .monaco-tl-twistie.loading{background-image:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0nMS4wJyBzdGFuZGFsb25lPSdubycgPz4KPHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZlcnNpb249JzEuMScgd2lkdGg9JzEwcHgnIGhlaWdodD0nMTBweCc+Cgk8c3R5bGU+CiAgICBjaXJjbGUgewogICAgICBhbmltYXRpb246IGJhbGwgMC42cyBsaW5lYXIgaW5maW5pdGU7CiAgICB9CgogICAgY2lyY2xlOm50aC1jaGlsZCgyKSB7IGFuaW1hdGlvbi1kZWxheTogMC4wNzVzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDMpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjE1czsgfQogICAgY2lyY2xlOm50aC1jaGlsZCg0KSB7IGFuaW1hdGlvbi1kZWxheTogMC4yMjVzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDUpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjNzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDYpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjM3NXM7IH0KICAgIGNpcmNsZTpudGgtY2hpbGQoNykgeyBhbmltYXRpb24tZGVsYXk6IDAuNDVzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDgpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjUyNXM7IH0KCiAgICBAa2V5ZnJhbWVzIGJhbGwgewogICAgICBmcm9tIHsgb3BhY2l0eTogMTsgfQogICAgICB0byB7IG9wYWNpdHk6IDAuMzsgfQogICAgfQoJPC9zdHlsZT4KCTxnIHN0eWxlPSJmaWxsOndoaXRlOyI+CgkJPGNpcmNsZSBjeD0nNScgY3k9JzEnIHI9JzEnIHN0eWxlPSdvcGFjaXR5OjAuMzsnIC8+CgkJPGNpcmNsZSBjeD0nNy44Mjg0JyBjeT0nMi4xNzE2JyByPScxJyBzdHlsZT0nb3BhY2l0eTowLjM7JyAvPgoJCTxjaXJjbGUgY3g9JzknIGN5PSc1JyByPScxJyBzdHlsZT0nb3BhY2l0eTowLjM7JyAvPgoJCTxjaXJjbGUgY3g9JzcuODI4NCcgY3k9JzcuODI4NCcgcj0nMScgc3R5bGU9J29wYWNpdHk6MC4zOycgLz4KCQk8Y2lyY2xlIGN4PSc1JyBjeT0nOScgcj0nMScgc3R5bGU9J29wYWNpdHk6MC4zOycgLz4KCQk8Y2lyY2xlIGN4PScyLjE3MTYnIGN5PSc3LjgyODQnIHI9JzEnIHN0eWxlPSdvcGFjaXR5OjAuMzsnIC8+CgkJPGNpcmNsZSBjeD0nMScgY3k9JzUnIHI9JzEnIHN0eWxlPSdvcGFjaXR5OjAuMzsnIC8+CgkJPGNpcmNsZSBjeD0nMi4xNzE2JyBjeT0nMi4xNzE2JyByPScxJyBzdHlsZT0nb3BhY2l0eTowLjM7JyAvPgoJPC9nPgo8L3N2Zz4K")}.monaco-split-view2{position:relative;width:100%;height:100%}.monaco-split-view2>.sash-container{position:absolute;width:100%;height:100%;pointer-events:none}.monaco-split-view2>.sash-container>.monaco-sash{pointer-events:auto}.monaco-split-view2>.split-view-container{display:-ms-flexbox;display:flex;width:100%;height:100%;white-space:nowrap}.monaco-split-view2.vertical>.split-view-container{-ms-flex-direction:column;flex-direction:column}.monaco-split-view2.horizontal>.split-view-container{-ms-flex-direction:row;flex-direction:row}.monaco-split-view2>.split-view-container>.split-view-view{white-space:normal;-ms-flex:none;flex:none;position:relative}.monaco-split-view2>.split-view-container>.split-view-view:not(.visible){display:none}.monaco-split-view2.vertical>.split-view-container>.split-view-view{width:100%}.monaco-split-view2.horizontal>.split-view-container>.split-view-view{height:100%;display:inline-block}.monaco-split-view2.separator-border>.split-view-container>.split-view-view:not(:first-child):before{content:" ";position:absolute;top:0;left:0;z-index:5;pointer-events:none;background-color:var(--separator-border)}.monaco-split-view2.separator-border.horizontal>.split-view-container>.split-view-view:not(:first-child):before{height:100%;width:1px}.monaco-split-view2.separator-border.vertical>.split-view-container>.split-view-view:not(:first-child):before{height:1px;width:100%}.monaco-editor .goto-definition-link{text-decoration:underline;cursor:pointer}.monaco-editor .peekview-widget .head .peekview-title .severity-icon{display:inline-block;vertical-align:text-top;margin-right:4px}.monaco-editor .marker-widget{text-overflow:ellipsis;white-space:nowrap}.monaco-editor .marker-widget>.stale{opacity:.6;font-style:italic}.monaco-editor .marker-widget .title{display:inline-block;padding-right:5px}.monaco-editor .marker-widget .descriptioncontainer{position:absolute;white-space:pre;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text;padding:8px 12px 0 20px}.monaco-editor .marker-widget .descriptioncontainer .message{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column}.monaco-editor .marker-widget .descriptioncontainer .message .details{padding-left:6px}.monaco-editor .marker-widget .descriptioncontainer .message .code,.monaco-editor .marker-widget .descriptioncontainer .message .source{opacity:.6}.monaco-editor .marker-widget .descriptioncontainer .filename{cursor:pointer}.monaco-keybinding{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;line-height:10px}.monaco-keybinding>.monaco-keybinding-key{display:inline-block;border:1px solid hsla(0,0%,80%,.4);border-bottom-color:hsla(0,0%,73%,.4);border-radius:3px;box-shadow:inset 0 -1px 0 hsla(0,0%,73%,.4);background-color:hsla(0,0%,87%,.4);vertical-align:middle;color:#555;font-size:11px;padding:3px 5px;margin:0 2px}.monaco-keybinding>.monaco-keybinding-key:first-child{margin-left:0}.monaco-keybinding>.monaco-keybinding-key:last-child{margin-right:0}.hc-black .monaco-keybinding>.monaco-keybinding-key,.vs-dark .monaco-keybinding>.monaco-keybinding-key{background-color:hsla(0,0%,50%,.17);color:#ccc;border:1px solid rgba(51,51,51,.6);border-bottom-color:rgba(68,68,68,.6);box-shadow:inset 0 -1px 0 rgba(68,68,68,.6)}.monaco-keybinding>.monaco-keybinding-key-separator{display:inline-block}.monaco-keybinding>.monaco-keybinding-key-chord-separator{width:6px}.monaco-quick-open-widget .monaco-list .monaco-list-row .monaco-highlighted-label .highlight,.monaco-quick-open-widget .monaco-tree .monaco-tree-row .monaco-highlighted-label .highlight{color:#0066bf}.vs-dark .monaco-quick-open-widget .monaco-list .monaco-list-row .monaco-highlighted-label .highlight,.vs-dark .monaco-quick-open-widget .monaco-tree .monaco-tree-row .monaco-highlighted-label .highlight{color:#0097fb}.hc-black .monaco-quick-open-widget .monaco-list .monaco-list-row .monaco-highlighted-label .highlight,.hc-black .monaco-quick-open-widget .monaco-tree .monaco-tree-row .monaco-highlighted-label .highlight{color:#f38518}.monaco-quick-open-widget{position:absolute;width:600px;z-index:2000;padding-bottom:6px;left:50%;margin-left:-300px}.monaco-quick-open-widget .monaco-progress-container{position:absolute;left:0;top:38px;z-index:1;height:2px}.monaco-quick-open-widget .monaco-progress-container .progress-bit{height:2px}.monaco-quick-open-widget .quick-open-input{width:588px;border:none;margin:6px}.monaco-quick-open-widget .quick-open-input .monaco-inputbox{width:100%;height:25px}.monaco-quick-open-widget .quick-open-result-count{position:absolute;left:-10000px}.monaco-quick-open-widget .quick-open-tree{line-height:22px}.monaco-quick-open-widget .quick-open-tree .monaco-tree-row>.content>.sub-content{overflow:hidden}.monaco-quick-open-widget.content-changing .quick-open-tree .monaco-scrollable-element .slider{display:none}.monaco-quick-open-widget .quick-open-tree .quick-open-entry{overflow:hidden;text-overflow:ellipsis;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;height:100%}.monaco-quick-open-widget .quick-open-tree .quick-open-entry>.quick-open-row{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}.monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon{overflow:hidden;width:16px;height:16px;margin-right:4px;display:inline-block;vertical-align:middle;-ms-flex-negative:0;flex-shrink:0}.monaco-quick-open-widget .quick-open-tree .monaco-icon-label,.monaco-quick-open-widget .quick-open-tree .monaco-icon-label .monaco-icon-label-description-container{-ms-flex:1;flex:1}.monaco-quick-open-widget .quick-open-tree .quick-open-entry .monaco-highlighted-label span{opacity:1}.monaco-quick-open-widget .quick-open-tree .quick-open-entry-meta{opacity:.7;line-height:normal}.monaco-quick-open-widget .quick-open-tree .content.has-group-label .quick-open-entry-keybinding{margin-right:8px}.monaco-quick-open-widget .quick-open-tree .quick-open-entry-keybinding .monaco-keybinding-key{vertical-align:text-bottom}.monaco-quick-open-widget .quick-open-tree .results-group{margin-right:18px}.monaco-quick-open-widget .quick-open-tree .focused .monaco-tree-row.focused>.content.has-actions>.results-group,.monaco-quick-open-widget .quick-open-tree .monaco-tree-row.focused>.content.has-actions>.results-group,.monaco-quick-open-widget .quick-open-tree .monaco-tree-row:hover:not(.highlighted)>.content.has-actions>.results-group{margin-right:0}.monaco-quick-open-widget .quick-open-tree .results-group-separator{border-top-width:1px;border-top-style:solid;box-sizing:border-box;margin-left:-11px;padding-left:11px}.monaco-tree .monaco-tree-row>.content.actions{position:relative;display:-ms-flexbox;display:flex}.monaco-tree .monaco-tree-row>.content.actions>.sub-content{-ms-flex:1;flex:1}.monaco-tree .monaco-tree-row>.content.actions .action-item{margin:0}.monaco-tree .monaco-tree-row>.content.actions>.primary-action-bar{line-height:22px;display:none;padding:0 .8em 0 .4em}.monaco-tree .monaco-tree-row.focused>.content.has-actions>.primary-action-bar{width:0;display:block}.monaco-tree.focused .monaco-tree-row.focused>.content.has-actions>.primary-action-bar,.monaco-tree .monaco-tree-row:hover:not(.highlighted)>.content.has-actions>.primary-action-bar,.monaco-tree .monaco-tree-row>.content.has-actions.more>.primary-action-bar{width:inherit;display:block}.monaco-tree .monaco-tree-row>.content.actions>.primary-action-bar .action-label{margin-right:.4em;margin-top:4px;background-repeat:no-repeat;width:16px;height:16px}.monaco-quick-open-widget .quick-open-tree .monaco-highlighted-label .highlight{font-weight:700}.monaco-tree{height:100%;width:100%;white-space:nowrap;-webkit-user-select:none;-moz-user-select:-moz-none;-ms-user-select:none;-o-user-select:none;user-select:none;position:relative}.monaco-tree>.monaco-scrollable-element{height:100%}.monaco-tree>.monaco-scrollable-element>.monaco-tree-wrapper{height:100%;width:100%;position:relative}.monaco-tree .monaco-tree-rows{position:absolute;width:100%;height:100%}.monaco-tree .monaco-tree-rows>.monaco-tree-row{-o-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;cursor:pointer;overflow:hidden;width:100%;-ms-touch-action:none;touch-action:none}.monaco-tree .monaco-tree-rows>.monaco-tree-row>.content{position:relative;height:100%}.monaco-tree-drag-image{display:inline-block;padding:1px 7px;border-radius:10px;font-size:12px;position:absolute}.monaco-tree .monaco-tree-rows>.monaco-tree-row.scrolling{display:none}.monaco-tree .monaco-tree-rows.show-twisties>.monaco-tree-row.has-children>.content:before{content:" ";position:absolute;display:block;background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMC4wNzE5IDcuOTk5OTlMNS43MTQ2MSAxMi4zNTczTDYuMzMzMzMgMTIuOTc2TDExIDguMzA5MzVWNy42OTA2M0w2LjMzMzMzIDMuMDIzOTZMNS43MTQ2MSAzLjY0MjY4TDEwLjA3MTkgNy45OTk5OVoiIGZpbGw9IiM0MjQyNDIiLz4KPC9zdmc+Cg==") 50% 50% no-repeat;width:16px;height:100%;top:0;left:-16px}.monaco-tree .monaco-tree-rows.show-twisties>.monaco-tree-row.expanded>.content:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03Ljk3NjAyIDEwLjA3MTlMMTIuMzMzMyA1LjcxNDYxTDEyLjk1MiA2LjMzMzMzTDguMjg1MzggMTFMNy42NjY2NiAxMUwzIDYuMzMzMzNMMy42MTg3MiA1LjcxNDYxTDcuOTc2MDIgMTAuMDcxOVoiIGZpbGw9IiM0MjQyNDIiLz4KPC9zdmc+Cg==")}.monaco-tree .monaco-tree-rows>.monaco-tree-row.has-children.loading>.content:before{background-image:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0nMS4wJyBzdGFuZGFsb25lPSdubycgPz4KPHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZlcnNpb249JzEuMScgd2lkdGg9JzEwcHgnIGhlaWdodD0nMTBweCc+Cgk8c3R5bGU+CiAgICBjaXJjbGUgewogICAgICBhbmltYXRpb246IGJhbGwgMC42cyBsaW5lYXIgaW5maW5pdGU7CiAgICB9CgogICAgY2lyY2xlOm50aC1jaGlsZCgyKSB7IGFuaW1hdGlvbi1kZWxheTogMC4wNzVzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDMpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjE1czsgfQogICAgY2lyY2xlOm50aC1jaGlsZCg0KSB7IGFuaW1hdGlvbi1kZWxheTogMC4yMjVzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDUpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjNzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDYpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjM3NXM7IH0KICAgIGNpcmNsZTpudGgtY2hpbGQoNykgeyBhbmltYXRpb24tZGVsYXk6IDAuNDVzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDgpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjUyNXM7IH0KCiAgICBAa2V5ZnJhbWVzIGJhbGwgewogICAgICBmcm9tIHsgb3BhY2l0eTogMTsgfQogICAgICB0byB7IG9wYWNpdHk6IDAuMzsgfQogICAgfQoJPC9zdHlsZT4KCTxnPgoJCTxjaXJjbGUgY3g9JzUnIGN5PScxJyByPScxJyBzdHlsZT0nb3BhY2l0eTowLjM7JyAvPgoJCTxjaXJjbGUgY3g9JzcuODI4NCcgY3k9JzIuMTcxNicgcj0nMScgc3R5bGU9J29wYWNpdHk6MC4zOycgLz4KCQk8Y2lyY2xlIGN4PSc5JyBjeT0nNScgcj0nMScgc3R5bGU9J29wYWNpdHk6MC4zOycgLz4KCQk8Y2lyY2xlIGN4PSc3LjgyODQnIGN5PSc3LjgyODQnIHI9JzEnIHN0eWxlPSdvcGFjaXR5OjAuMzsnIC8+CgkJPGNpcmNsZSBjeD0nNScgY3k9JzknIHI9JzEnIHN0eWxlPSdvcGFjaXR5OjAuMzsnIC8+CgkJPGNpcmNsZSBjeD0nMi4xNzE2JyBjeT0nNy44Mjg0JyByPScxJyBzdHlsZT0nb3BhY2l0eTowLjM7JyAvPgoJCTxjaXJjbGUgY3g9JzEnIGN5PSc1JyByPScxJyBzdHlsZT0nb3BhY2l0eTowLjM7JyAvPgoJCTxjaXJjbGUgY3g9JzIuMTcxNicgY3k9JzIuMTcxNicgcj0nMScgc3R5bGU9J29wYWNpdHk6MC4zOycgLz4KCTwvZz4KPC9zdmc+Cg==")}.monaco-tree.highlighted .monaco-tree-rows>.monaco-tree-row:not(.highlighted){opacity:.3}.vs-dark .monaco-tree .monaco-tree-rows.show-twisties>.monaco-tree-row.has-children>.content:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMC4wNzE5IDcuOTk5OTlMNS43MTQ2MSAxMi4zNTczTDYuMzMzMzMgMTIuOTc2TDExIDguMzA5MzVWNy42OTA2NEw2LjMzMzMzIDMuMDIzOTdMNS43MTQ2MSAzLjY0MjY5TDEwLjA3MTkgNy45OTk5OVoiIGZpbGw9IiNDNUM1QzUiLz4KPC9zdmc+Cg==")}.vs-dark .monaco-tree .monaco-tree-rows.show-twisties>.monaco-tree-row.expanded>.content:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03Ljk3NjAyIDEwLjA3MTlMMTIuMzMzMyA1LjcxNDYxTDEyLjk1MiA2LjMzMzMzTDguMjg1MzggMTFMNy42NjY2NiAxMUwzIDYuMzMzMzNMMy42MTg3MiA1LjcxNDYxTDcuOTc2MDIgMTAuMDcxOVoiIGZpbGw9IiNDNUM1QzUiLz4KPC9zdmc+Cg==")}.vs-dark .monaco-tree .monaco-tree-rows>.monaco-tree-row.has-children.loading>.content:before{background-image:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0nMS4wJyBzdGFuZGFsb25lPSdubycgPz4KPHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZlcnNpb249JzEuMScgd2lkdGg9JzEwcHgnIGhlaWdodD0nMTBweCc+Cgk8c3R5bGU+CiAgICBjaXJjbGUgewogICAgICBhbmltYXRpb246IGJhbGwgMC42cyBsaW5lYXIgaW5maW5pdGU7CiAgICB9CgogICAgY2lyY2xlOm50aC1jaGlsZCgyKSB7IGFuaW1hdGlvbi1kZWxheTogMC4wNzVzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDMpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjE1czsgfQogICAgY2lyY2xlOm50aC1jaGlsZCg0KSB7IGFuaW1hdGlvbi1kZWxheTogMC4yMjVzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDUpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjNzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDYpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjM3NXM7IH0KICAgIGNpcmNsZTpudGgtY2hpbGQoNykgeyBhbmltYXRpb24tZGVsYXk6IDAuNDVzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDgpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjUyNXM7IH0KCiAgICBAa2V5ZnJhbWVzIGJhbGwgewogICAgICBmcm9tIHsgb3BhY2l0eTogMTsgfQogICAgICB0byB7IG9wYWNpdHk6IDAuMzsgfQogICAgfQoJPC9zdHlsZT4KCTxnIHN0eWxlPSJmaWxsOmdyZXk7Ij4KCQk8Y2lyY2xlIGN4PSc1JyBjeT0nMScgcj0nMScgc3R5bGU9J29wYWNpdHk6MC4zOycgLz4KCQk8Y2lyY2xlIGN4PSc3LjgyODQnIGN5PScyLjE3MTYnIHI9JzEnIHN0eWxlPSdvcGFjaXR5OjAuMzsnIC8+CgkJPGNpcmNsZSBjeD0nOScgY3k9JzUnIHI9JzEnIHN0eWxlPSdvcGFjaXR5OjAuMzsnIC8+CgkJPGNpcmNsZSBjeD0nNy44Mjg0JyBjeT0nNy44Mjg0JyByPScxJyBzdHlsZT0nb3BhY2l0eTowLjM7JyAvPgoJCTxjaXJjbGUgY3g9JzUnIGN5PSc5JyByPScxJyBzdHlsZT0nb3BhY2l0eTowLjM7JyAvPgoJCTxjaXJjbGUgY3g9JzIuMTcxNicgY3k9JzcuODI4NCcgcj0nMScgc3R5bGU9J29wYWNpdHk6MC4zOycgLz4KCQk8Y2lyY2xlIGN4PScxJyBjeT0nNScgcj0nMScgc3R5bGU9J29wYWNpdHk6MC4zOycgLz4KCQk8Y2lyY2xlIGN4PScyLjE3MTYnIGN5PScyLjE3MTYnIHI9JzEnIHN0eWxlPSdvcGFjaXR5OjAuMzsnIC8+Cgk8L2c+Cjwvc3ZnPgo=")}.hc-black .monaco-tree .monaco-tree-rows.show-twisties>.monaco-tree-row.has-children>.content:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMC4wNzE5IDcuOTk5OTlMNS43MTQ2MSAxMi4zNTczTDYuMzMzMzMgMTIuOTc2TDExIDguMzA5MzVWNy42OTA2M0w2LjMzMzMzIDMuMDIzOTZMNS43MTQ2MSAzLjY0MjY4TDEwLjA3MTkgNy45OTk5OVoiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPgo=")}.hc-black .monaco-tree .monaco-tree-rows.show-twisties>.monaco-tree-row.expanded>.content:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03Ljk3NjAyIDEwLjA3MTlMMTIuMzMzMyA1LjcxNDYxTDEyLjk1MiA2LjMzMzMzTDguMjg1MzggMTFMNy42NjY2NiAxMUwzIDYuMzMzMzNMMy42MTg3MiA1LjcxNDYxTDcuOTc2MDIgMTAuMDcxOVoiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPgo=")}.hc-black .monaco-tree .monaco-tree-rows>.monaco-tree-row.has-children.loading>.content:before{background-image:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0nMS4wJyBzdGFuZGFsb25lPSdubycgPz4KPHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZlcnNpb249JzEuMScgd2lkdGg9JzEwcHgnIGhlaWdodD0nMTBweCc+Cgk8c3R5bGU+CiAgICBjaXJjbGUgewogICAgICBhbmltYXRpb246IGJhbGwgMC42cyBsaW5lYXIgaW5maW5pdGU7CiAgICB9CgogICAgY2lyY2xlOm50aC1jaGlsZCgyKSB7IGFuaW1hdGlvbi1kZWxheTogMC4wNzVzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDMpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjE1czsgfQogICAgY2lyY2xlOm50aC1jaGlsZCg0KSB7IGFuaW1hdGlvbi1kZWxheTogMC4yMjVzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDUpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjNzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDYpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjM3NXM7IH0KICAgIGNpcmNsZTpudGgtY2hpbGQoNykgeyBhbmltYXRpb24tZGVsYXk6IDAuNDVzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDgpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjUyNXM7IH0KCiAgICBAa2V5ZnJhbWVzIGJhbGwgewogICAgICBmcm9tIHsgb3BhY2l0eTogMTsgfQogICAgICB0byB7IG9wYWNpdHk6IDAuMzsgfQogICAgfQoJPC9zdHlsZT4KCTxnIHN0eWxlPSJmaWxsOndoaXRlOyI+CgkJPGNpcmNsZSBjeD0nNScgY3k9JzEnIHI9JzEnIHN0eWxlPSdvcGFjaXR5OjAuMzsnIC8+CgkJPGNpcmNsZSBjeD0nNy44Mjg0JyBjeT0nMi4xNzE2JyByPScxJyBzdHlsZT0nb3BhY2l0eTowLjM7JyAvPgoJCTxjaXJjbGUgY3g9JzknIGN5PSc1JyByPScxJyBzdHlsZT0nb3BhY2l0eTowLjM7JyAvPgoJCTxjaXJjbGUgY3g9JzcuODI4NCcgY3k9JzcuODI4NCcgcj0nMScgc3R5bGU9J29wYWNpdHk6MC4zOycgLz4KCQk8Y2lyY2xlIGN4PSc1JyBjeT0nOScgcj0nMScgc3R5bGU9J29wYWNpdHk6MC4zOycgLz4KCQk8Y2lyY2xlIGN4PScyLjE3MTYnIGN5PSc3LjgyODQnIHI9JzEnIHN0eWxlPSdvcGFjaXR5OjAuMzsnIC8+CgkJPGNpcmNsZSBjeD0nMScgY3k9JzUnIHI9JzEnIHN0eWxlPSdvcGFjaXR5OjAuMzsnIC8+CgkJPGNpcmNsZSBjeD0nMi4xNzE2JyBjeT0nMi4xNzE2JyByPScxJyBzdHlsZT0nb3BhY2l0eTowLjM7JyAvPgoJPC9nPgo8L3N2Zz4K")}.monaco-tree-action.collapse-all{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTkgOUg0VjEwSDlWOVoiIGZpbGw9IiM0MjQyNDIiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik01IDNMNiAySDEzTDE0IDNWMTBMMTMgMTFIMTFWMTNMMTAgMTRIM0wyIDEzVjZMMyA1SDVWM1pNNiA1SDEwTDExIDZWMTBIMTNWM0g2VjVaTTEwIDZIM1YxM0gxMFY2WiIgZmlsbD0iIzQyNDI0MiIvPgo8L3N2Zz4K") 50% no-repeat}.vs-dark .monaco-tree-action.collapse-all{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTkgOUg0VjEwSDlWOVoiIGZpbGw9IiNDNUM1QzUiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik01IDNMNiAySDEzTDE0IDNWMTBMMTMgMTFIMTFWMTNMMTAgMTRIM0wyIDEzVjZMMyA1SDVWM1pNNiA1SDEwTDExIDZWMTBIMTNWM0g2VjVaTTEwIDZIM1YxM0gxMFY2WiIgZmlsbD0iI0M1QzVDNSIvPgo8L3N2Zz4K") 50% no-repeat}.hc-black .monaco-tree-action.collapse-all{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTkgOUg0VjEwSDlWOVoiIGZpbGw9IndoaXRlIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNNSAzTDYgMkgxM0wxNCAzVjEwTDEzIDExSDExVjEzTDEwIDE0SDNMMiAxM1Y2TDMgNUg1VjNaTTYgNUgxMEwxMSA2VjEwSDEzVjNINlY1Wk0xMCA2SDNWMTNIMTBWNloiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPgo=") 50% no-repeat}.monaco-progress-container{width:100%;height:5px;overflow:hidden}.monaco-progress-container .progress-bit{width:2%;height:5px;position:absolute;left:0;display:none}.monaco-progress-container.active .progress-bit{display:inherit}.monaco-progress-container.discrete .progress-bit{left:0;transition:width .1s linear}.monaco-progress-container.discrete.done .progress-bit{width:100%}.monaco-progress-container.infinite .progress-bit{animation-name:progress;animation-duration:4s;animation-iteration-count:infinite;animation-timing-function:linear;-ms-animation-name:progress;-ms-animation-duration:4s;-ms-animation-iteration-count:infinite;-ms-animation-timing-function:linear;-webkit-animation-name:progress;-webkit-animation-duration:4s;-webkit-animation-iteration-count:infinite;-webkit-animation-timing-function:linear;-moz-animation-name:progress;-moz-animation-duration:4s;-moz-animation-iteration-count:infinite;-moz-animation-timing-function:linear;will-change:transform}.monaco-editor-hover{cursor:default;position:absolute;overflow:hidden;z-index:50;-webkit-user-select:text;-ms-user-select:text;-moz-user-select:text;-o-user-select:text;user-select:text;box-sizing:initial;animation:fadein .1s linear;line-height:1.5em}.monaco-editor-hover.hidden{display:none}.monaco-editor-hover .hover-contents{padding:4px 8px}.monaco-editor-hover .markdown-hover>.hover-contents:not(.code-hover-contents){max-width:500px;word-wrap:break-word}.monaco-editor-hover p,.monaco-editor-hover ul{margin:8px 0}.monaco-editor-hover hr{margin:4px -10px -6px;height:1px}.monaco-editor-hover p:first-child,.monaco-editor-hover ul:first-child{margin-top:0}.monaco-editor-hover p:last-child,.monaco-editor-hover ul:last-child{margin-bottom:0}.monaco-editor-hover ul{padding-left:20px}.monaco-editor-hover li>p{margin-bottom:0}.monaco-editor-hover li>ul{margin-top:0}.monaco-editor-hover code{border-radius:3px;padding:0 .4em}.monaco-editor-hover .monaco-tokenized-source{white-space:pre-wrap;word-break:break-all}.monaco-editor-hover .hover-row.status-bar{font-size:12px;line-height:22px}.monaco-editor-hover .hover-row.status-bar .actions{display:-ms-flexbox;display:flex;padding:0 8px}.monaco-editor-hover .hover-row.status-bar .actions .action-container{margin-right:16px;cursor:pointer}.monaco-editor-hover .hover-row.status-bar .actions .action-container .action .icon{padding-right:4px}.colorpicker-widget{height:190px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.monaco-editor .colorpicker-hover:focus{outline:none}.colorpicker-header{display:-ms-flexbox;display:flex;height:24px;position:relative;background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAYAAACp8Z5+AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAZdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuMTZEaa/1AAAAHUlEQVQYV2PYvXu3JAi7uLiAMaYAjAGTQBPYLQkAa/0Zef3qRswAAAAASUVORK5CYII=");background-size:9px 9px;-ms-interpolation-mode:nearest-neighbor;image-rendering:pixelated}.colorpicker-header .picked-color{width:216px;line-height:24px;cursor:pointer;color:#fff;-ms-flex:1;flex:1;text-align:center}.colorpicker-header .picked-color.light{color:#000}.colorpicker-header .original-color{width:74px;z-index:inherit;cursor:pointer}.colorpicker-body{display:-ms-flexbox;display:flex;padding:8px;position:relative}.colorpicker-body .saturation-wrap{overflow:hidden;height:150px;position:relative;min-width:220px;-ms-flex:1;flex:1}.colorpicker-body .saturation-box{height:150px;position:absolute}.colorpicker-body .saturation-selection{width:9px;height:9px;margin:-5px 0 0 -5px;border:1px solid #fff;border-radius:100%;box-shadow:0 0 2px rgba(0,0,0,.8);position:absolute}.colorpicker-body .strip{width:25px;height:150px}.colorpicker-body .hue-strip{position:relative;margin-left:8px;cursor:grab;background:linear-gradient(180deg,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red)}.colorpicker-body .opacity-strip{position:relative;margin-left:8px;cursor:grab;background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAYAAACp8Z5+AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAZdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuMTZEaa/1AAAAHUlEQVQYV2PYvXu3JAi7uLiAMaYAjAGTQBPYLQkAa/0Zef3qRswAAAAASUVORK5CYII=");background-size:9px 9px;-ms-interpolation-mode:nearest-neighbor;image-rendering:pixelated}.colorpicker-body .strip.grabbing{cursor:grabbing}.colorpicker-body .slider{position:absolute;top:0;left:-2px;width:calc(100% + 4px);height:4px;box-sizing:border-box;border:1px solid hsla(0,0%,100%,.71);box-shadow:0 0 1px rgba(0,0,0,.85)}.colorpicker-body .strip .overlay{height:150px;pointer-events:none}.monaco-editor .tokens-inspect-widget{z-index:50;-webkit-user-select:text;-ms-user-select:text;-moz-user-select:text;-o-user-select:text;user-select:text;padding:10px}.tokens-inspect-separator{height:1px;border:0}.monaco-editor .tokens-inspect-widget .tm-token{font-family:monospace}.monaco-editor .tokens-inspect-widget .tm-token-length{font-weight:400;font-size:60%;float:right}.monaco-editor .tokens-inspect-widget .tm-metadata-table{width:100%}.monaco-editor .tokens-inspect-widget .tm-metadata-value{font-family:monospace;text-align:right}.monaco-editor .tokens-inspect-widget .tm-token-type{font-family:monospace}.monaco-editor .iPadShowKeyboard{width:58px;min-width:0;height:36px;min-height:0;margin:0;padding:0;position:absolute;resize:none;overflow:hidden;background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTMiIGhlaWdodD0iMzYiIHZpZXdCb3g9IjAgMCA1MyAzNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwKSI+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNNDguMDM2NCA0LjAxMDQySDQuMDA3NzlMNC4wMDc3OSAzMi4wMjg2SDQ4LjAzNjRWNC4wMTA0MlpNNC4wMDc3OSAwLjAwNzgxMjVDMS43OTcyMSAwLjAwNzgxMjUgMC4wMDUxODc5OSAxLjc5OTg0IDAuMDA1MTg3OTkgNC4wMTA0MlYzMi4wMjg2QzAuMDA1MTg3OTkgMzQuMjM5MiAxLjc5NzIxIDM2LjAzMTIgNC4wMDc3OSAzNi4wMzEySDQ4LjAzNjRDNTAuMjQ3IDM2LjAzMTIgNTIuMDM5IDM0LjIzOTIgNTIuMDM5IDMyLjAyODZWNC4wMTA0MkM1Mi4wMzkgMS43OTk4NCA1MC4yNDcgMC4wMDc4MTI1IDQ4LjAzNjQgMC4wMDc4MTI1SDQuMDA3NzlaTTguMDEwNDIgOC4wMTMwMkgxMi4wMTNWMTIuMDE1Nkg4LjAxMDQyVjguMDEzMDJaTTIwLjAxODIgOC4wMTMwMkgxNi4wMTU2VjEyLjAxNTZIMjAuMDE4MlY4LjAxMzAyWk0yNC4wMjA4IDguMDEzMDJIMjguMDIzNFYxMi4wMTU2SDI0LjAyMDhWOC4wMTMwMlpNMzYuMDI4NiA4LjAxMzAySDMyLjAyNlYxMi4wMTU2SDM2LjAyODZWOC4wMTMwMlpNNDAuMDMxMiA4LjAxMzAySDQ0LjAzMzlWMTIuMDE1Nkg0MC4wMzEyVjguMDEzMDJaTTE2LjAxNTYgMTYuMDE4Mkg4LjAxMDQyVjIwLjAyMDhIMTYuMDE1NlYxNi4wMTgyWk0yMC4wMTgyIDE2LjAxODJIMjQuMDIwOFYyMC4wMjA4SDIwLjAxODJWMTYuMDE4MlpNMzIuMDI2IDE2LjAxODJIMjguMDIzNFYyMC4wMjA4SDMyLjAyNlYxNi4wMTgyWk00NC4wMzM5IDE2LjAxODJWMjAuMDIwOEgzNi4wMjg2VjE2LjAxODJINDQuMDMzOVpNMTIuMDEzIDI0LjAyMzRIOC4wMTA0MlYyOC4wMjZIMTIuMDEzVjI0LjAyMzRaTTE2LjAxNTYgMjQuMDIzNEgzNi4wMjg2VjI4LjAyNkgxNi4wMTU2VjI0LjAyMzRaTTQ0LjAzMzkgMjQuMDIzNEg0MC4wMzEyVjI4LjAyNkg0NC4wMzM5VjI0LjAyMzRaIiBmaWxsPSIjNDI0MjQyIi8+CjwvZz4KPGRlZnM+CjxjbGlwUGF0aCBpZD0iY2xpcDAiPgo8cmVjdCB3aWR0aD0iNTMiIGhlaWdodD0iMzYiIGZpbGw9IndoaXRlIi8+CjwvY2xpcFBhdGg+CjwvZGVmcz4KPC9zdmc+Cg==") 50% no-repeat;border:4px solid #f6f6f6;border-radius:4px}.monaco-editor.vs-dark .iPadShowKeyboard{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTMiIGhlaWdodD0iMzYiIHZpZXdCb3g9IjAgMCA1MyAzNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwKSI+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNNDguMDM2NCA0LjAxMDQySDQuMDA3NzlMNC4wMDc3OSAzMi4wMjg2SDQ4LjAzNjRWNC4wMTA0MlpNNC4wMDc3OSAwLjAwNzgxMjVDMS43OTcyMSAwLjAwNzgxMjUgMC4wMDUxODc5OSAxLjc5OTg0IDAuMDA1MTg3OTkgNC4wMTA0MlYzMi4wMjg2QzAuMDA1MTg3OTkgMzQuMjM5MiAxLjc5NzIxIDM2LjAzMTIgNC4wMDc3OSAzNi4wMzEySDQ4LjAzNjRDNTAuMjQ3IDM2LjAzMTIgNTIuMDM5IDM0LjIzOTIgNTIuMDM5IDMyLjAyODZWNC4wMTA0MkM1Mi4wMzkgMS43OTk4NCA1MC4yNDcgMC4wMDc4MTI1IDQ4LjAzNjQgMC4wMDc4MTI1SDQuMDA3NzlaTTguMDEwNDIgOC4wMTMwMkgxMi4wMTNWMTIuMDE1Nkg4LjAxMDQyVjguMDEzMDJaTTIwLjAxODIgOC4wMTMwMkgxNi4wMTU2VjEyLjAxNTZIMjAuMDE4MlY4LjAxMzAyWk0yNC4wMjA4IDguMDEzMDJIMjguMDIzNFYxMi4wMTU2SDI0LjAyMDhWOC4wMTMwMlpNMzYuMDI4NiA4LjAxMzAySDMyLjAyNlYxMi4wMTU2SDM2LjAyODZWOC4wMTMwMlpNNDAuMDMxMiA4LjAxMzAySDQ0LjAzMzlWMTIuMDE1Nkg0MC4wMzEyVjguMDEzMDJaTTE2LjAxNTYgMTYuMDE4Mkg4LjAxMDQyVjIwLjAyMDhIMTYuMDE1NlYxNi4wMTgyWk0yMC4wMTgyIDE2LjAxODJIMjQuMDIwOFYyMC4wMjA4SDIwLjAxODJWMTYuMDE4MlpNMzIuMDI2IDE2LjAxODJIMjguMDIzNFYyMC4wMjA4SDMyLjAyNlYxNi4wMTgyWk00NC4wMzM5IDE2LjAxODJWMjAuMDIwOEgzNi4wMjg2VjE2LjAxODJINDQuMDMzOVpNMTIuMDEzIDI0LjAyMzRIOC4wMTA0MlYyOC4wMjZIMTIuMDEzVjI0LjAyMzRaTTE2LjAxNTYgMjQuMDIzNEgzNi4wMjg2VjI4LjAyNkgxNi4wMTU2VjI0LjAyMzRaTTQ0LjAzMzkgMjQuMDIzNEg0MC4wMzEyVjI4LjAyNkg0NC4wMzM5VjI0LjAyMzRaIiBmaWxsPSIjQzVDNUM1Ii8+CjwvZz4KPGRlZnM+CjxjbGlwUGF0aCBpZD0iY2xpcDAiPgo8cmVjdCB3aWR0aD0iNTMiIGhlaWdodD0iMzYiIGZpbGw9IndoaXRlIi8+CjwvY2xpcFBhdGg+CjwvZGVmcz4KPC9zdmc+Cg==") 50% no-repeat;border:4px solid #252526}.monaco-editor .detected-link,.monaco-editor .detected-link-active{text-decoration:underline;text-underline-position:under}.monaco-editor .detected-link-active{cursor:pointer}.monaco-editor .parameter-hints-widget{z-index:10;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;line-height:1.5em}.monaco-editor .parameter-hints-widget>.wrapper{max-width:440px;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column}.monaco-editor .parameter-hints-widget.multiple{min-height:3.3em;padding:0 0 0 1.9em}.monaco-editor .parameter-hints-widget.visible{transition:left .05s ease-in-out}.monaco-editor .parameter-hints-widget p,.monaco-editor .parameter-hints-widget ul{margin:8px 0}.monaco-editor .parameter-hints-widget .body,.monaco-editor .parameter-hints-widget .monaco-scrollable-element{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column}.monaco-editor .parameter-hints-widget .signature{padding:4px 5px}.monaco-editor .parameter-hints-widget .docs{padding:0 10px 0 5px;white-space:pre-wrap}.monaco-editor .parameter-hints-widget .docs.empty{display:none}.monaco-editor .parameter-hints-widget .docs .markdown-docs{white-space:normal}.monaco-editor .parameter-hints-widget .docs .code{white-space:pre-wrap}.monaco-editor .parameter-hints-widget .docs code{border-radius:3px;padding:0 .4em}.monaco-editor .parameter-hints-widget .buttons{position:absolute;display:none;bottom:0;left:0}.monaco-editor .parameter-hints-widget.multiple .buttons{display:block}.monaco-editor .parameter-hints-widget.multiple .button{position:absolute;left:2px;width:16px;height:16px;background-repeat:no-repeat;cursor:pointer}.monaco-editor .parameter-hints-widget .button.previous{bottom:24px;background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHBhdGggZmlsbD0iIzQyNDI0MiIgZD0iTTEwLjggOS41bC45LS45TDguMSA1IDQuMiA4LjZsLjkuOSAzLTIuNyAyLjcgMi43eiIvPjwvc3ZnPg==")}.monaco-editor .parameter-hints-widget .button.next{bottom:0;background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHBhdGggZmlsbD0iIzQyNDI0MiIgZD0iTTUuMSA1bC0uOS45IDMuNiAzLjYgMy45LTMuNi0xLS45LTMgMi43TDUuMSA1eiIvPjwvc3ZnPg==")}.monaco-editor .parameter-hints-widget .overloads{position:absolute;display:none;text-align:center;bottom:14px;left:0;width:22px;height:12px;line-height:12px;opacity:.5}.monaco-editor .parameter-hints-widget.multiple .overloads{display:block}.monaco-editor .parameter-hints-widget .signature .parameter.active{font-weight:700;text-decoration:underline}.monaco-editor .parameter-hints-widget .documentation-parameter>.parameter{font-weight:700;margin-right:.5em}.monaco-editor.hc-black .parameter-hints-widget .button.previous,.monaco-editor.vs-dark .parameter-hints-widget .button.previous{background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHBhdGggZmlsbD0iI0U4RThFOCIgZD0iTTEwLjggOS41bC45LS45TDguMSA1IDQuMiA4LjZsLjkuOSAzLTIuNyAyLjcgMi43eiIvPjwvc3ZnPg==")}.monaco-editor.hc-black .parameter-hints-widget .button.next,.monaco-editor.vs-dark .parameter-hints-widget .button.next{background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHBhdGggZmlsbD0iI0U4RThFOCIgZD0iTTUuMSA1bC0uOS45IDMuNiAzLjYgMy45LTMuNi0xLS45LTMgMi43TDUuMSA1eiIvPjwvc3ZnPg==")}.monaco-quick-open-widget{font-size:13px}.monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon,.vs-dark .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzAwIiBoZWlnaHQ9IjQwIiB2aWV3Qm94PSIwIDAgMzAwIDQwIiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTQgMjYuODU3NUw0LjQ4NTUgMjZMOS40ODU1IDIzSDEwLjUxNDVMMTUuNTE0NSAyNkwxNiAyNi44NTc1VjMyLjg1NzVMMTUuNTE0NSAzMy43MTVMMTAuNTE0NSAzNi43MTVIOS40ODU1TDQuNDg1NSAzMy43MTVMNCAzMi44NTc1VjI2Ljg1NzVaTTkuNSAzNS41NTc1TDUgMzIuODU3NVYyNy42OTk4TDkuNSAzMC4xNTQzVjM1LjU1NzVaTTEwLjUgMzUuNTU3NUwxNSAzMi44NTc1VjI3LjY5OThMMTAuNSAzMC4xNTQzVjM1LjU1NzVaTTEwIDIzLjg1NzVMNS4yNTkxMyAyNi43MDJMMTAgMjkuMjg3OUwxNC43NDA5IDI2LjcwMkwxMCAyMy44NTc1WiIgZmlsbD0iI0IxODBENyIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTQgNi44NTc0OUw0LjQ4NTUgNkw5LjQ4NTUgM0gxMC41MTQ1TDE1LjUxNDUgNkwxNiA2Ljg1NzQ5VjEyLjg1NzVMMTUuNTE0NSAxMy43MTVMMTAuNTE0NSAxNi43MTVIOS40ODU1TDQuNDg1NSAxMy43MTVMNCAxMi44NTc1VjYuODU3NDlaTTkuNSAxNS41NTc1TDUgMTIuODU3NVY3LjY5OTc1TDkuNSAxMC4xNTQzVjE1LjU1NzVaTTEwLjUgMTUuNTU3NUwxNSAxMi44NTc1VjcuNjk5NzVMMTAuNSAxMC4xNTQzVjE1LjU1NzVaTTEwIDMuODU3NDlMNS4yNTkxMyA2LjcwMjAxTDEwIDkuMjg3OTRMMTQuNzQwOSA2LjcwMjAxTDEwIDMuODU3NDlaIiBmaWxsPSIjNjUyRDkwIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMjMgMjguMzk0NEwyMy41NTI4IDI3LjVMMzAuNTUyOCAyNEgzMS40NDcyTDM2LjQ0NzIgMjYuNUwzNyAyNy4zOTQ0VjMxLjg5NDRMMzYuNDQ3MiAzMi43ODg5TDI5LjQ0NzIgMzYuMjg4OUgyOC41NTI4TDIzLjU1MjggMzMuNzg4OUwyMyAzMi44OTQ0VjI4LjM5NDRaTTI4LjUgMzUuMTQ0NEwyNCAzMi44OTQ0VjI5LjE3MDlMMjguNSAzMS4yMTY0VjM1LjE0NDRaTTI5LjUgMzUuMTQ0NEwzNiAzMS44OTQ0VjI4LjE3OTVMMjkuNSAzMS4yMTI5VjM1LjE0NDRaTTMxIDI0Ljg5NDRMMjQuMzM3MyAyOC4yMjU4TDI4Ljk5NzIgMzAuMzQ0TDM1LjY3MDYgMjcuMjI5N0wzMSAyNC44OTQ0WiIgZmlsbD0iIzc1QkVGRiIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTIzIDguMzk0NDNMMjMuNTUyOCA3LjVMMzAuNTUyOCA0SDMxLjQ0NzJMMzYuNDQ3MiA2LjVMMzcgNy4zOTQ0M1YxMS44OTQ0TDM2LjQ0NzIgMTIuNzg4OUwyOS40NDcyIDE2LjI4ODlIMjguNTUyOEwyMy41NTI4IDEzLjc4ODlMMjMgMTIuODk0NFY4LjM5NDQzWk0yOC41IDE1LjE0NDRMMjQgMTIuODk0NFY5LjE3MDk0TDI4LjUgMTEuMjE2NFYxNS4xNDQ0Wk0yOS41IDE1LjE0NDRMMzYgMTEuODk0NFY4LjE3OTU0TDI5LjUgMTEuMjEyOVYxNS4xNDQ0Wk0zMSA0Ljg5NDQzTDI0LjMzNzMgOC4yMjU3OUwyOC45OTcyIDEwLjM0NEwzNS42NzA2IDcuMjI5NzNMMzEgNC44OTQ0M1oiIGZpbGw9IiMwMDdBQ0MiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik00NS4zNTM2IDI4LjY0NjRMNDQuMDYwNyAyNy4zNTM1TDQ3LjM1MzYgMjQuMDYwN0w0OC42NDY1IDI1LjM1MzVMNDUuMzUzNiAyOC42NDY0Wk00NyAyM0w0MyAyN1YyNy43MDcxTDQ1IDI5LjcwNzFINDUuNzA3MUw0Ni44NTM2IDI4LjU2MDZWMzQuMzUzNUw0Ny4zNTM2IDM0Ljg1MzVINTIuMDA5N1YzNS4zNzQxTDUzLjM0MyAzNi43MDc0SDU0LjA1MDFMNTYuNzE2OCAzNC4wNDA3VjMzLjMzMzZMNTUuMzgzNSAzMi4wMDAzSDU0LjY3NjNMNTIuODIzMSAzMy44NTM1SDQ3Ljg1MzZWMjkuODkzNUg1Mi4wMDk3VjMwLjM3NEw1My4zNDMgMzEuNzA3M0g1NC4wNTAxTDU2LjcxNjggMjkuMDQwN1YyOC4zMzM2TDU1LjM4MzUgMjcuMDAwMkg1NC42NzYzTDUyLjg2MyAyOC44MTM2SDQ3Ljg1MzZWMjcuNTYwNkw0OS43MDcxIDI1LjcwNzFWMjVMNDcuNzA3MSAyM0g0N1pNNTMuMDcwMyAzMC4wMjA1TDUzLjY5NjYgMzAuNjQ2N0w1NS42NTYxIDI4LjY4NzFMNTUuMDI5OSAyOC4wNjA5TDUzLjA3MDMgMzAuMDIwNVpNNTMuMDcwMyAzNS4wMjA1TDUzLjY5NjYgMzUuNjQ2N0w1NS42NTYxIDMzLjY4NzJMNTUuMDI5OSAzMy4wNjFMNTMuMDcwMyAzNS4wMjA1WiIgZmlsbD0iI0VFOUQyOCIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTQ1LjM1MzYgOC42NDY0Mkw0NC4wNjA3IDcuMzUzNTNMNDcuMzUzNiA0LjA2MDY1TDQ4LjY0NjUgNS4zNTM1NEw0NS4zNTM2IDguNjQ2NDJaTTQ3IDNMNDMgNi45OTk5OFY3LjcwNzA4TDQ1IDkuNzA3MDdINDUuNzA3MUw0Ni44NTM2IDguNTYwNjNWMTQuMzUzNUw0Ny4zNTM2IDE0Ljg1MzVINTIuMDA5N1YxNS4zNzQxTDUzLjM0MyAxNi43MDc0SDU0LjA1MDFMNTYuNzE2OCAxNC4wNDA3VjEzLjMzMzZMNTUuMzgzNSAxMi4wMDAzSDU0LjY3NjNMNTIuODIzMSAxMy44NTM1SDQ3Ljg1MzZWOS44OTM1NUg1Mi4wMDk3VjEwLjM3NEw1My4zNDMgMTEuNzA3M0g1NC4wNTAxTDU2LjcxNjggOS4wNDA2OFY4LjMzMzU3TDU1LjM4MzUgNy4wMDAyNEg1NC42NzYzTDUyLjg2MyA4LjgxMzU2SDQ3Ljg1MzZWNy41NjA2NEw0OS43MDcxIDUuNzA3MDlWNC45OTk5OUw0Ny43MDcxIDNINDdaTTUzLjA3MDMgMTAuMDIwNUw1My42OTY2IDEwLjY0NjdMNTUuNjU2MSA4LjY4NzEzTDU1LjAyOTkgOC4wNjA5TDUzLjA3MDMgMTAuMDIwNVpNNTMuMDcwMyAxNS4wMjA1TDUzLjY5NjYgMTUuNjQ2N0w1NS42NTYxIDEzLjY4NzJMNTUuMDI5OSAxMy4wNjFMNTMuMDcwMyAxNS4wMjA1WiIgZmlsbD0iI0Q2N0UwMCIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTg4IDI0Ljk4MzZWMjQuOTcxOFYyNEg4Ny45MTA4Qzg3LjU5NzQgMjQgODcuMjk0MSAyNC4wNjE2IDg3LjAwMTMgMjQuMTg0N0M4Ni43MDgyIDI0LjMwOCA4Ni40NDk0IDI0LjQ4NDcgODYuMjI1OCAyNC43MTVDODYuMDAzMSAyNC45NDQyIDg1LjgzNzkgMjUuMTk1IDg1LjczMjggMjUuNDY3N0w4NS43MzIzIDI1LjQ2OUM4NS42MzM4IDI1LjczNTIgODUuNTY4MSAyNi4wMTIgODUuNTM1MyAyNi4yOTkyTDg1LjUzNTIgMjYuMzAwNUM4NS41MDY4IDI2LjU4MDUgODUuNDk4NyAyNi44Njg0IDg1LjUxMDggMjcuMTY0M0M4NS41MjI3IDI3LjQ1MzggODUuNTI4NyAyNy43NDMzIDg1LjUyODcgMjguMDMyOEM4NS41Mjg3IDI4LjIzNTYgODUuNDg5NyAyOC40MjU5IDg1LjQxMiAyOC42MDUxTDg1LjQxMTYgMjguNjA2Qzg1LjMzNjkgMjguNzgzIDg1LjIzNDIgMjguOTM4NyA4NS4xMDMyIDI5LjA3MzZDODQuOTc2NCAyOS4yMDQxIDg0LjgyNDcgMjkuMzEwNiA4NC42NDY3IDI5LjM5MjVDODQuNDcwNiAyOS40Njk1IDg0LjI4NSAyOS41MDgyIDg0LjA4OTIgMjkuNTA4Mkg4NFYyOS42VjMwLjRWMzAuNDkxOEg4NC4wODkyQzg0LjI4NDcgMzAuNDkxOCA4NC40NyAzMC41MzI0IDg0LjY0NiAzMC42MTMzTDg0LjY0NzQgMzAuNjE0Qzg0LjgyNDYgMzAuNjkxNiA4NC45NzU4IDMwLjc5NzYgODUuMTAyMiAzMC45MzE2TDg1LjEwNDEgMzAuOTMzNUM4NS4yMzQzIDMxLjA2MzcgODUuMzM2NiAzMS4yMTg3IDg1LjQxMTMgMzEuMzk5NEw4NS40MTIgMzEuNDAxMUM4NS40ODk5IDMxLjU4MDUgODUuNTI4NyAzMS43Njg4IDg1LjUyODcgMzEuOTY3MkM4NS41Mjg3IDMyLjI1NjcgODUuNTIyNyAzMi41NDYyIDg1LjUxMDggMzIuODM1N0M4NS40OTg3IDMzLjEzMTYgODUuNTA2OCAzMy40MjE1IDg1LjUzNTIgMzMuNzA1NUw4NS41MzU0IDMzLjcwNzJDODUuNTY4MiAzMy45OTAzIDg1LjYzMzkgMzQuMjY1IDg1LjczMjMgMzQuNTMxTDg1LjczMjggMzQuNTMyM0M4NS44Mzc5IDM0LjgwNSA4Ni4wMDMxIDM1LjA1NTggODYuMjI1OCAzNS4yODVDODYuNDQ5NCAzNS41MTUzIDg2LjcwODIgMzUuNjkyIDg3LjAwMTMgMzUuODE1M0M4Ny4yOTQxIDM1LjkzODQgODcuNTk3NCAzNiA4Ny45MTA4IDM2SDg4VjM1LjJWMzUuMDE2NEg4Ny45MTA4Qzg3LjcxMDkgMzUuMDE2NCA4Ny41MjM1IDM0Ljk3NzcgODcuMzQ3NiAzNC45MDA4Qzg3LjE3NCAzNC44MTkxIDg3LjAyMTkgMzQuNzEyNiA4Ni44OTA5IDM0LjU4MThDODYuNzYzOSAzNC40NDY5IDg2LjY2MSAzNC4yOTExIDg2LjU4MjIgMzQuMTEzN0M4Ni41MDg0IDMzLjkzNDYgODYuNDcxMyAzMy43NDQgODYuNDcxMyAzMy41NDFDODYuNDcxMyAzMy4zMTI3IDg2LjQ3NTMgMzMuMDg4NSA4Ni40ODMyIDMyLjg2ODZDODYuNDkxMiAzMi42NDExIDg2LjQ5MTMgMzIuNDE5NSA4Ni40ODMyIDMyLjIwMzlDODYuNDc5MSAzMS45ODI1IDg2LjQ2MDggMzEuNzY4OCA4Ni40MjgyIDMxLjU2MzFDODYuMzk1MSAzMS4zNTAyIDg2LjMzOTIgMzEuMTQ3NiA4Ni4yNjA0IDMwLjk1NTRDODYuMTgwOSAzMC43NjE2IDg2LjA3MjYgMzAuNTc3NSA4NS45MzYyIDMwLjQwM0M4NS44MjM1IDMwLjI1ODggODUuNjg1NCAzMC4xMjQ2IDg1LjUyMjggMzBDODUuNjg1NCAyOS44NzU0IDg1LjgyMzUgMjkuNzQxMiA4NS45MzYyIDI5LjU5N0M4Ni4wNzI2IDI5LjQyMjUgODYuMTgwOSAyOS4yMzg0IDg2LjI2MDQgMjkuMDQ0NkM4Ni4zMzkxIDI4Ljg1MjYgODYuMzk1MSAyOC42NTE3IDg2LjQyODMgMjguNDQyOEM4Ni40NjA4IDI4LjIzMzMgODYuNDc5MSAyOC4wMTk3IDg2LjQ4MzIgMjcuODAyMkM4Ni40OTEzIDI3LjU4MjYgODYuNDkxMyAyNy4zNjExIDg2LjQ4MzIgMjcuMTM3NUM4Ni40NzUzIDI2LjkxMzQgODYuNDcxMyAyNi42ODcyIDg2LjQ3MTMgMjYuNDU5Qzg2LjQ3MTMgMjYuMjYwMiA4Ni41MDgzIDI2LjA3MTUgODYuNTgyNCAyNS44OTIxQzg2LjY2MTQgMjUuNzEwMyA4Ni43NjQyIDI1LjU1NDggODYuODkwOSAyNS40MjQ0Qzg3LjAyMTkgMjUuMjg5NCA4Ny4xNzQ2IDI1LjE4MjcgODcuMzQ4IDI1LjEwNTFDODcuNTIzOCAyNS4wMjQzIDg3LjcxMTEgMjQuOTgzNiA4Ny45MTA4IDI0Ljk4MzZIODhaTTkyIDM1LjAxNjRWMzUuMDI4MlYzNkg5Mi4wODkyQzkyLjQwMjYgMzYgOTIuNzA1OSAzNS45Mzg0IDkyLjk5ODcgMzUuODE1M0M5My4yOTE4IDM1LjY5MiA5My41NTA2IDM1LjUxNTMgOTMuNzc0MiAzNS4yODVDOTMuOTk2OSAzNS4wNTU4IDk0LjE2MjEgMzQuODA1IDk0LjI2NzIgMzQuNTMyM0w5NC4yNjc3IDM0LjUzMUM5NC4zNjYyIDM0LjI2NDggOTQuNDMxOSAzMy45ODggOTQuNDY0NyAzMy43MDA4TDk0LjQ2NDggMzMuNjk5NUM5NC40OTMyIDMzLjQxOTUgOTQuNTAxMyAzMy4xMzE2IDk0LjQ4OTIgMzIuODM1N0M5NC40NzczIDMyLjU0NjIgOTQuNDcxMyAzMi4yNTY3IDk0LjQ3MTMgMzEuOTY3MkM5NC40NzEzIDMxLjc2NDQgOTQuNTEwMyAzMS41NzQxIDk0LjU4OCAzMS4zOTQ5TDk0LjU4ODQgMzEuMzk0Qzk0LjY2MzEgMzEuMjE3IDk0Ljc2NTggMzEuMDYxMyA5NC44OTY4IDMwLjkyNjRDOTUuMDIzNiAzMC43OTU5IDk1LjE3NTMgMzAuNjg5NCA5NS4zNTMzIDMwLjYwNzVDOTUuNTI5NCAzMC41MzA1IDk1LjcxNSAzMC40OTE4IDk1LjkxMDggMzAuNDkxOEg5NlYzMC40VjI5LjZWMjkuNTA4Mkg5NS45MTA4Qzk1LjcxNTMgMjkuNTA4MiA5NS41MyAyOS40Njc2IDk1LjM1NCAyOS4zODY3TDk1LjM1MjYgMjkuMzg2Qzk1LjE3NTQgMjkuMzA4NCA5NS4wMjQyIDI5LjIwMjQgOTQuODk3OCAyOS4wNjg0TDk0Ljg5NTkgMjkuMDY2NUM5NC43NjU3IDI4LjkzNjMgOTQuNjYzNCAyOC43ODEzIDk0LjU4ODcgMjguNjAwNkw5NC41ODggMjguNTk4OUM5NC41MTAxIDI4LjQxOTUgOTQuNDcxMyAyOC4yMzEyIDk0LjQ3MTMgMjguMDMyOEM5NC40NzEzIDI3Ljc0MzMgOTQuNDc3MyAyNy40NTM4IDk0LjQ4OTIgMjcuMTY0M0M5NC41MDEzIDI2Ljg2ODQgOTQuNDkzMiAyNi41Nzg1IDk0LjQ2NDggMjYuMjk0NUw5NC40NjQ2IDI2LjI5MjhDOTQuNDMxOCAyNi4wMDk3IDk0LjM2NjEgMjUuNzM1IDk0LjI2NzcgMjUuNDY5TDk0LjI2NzIgMjUuNDY3N0M5NC4xNjIxIDI1LjE5NSA5My45OTY5IDI0Ljk0NDIgOTMuNzc0MiAyNC43MTVDOTMuNTUwNiAyNC40ODQ3IDkzLjI5MTggMjQuMzA4IDkyLjk5ODcgMjQuMTg0N0M5Mi43MDU5IDI0LjA2MTYgOTIuNDAyNiAyNCA5Mi4wODkyIDI0SDkyVjI0LjhWMjQuOTgzNkg5Mi4wODkyQzkyLjI4OTEgMjQuOTgzNiA5Mi40NzY1IDI1LjAyMjMgOTIuNjUyNCAyNS4wOTkyQzkyLjgyNiAyNS4xODA5IDkyLjk3ODEgMjUuMjg3NCA5My4xMDkxIDI1LjQxODJDOTMuMjM2MSAyNS41NTMxIDkzLjMzOSAyNS43MDg5IDkzLjQxNzggMjUuODg2M0M5My40OTE2IDI2LjA2NTQgOTMuNTI4NyAyNi4yNTYgOTMuNTI4NyAyNi40NTlDOTMuNTI4NyAyNi42ODczIDkzLjUyNDcgMjYuOTExNSA5My41MTY4IDI3LjEzMTRDOTMuNTA4OCAyNy4zNTg5IDkzLjUwODcgMjcuNTgwNSA5My41MTY4IDI3Ljc5NjFDOTMuNTIwOSAyOC4wMTc1IDkzLjUzOTIgMjguMjMxMiA5My41NzE4IDI4LjQzNjlDOTMuNjA0OSAyOC42NDk4IDkzLjY2MDggMjguODUyNCA5My43Mzk2IDI5LjA0NDZDOTMuODE5MSAyOS4yMzg0IDkzLjkyNzQgMjkuNDIyNSA5NC4wNjM4IDI5LjU5N0M5NC4xNzY1IDI5Ljc0MTIgOTQuMzE0NiAyOS44NzU0IDk0LjQ3NzIgMzBDOTQuMzE0NiAzMC4xMjQ2IDk0LjE3NjUgMzAuMjU4OCA5NC4wNjM4IDMwLjQwM0M5My45Mjc0IDMwLjU3NzUgOTMuODE5MSAzMC43NjE2IDkzLjczOTYgMzAuOTU1NEM5My42NjA5IDMxLjE0NzQgOTMuNjA0OSAzMS4zNDgzIDkzLjU3MTcgMzEuNTU3MkM5My41MzkyIDMxLjc2NjcgOTMuNTIwOSAzMS45ODAzIDkzLjUxNjggMzIuMTk3OEM5My41MDg3IDMyLjQxNzQgOTMuNTA4NyAzMi42Mzg5IDkzLjUxNjggMzIuODYyNUM5My41MjQ3IDMzLjA4NjYgOTMuNTI4NyAzMy4zMTI4IDkzLjUyODcgMzMuNTQxQzkzLjUyODcgMzMuNzM5OCA5My40OTE3IDMzLjkyODUgOTMuNDE3NiAzNC4xMDc5QzkzLjMzODYgMzQuMjg5NyA5My4yMzU4IDM0LjQ0NTIgOTMuMTA5MSAzNC41NzU2QzkyLjk3ODEgMzQuNzEwNiA5Mi44MjU0IDM0LjgxNzMgOTIuNjUyIDM0Ljg5NDlDOTIuNDc2MiAzNC45NzU3IDkyLjI4ODkgMzUuMDE2NCA5Mi4wODkyIDM1LjAxNjRIOTJaIiBmaWxsPSIjQzVDNUM1Ii8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNODggNC45ODM2MVY0Ljk3MTg0VjRIODcuOTEwOEM4Ny41OTc0IDQgODcuMjk0MSA0LjA2MTYxIDg3LjAwMTMgNC4xODQ3M0M4Ni43MDgyIDQuMzA3OTggODYuNDQ5NCA0LjQ4NDc0IDg2LjIyNTggNC43MTQ5OEM4Ni4wMDMxIDQuOTQ0MjIgODUuODM3OSA1LjE5NDk4IDg1LjczMjggNS40Njc2Nkw4NS43MzIzIDUuNDY4OThDODUuNjMzOCA1LjczNTIgODUuNTY4MSA2LjAxMjAxIDg1LjUzNTMgNi4yOTkxN0w4NS41MzUyIDYuMzAwNTNDODUuNTA2OCA2LjU4MDUgODUuNDk4NyA2Ljg2ODQ0IDg1LjUxMDggNy4xNjQyOEM4NS41MjI3IDcuNDUzNzkgODUuNTI4NyA3Ljc0MzI5IDg1LjUyODcgOC4wMzI3OUM4NS41Mjg3IDguMjM1NTYgODUuNDg5NyA4LjQyNTk0IDg1LjQxMiA4LjYwNTA3TDg1LjQxMTYgOC42MDYwMUM4NS4zMzY5IDguNzgyOTYgODUuMjM0MiA4LjkzODY2IDg1LjEwMzIgOS4wNzM1OUM4NC45NzY0IDkuMjA0MDUgODQuODI0NyA5LjMxMDU1IDg0LjY0NjcgOS4zOTI1Qzg0LjQ3MDYgOS40Njk1NCA4NC4yODUgOS41MDgyIDg0LjA4OTIgOS41MDgySDg0VjkuNlYxMC40VjEwLjQ5MThIODQuMDg5MkM4NC4yODQ3IDEwLjQ5MTggODQuNDcgMTAuNTMyNCA4NC42NDYgMTAuNjEzM0w4NC42NDc0IDEwLjYxNEM4NC44MjQ2IDEwLjY5MTYgODQuOTc1OCAxMC43OTc2IDg1LjEwMjIgMTAuOTMxNkw4NS4xMDQxIDEwLjkzMzVDODUuMjM0MyAxMS4wNjM3IDg1LjMzNjYgMTEuMjE4NyA4NS40MTEzIDExLjM5OTRMODUuNDEyIDExLjQwMTFDODUuNDg5OSAxMS41ODA1IDg1LjUyODcgMTEuNzY4OCA4NS41Mjg3IDExLjk2NzJDODUuNTI4NyAxMi4yNTY3IDg1LjUyMjcgMTIuNTQ2MiA4NS41MTA4IDEyLjgzNTdDODUuNDk4NyAxMy4xMzE2IDg1LjUwNjggMTMuNDIxNSA4NS41MzUyIDEzLjcwNTVMODUuNTM1NCAxMy43MDcyQzg1LjU2ODIgMTMuOTkwMyA4NS42MzM5IDE0LjI2NSA4NS43MzIzIDE0LjUzMUw4NS43MzI4IDE0LjUzMjNDODUuODM3OSAxNC44MDUgODYuMDAzMSAxNS4wNTU4IDg2LjIyNTggMTUuMjg1Qzg2LjQ0OTQgMTUuNTE1MyA4Ni43MDgyIDE1LjY5MiA4Ny4wMDEzIDE1LjgxNTNDODcuMjk0MSAxNS45Mzg0IDg3LjU5NzQgMTYgODcuOTEwOCAxNkg4OFYxNS4yVjE1LjAxNjRIODcuOTEwOEM4Ny43MTA5IDE1LjAxNjQgODcuNTIzNSAxNC45Nzc3IDg3LjM0NzYgMTQuOTAwOEM4Ny4xNzQgMTQuODE5MSA4Ny4wMjE5IDE0LjcxMjYgODYuODkwOSAxNC41ODE4Qzg2Ljc2MzkgMTQuNDQ2OSA4Ni42NjEgMTQuMjkxMSA4Ni41ODIyIDE0LjExMzdDODYuNTA4NCAxMy45MzQ2IDg2LjQ3MTMgMTMuNzQ0IDg2LjQ3MTMgMTMuNTQxQzg2LjQ3MTMgMTMuMzEyNyA4Ni40NzUzIDEzLjA4ODUgODYuNDgzMiAxMi44Njg2Qzg2LjQ5MTIgMTIuNjQxMSA4Ni40OTEzIDEyLjQxOTUgODYuNDgzMiAxMi4yMDM5Qzg2LjQ3OTEgMTEuOTgyNSA4Ni40NjA4IDExLjc2ODggODYuNDI4MiAxMS41NjMxQzg2LjM5NTEgMTEuMzUwMiA4Ni4zMzkyIDExLjE0NzYgODYuMjYwNCAxMC45NTU0Qzg2LjE4MDkgMTAuNzYxNiA4Ni4wNzI2IDEwLjU3NzUgODUuOTM2MiAxMC40MDNDODUuODIzNSAxMC4yNTg4IDg1LjY4NTQgMTAuMTI0NiA4NS41MjI4IDEwQzg1LjY4NTQgOS44NzUzOCA4NS44MjM1IDkuNzQxMTkgODUuOTM2MiA5LjU5NzAyQzg2LjA3MjYgOS40MjI1NCA4Ni4xODA5IDkuMjM4NDMgODYuMjYwNCA5LjA0NDY0Qzg2LjMzOTEgOC44NTI2MyA4Ni4zOTUxIDguNjUxNzUgODYuNDI4MyA4LjQ0Mjg1Qzg2LjQ2MDggOC4yMzMzIDg2LjQ3OTEgOC4wMTk3MyA4Ni40ODMyIDcuODAyMTlDODYuNDkxMyA3LjU4MjYyIDg2LjQ5MTMgNy4zNjEwNSA4Ni40ODMyIDcuMTM3NDlDODYuNDc1MyA2LjkxMzQgODYuNDcxMyA2LjY4NzI1IDg2LjQ3MTMgNi40NTkwMkM4Ni40NzEzIDYuMjYwMTkgODYuNTA4MyA2LjA3MTUyIDg2LjU4MjQgNS44OTIwNUM4Ni42NjE0IDUuNzEwMzQgODYuNzY0MiA1LjU1NDc1IDg2Ljg5MDkgNS40MjQzN0M4Ny4wMjE5IDUuMjg5NDIgODcuMTc0NiA1LjE4Mjc1IDg3LjM0OCA1LjEwNTEzQzg3LjUyMzggNS4wMjQyNyA4Ny43MTExIDQuOTgzNjEgODcuOTEwOCA0Ljk4MzYxSDg4Wk05MiAxNS4wMTY0VjE1LjAyODJWMTZIOTIuMDg5MkM5Mi40MDI2IDE2IDkyLjcwNTkgMTUuOTM4NCA5Mi45OTg3IDE1LjgxNTNDOTMuMjkxOCAxNS42OTIgOTMuNTUwNiAxNS41MTUzIDkzLjc3NDIgMTUuMjg1QzkzLjk5NjkgMTUuMDU1OCA5NC4xNjIxIDE0LjgwNSA5NC4yNjcyIDE0LjUzMjNMOTQuMjY3NyAxNC41MzFDOTQuMzY2MiAxNC4yNjQ4IDk0LjQzMTkgMTMuOTg4IDk0LjQ2NDcgMTMuNzAwOEw5NC40NjQ4IDEzLjY5OTVDOTQuNDkzMiAxMy40MTk1IDk0LjUwMTMgMTMuMTMxNiA5NC40ODkyIDEyLjgzNTdDOTQuNDc3MyAxMi41NDYyIDk0LjQ3MTMgMTIuMjU2NyA5NC40NzEzIDExLjk2NzJDOTQuNDcxMyAxMS43NjQ0IDk0LjUxMDMgMTEuNTc0MSA5NC41ODggMTEuMzk0OUw5NC41ODg0IDExLjM5NEM5NC42NjMxIDExLjIxNyA5NC43NjU4IDExLjA2MTMgOTQuODk2OCAxMC45MjY0Qzk1LjAyMzYgMTAuNzk1OSA5NS4xNzUzIDEwLjY4OTQgOTUuMzUzMyAxMC42MDc1Qzk1LjUyOTQgMTAuNTMwNSA5NS43MTUgMTAuNDkxOCA5NS45MTA4IDEwLjQ5MThIOTZWMTAuNFY5LjZWOS41MDgySDk1LjkxMDhDOTUuNzE1MyA5LjUwODIgOTUuNTMgOS40Njc2MiA5NS4zNTQgOS4zODY2Nkw5NS4zNTI2IDkuMzg2MDRDOTUuMTc1NCA5LjMwODQ0IDk1LjAyNDIgOS4yMDIzOCA5NC44OTc4IDkuMDY4MzlMOTQuODk1OSA5LjA2NjQ4Qzk0Ljc2NTcgOC45MzYzIDk0LjY2MzQgOC43ODEyOSA5NC41ODg3IDguNjAwNThMOTQuNTg4IDguNTk4OTJDOTQuNTEwMSA4LjQxOTUzIDk0LjQ3MTMgOC4yMzExNyA5NC40NzEzIDguMDMyNzlDOTQuNDcxMyA3Ljc0MzI5IDk0LjQ3NzMgNy40NTM3OSA5NC40ODkyIDcuMTY0MjhDOTQuNTAxMyA2Ljg2ODQyIDk0LjQ5MzIgNi41Nzg0OCA5NC40NjQ4IDYuMjk0NTRMOTQuNDY0NiA2LjI5Mjg1Qzk0LjQzMTggNi4wMDk3MSA5NC4zNjYxIDUuNzM1MDIgOTQuMjY3NyA1LjQ2ODk3TDk0LjI2NzIgNS40Njc2NkM5NC4xNjIxIDUuMTk0OTkgOTMuOTk2OSA0Ljk0NDIyIDkzLjc3NDIgNC43MTQ5OEM5My41NTA2IDQuNDg0NzQgOTMuMjkxOCA0LjMwNzk4IDkyLjk5ODcgNC4xODQ3M0M5Mi43MDU5IDQuMDYxNjEgOTIuNDAyNiA0IDkyLjA4OTIgNEg5MlY0LjhWNC45ODM2MUg5Mi4wODkyQzkyLjI4OTEgNC45ODM2MSA5Mi40NzY1IDUuMDIyMyA5Mi42NTI0IDUuMDk5MTdDOTIuODI2IDUuMTgwOTIgOTIuOTc4MSA1LjI4NzM2IDkzLjEwOTEgNS40MTgyM0M5My4yMzYxIDUuNTUzMDUgOTMuMzM5IDUuNzA4ODkgOTMuNDE3OCA1Ljg4NjI4QzkzLjQ5MTYgNi4wNjU0IDkzLjUyODcgNi4yNTU5NiA5My41Mjg3IDYuNDU5MDJDOTMuNTI4NyA2LjY4NzI3IDkzLjUyNDcgNi45MTE0NSA5My41MTY4IDcuMTMxNDJDOTMuNTA4OCA3LjM1ODk0IDkzLjUwODcgNy41ODA0OSA5My41MTY4IDcuNzk2MDVDOTMuNTIwOSA4LjAxNzU0IDkzLjUzOTIgOC4yMzExNyA5My41NzE4IDguNDM2ODhDOTMuNjA0OSA4LjY0OTc2IDkzLjY2MDggOC44NTI0MyA5My43Mzk2IDkuMDQ0NjRDOTMuODE5MSA5LjIzODQzIDkzLjkyNzQgOS40MjI1NCA5NC4wNjM4IDkuNTk3MDJDOTQuMTc2NSA5Ljc0MTE5IDk0LjMxNDYgOS44NzUzOCA5NC40NzcyIDEwQzk0LjMxNDYgMTAuMTI0NiA5NC4xNzY1IDEwLjI1ODggOTQuMDYzOCAxMC40MDNDOTMuOTI3NCAxMC41Nzc1IDkzLjgxOTEgMTAuNzYxNiA5My43Mzk2IDEwLjk1NTRDOTMuNjYwOSAxMS4xNDc0IDkzLjYwNDkgMTEuMzQ4MyA5My41NzE3IDExLjU1NzJDOTMuNTM5MiAxMS43NjY3IDkzLjUyMDkgMTEuOTgwMyA5My41MTY4IDEyLjE5NzhDOTMuNTA4NyAxMi40MTc0IDkzLjUwODcgMTIuNjM4OSA5My41MTY4IDEyLjg2MjVDOTMuNTI0NyAxMy4wODY2IDkzLjUyODcgMTMuMzEyOCA5My41Mjg3IDEzLjU0MUM5My41Mjg3IDEzLjczOTggOTMuNDkxNyAxMy45Mjg1IDkzLjQxNzYgMTQuMTA3OUM5My4zMzg2IDE0LjI4OTcgOTMuMjM1OCAxNC40NDUyIDkzLjEwOTEgMTQuNTc1NkM5Mi45NzgxIDE0LjcxMDYgOTIuODI1NCAxNC44MTczIDkyLjY1MiAxNC44OTQ5QzkyLjQ3NjIgMTQuOTc1NyA5Mi4yODg5IDE1LjAxNjQgOTIuMDg5MiAxNS4wMTY0SDkyWiIgZmlsbD0iIzQyNDI0MiIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTczLjUgMjdDNzIuMTE5MyAyNyA3MSAyOC4xMTkzIDcxIDI5LjVDNzEgMzAuODgwNyA3Mi4xMTkzIDMyIDczLjUgMzJDNzQuODgwNyAzMiA3NiAzMC44ODA3IDc2IDI5LjVDNzYgMjguMTE5MyA3NC44ODA3IDI3IDczLjUgMjdaTTcwLjAzNTQgMzBDNzAuMjc4MSAzMS42OTYxIDcxLjczNjggMzMgNzMuNSAzM0M3NS40MzMgMzMgNzcgMzEuNDMzIDc3IDI5LjVDNzcgMjcuNTY3IDc1LjQzMyAyNiA3My41IDI2QzcxLjczNjggMjYgNzAuMjc4MSAyNy4zMDM5IDcwLjAzNTQgMjlINjYuOTM3QzY2LjcxNSAyOC4xMzc0IDY1LjkzMTkgMjcuNSA2NSAyNy41QzYzLjg5NTQgMjcuNSA2MyAyOC4zOTU0IDYzIDI5LjVDNjMgMzAuNjA0NiA2My44OTU0IDMxLjUgNjUgMzEuNUM2NS45MzE5IDMxLjUgNjYuNzE1IDMwLjg2MjYgNjYuOTM3IDMwSDcwLjAzNTRaIiBmaWxsPSIjNzVCRUZGIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNNzMuNSA3QzcyLjExOTMgNyA3MSA4LjExOTI5IDcxIDkuNUM3MSAxMC44ODA3IDcyLjExOTMgMTIgNzMuNSAxMkM3NC44ODA3IDEyIDc2IDEwLjg4MDcgNzYgOS41Qzc2IDguMTE5MjkgNzQuODgwNyA3IDczLjUgN1pNNzAuMDM1NCAxMEM3MC4yNzgxIDExLjY5NjEgNzEuNzM2OCAxMyA3My41IDEzQzc1LjQzMyAxMyA3NyAxMS40MzMgNzcgOS41Qzc3IDcuNTY3IDc1LjQzMyA2IDczLjUgNkM3MS43MzY4IDYgNzAuMjc4MSA3LjMwMzg1IDcwLjAzNTQgOUg2Ni45MzdDNjYuNzE1IDguMTM3MzkgNjUuOTMxOSA3LjUgNjUgNy41QzYzLjg5NTQgNy41IDYzIDguMzk1NDMgNjMgOS41QzYzIDEwLjYwNDYgNjMuODk1NCAxMS41IDY1IDExLjVDNjUuOTMxOSAxMS41IDY2LjcxNSAxMC44NjI2IDY2LjkzNyAxMEg3MC4wMzU0WiIgZmlsbD0iIzAwN0FDQyIvPgo8cGF0aCBkPSJNMTA0LjgwNyAzNi45NzU0QzEwNC41NzEgMzYuOTcyMSAxMDQuMzM4IDM2LjkyMTEgMTA0LjEyMiAzNi44MjU0QzEwMy45MDcgMzYuNzI5NyAxMDMuNzEyIDM2LjU5MTMgMTAzLjU1MiAzNi40MTg2QzEwMy4yMzkgMzYuMTMzNCAxMDMuMDQ0IDM1Ljc0MDggMTAzLjAwOCAzNS4zMTg5QzEwMi45NjYgMzQuODgyOCAxMDMuMDkzIDM0LjQ0NzMgMTAzLjM2MSAzNC4xMDEzQzEwNC41NjggMzIuODI4OSAxMDYuOTQ3IDMwLjQ0OTQgMTA4LjY3OCAyOC43NTQ4QzEwOC4zMSAyNy43NTg5IDEwOC4zMjcgMjYuNjYxMyAxMDguNzI2IDI1LjY3NzRDMTA5LjA1NSAyNC44NTg4IDEwOS42MzkgMjQuMTY4MSAxMTAuMzkxIDIzLjcwODFDMTEwLjk4MiAyMy4zMTcxIDExMS42NiAyMy4wNzk0IDExMi4zNjYgMjMuMDE2N0MxMTMuMDcxIDIyLjk1NCAxMTMuNzgxIDIzLjA2ODIgMTE0LjQzMSAyMy4zNDg5TDExNS4wNDggMjMuNjE2MkwxMTIuMTgyIDI2LjU2NzRMMTEzLjQzNyAyNy44MjU4TDExNi4zODEgMjQuOTQ4OUwxMTYuNjQ4IDI1LjU2NzlDMTE2Ljg3NCAyNi4wODk4IDExNi45OTMgMjYuNjUxMiAxMTcgMjcuMjE5NkMxMTcuMDA2IDI3Ljc4OCAxMTYuOSAyOC4zNTIxIDExNi42ODcgMjguODc5MUMxMTYuNDc2IDI5LjQwMDMgMTE2LjE2MiAyOS44NzM3IDExNS43NjUgMzAuMjcxMkMxMTUuNTM5IDMwLjQ5MTcgMTE1LjI5IDMwLjY4NjUgMTE1LjAyMiAzMC44NTIyQzExNC40NjcgMzEuMjIyOCAxMTMuODMyIDMxLjQ1NjQgMTEzLjE3IDMxLjUzMzhDMTEyLjUwNyAzMS42MTEyIDExMS44MzUgMzEuNTMwMyAxMTEuMjEgMzEuMjk3NkMxMTAuMTEyIDMyLjQxMTMgMTA3LjM3MSAzNS4xNzA0IDEwNS44OTEgMzYuNTUyMkMxMDUuNTk0IDM2LjgyMTkgMTA1LjIwOCAzNi45NzI2IDEwNC44MDcgMzYuOTc1NFpNMTEyLjc0NSAyMy45MjhDMTEyLjA4NyAyMy45MjY0IDExMS40NDQgMjQuMTIwMiAxMTAuODk2IDI0LjQ4NDhDMTEwLjY4MyAyNC42MTUyIDExMC40ODQgMjQuNzY5IDExMC4zMDUgMjQuOTQzM0MxMDkuODI4IDI1LjQyNDIgMTA5LjUwOSAyNi4wMzk1IDEwOS4zOTIgMjYuNzA2N0MxMDkuMjc0IDI3LjM3MzkgMTA5LjM2NCAyOC4wNjEgMTA5LjY0OCAyOC42NzU5TDEwOS43ODMgMjguOTcyOUwxMDkuNTUgMjkuMjAwM0MxMDcuODEyIDMwLjg5NjcgMTA1LjI4MSAzMy40MjAxIDEwNC4wNjUgMzQuNzA0NUMxMDMuOTU2IDM0Ljg2NTggMTAzLjkxIDM1LjA2MDggMTAzLjkzNCAzNS4yNTM1QzEwMy45NTkgMzUuNDQ2MyAxMDQuMDUyIDM1LjYyMzggMTA0LjE5NyAzNS43NTMyQzEwNC4yOCAzNS44NDYyIDEwNC4zODIgMzUuOTIxMSAxMDQuNDk1IDM1Ljk3MzFDMTA0LjU5NiAzNi4wMTg0IDEwNC43MDQgMzYuMDQzIDEwNC44MTQgMzYuMDQ1NUMxMDQuOTgxIDM2LjA0MTMgMTA1LjE0IDM1Ljk3NyAxMDUuMjY0IDM1Ljg2NDZDMTA2LjgzNyAzNC4zOTY0IDEwOS44NzYgMzEuMzI2NCAxMTAuNzY4IDMwLjQyNDNMMTEwLjk5NyAzMC4xOTMzTDExMS4yOTIgMzAuMzI3OEMxMTEuODA2IDMwLjU2NzMgMTEyLjM3MyAzMC42Njk4IDExMi45MzggMzAuNjI1NUMxMTMuNTAzIDMwLjU4MTEgMTE0LjA0NyAzMC4zOTEzIDExNC41MTcgMzAuMDc0NUMxMTQuNzMxIDI5Ljk0MjYgMTE0LjkzIDI5Ljc4NjkgMTE1LjEwOSAyOS42MTA1QzExNS40MTggMjkuMzAxNSAxMTUuNjYzIDI4LjkzMzcgMTE1LjgyOSAyOC41Mjg3QzExNS45OTQgMjguMTIzNyAxMTYuMDc3IDI3LjY4OTcgMTE2LjA3MiAyNy4yNTIzQzExNi4wNzIgMjcuMDM2NiAxMTYuMDUgMjYuODIxNSAxMTYuMDA4IDI2LjYxMDFMMTEzLjQzMSAyOS4xMjUxTDExMC44NzkgMjYuNTc3NkwxMTMuMzk0IDIzLjk4ODNDMTEzLjE4IDIzLjk0NjcgMTEyLjk2MyAyMy45MjY1IDExMi43NDUgMjMuOTI4WiIgZmlsbD0iI0M1QzVDNSIvPgo8cGF0aCBkPSJNMTA0LjgwNyAxNi45NzU0QzEwNC41NzEgMTYuOTcyMSAxMDQuMzM4IDE2LjkyMTEgMTA0LjEyMiAxNi44MjU0QzEwMy45MDcgMTYuNzI5NyAxMDMuNzEyIDE2LjU5MTMgMTAzLjU1MiAxNi40MTg2QzEwMy4yMzkgMTYuMTMzNCAxMDMuMDQ0IDE1Ljc0MDggMTAzLjAwOCAxNS4zMTg5QzEwMi45NjYgMTQuODgyOCAxMDMuMDkzIDE0LjQ0NzMgMTAzLjM2MSAxNC4xMDEzQzEwNC41NjggMTIuODI4OSAxMDYuOTQ3IDEwLjQ0OTQgMTA4LjY3OCA4Ljc1NDc5QzEwOC4zMSA3Ljc1ODg3IDEwOC4zMjcgNi42NjEyNyAxMDguNzI2IDUuNjc3MzlDMTA5LjA1NSA0Ljg1ODc2IDEwOS42MzkgNC4xNjgwNSAxMTAuMzkxIDMuNzA4MDdDMTEwLjk4MiAzLjMxNzA2IDExMS42NiAzLjA3OTQ0IDExMi4zNjYgMy4wMTY3M0MxMTMuMDcxIDIuOTU0MDIgMTEzLjc4MSAzLjA2ODE5IDExNC40MzEgMy4zNDg5MkwxMTUuMDQ4IDMuNjE2MkwxMTIuMTgyIDYuNTY3MzhMMTEzLjQzNyA3LjgyNTgyTDExNi4zODEgNC45NDg4N0wxMTYuNjQ4IDUuNTY3ODhDMTE2Ljg3NCA2LjA4OTc2IDExNi45OTMgNi42NTExOSAxMTcgNy4yMTk2MUMxMTcuMDA2IDcuNzg4MDIgMTE2LjkgOC4zNTIxMSAxMTYuNjg3IDguODc5MTVDMTE2LjQ3NiA5LjQwMDI5IDExNi4xNjIgOS44NzM2OCAxMTUuNzY1IDEwLjI3MTJDMTE1LjUzOSAxMC40OTE3IDExNS4yOSAxMC42ODY1IDExNS4wMjIgMTAuODUyMkMxMTQuNDY3IDExLjIyMjggMTEzLjgzMiAxMS40NTY0IDExMy4xNyAxMS41MzM4QzExMi41MDcgMTEuNjExMiAxMTEuODM1IDExLjUzMDMgMTExLjIxIDExLjI5NzZDMTEwLjExMiAxMi40MTEzIDEwNy4zNzEgMTUuMTcwNCAxMDUuODkxIDE2LjU1MjJDMTA1LjU5NCAxNi44MjE5IDEwNS4yMDggMTYuOTcyNiAxMDQuODA3IDE2Ljk3NTRaTTExMi43NDUgMy45MjgwMkMxMTIuMDg3IDMuOTI2MzcgMTExLjQ0NCA0LjEyMDE4IDExMC44OTYgNC40ODQ4NUMxMTAuNjgzIDQuNjE1MiAxMTAuNDg0IDQuNzY4OTcgMTEwLjMwNSA0Ljk0MzNDMTA5LjgyOCA1LjQyNDIzIDEwOS41MDkgNi4wMzk1MyAxMDkuMzkyIDYuNzA2NjlDMTA5LjI3NCA3LjM3Mzg1IDEwOS4zNjQgOC4wNjA5OCAxMDkuNjQ4IDguNjc1OTFMMTA5Ljc4MyA4Ljk3Mjg4TDEwOS41NSA5LjIwMDI1QzEwNy44MTIgMTAuODk2NyAxMDUuMjgxIDEzLjQyMDEgMTA0LjA2NSAxNC43MDQ1QzEwMy45NTYgMTQuODY1OCAxMDMuOTEgMTUuMDYwOCAxMDMuOTM0IDE1LjI1MzVDMTAzLjk1OSAxNS40NDYzIDEwNC4wNTIgMTUuNjIzOCAxMDQuMTk3IDE1Ljc1MzJDMTA0LjI4IDE1Ljg0NjIgMTA0LjM4MiAxNS45MjExIDEwNC40OTUgMTUuOTczMUMxMDQuNTk2IDE2LjAxODQgMTA0LjcwNCAxNi4wNDMgMTA0LjgxNCAxNi4wNDU1QzEwNC45ODEgMTYuMDQxMyAxMDUuMTQgMTUuOTc3IDEwNS4yNjQgMTUuODY0NkMxMDYuODM3IDE0LjM5NjQgMTA5Ljg3NiAxMS4zMjY0IDExMC43NjggMTAuNDI0M0wxMTAuOTk3IDEwLjE5MzNMMTExLjI5MiAxMC4zMjc4QzExMS44MDYgMTAuNTY3MyAxMTIuMzczIDEwLjY2OTggMTEyLjkzOCAxMC42MjU1QzExMy41MDMgMTAuNTgxMSAxMTQuMDQ3IDEwLjM5MTMgMTE0LjUxNyAxMC4wNzQ1QzExNC43MzEgOS45NDI2IDExNC45MyA5Ljc4Njk0IDExNS4xMDkgOS42MTA0NUMxMTUuNDE4IDkuMzAxNTMgMTE1LjY2MyA4LjkzMzc0IDExNS44MjkgOC41Mjg3NEMxMTUuOTk0IDguMTIzNzUgMTE2LjA3NyA3LjY4OTc0IDExNi4wNzIgNy4yNTIyOEMxMTYuMDcyIDcuMDM2NjIgMTE2LjA1IDYuODIxNDggMTE2LjAwOCA2LjYxMDA3TDExMy40MzEgOS4xMjUwOEwxMTAuODc5IDYuNTc3NTlMMTEzLjM5NCAzLjk4ODM0QzExMy4xOCAzLjk0Njc0IDExMi45NjMgMy45MjY1MyAxMTIuNzQ1IDMuOTI4MDJaIiBmaWxsPSIjNDI0MjQyIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTQ5IDI1TDE1MCAyNEgxNTZMMTU3IDI1VjMwTDE1NiAzMUgxNTJWMzBIMTU2VjI1SDE1MFYyOEgxNDlWMjVaTTE1MCAyOUwxNTEgMzBWMzFWMzVMMTUwIDM2SDE0NEwxNDMgMzVWMzBMMTQ0IDI5SDE0OUgxNTBaTTE1MCAzMFYzMVYzNUgxNDRWMzBIMTQ5SDE1MFpNMTUxLjQxNCAyOUwxNTEgMjguNTg1OFYyOEgxNTVWMjlIMTUxLjQxNFpNMTUxIDI2SDE1NVYyN0gxNTFWMjZaTTE0OSAzMkgxNDVWMzNIMTQ5VjMyWiIgZmlsbD0iIzc1QkVGRiIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTE0OSA1TDE1MCA0SDE1NkwxNTcgNVYxMEwxNTYgMTFIMTUyVjEwSDE1NlY1SDE1MFY4SDE0OVY1Wk0xNTAgOUwxNTEgMTBWMTFWMTVMMTUwIDE2SDE0NEwxNDMgMTVWMTBMMTQ0IDlIMTQ5SDE1MFpNMTUwIDEwVjExVjE1SDE0NFYxMEgxNDlIMTUwWk0xNTEuNDE0IDlMMTUxIDguNTg1NzlWOEgxNTVWOUgxNTEuNDE0Wk0xNTEgNkgxNTVWN0gxNTFWNlpNMTQ5IDEySDE0NVYxM0gxNDlWMTJaIiBmaWxsPSIjMDA3QUNDIi8+CjxwYXRoIGQ9Ik0xNzcgNkgxNzJWNUgxNzdWNlpNMTc2IDlIMTc0VjEwSDE3NlY5Wk0xNzIgOUgxNjNWMTBIMTcyVjlaTTE3NCAxNUgxNjNWMTZIMTc0VjE1Wk0xNjkgMTJIMTYzVjEzSDE2OVYxMlpNMTc3IDEySDE3MlYxM0gxNzdWMTJaTTE3MCA0VjdIMTYzVjRIMTcwWk0xNjkgNUgxNjRWNkgxNjlWNVoiIGZpbGw9IiNDNUM1QzUiLz4KPHBhdGggZD0iTTE3NyAyNkgxNzJWMjVIMTc3VjI2Wk0xNzYgMjlIMTc0VjMwSDE3NlYyOVpNMTcyIDI5SDE2M1YzMEgxNzJWMjlaTTE3NCAzNUgxNjNWMzZIMTc0VjM1Wk0xNjkgMzJIMTYzVjMzSDE2OVYzMlpNMTc3IDMySDE3MlYzM0gxNzdWMzJaTTE3MCAyNFYyN0gxNjNWMjRIMTcwWk0xNjkgMjVIMTY0VjI2SDE2OVYyNVoiIGZpbGw9IiM0MjQyNDIiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0yMDkuMjIzIDMyLjkzM0MyMDkuNTQ5IDMzLjEyNTQgMjA5LjkyMiAzMy4yMjMxIDIxMC4zIDMzLjIxNUMyMTAuNjM4IDMzLjIyMTggMjEwLjk3MyAzMy4xNDkyIDIxMS4yNzcgMzMuMDAzQzIxMS41ODIgMzIuODU2NyAyMTEuODQ4IDMyLjY0MDkgMjEyLjA1NCAzMi4zNzNDMjEyLjUwOSAzMS43NjUyIDIxMi43NCAzMS4wMTg3IDIxMi43MDggMzAuMjZDMjEyLjc0MSAyOS41ODYyIDIxMi41MzcgMjguOTIyMSAyMTIuMTMyIDI4LjM4M0MyMTEuOTM2IDI4LjE0MTYgMjExLjY4NiAyNy45NDk2IDIxMS40MDIgMjcuODIyM0MyMTEuMTE4IDI3LjY5NSAyMTAuODA5IDI3LjYzNiAyMTAuNDk4IDI3LjY1QzIxMC4wNzUgMjcuNjQ3IDIwOS42NiAyNy43NjA4IDIwOS4yOTggMjcuOTc5QzIwOS4xODMgMjguMDQ4MSAyMDkuMDc1IDI4LjEyNzggMjA4Ljk3NSAyOC4yMTdWMjUuNDc1SDIwNy45ODRWMzMuMUgyMDguOTc5VjMyLjc1NkMyMDkuMDU1IDMyLjgyMTcgMjA5LjEzNyAzMi44ODA5IDIwOS4yMjMgMzIuOTMzWk0yMDkuODUgMjguNzAwMUMyMTAuMDM2IDI4LjYyMSAyMTAuMjM4IDI4LjU4NjggMjEwLjQ0IDI4LjZDMjEwLjYxMyAyOC41OTQ1IDIxMC43ODQgMjguNjMwNSAyMTAuOTQgMjguNzA1QzIxMS4wOTYgMjguNzc5NSAyMTEuMjMyIDI4Ljg5MDIgMjExLjMzNiAyOS4wMjhDMjExLjU5MyAyOS4zOTA1IDIxMS43MTggMjkuODI5NSAyMTEuNjkzIDMwLjI3M0MyMTEuNzIgMzAuNzk3NSAyMTEuNTggMzEuMzE3IDIxMS4yOTMgMzEuNzU3QzIxMS4xODggMzEuOTE1MyAyMTEuMDQ1IDMyLjA0NDcgMjEwLjg3OCAzMi4xMzM1QzIxMC43MSAzMi4yMjIzIDIxMC41MjMgMzIuMjY3NSAyMTAuMzMzIDMyLjI2NUMyMTAuMTQ5IDMyLjI3MzIgMjA5Ljk2NiAzMi4yNCAyMDkuNzk3IDMyLjE2NzhDMjA5LjYyOCAzMi4wOTU2IDIwOS40NzggMzEuOTg2MyAyMDkuMzU3IDMxLjg0OEMyMDkuMTAyIDMxLjU1OTYgMjA4Ljk2NSAzMS4xODUxIDIwOC45NzUgMzAuOFYzMC4yQzIwOC45NjMgMjkuNzgzMyAyMDkuMTAzIDI5LjM3NjUgMjA5LjM2OCAyOS4wNTVDMjA5LjQ5OSAyOC45MDA2IDIwOS42NjQgMjguNzc5MSAyMDkuODUgMjguNzAwMVpNMjA1LjI4OSAyNy42NzVDMjA0Ljk3IDI3LjY3OTMgMjA0LjY1NCAyNy43MzQgMjA0LjM1MiAyNy44MzdDMjA0LjA2NCAyNy45MjI5IDIwMy43OTMgMjguMDU4MyAyMDMuNTUyIDI4LjIzN0wyMDMuNDUyIDI4LjMxNFYyOS41MTRMMjAzLjg3NSAyOS4xNTVDMjA0LjI0NiAyOC44MDQ4IDIwNC43MzEgMjguNjAxNSAyMDUuMjQxIDI4LjU4M0MyMDUuMzY2IDI4LjU3MTYgMjA1LjQ5MiAyOC41OTE1IDIwNS42MDcgMjguNjQwN0MyMDUuNzIyIDI4LjY4OTkgMjA1LjgyNCAyOC43NjcgMjA1LjkwMiAyOC44NjVDMjA2LjA1MiAyOS4wOTcxIDIwNi4xMzIgMjkuMzY3NSAyMDYuMTMzIDI5LjY0NEwyMDQuOSAyOS44MjVDMjA0LjM5NCAyOS44Nzc4IDIwMy45MTUgMzAuMDc3NyAyMDMuNTIyIDMwLjRDMjAzLjM2NyAzMC41NTE4IDIwMy4yNDMgMzAuNzMyNyAyMDMuMTU4IDMwLjkzMjRDMjAzLjA3MyAzMS4xMzIgMjAzLjAyOCAzMS4zNDY0IDIwMy4wMjYgMzEuNTYzNEMyMDMuMDI0IDMxLjc4MDQgMjAzLjA2NSAzMS45OTU3IDIwMy4xNDYgMzIuMTk2OUMyMDMuMjI4IDMyLjM5ODEgMjAzLjM0OCAzMi41ODEzIDIwMy41IDMyLjczNkMyMDMuNjY5IDMyLjg5MDQgMjAzLjg2NiAzMy4wMSAyMDQuMDgxIDMzLjA4NzlDMjA0LjI5NiAzMy4xNjU5IDIwNC41MjUgMzMuMjAwNSAyMDQuNzUzIDMzLjE5QzIwNS4xNDcgMzMuMTkzMSAyMDUuNTMzIDMzLjA3NzQgMjA1Ljg2IDMyLjg1OEMyMDUuOTYyIDMyLjc4OTcgMjA2LjA1NyAzMi43MTMxIDIwNi4xNDYgMzIuNjI5VjMzLjA3M0gyMDcuMDg3VjI5LjcxNUMyMDcuMTIxIDI5LjE3NDIgMjA2Ljk1NCAyOC42Mzk5IDIwNi42MTggMjguMjE1QzIwNi40NSAyOC4wMzI5IDIwNi4yNDMgMjcuODkgMjA2LjAxNCAyNy43OTY3QzIwNS43ODQgMjcuNzAzNCAyMDUuNTM3IDI3LjY2MTggMjA1LjI4OSAyNy42NzVaTTIwNi4xNDYgMzAuNzE2QzIwNi4xNjYgMzEuMTM0MyAyMDYuMDI2IDMxLjU0NDYgMjA1Ljc1NSAzMS44NjRDMjA1LjYzNyAzMi4wMDA1IDIwNS40OSAzMi4xMDkyIDIwNS4zMjUgMzIuMTgyMUMyMDUuMTYgMzIuMjU1MSAyMDQuOTggMzIuMjkwNiAyMDQuOCAzMi4yODZDMjA0LjY5IDMyLjI5NDUgMjA0LjU4IDMyLjI4MTIgMjA0LjQ3NiAzMi4yNDY5QzIwNC4zNzIgMzIuMjEyNSAyMDQuMjc1IDMyLjE1NzkgMjA0LjE5MiAzMi4wODZDMjA0LjA2MSAzMS45MzQ2IDIwMy45ODkgMzEuNzQwOSAyMDMuOTg5IDMxLjU0MDVDMjAzLjk4OSAzMS4zNDAxIDIwNC4wNjEgMzEuMTQ2NCAyMDQuMTkyIDMwLjk5NUMyMDQuNDczIDMwLjgyMTMgMjA0Ljc5MiAzMC43MTg0IDIwNS4xMjIgMzAuNjk1TDIwNi4xNDIgMzAuNTQ3TDIwNi4xNDYgMzAuNzE2Wk0yMTQuNDU5IDMzLjAzMjVDMjE0Ljc2NiAzMy4xNjM4IDIxNS4wOTggMzMuMjI2MSAyMTUuNDMyIDMzLjIxNUMyMTUuOTI3IDMzLjIyNyAyMTYuNDE1IDMzLjEwMDYgMjE2Ljg0MiAzMi44NUwyMTYuOTY1IDMyLjc3NUwyMTYuOTc4IDMyLjc2OFYzMS42MTVMMjE2LjUzMiAzMS45MzVDMjE2LjIxNiAzMi4xNTkyIDIxNS44MzYgMzIuMjc0NyAyMTUuNDQ4IDMyLjI2NEMyMTUuMjUgMzIuMjcxOSAyMTUuMDUyIDMyLjIzNDIgMjE0Ljg3IDMyLjE1MzhDMjE0LjY4OSAzMi4wNzMzIDIxNC41MjggMzEuOTUyMyAyMTQuNCAzMS44QzIxNC4xMTQgMzEuNDI0NSAyMTMuOTczIDMwLjk1OTEgMjE0IDMwLjQ4OEMyMTMuOTc0IDI5Ljk4NzMgMjE0LjEzNSAyOS40OTQ4IDIxNC40NTMgMjkuMTA3QzIxNC41OTMgMjguOTQxMSAyMTQuNzcgMjguODA5MSAyMTQuOTY4IDI4LjcyMTNDMjE1LjE2NyAyOC42MzM1IDIxNS4zODMgMjguNTkyIDIxNS42IDI4LjZDMjE1Ljk0NCAyOC41OTg0IDIxNi4yODEgMjguNjk1MyAyMTYuNTcxIDI4Ljg3OUwyMTcgMjkuMTQ0VjI3Ljk3TDIxNi44MzEgMjcuODk3QzIxNi40NjMgMjcuNzM0MyAyMTYuMDY0IDI3LjY1MDIgMjE1LjY2MSAyNy42NUMyMTUuMyAyNy42Mzk5IDIxNC45NDEgMjcuNzA3NiAyMTQuNjA4IDI3Ljg0ODZDMjE0LjI3NSAyNy45ODk2IDIxMy45NzYgMjguMjAwNSAyMTMuNzMyIDI4LjQ2N0MyMTMuMjI2IDI5LjAyNjggMjEyLjk1OCAyOS43NjE5IDIxMi45ODUgMzAuNTE2QzIxMi45NTcgMzEuMjIzNSAyMTMuMTk2IDMxLjkxNTcgMjEzLjY1NCAzMi40NTVDMjEzLjg3NyAzMi43MDQgMjE0LjE1MiAzMi45MDEyIDIxNC40NTkgMzMuMDMyNVoiIGZpbGw9IiNDNUM1QzUiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0yMDkuMjIzIDEyLjkzM0MyMDkuNTQ5IDEzLjEyNTQgMjA5LjkyMiAxMy4yMjMxIDIxMC4zIDEzLjIxNUMyMTAuNjM4IDEzLjIyMTggMjEwLjk3MyAxMy4xNDkyIDIxMS4yNzcgMTMuMDAzQzIxMS41ODIgMTIuODU2NyAyMTEuODQ4IDEyLjY0MDkgMjEyLjA1NCAxMi4zNzNDMjEyLjUwOSAxMS43NjUyIDIxMi43NCAxMS4wMTg3IDIxMi43MDggMTAuMjZDMjEyLjc0MSA5LjU4NjIyIDIxMi41MzcgOC45MjIxIDIxMi4xMzIgOC4zODI5OEMyMTEuOTM2IDguMTQxNjEgMjExLjY4NiA3Ljk0OTU3IDIxMS40MDIgNy44MjIyOEMyMTEuMTE4IDcuNjk0OTggMjEwLjgwOSA3LjYzNTk3IDIxMC40OTggNy42NDk5N0MyMTAuMDc1IDcuNjQ2OTkgMjA5LjY2IDcuNzYwODUgMjA5LjI5OCA3Ljk3ODk4QzIwOS4xODMgOC4wNDgwNyAyMDkuMDc1IDguMTI3NzUgMjA4Ljk3NSA4LjIxNjk4VjUuNDc0OThIMjA3Ljk4NFYxMy4xSDIwOC45NzlWMTIuNzU2QzIwOS4wNTUgMTIuODIxNyAyMDkuMTM3IDEyLjg4MDkgMjA5LjIyMyAxMi45MzNaTTIwOS44NSA4LjcwMDA2QzIxMC4wMzYgOC42MjEwNSAyMTAuMjM4IDguNTg2NzcgMjEwLjQ0IDguNTk5OThDMjEwLjYxMyA4LjU5NDUyIDIxMC43ODQgOC42MzA1NCAyMTAuOTQgOC43MDUwMUMyMTEuMDk2IDguNzc5NDggMjExLjIzMiA4Ljg5MDIzIDIxMS4zMzYgOS4wMjc5OEMyMTEuNTkzIDkuMzkwNTMgMjExLjcxOCA5LjgyOTUxIDIxMS42OTMgMTAuMjczQzIxMS43MiAxMC43OTc1IDIxMS41OCAxMS4zMTcgMjExLjI5MyAxMS43NTdDMjExLjE4OCAxMS45MTUzIDIxMS4wNDUgMTIuMDQ0NyAyMTAuODc4IDEyLjEzMzVDMjEwLjcxIDEyLjIyMjMgMjEwLjUyMyAxMi4yNjc1IDIxMC4zMzMgMTIuMjY1QzIxMC4xNDkgMTIuMjczMiAyMDkuOTY2IDEyLjI0IDIwOS43OTcgMTIuMTY3OEMyMDkuNjI4IDEyLjA5NTYgMjA5LjQ3OCAxMS45ODYzIDIwOS4zNTcgMTEuODQ4QzIwOS4xMDIgMTEuNTU5NiAyMDguOTY1IDExLjE4NTEgMjA4Ljk3NSAxMC44VjEwLjJDMjA4Ljk2MyA5Ljc4MzMyIDIwOS4xMDMgOS4zNzY1IDIwOS4zNjggOS4wNTQ5OEMyMDkuNDk5IDguOTAwNjQgMjA5LjY2NCA4Ljc3OTA4IDIwOS44NSA4LjcwMDA2Wk0yMDUuMjg5IDcuNjc0OTlDMjA0Ljk3IDcuNjc5MzMgMjA0LjY1NCA3LjczNCAyMDQuMzUyIDcuODM2OTlDMjA0LjA2NCA3LjkyMjkzIDIwMy43OTMgOC4wNTgyOCAyMDMuNTUyIDguMjM2OTlMMjAzLjQ1MiA4LjMxMzk5VjkuNTEzOTlMMjAzLjg3NSA5LjE1NDk5QzIwNC4yNDYgOC44MDQ3OCAyMDQuNzMxIDguNjAxNDYgMjA1LjI0MSA4LjU4Mjk5QzIwNS4zNjYgOC41NzE2NCAyMDUuNDkyIDguNTkxNDcgMjA1LjYwNyA4LjY0MDY4QzIwNS43MjIgOC42ODk5IDIwNS44MjQgOC43NjY5NyAyMDUuOTAyIDguODY0OTlDMjA2LjA1MiA5LjA5NzEgMjA2LjEzMiA5LjM2NzU0IDIwNi4xMzMgOS42NDM5OUwyMDQuOSA5LjgyNDk5QzIwNC4zOTQgOS44Nzc4MSAyMDMuOTE1IDEwLjA3NzcgMjAzLjUyMiAxMC40QzIwMy4zNjcgMTAuNTUxOCAyMDMuMjQzIDEwLjczMjcgMjAzLjE1OCAxMC45MzI0QzIwMy4wNzMgMTEuMTMyIDIwMy4wMjggMTEuMzQ2NCAyMDMuMDI2IDExLjU2MzRDMjAzLjAyNCAxMS43ODA0IDIwMy4wNjUgMTEuOTk1NyAyMDMuMTQ2IDEyLjE5NjlDMjAzLjIyOCAxMi4zOTgxIDIwMy4zNDggMTIuNTgxMyAyMDMuNSAxMi43MzZDMjAzLjY2OSAxMi44OTA0IDIwMy44NjYgMTMuMDEgMjA0LjA4MSAxMy4wODc5QzIwNC4yOTYgMTMuMTY1OSAyMDQuNTI1IDEzLjIwMDUgMjA0Ljc1MyAxMy4xOUMyMDUuMTQ3IDEzLjE5MzEgMjA1LjUzMyAxMy4wNzc0IDIwNS44NiAxMi44NThDMjA1Ljk2MiAxMi43ODk3IDIwNi4wNTcgMTIuNzEzMSAyMDYuMTQ2IDEyLjYyOVYxMy4wNzNIMjA3LjA4N1Y5LjcxNDk5QzIwNy4xMjEgOS4xNzQyMiAyMDYuOTU0IDguNjM5ODggMjA2LjYxOCA4LjIxNDk5QzIwNi40NSA4LjAzMjg1IDIwNi4yNDMgNy44OTAwMyAyMDYuMDE0IDcuNzk2N0MyMDUuNzg0IDcuNzAzMzYgMjA1LjUzNyA3LjY2MTgxIDIwNS4yODkgNy42NzQ5OVpNMjA2LjE0NiAxMC43MTZDMjA2LjE2NiAxMS4xMzQzIDIwNi4wMjYgMTEuNTQ0NiAyMDUuNzU1IDExLjg2NEMyMDUuNjM3IDEyLjAwMDUgMjA1LjQ5IDEyLjEwOTIgMjA1LjMyNSAxMi4xODIxQzIwNS4xNiAxMi4yNTUxIDIwNC45OCAxMi4yOTA2IDIwNC44IDEyLjI4NkMyMDQuNjkgMTIuMjk0NSAyMDQuNTggMTIuMjgxMiAyMDQuNDc2IDEyLjI0NjlDMjA0LjM3MiAxMi4yMTI1IDIwNC4yNzUgMTIuMTU3OSAyMDQuMTkyIDEyLjA4NkMyMDQuMDYxIDExLjkzNDYgMjAzLjk4OSAxMS43NDA5IDIwMy45ODkgMTEuNTQwNUMyMDMuOTg5IDExLjM0MDEgMjA0LjA2MSAxMS4xNDY0IDIwNC4xOTIgMTAuOTk1QzIwNC40NzMgMTAuODIxMyAyMDQuNzkyIDEwLjcxODQgMjA1LjEyMiAxMC42OTVMMjA2LjE0MiAxMC41NDdMMjA2LjE0NiAxMC43MTZaTTIxNC40NTkgMTMuMDMyNUMyMTQuNzY2IDEzLjE2MzggMjE1LjA5OCAxMy4yMjYxIDIxNS40MzIgMTMuMjE1QzIxNS45MjcgMTMuMjI3IDIxNi40MTUgMTMuMTAwNiAyMTYuODQyIDEyLjg1TDIxNi45NjUgMTIuNzc1TDIxNi45NzggMTIuNzY4VjExLjYxNUwyMTYuNTMyIDExLjkzNUMyMTYuMjE2IDEyLjE1OTIgMjE1LjgzNiAxMi4yNzQ3IDIxNS40NDggMTIuMjY0QzIxNS4yNSAxMi4yNzE5IDIxNS4wNTIgMTIuMjM0MiAyMTQuODcgMTIuMTUzOEMyMTQuNjg5IDEyLjA3MzMgMjE0LjUyOCAxMS45NTIzIDIxNC40IDExLjhDMjE0LjExNCAxMS40MjQ1IDIxMy45NzMgMTAuOTU5MSAyMTQgMTAuNDg4QzIxMy45NzQgOS45ODczMiAyMTQuMTM1IDkuNDk0NzUgMjE0LjQ1MyA5LjEwNzA0QzIxNC41OTMgOC45NDEwNSAyMTQuNzcgOC44MDkxNCAyMTQuOTY4IDguNzIxM0MyMTUuMTY3IDguNjMzNDYgMjE1LjM4MyA4LjU5MiAyMTUuNiA4LjYwMDA0QzIxNS45NDQgOC41OTg0NCAyMTYuMjgxIDguNjk1MjUgMjE2LjU3MSA4Ljg3OTA0TDIxNyA5LjE0NDA0VjcuOTcwMDRMMjE2LjgzMSA3Ljg5NzA0QzIxNi40NjMgNy43MzQzMiAyMTYuMDY0IDcuNjUwMiAyMTUuNjYxIDcuNjUwMDRDMjE1LjMgNy42Mzk5MSAyMTQuOTQxIDcuNzA3NjIgMjE0LjYwOCA3Ljg0ODU5QzIxNC4yNzUgNy45ODk1NiAyMTMuOTc2IDguMjAwNDggMjEzLjczMiA4LjQ2NzA0QzIxMy4yMjYgOS4wMjY4MyAyMTIuOTU4IDkuNzYxODYgMjEyLjk4NSAxMC41MTZDMjEyLjk1NyAxMS4yMjM1IDIxMy4xOTYgMTEuOTE1NyAyMTMuNjU0IDEyLjQ1NUMyMTMuODc3IDEyLjcwNCAyMTQuMTUyIDEyLjkwMTIgMjE0LjQ1OSAxMy4wMzI1WiIgZmlsbD0iIzQyNDI0MiIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTI2NiAzTDI2NSA0VjE2TDI2NiAxN0gyNzVMMjc2IDE2VjdMMjc1LjcwNyA2LjI5Mjg5TDI3Mi43MDcgMy4yOTI4OUwyNzIgM0gyNjZaTTI2NiAxNlY0TDI3MSA0VjhIMjc1VjE2SDI2NlpNMjc1IDdMMjcyIDRWN0wyNzUgN1oiIGZpbGw9IiM0MjQyNDIiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0yNjYgMjNMMjY1IDI0VjM2TDI2NiAzN0gyNzVMMjc2IDM2VjI3TDI3NS43MDcgMjYuMjkyOUwyNzIuNzA3IDIzLjI5MjlMMjcyIDIzSDI2NlpNMjY2IDM2VjI0TDI3MSAyNFYyOEgyNzVWMzZIMjY2Wk0yNzUgMjdMMjcyIDI0VjI3TDI3NSAyN1oiIGZpbGw9IiNDNUM1QzUiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMzAgMjRMMTI5IDI1VjI4SDEzMFYyNUgxMzZWMzBIMTMyVjMxSDEzNkwxMzcgMzBWMjVMMTM2IDI0SDEzMFpNMTMxIDMwTDEzMCAyOUgxMjlIMTI0TDEyMyAzMFYzNUwxMjQgMzZIMTMwTDEzMSAzNVYzMVYzMFpNMTMwIDMxVjMwSDEyOUgxMjRWMzVIMTMwVjMxWk0xMzEgMjguNTg1OEwxMzEuNDE0IDI5SDEzNVYyOEgxMzFWMjguNTg1OFpNMTM1IDI2SDEzMVYyN0gxMzVWMjZaTTEyOSAzMUgxMjVWMzJIMTI5VjMxWk0xMjUgMzNIMTI5VjM0SDEyNVYzM1oiIGZpbGw9IiNFRTlEMjgiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMzAgNEwxMjkgNVY4SDEzMFY1SDEzNlYxMEgxMzJWMTFIMTM2TDEzNyAxMFY1TDEzNiA0SDEzMFpNMTMxIDEwTDEzMCA5SDEyOUgxMjRMMTIzIDEwVjE1TDEyNCAxNkgxMzBMMTMxIDE1VjExVjEwWk0xMzAgMTFWMTBIMTI5SDEyNFYxNUgxMzBWMTFaTTEzMSA4LjU4NTc5TDEzMS40MTQgOUgxMzVWOEgxMzFWOC41ODU3OVpNMTM1IDZIMTMxVjdIMTM1VjZaTTEyOSAxMUgxMjVWMTJIMTI5VjExWk0xMjUgMTNIMTI5VjE0SDEyNVYxM1oiIGZpbGw9IiNENjdFMDAiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0yNDYgM0wyNDUgNFYxNkwyNDYgMTdIMjU0TDI1NSAxNlY0TDI1NCAzSDI0NlpNMjQ2IDVWNEgyNTRWMTZIMjQ2VjE1SDI0OFYxNEgyNDZWMTJIMjUwVjExSDI0NlY5SDI0OFY4SDI0NlY2SDI1MFY1SDI0NloiIGZpbGw9IiM0MjQyNDIiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0yNDYgMjNMMjQ1IDI0VjM2TDI0NiAzN0gyNTRMMjU1IDM2VjI0TDI1NCAyM0gyNDZaTTI0NiAyNVYyNEgyNTRWMzZIMjQ2VjM1SDI0OFYzNEgyNDZWMzJIMjUwVjMxSDI0NlYyOUgyNDhWMjhIMjQ2VjI2SDI1MFYyNUgyNDZaIiBmaWxsPSIjQzVDNUM1Ii8+Cjwvc3ZnPgo=");background-repeat:no-repeat;background-position:-2px -22px}.monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon,.monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.constructor,.monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.function,.monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.method{background-position:-2px -2px}.monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.field,.monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.variable{background-position:-22px -2px}.monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.class{background-position:-42px -2px}.monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.interface{background-position:-62px -2px}.monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.module{background-position:-82px -2px}.monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.property{background-position:-102px -2px}.monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.enum{background-position:-122px -2px}.monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.string{background-position:-202px -2px}.monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.rule{background-position:-242px -2px}.monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.file{background-position:-262px -2px}.vs-dark .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.constructor,.vs-dark .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.function,.vs-dark .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.method{background-position:-2px -22px}.vs-dark .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.field,.vs-dark .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.variable{background-position:-22px -22px}.vs-dark .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.class{background-position:-43px -22px}.vs-dark .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.interface{background-position:-63px -22px}.vs-dark .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.module{background-position:-82px -22px}.vs-dark .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.property{background-position:-102px -22px}.vs-dark .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.enum{background-position:-122px -22px}.vs-dark .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.string{background-position:-202px -22px}.vs-dark .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.rule{background-position:-242px -22px}.vs-dark .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.file{background-position:-262px -22px}.hc-black .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon{background:none;display:inline}.hc-black .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon:before{height:16px;width:16px;display:inline-block}.hc-black .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.constructor:before,.hc-black .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.function:before,.hc-black .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.method:before,.hc-black .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon:before{content:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0yIDQuODU3NDlMMi40ODU1IDRMNy40ODU1IDFIOC41MTQ1TDEzLjUxNDUgNEwxNCA0Ljg1NzQ5VjEwLjg1NzVMMTMuNTE0NSAxMS43MTVMOC41MTQ1IDE0LjcxNUg3LjQ4NTVMMi40ODU1IDExLjcxNUwyIDEwLjg1NzVWNC44NTc0OVpNNy41IDEzLjU1NzVMMyAxMC44NTc1VjUuNjk5NzVMNy41IDguMTU0M1YxMy41NTc1Wk04LjUgMTMuNTU3NUwxMyAxMC44NTc1VjUuNjk5NzVMOC41IDguMTU0M1YxMy41NTc1Wk04IDEuODU3NDlMMy4yNTkxMyA0LjcwMjAxTDggNy4yODc5NEwxMi43NDA5IDQuNzAyMDFMOCAxLjg1NzQ5WiIgZmlsbD0iI0IxODBENyIvPgo8L3N2Zz4K)}.hc-black .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.field:before,.hc-black .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.variable:before{content:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xIDYuMzk0NDNMMS41NTI3OSA1LjVMOC41NTI3OSAySDkuNDQ3MjFMMTQuNDQ3MiA0LjVMMTUgNS4zOTQ0M1Y5Ljg5NDQzTDE0LjQ0NzIgMTAuNzg4OUw3LjQ0NzIxIDE0LjI4ODlINi41NTI3OUwxLjU1Mjc5IDExLjc4ODlMMSAxMC44OTQ0VjYuMzk0NDNaTTYuNSAxMy4xNDQ0TDIgMTAuODk0NFY3LjE3MDk0TDYuNSA5LjIxNjM5VjEzLjE0NDRaTTcuNSAxMy4xNDQ0TDE0IDkuODk0NDNWNi4xNzk1NEw3LjUgOS4yMTI4N1YxMy4xNDQ0Wk05IDIuODk0NDNMMi4zMzcyOCA2LjIyNTc5TDYuOTk3MjUgOC4zNDM5NkwxMy42NzA2IDUuMjI5NzNMOSAyLjg5NDQzWiIgZmlsbD0iIzc1QkVGRiIvPgo8L3N2Zz4K)}.hc-black .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.class:before{content:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0zLjM1MzU2IDYuNjQ2NDJMMi4wNjA2NiA1LjM1MzUzTDUuMzUzNTYgMi4wNjA2NUw2LjY0NjQ1IDMuMzUzNTRMMy4zNTM1NiA2LjY0NjQyWk01IDFMMSA0Ljk5OTk4VjUuNzA3MDhMMyA3LjcwNzA3SDMuNzA3MTFMNC44NTM1NSA2LjU2MDYzVjEyLjM1MzVMNS4zNTM1NSAxMi44NTM1SDEwLjAwOTdWMTMuMzc0MUwxMS4zNDMgMTQuNzA3NEgxMi4wNTAxTDE0LjcxNjggMTIuMDQwN1YxMS4zMzM2TDEzLjM4MzUgMTAuMDAwM0gxMi42NzYzTDEwLjgyMzEgMTEuODUzNUg1Ljg1MzU1VjcuODkzNTVIMTAuMDA5N1Y4LjM3NDAxTDExLjM0MyA5LjcwNzM0SDEyLjA1MDFMMTQuNzE2OCA3LjA0MDY4VjYuMzMzNTdMMTMuMzgzNSA1LjAwMDI0SDEyLjY3NjNMMTAuODYzIDYuODEzNTZINS44NTM1NVY1LjU2MDY0TDcuNzA3MTEgMy43MDcwOVYyLjk5OTk5TDUuNzA3MTEgMUg1Wk0xMS4wNzAzIDguMDIwNDZMMTEuNjk2NiA4LjY0NjY4TDEzLjY1NjEgNi42ODcxM0wxMy4wMjk5IDYuMDYwOUwxMS4wNzAzIDguMDIwNDZaTTExLjA3MDMgMTMuMDIwNUwxMS42OTY2IDEzLjY0NjdMMTMuNjU2MSAxMS42ODcyTDEzLjAyOTkgMTEuMDYxTDExLjA3MDMgMTMuMDIwNVoiIGZpbGw9IiNFRTlEMjgiLz4KPC9zdmc+Cg==)}.hc-black .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.interface:before{content:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMS41IDVDMTAuMTE5MyA1IDkgNi4xMTkyOSA5IDcuNUM5IDguODgwNzEgMTAuMTE5MyAxMCAxMS41IDEwQzEyLjg4MDcgMTAgMTQgOC44ODA3MSAxNCA3LjVDMTQgNi4xMTkyOSAxMi44ODA3IDUgMTEuNSA1Wk04LjAzNTQ0IDhDOC4yNzgwNiA5LjY5NjE1IDkuNzM2NzYgMTEgMTEuNSAxMUMxMy40MzMgMTEgMTUgOS40MzMgMTUgNy41QzE1IDUuNTY3IDEzLjQzMyA0IDExLjUgNEM5LjczNjc2IDQgOC4yNzgwNiA1LjMwMzg1IDguMDM1NDQgN0g0LjkzNjk5QzQuNzE0OTcgNi4xMzczOSAzLjkzMTkyIDUuNSAzIDUuNUMxLjg5NTQzIDUuNSAxIDYuMzk1NDMgMSA3LjVDMSA4LjYwNDU3IDEuODk1NDMgOS41IDMgOS41QzMuOTMxOTIgOS41IDQuNzE0OTcgOC44NjI2MSA0LjkzNjk5IDhIOC4wMzU0NFoiIGZpbGw9IiM3NUJFRkYiLz4KPC9zdmc+Cg==)}.hc-black .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.module:before{content:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik02IDIuOTgzNjFWMi45NzE4NFYySDUuOTEwODNDNS41OTc0MyAyIDUuMjk0MDcgMi4wNjE2MSA1LjAwMTI4IDIuMTg0NzNDNC43MDgxOCAyLjMwNzk4IDQuNDQ5NDIgMi40ODQ3NCA0LjIyNTc4IDIuNzE0OThDNC4wMDMxMSAyLjk0NDIyIDMuODM3OTIgMy4xOTQ5OCAzLjczMjgyIDMuNDY3NjZMMy43MzIzMyAzLjQ2ODk4QzMuNjMzODIgMy43MzUyIDMuNTY4MTQgNC4wMTIwMSAzLjUzNTMzIDQuMjk5MTdMMy41MzUxOSA0LjMwMDUzQzMuNTA2NzggNC41ODA1IDMuNDk4NyA0Ljg2ODQ0IDMuNTEwODQgNS4xNjQyOEMzLjUyMjcyIDUuNDUzNzkgMy41Mjg2NiA1Ljc0MzI5IDMuNTI4NjYgNi4wMzI3OUMzLjUyODY2IDYuMjM1NTYgMy40ODk3NCA2LjQyNTk0IDMuNDEyIDYuNjA1MDdMMy40MTE2IDYuNjA2MDFDMy4zMzY4NyA2Ljc4Mjk2IDMuMjM0MjMgNi45Mzg2NiAzLjEwMzE3IDcuMDczNTlDMi45NzY0NCA3LjIwNDA1IDIuODI0NjYgNy4zMTA1NSAyLjY0NjcyIDcuMzkyNUMyLjQ3MDYgNy40Njk1NCAyLjI4NDk3IDcuNTA4MiAyLjA4OTE3IDcuNTA4MkgyVjcuNlY4LjRWOC40OTE4SDIuMDg5MTdDMi4yODQ2NSA4LjQ5MTggMi40NzAwMSA4LjUzMjM4IDIuNjQ2MDEgOC42MTMzNEwyLjY0NzQyIDguNjEzOTZDMi44MjQ1NyA4LjY5MTU3IDIuOTc1NzcgOC43OTc2MiAzLjEwMjIxIDguOTMxNjFMMy4xMDQxMiA4LjkzMzUyQzMuMjM0MjggOS4wNjM3IDMuMzM2NTkgOS4yMTg3MSAzLjQxMTI5IDkuMzk5NDJMMy40MTIwMSA5LjQwMTA4QzMuNDg5ODYgOS41ODA0NyAzLjUyODY2IDkuNzY4ODMgMy41Mjg2NiA5Ljk2NzIxQzMuNTI4NjYgMTAuMjU2NyAzLjUyMjcyIDEwLjU0NjIgMy41MTA4NCAxMC44MzU3QzMuNDk4NyAxMS4xMzE2IDMuNTA2NzcgMTEuNDIxNSAzLjUzNTE2IDExLjcwNTVMMy41MzUzNSAxMS43MDcyQzMuNTY4MTkgMTEuOTkwMyAzLjYzMzg3IDEyLjI2NSAzLjczMjMyIDEyLjUzMUwzLjczMjgzIDEyLjUzMjNDMy44Mzc5MyAxMi44MDUgNC4wMDMxMSAxMy4wNTU4IDQuMjI1NzggMTMuMjg1QzQuNDQ5NDIgMTMuNTE1MyA0LjcwODE4IDEzLjY5MiA1LjAwMTI4IDEzLjgxNTNDNS4yOTQwNyAxMy45Mzg0IDUuNTk3NDMgMTQgNS45MTA4MyAxNEg2VjEzLjJWMTMuMDE2NEg1LjkxMDgzQzUuNzEwOTUgMTMuMDE2NCA1LjUyMzQ2IDEyLjk3NzcgNS4zNDc2MyAxMi45MDA4QzUuMTczOTYgMTIuODE5MSA1LjAyMTk0IDEyLjcxMjYgNC44OTA4NiAxMi41ODE4QzQuNzYzODYgMTIuNDQ2OSA0LjY2MTA0IDEyLjI5MTEgNC41ODIyMyAxMi4xMTM3QzQuNTA4MzggMTEuOTM0NiA0LjQ3MTM0IDExLjc0NCA0LjQ3MTM0IDExLjU0MUM0LjQ3MTM0IDExLjMxMjcgNC40NzUzIDExLjA4ODUgNC40ODMyMSAxMC44Njg2QzQuNDkxMjUgMTAuNjQxMSA0LjQ5MTI3IDEwLjQxOTUgNC40ODMyNCAxMC4yMDM5QzQuNDc5MTQgOS45ODI0NiA0LjQ2MDg0IDkuNzY4ODMgNC40MjgyMyA5LjU2MzEyQzQuMzk1MTMgOS4zNTAyNCA0LjMzOTIxIDkuMTQ3NTcgNC4yNjAzOSA4Ljk1NTM2QzQuMTgwOTEgOC43NjE1NyA0LjA3MjU4IDguNTc3NDYgMy45MzYxNiA4LjQwMjk4QzMuODIzNDUgOC4yNTg4MSAzLjY4NTM4IDguMTI0NjIgMy41MjI4MyA4QzMuNjg1MzggNy44NzUzOCAzLjgyMzQ1IDcuNzQxMTkgMy45MzYxNiA3LjU5NzAyQzQuMDcyNTggNy40MjI1NCA0LjE4MDkxIDcuMjM4NDMgNC4yNjAzOSA3LjA0NDY0QzQuMzM5MTMgNi44NTI2MyA0LjM5NTEzIDYuNjUxNzUgNC40MjgyNiA2LjQ0Mjg1QzQuNDYwODIgNi4yMzMzIDQuNDc5MTQgNi4wMTk3MyA0LjQ4MzI0IDUuODAyMTlDNC40OTEyNyA1LjU4MjYyIDQuNDkxMjUgNS4zNjEwNSA0LjQ4MzIxIDUuMTM3NDlDNC40NzUzIDQuOTEzNCA0LjQ3MTM0IDQuNjg3MjUgNC40NzEzNCA0LjQ1OTAyQzQuNDcxMzQgNC4yNjAxOSA0LjUwODMzIDQuMDcxNTIgNC41ODIzOCAzLjg5MjA1QzQuNjYxMzUgMy43MTAzNCA0Ljc2NDIxIDMuNTU0NzUgNC44OTA4NiAzLjQyNDM3QzUuMDIxOTMgMy4yODk0MiA1LjE3NDYxIDMuMTgyNzUgNS4zNDgwMiAzLjEwNTEzQzUuNTIzOCAzLjAyNDI3IDUuNzExMTMgMi45ODM2MSA1LjkxMDgzIDIuOTgzNjFINlpNMTAgMTMuMDE2NFYxMy4wMjgyVjE0SDEwLjA4OTJDMTAuNDAyNiAxNCAxMC43MDU5IDEzLjkzODQgMTAuOTk4NyAxMy44MTUzQzExLjI5MTggMTMuNjkyIDExLjU1MDYgMTMuNTE1MyAxMS43NzQyIDEzLjI4NUMxMS45OTY5IDEzLjA1NTggMTIuMTYyMSAxMi44MDUgMTIuMjY3MiAxMi41MzIzTDEyLjI2NzcgMTIuNTMxQzEyLjM2NjIgMTIuMjY0OCAxMi40MzE5IDExLjk4OCAxMi40NjQ3IDExLjcwMDhMMTIuNDY0OCAxMS42OTk1QzEyLjQ5MzIgMTEuNDE5NSAxMi41MDEzIDExLjEzMTYgMTIuNDg5MiAxMC44MzU3QzEyLjQ3NzMgMTAuNTQ2MiAxMi40NzEzIDEwLjI1NjcgMTIuNDcxMyA5Ljk2NzIxQzEyLjQ3MTMgOS43NjQ0NCAxMi41MTAzIDkuNTc0MDYgMTIuNTg4IDkuMzk0OTNMMTIuNTg4NCA5LjM5Mzk5QzEyLjY2MzEgOS4yMTcwNCAxMi43NjU4IDkuMDYxMzQgMTIuODk2OCA4LjkyNjQyQzEzLjAyMzYgOC43OTU5NSAxMy4xNzUzIDguNjg5NDUgMTMuMzUzMyA4LjYwNzVDMTMuNTI5NCA4LjUzMDQ2IDEzLjcxNSA4LjQ5MTggMTMuOTEwOCA4LjQ5MThIMTRWOC40VjcuNlY3LjUwODJIMTMuOTEwOEMxMy43MTUzIDcuNTA4MiAxMy41MyA3LjQ2NzYyIDEzLjM1NCA3LjM4NjY2TDEzLjM1MjYgNy4zODYwNEMxMy4xNzU0IDcuMzA4NDQgMTMuMDI0MiA3LjIwMjM4IDEyLjg5NzggNy4wNjgzOUwxMi44OTU5IDcuMDY2NDhDMTIuNzY1NyA2LjkzNjMgMTIuNjYzNCA2Ljc4MTI5IDEyLjU4ODcgNi42MDA1OEwxMi41ODggNi41OTg5MkMxMi41MTAxIDYuNDE5NTMgMTIuNDcxMyA2LjIzMTE3IDEyLjQ3MTMgNi4wMzI3OUMxMi40NzEzIDUuNzQzMjkgMTIuNDc3MyA1LjQ1Mzc5IDEyLjQ4OTIgNS4xNjQyOEMxMi41MDEzIDQuODY4NDIgMTIuNDkzMiA0LjU3ODQ4IDEyLjQ2NDggNC4yOTQ1NEwxMi40NjQ2IDQuMjkyODVDMTIuNDMxOCA0LjAwOTcxIDEyLjM2NjEgMy43MzUwMiAxMi4yNjc3IDMuNDY4OTdMMTIuMjY3MiAzLjQ2NzY2QzEyLjE2MjEgMy4xOTQ5OSAxMS45OTY5IDIuOTQ0MjIgMTEuNzc0MiAyLjcxNDk4QzExLjU1MDYgMi40ODQ3NCAxMS4yOTE4IDIuMzA3OTggMTAuOTk4NyAyLjE4NDczQzEwLjcwNTkgMi4wNjE2MSAxMC40MDI2IDIgMTAuMDg5MiAySDEwVjIuOFYyLjk4MzYxSDEwLjA4OTJDMTAuMjg5MSAyLjk4MzYxIDEwLjQ3NjUgMy4wMjIzIDEwLjY1MjQgMy4wOTkxN0MxMC44MjYgMy4xODA5MiAxMC45NzgxIDMuMjg3MzYgMTEuMTA5MSAzLjQxODIzQzExLjIzNjEgMy41NTMwNSAxMS4zMzkgMy43MDg4OSAxMS40MTc4IDMuODg2MjhDMTEuNDkxNiA0LjA2NTQgMTEuNTI4NyA0LjI1NTk2IDExLjUyODcgNC40NTkwMkMxMS41Mjg3IDQuNjg3MjcgMTEuNTI0NyA0LjkxMTQ1IDExLjUxNjggNS4xMzE0MkMxMS41MDg4IDUuMzU4OTQgMTEuNTA4NyA1LjU4MDQ5IDExLjUxNjggNS43OTYwNUMxMS41MjA5IDYuMDE3NTQgMTEuNTM5MiA2LjIzMTE3IDExLjU3MTggNi40MzY4OEMxMS42MDQ5IDYuNjQ5NzYgMTEuNjYwOCA2Ljg1MjQzIDExLjczOTYgNy4wNDQ2NEMxMS44MTkxIDcuMjM4NDMgMTEuOTI3NCA3LjQyMjU0IDEyLjA2MzggNy41OTcwMkMxMi4xNzY1IDcuNzQxMTkgMTIuMzE0NiA3Ljg3NTM4IDEyLjQ3NzIgOEMxMi4zMTQ2IDguMTI0NjIgMTIuMTc2NSA4LjI1ODgxIDEyLjA2MzggOC40MDI5OEMxMS45Mjc0IDguNTc3NDYgMTEuODE5MSA4Ljc2MTU3IDExLjczOTYgOC45NTUzNkMxMS42NjA5IDkuMTQ3MzcgMTEuNjA0OSA5LjM0ODI1IDExLjU3MTcgOS41NTcxNUMxMS41MzkyIDkuNzY2NyAxMS41MjA5IDkuOTgwMjcgMTEuNTE2OCAxMC4xOTc4QzExLjUwODcgMTAuNDE3NCAxMS41MDg3IDEwLjYzODkgMTEuNTE2OCAxMC44NjI1QzExLjUyNDcgMTEuMDg2NiAxMS41Mjg3IDExLjMxMjggMTEuNTI4NyAxMS41NDFDMTEuNTI4NyAxMS43Mzk4IDExLjQ5MTcgMTEuOTI4NSAxMS40MTc2IDEyLjEwNzlDMTEuMzM4NiAxMi4yODk3IDExLjIzNTggMTIuNDQ1MiAxMS4xMDkxIDEyLjU3NTZDMTAuOTc4MSAxMi43MTA2IDEwLjgyNTQgMTIuODE3MyAxMC42NTIgMTIuODk0OUMxMC40NzYyIDEyLjk3NTcgMTAuMjg4OSAxMy4wMTY0IDEwLjA4OTIgMTMuMDE2NEgxMFoiIGZpbGw9IiNDNUM1QzUiLz4KPC9zdmc+Cg==)}.hc-black .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.property:before{content:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTIuODA3MjMgMTQuOTc1NEMyLjU3MTE5IDE0Ljk3MjEgMi4zMzgyNiAxNC45MjExIDIuMTIyNDcgMTQuODI1NEMxLjkwNjY3IDE0LjcyOTcgMS43MTI0OCAxNC41OTEzIDEuNTUxNTggMTQuNDE4NkMxLjIzODUgMTQuMTMzNCAxLjA0NDMzIDEzLjc0MDggMS4wMDc3NSAxMy4zMTg5QzAuOTY2MjI1IDEyLjg4MjggMS4wOTI2OSAxMi40NDczIDEuMzYxMzMgMTIuMTAxM0MyLjU2Nzc5IDEwLjgyODkgNC45NDczIDguNDQ5NCA2LjY3ODExIDYuNzU0NzlDNi4zMDk4MyA1Ljc1ODg3IDYuMzI3MDQgNC42NjEyNyA2LjcyNjM3IDMuNjc3MzlDNy4wNTQ3NCAyLjg1ODc2IDcuNjM4NjkgMi4xNjgwNSA4LjM5MTI5IDEuNzA4MDdDOC45ODE3IDEuMzE3MDYgOS42NjAzMSAxLjA3OTQ0IDEwLjM2NTcgMS4wMTY3M0MxMS4wNzExIDAuOTU0MDIyIDExLjc4MDkgMS4wNjgxOSAxMi40MzExIDEuMzQ4OTJMMTMuMDQ4MiAxLjYxNjJMMTAuMTgyNCA0LjU2NzM4TDExLjQzNzEgNS44MjU4MkwxNC4zODA5IDIuOTQ4ODdMMTQuNjQ4MiAzLjU2Nzg4QzE0Ljg3MzUgNC4wODk3NiAxNC45OTMgNC42NTExOSAxNC45OTk3IDUuMjE5NjFDMTUuMDA2NCA1Ljc4ODAyIDE0LjkwMDIgNi4zNTIxMSAxNC42ODcyIDYuODc5MTVDMTQuNDc2IDcuNDAwMjkgMTQuMTYyMyA3Ljg3MzY4IDEzLjc2NDcgOC4yNzEyMkMxMy41Mzk0IDguNDkxNjkgMTMuMjkwNCA4LjY4NjUzIDEzLjAyMjIgOC44NTIxOEMxMi40NjczIDkuMjIyNzUgMTEuODMyNCA5LjQ1NjM2IDExLjE2OTcgOS41MzM4QzEwLjUwNjkgOS42MTEyNCA5LjgzNTIxIDkuNTMwMyA5LjIwOTgyIDkuMjk3NjRDOC4xMTE5NCAxMC40MTEzIDUuMzcxNDIgMTMuMTcwNCAzLjg5MTE5IDE0LjU1MjJDMy41OTQyNiAxNC44MjE5IDMuMjA4MzIgMTQuOTcyNiAyLjgwNzIzIDE0Ljk3NTRaTTEwLjc0NDggMS45MjgwMkMxMC4wODcgMS45MjYzNyA5LjQ0MzU5IDIuMTIwMTggOC44OTYxNCAyLjQ4NDg1QzguNjgyNjUgMi42MTUyIDguNDg0MzcgMi43Njg5NyA4LjMwNDk4IDIuOTQzM0M3LjgyNzg5IDMuNDI0MjMgNy41MDkyNiA0LjAzOTUzIDcuMzkxODIgNC43MDY2OUM3LjI3NDM4IDUuMzczODUgNy4zNjM3NCA2LjA2MDk4IDcuNjQ3OTIgNi42NzU5MUw3Ljc4MzQyIDYuOTcyODhMNy41NTA0OCA3LjIwMDI1QzUuODEyMjQgOC44OTY3MiAzLjI4MTQ2IDExLjQyMDEgMi4wNjQ3OSAxMi43MDQ1QzEuOTU2NDYgMTIuODY1OCAxLjkxMDEyIDEzLjA2MDggMS45MzQzNSAxMy4yNTM1QzEuOTU4NTcgMTMuNDQ2MyAyLjA1MTcxIDEzLjYyMzggMi4xOTY1NyAxMy43NTMyQzIuMjgwMDUgMTMuODQ2MiAyLjM4MTc3IDEzLjkyMTEgMi40OTU0MSAxMy45NzMxQzIuNTk1NTcgMTQuMDE4NCAyLjcwMzgzIDE0LjA0MyAyLjgxMzczIDE0LjA0NTVDMi45ODA2NCAxNC4wNDEzIDMuMTQwNDQgMTMuOTc3IDMuMjYzODMgMTMuODY0NkM0LjgzNjg3IDEyLjM5NjQgNy44NzYyMiA5LjMyNjQxIDguNzY4MDcgOC40MjQzNUw4Ljk5NzMgOC4xOTMyNkw5LjI5MjQyIDguMzI3ODNDOS44MDYxNyA4LjU2NzMyIDEwLjM3MzEgOC42Njk4NSAxMC45MzgyIDguNjI1NDVDMTEuNTAzMyA4LjU4MTA2IDEyLjA0NzMgOC4zOTEyNSAxMi41MTc0IDguMDc0NDdDMTIuNzMxMyA3Ljk0MjYgMTIuOTI5NiA3Ljc4Njk0IDEzLjEwODUgNy42MTA0NUMxMy40MTgzIDcuMzAxNTMgMTMuNjYzMSA2LjkzMzc0IDEzLjgyODYgNi41Mjg3NEMxMy45OTQgNi4xMjM3NSAxNC4wNzY3IDUuNjg5NzQgMTQuMDcxOSA1LjI1MjI4QzE0LjA3MTkgNS4wMzY2MiAxNC4wNTA1IDQuODIxNDggMTQuMDA3OCA0LjYxMDA3TDExLjQzMDYgNy4xMjUwOEw4Ljg3OTQ0IDQuNTc3NTlMMTEuMzk0NCAxLjk4ODM0QzExLjE4MDQgMS45NDY3NCAxMC45NjI4IDEuOTI2NTMgMTAuNzQ0OCAxLjkyODAyWiIgZmlsbD0iI0M1QzVDNSIvPgo8L3N2Zz4K)}.hc-black .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.enum:before,.hc-black .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.value:before{content:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik04IDJMNyAzVjZIOFYzSDE0VjhIMTBWOUgxNEwxNSA4VjNMMTQgMkg4Wk05IDhMOCA3SDdIMkwxIDhWMTNMMiAxNEg4TDkgMTNWOVY4Wk04IDlWOEg3SDJWMTNIOFY5Wk05IDYuNTg1NzlMOS40MTQyMSA3SDEzVjZIOVY2LjU4NTc5Wk0xMyA0SDlWNUgxM1Y0Wk03IDlIM1YxMEg3VjlaTTMgMTFIN1YxMkgzVjExWiIgZmlsbD0iI0VFOUQyOCIvPgo8L3N2Zz4K)}.hc-black .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.rule:before{content:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik00IDFMMyAyVjE0TDQgMTVIMTJMMTMgMTRWMkwxMiAxSDRaTTQgM1YySDEyVjE0SDRWMTNINlYxMkg0VjEwSDhWOUg0VjdINlY2SDRWNEg4VjNINFoiIGZpbGw9IiNDNUM1QzUiLz4KPC9zdmc+Cg==)}.hc-black .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.file:before{content:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik00IDFMMyAyVjE0TDQgMTVIMTNMMTQgMTRWNUwxMy43MDcxIDQuMjkyODlMMTAuNzA3MSAxLjI5Mjg5TDEwIDFINFpNNCAxNFYyTDkgMlY2SDEzVjE0SDRaTTEzIDVMMTAgMlY1TDEzIDVaIiBmaWxsPSIjQzVDNUM1Ii8+Cjwvc3ZnPgo=)}.hc-black .monaco-quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.string:before{content:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03LjIyMjg5IDEwLjkzM0M3LjU0ODYzIDExLjEyNTQgNy45MjE2MyAxMS4yMjMxIDguMjk5ODkgMTEuMjE1QzguNjM3NzcgMTEuMjIxOCA4Ljk3MjU0IDExLjE0OTIgOS4yNzcyMSAxMS4wMDNDOS41ODE4OCAxMC44NTY3IDkuODQ3OTIgMTAuNjQwOSAxMC4wNTM5IDEwLjM3M0MxMC41MDkxIDkuNzY1MTkgMTAuNzQwMiA5LjAxODY3IDEwLjcwNzkgOC4yNTk5OEMxMC43NDEyIDcuNTg2MjIgMTAuNTM3NCA2LjkyMjEgMTAuMTMxOSA2LjM4Mjk4QzkuOTM1NzUgNi4xNDE2MSA5LjY4NTc3IDUuOTQ5NTcgOS40MDIgNS44MjIyOEM5LjExODI0IDUuNjk0OTggOC44MDg1OCA1LjYzNTk3IDguNDk3ODkgNS42NDk5N0M4LjA3NTIyIDUuNjQ2OTkgNy42NTk5NCA1Ljc2MDg1IDcuMjk3ODkgNS45Nzg5OEM3LjE4MzA0IDYuMDQ4MDcgNy4wNzQ5IDYuMTI3NzUgNi45NzQ4OSA2LjIxNjk4VjMuNDc0OThINS45ODM4OVYxMS4xSDYuOTc4ODlWMTAuNzU2QzcuMDU1MTYgMTAuODIxNyA3LjEzNjc3IDEwLjg4MDkgNy4yMjI4OSAxMC45MzNaTTcuODQ5ODEgNi43MDAwNkM4LjAzNTk4IDYuNjIxMDUgOC4yMzgwNyA2LjU4Njc3IDguNDM5ODkgNi41OTk5OEM4LjYxMjU3IDYuNTk0NTIgOC43ODQwNCA2LjYzMDU0IDguOTM5OTQgNi43MDUwMUM5LjA5NTgzIDYuNzc5NDggOS4yMzE2MSA2Ljg5MDIzIDkuMzM1ODkgNy4wMjc5OEM5LjU5MjUzIDcuMzkwNTMgOS43MTg0IDcuODI5NTEgOS42OTI4OSA4LjI3Mjk3QzkuNzE5NzIgOC43OTc0OCA5LjU3OTY5IDkuMzE3MDEgOS4yOTI4OSA5Ljc1Njk4QzkuMTg4MjIgOS45MTUyNyA5LjA0NTQ2IDEwLjA0NDcgOC44Nzc3MyAxMC4xMzM1QzguNzA5OTkgMTAuMjIyMyA4LjUyMjY0IDEwLjI2NzUgOC4zMzI4OSAxMC4yNjVDOC4xNDkzNCAxMC4yNzMyIDcuOTY2MyAxMC4yNCA3Ljc5NzM0IDEwLjE2NzhDNy42MjgzOCAxMC4wOTU2IDcuNDc3ODQgOS45ODYyOCA3LjM1Njg5IDkuODQ3OTdDNy4xMDE1MiA5LjU1OTU3IDYuOTY1MDEgOS4xODUwNiA2Ljk3NDg5IDguNzk5OThWOC4xOTk5OEM2Ljk2Mjk5IDcuNzgzMzIgNy4xMDI2MyA3LjM3NjUgNy4zNjc4OSA3LjA1NDk4QzcuNDk4NTggNi45MDA2NCA3LjY2MzY0IDYuNzc5MDggNy44NDk4MSA2LjcwMDA2Wk0zLjI4OTAyIDUuNjc0OTlDMi45NzAxMSA1LjY3OTMzIDIuNjUzODggNS43MzQgMi4zNTIwMiA1LjgzNjk5QzIuMDY0MTcgNS45MjI5MyAxLjc5MzQ3IDYuMDU4MjggMS41NTIwMiA2LjIzNjk5TDEuNDUyMDIgNi4zMTM5OVY3LjUxMzk5TDEuODc1MDIgNy4xNTQ5OUMyLjI0NTc5IDYuODA0NzggMi43MzEzMyA2LjYwMTQ2IDMuMjQxMDIgNi41ODI5OUMzLjM2NTkzIDYuNTcxNjQgMy40OTE3IDYuNTkxNDcgMy42MDcwNiA2LjY0MDY4QzMuNzIyNDMgNi42ODk5IDMuODIzNzcgNi43NjY5NyAzLjkwMjAyIDYuODY0OTlDNC4wNTIyIDcuMDk3MSA0LjEzMjM5IDcuMzY3NTQgNC4xMzMwMiA3LjY0Mzk5TDIuOTAwMDIgNy44MjQ5OUMyLjM5NDM1IDcuODc3ODEgMS45MTUyNSA4LjA3NzcyIDEuNTIyMDIgOC4zOTk5OUMxLjM2Njk3IDguNTUxODEgMS4yNDMzOSA4LjczMjcxIDEuMTU4MzUgOC45MzIzNUMxLjA3MzMxIDkuMTMxOTkgMS4wMjg0OCA5LjM0NjQ0IDEuMDI2NDQgOS41NjM0M0MxLjAyNDQgOS43ODA0MiAxLjA2NTE3IDkuOTk1NjggMS4xNDY0NCAxMC4xOTY5QzEuMjI3NyAxMC4zOTgxIDEuMzQ3ODYgMTAuNTgxMyAxLjUwMDAyIDEwLjczNkMxLjY2ODcgMTAuODkwNCAxLjg2NjIyIDExLjAxIDIuMDgxMjUgMTEuMDg3OUMyLjI5NjI3IDExLjE2NTkgMi41MjQ1NiAxMS4yMDA1IDIuNzUzMDIgMTEuMTlDMy4xNDcgMTEuMTkzMSAzLjUzMjc4IDExLjA3NzQgMy44NjAwMiAxMC44NThDMy45NjE1MyAxMC43ODk3IDQuMDU3MiAxMC43MTMxIDQuMTQ2MDIgMTAuNjI5VjExLjA3M0g1LjA4NzAyVjcuNzE0OTlDNS4xMjEzNyA3LjE3NDIyIDQuOTU0MyA2LjYzOTg4IDQuNjE4MDIgNi4yMTQ5OUM0LjQ0OTc5IDYuMDMyODUgNC4yNDM0OCA1Ljg5MDAzIDQuMDEzNzggNS43OTY3QzMuNzg0MDcgNS43MDMzNiAzLjUzNjYxIDUuNjYxODEgMy4yODkwMiA1LjY3NDk5Wk00LjE0NjAyIDguNzE1OTlDNC4xNjU2NCA5LjEzNDM1IDQuMDI1OTIgOS41NDQ1OSAzLjc1NTAyIDkuODY0QzMuNjM2ODkgMTAuMDAwNSAzLjQ4OTk4IDEwLjEwOTIgMy4zMjQ4NiAxMC4xODIxQzMuMTU5NzMgMTAuMjU1MSAyLjk4MDQ5IDEwLjI5MDYgMi44MDAwMiAxMC4yODZDMi42OTA0OSAxMC4yOTQ1IDIuNTgwMzUgMTAuMjgxMiAyLjQ3NTk5IDEwLjI0NjlDMi4zNzE2MyAxMC4yMTI1IDIuMjc1MTEgMTAuMTU3OSAyLjE5MjAyIDEwLjA4NkMyLjA2MDc5IDkuOTM0NTUgMS45ODg1NiA5Ljc0MDg4IDEuOTg4NTYgOS41NDA0OUMxLjk4ODU2IDkuMzQwMTEgMi4wNjA3OSA5LjE0NjQ0IDIuMTkyMDIgOC45OTQ5OUMyLjQ3MzIyIDguODIxMzEgMi43OTIzMyA4LjcxODM3IDMuMTIyMDIgOC42OTQ5OUw0LjE0MjAyIDguNTQ2OTlMNC4xNDYwMiA4LjcxNTk5Wk0xMi40NTg4IDExLjAzMjVDMTIuNzY2IDExLjE2MzggMTMuMDk4MyAxMS4yMjYxIDEzLjQzMjIgMTEuMjE1QzEzLjkyNyAxMS4yMjcgMTQuNDE1MyAxMS4xMDA2IDE0Ljg0MjIgMTAuODVMMTQuOTY1MiAxMC43NzVMMTQuOTc4MiAxMC43NjhWOS42MTUwNEwxNC41MzIyIDkuOTM1MDRDMTQuMjE2IDEwLjE1OTIgMTMuODM1NiAxMC4yNzQ3IDEzLjQ0ODIgMTAuMjY0QzEzLjI0OTcgMTAuMjcxOSAxMy4wNTIgMTAuMjM0MiAxMi44NzAzIDEwLjE1MzhDMTIuNjg4NiAxMC4wNzMzIDEyLjUyNzggOS45NTIzMiAxMi40MDAyIDkuODAwMDRDMTIuMTE0NCA5LjQyNDUzIDExLjk3MjUgOC45NTkxMSAxMi4wMDAyIDguNDg4MDRDMTEuOTczNyA3Ljk4NzMyIDEyLjEzNTIgNy40OTQ3NSAxMi40NTMyIDcuMTA3MDRDMTIuNTkzNCA2Ljk0MTA1IDEyLjc2OTUgNi44MDkxNCAxMi45NjgyIDYuNzIxM0MxMy4xNjcgNi42MzM0NiAxMy4zODMxIDYuNTkyIDEzLjYwMDIgNi42MDAwNEMxMy45NDM5IDYuNTk4NDQgMTQuMjgwOCA2LjY5NTI1IDE0LjU3MTIgNi44NzkwNEwxNS4wMDAyIDcuMTQ0MDRWNS45NzAwNEwxNC44MzEyIDUuODk3MDRDMTQuNDYyNiA1LjczNDMyIDE0LjA2NDEgNS42NTAyIDEzLjY2MTIgNS42NTAwNEMxMy4yOTk5IDUuNjM5OTEgMTIuOTQwNiA1LjcwNzYyIDEyLjYwNzggNS44NDg1OUMxMi4yNzQ5IDUuOTg5NTYgMTEuOTc2MyA2LjIwMDQ4IDExLjczMjIgNi40NjcwNEMxMS4yMjYxIDcuMDI2ODMgMTAuOTU4MSA3Ljc2MTg2IDEwLjk4NTIgOC41MTYwNEMxMC45NTY3IDkuMjIzNDYgMTEuMTk1NSA5LjkxNTY5IDExLjY1NDIgMTAuNDU1QzExLjg3NjkgMTAuNzA0IDEyLjE1MTYgMTAuOTAxMiAxMi40NTg4IDExLjAzMjVaIiBmaWxsPSIjQzVDNUM1Ii8+Cjwvc3ZnPgo=)}.monaco-editor .rename-box{z-index:100;color:inherit}.monaco-editor .rename-box .rename-input{padding:4px}.monaco-editor .snippet-placeholder{min-width:2px}.monaco-editor .finish-snippet-placeholder,.monaco-editor .snippet-placeholder{outline-style:solid;outline-width:1px}.monaco-editor .suggest-widget{z-index:40;width:430px}.monaco-editor .suggest-widget>.details,.monaco-editor .suggest-widget>.message,.monaco-editor .suggest-widget>.tree{width:100%;border-style:solid;border-width:1px;box-sizing:border-box}.monaco-editor.hc-black .suggest-widget>.details,.monaco-editor.hc-black .suggest-widget>.message,.monaco-editor.hc-black .suggest-widget>.tree{border-width:2px}.monaco-editor .suggest-widget.docs-side{width:660px}.monaco-editor .suggest-widget.docs-side>.details,.monaco-editor .suggest-widget.docs-side>.tree{width:50%;float:left}.monaco-editor .suggest-widget.docs-side.list-right>.details,.monaco-editor .suggest-widget.docs-side.list-right>.tree{float:right}.monaco-editor .suggest-widget>.message{padding-left:22px}.monaco-editor .suggest-widget>.tree{height:100%}.monaco-editor .suggest-widget .monaco-list{-webkit-user-select:none;-moz-user-select:-moz-none;-ms-user-select:none;-o-user-select:none;user-select:none}.monaco-editor .suggest-widget .monaco-list .monaco-list-row{display:-ms-flexbox;display:flex;-mox-box-sizing:border-box;box-sizing:border-box;padding-right:10px;background-repeat:no-repeat;background-position:2px 2px;white-space:nowrap;cursor:pointer;-ms-touch-action:none;touch-action:none}.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents{-ms-flex:1;flex:1;height:100%;overflow:hidden;padding-left:2px}.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents>.main{display:-ms-flexbox;display:flex;overflow:hidden;text-overflow:ellipsis;white-space:pre}.monaco-editor .suggest-widget:not(.frozen) .monaco-highlighted-label .highlight{font-weight:700}.monaco-editor .suggest-widget .details>.monaco-scrollable-element>.body>.header>.close,.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents>.main>.readMore{opacity:.6;background-position:50%;background-repeat:no-repeat;background-size:70%;cursor:pointer}.monaco-editor .suggest-widget .details>.monaco-scrollable-element>.body>.header>.close{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03Ljk5OTk4IDguNzA3MDhMMTEuNjQ2NCAxMi4zNTM1TDEyLjM1MzUgMTEuNjQ2NEw4LjcwNzA4IDcuOTk5OThMMTIuMzUzNSA0LjM1MzUzTDExLjY0NjQgMy42NDY0Mkw3Ljk5OTk4IDcuMjkyODdMNC4zNTM1MyAzLjY0NjQyTDMuNjQ2NDIgNC4zNTM1M0w3LjI5Mjg3IDcuOTk5OThMMy42NDY0MiAxMS42NDY0TDQuMzUzNTMgMTIuMzUzNUw3Ljk5OTk4IDguNzA3MDhaIiBmaWxsPSIjNDI0MjQyIi8+Cjwvc3ZnPgo=");position:absolute;top:0;right:0;margin-right:5px}.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents>.main>.readMore{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0zIDcuNUMzIDQuNDYyNDMgNS40NjI0MyAyIDguNSAyQzExLjUzNzYgMiAxNCA0LjQ2MjQzIDE0IDcuNUMxNCAxMC41Mzc2IDExLjUzNzYgMTMgOC41IDEzQzUuNDYyNDMgMTMgMyAxMC41Mzc2IDMgNy41Wk0yIDcuNUMyIDMuOTEwMTUgNC45MTAxNSAxIDguNSAxQzEyLjA4OTkgMSAxNSAzLjkxMDE1IDE1IDcuNUMxNSAxMS4wODk5IDEyLjA4OTkgMTQgOC41IDE0QzQuOTEwMTUgMTQgMiAxMS4wODk5IDIgNy41Wk04IDVWNEg5VjVIOFpNOCAxMFY5TDggN1Y2SDlWN0w5IDlWMTBIOFoiIGZpbGw9IiM0MjQyNDIiLz4KPC9zdmc+Cg==")}.monaco-editor .suggest-widget .details>.monaco-scrollable-element>.body>.header>.close:hover,.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents>.main>.readMore:hover{opacity:1}.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents>.main>.type-label{margin-left:.8em;-ms-flex:1;flex:1;text-align:right;overflow:hidden;text-overflow:ellipsis;opacity:.7;white-space:nowrap}.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents>.main>.type-label>.monaco-tokenized-source{display:inline}.monaco-editor .suggest-widget.docs-below .monaco-list .monaco-list-row.focused>.contents>.main>.readMore,.monaco-editor .suggest-widget.docs-side .monaco-list .monaco-list-row.focused>.contents>.main>.readMore,.monaco-editor .suggest-widget.docs-side .monaco-list .monaco-list-row.focused>.contents>.main>.type-label,.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents>.main>.readMore,.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents>.main>.type-label{display:none}.monaco-editor .suggest-widget .monaco-list .monaco-list-row.focused>.contents>.main>.readMore,.monaco-editor .suggest-widget .monaco-list .monaco-list-row.focused>.contents>.main>.type-label{display:inline}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .monaco-icon-label.deprecated{opacity:.66;text-decoration:unset}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .monaco-icon-label.deprecated>.monaco-icon-label-description-container{text-decoration:line-through}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .monaco-icon-label:before{height:100%}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon{display:block;height:16px;width:16px;margin-left:2px;background-repeat:no-repeat;background-size:80%;background-position:50%}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.hide,.monaco-editor .suggest-widget.no-icons .monaco-list .monaco-list-row .icon,.monaco-editor .suggest-widget.no-icons .monaco-list .monaco-list-row .monaco-icon-label.suggest-icon:before{display:none}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .monaco-icon-label.suggest-icon:before{content:" ";background-repeat:no-repeat;background-position:50%;background-size:75%}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.constructor:before,.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.function:before,.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.method:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0yIDQuODU3NDlMMi40ODU1IDRMNy40ODU1IDFIOC41MTQ1TDEzLjUxNDUgNEwxNCA0Ljg1NzQ5VjEwLjg1NzVMMTMuNTE0NSAxMS43MTVMOC41MTQ1IDE0LjcxNUg3LjQ4NTVMMi40ODU1IDExLjcxNUwyIDEwLjg1NzVWNC44NTc0OVpNNy41IDEzLjU1NzVMMyAxMC44NTc1VjUuNjk5NzVMNy41IDguMTU0M1YxMy41NTc1Wk04LjUgMTMuNTU3NUwxMyAxMC44NTc1VjUuNjk5NzVMOC41IDguMTU0M1YxMy41NTc1Wk04IDEuODU3NDlMMy4yNTkxMyA0LjcwMjAxTDggNy4yODc5NEwxMi43NDA5IDQuNzAyMDFMOCAxLjg1NzQ5WiIgZmlsbD0iIzY1MkQ5MCIvPgo8L3N2Zz4K")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.field:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xIDYuMzk0NDNMMS41NTI3OSA1LjVMOC41NTI3OSAySDkuNDQ3MjFMMTQuNDQ3MiA0LjVMMTUgNS4zOTQ0M1Y5Ljg5NDQzTDE0LjQ0NzIgMTAuNzg4OUw3LjQ0NzIxIDE0LjI4ODlINi41NTI3OUwxLjU1Mjc5IDExLjc4ODlMMSAxMC44OTQ0VjYuMzk0NDNaTTYuNSAxMy4xNDQ0TDIgMTAuODk0NFY3LjE3MDk0TDYuNSA5LjIxNjM5VjEzLjE0NDRaTTcuNSAxMy4xNDQ0TDE0IDkuODk0NDNWNi4xNzk1NEw3LjUgOS4yMTI4N1YxMy4xNDQ0Wk05IDIuODk0NDNMMi4zMzcyOCA2LjIyNTc5TDYuOTk3MjUgOC4zNDM5NkwxMy42NzA2IDUuMjI5NzNMOSAyLjg5NDQzWiIgZmlsbD0iIzAwN0FDQyIvPgo8L3N2Zz4K")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.event:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03LjQxMzU0IDEuNTU5OTZMOC4zMTE1MiAxSDExLjYwNTZMMTIuNDI0IDIuNTc0NjVMMTAuMjM1NiA2SDEyLjAxNzRMMTIuNzM2MyA3LjY5NTEyTDUuNjE5NDMgMTVMNC4wMTY3NSAxMy44MzdMNi4xMTk0MyAxMEg0Ljg5Nzk4TDQgOC41NTk5Nkw3LjQxMzU0IDEuNTU5OTZaTTcuNzgwMzMgOUw0LjkwMDU0IDE0LjMwNDlMMTIuMDE3NCA3SDguMzExNTJMMTEuNjA1NiAySDguMzExNTJMNC44OTc5OCA5SDcuNzgwMzNaIiBmaWxsPSIjRDY3RTAwIi8+Cjwvc3ZnPgo=")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.operator:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0yLjg3Mjg5IDEuMTAwMjNDMy4yMDc2OCAxLjIzNTc5IDMuNDc1NDUgMS40OTggMy42MTgwMiAxLjgyOTg4QzMuNjkwMzIgMS45OTk1OSAzLjcyNjc1IDIuMTgyNDIgMy43MjUwMiAyLjM2Njg4QzMuNzI2MTcgMi41NDk5OSAzLjY4OTc1IDIuNzMxNCAzLjYxODAyIDIuODk5ODhDMy41MTI5OSAzLjE0NTY3IDMuMzM3ODIgMy4zNTUwMyAzLjExNDQyIDMuNTAxNzdDMi44OTEwMiAzLjY0ODUxIDIuNjI5MyAzLjcyNjEyIDIuMzYyMDIgMy43MjQ4OEMyLjE3OTI0IDMuNzI1OTIgMS45OTgxOCAzLjY4OTUxIDEuODMwMDIgMy42MTc4OEMxLjU4Mjk4IDMuNTE0MDYgMS4zNzIyNyAzLjMzOTMyIDEuMjI0NTMgMy4xMTU3NUMxLjA3NjggMi44OTIxOSAwLjk5ODY2NiAyLjYyOTg0IDEuMDAwMDIgMi4zNjE4OEMwLjk5OTEzIDIuMTc5MjEgMS4wMzUxOSAxLjk5ODI1IDEuMTA2MDIgMS44Mjk4OEMxLjI0MzM3IDEuNTAzMTQgMS41MDMyOCAxLjI0MzIzIDEuODMwMDIgMS4xMDU4OEMyLjE2MzMyIDAuOTY2NjkyIDIuNTM4MDkgMC45NjQ2NjEgMi44NzI4OSAxLjEwMDIzWk0yLjU3NTAyIDIuODY0ODhDMi43MDU0IDIuODA5MTMgMi44MDkyNyAyLjcwNTI2IDIuODY1MDIgMi41NzQ4OEMyLjg5MjkgMi41MDgzOCAyLjkwNzE4IDIuNDM2OTggMi45MDcwMiAyLjM2NDg4QzIuOTA4MTMgMi4yNjU0IDIuODgyMTUgMi4xNjc1IDIuODMxODUgMi4wODE2N0MyLjc4MTU2IDEuOTk1ODQgMi43MDg4NCAxLjkyNTMxIDIuNjIxNTEgMS44Nzc2N0MyLjUzNDE4IDEuODMwMDIgMi40MzU1MyAxLjgwNzA1IDIuMzM2MTQgMS44MTEyMUMyLjIzNjc0IDEuODE1MzcgMi4xNDAzNSAxLjg0NjUgMi4wNTczMSAxLjkwMTI4QzEuOTc0MjYgMS45NTYwNiAxLjkwNzcgMi4wMzI0MSAxLjg2NDc1IDIuMTIyMTVDMS44MjE4IDIuMjExODggMS44MDQwOSAyLjMxMTYxIDEuODEzNTIgMi40MTA2NUMxLjgyMjk0IDIuNTA5NjggMS44NTkxNSAyLjYwNDI4IDEuOTE4MjUgMi42ODQzQzEuOTc3MzYgMi43NjQzMyAyLjA1NzEzIDIuODI2NzUgMi4xNDkwMiAyLjg2NDg4QzIuMjg1NDkgMi45MjA4OSAyLjQzODU0IDIuOTIwODkgMi41NzUwMiAyLjg2NDg4Wk02LjQyOTk1IDEuMTA5NUwxLjEwOTY3IDYuNDI5NzdMMS43OTU1NyA3LjExNTY3TDcuMTE1ODQgMS43OTU0TDYuNDI5OTUgMS4xMDk1Wk0xMS41IDguOTk5OTlIMTIuNVYxMS41SDE1VjEyLjVIMTIuNVYxNUgxMS41VjEyLjVIOVYxMS41SDExLjVWOC45OTk5OVpNNS43Njc3NyA5LjUyNTA5TDYuNDc0ODcgMTAuMjMyMkw0LjcwNzExIDEyTDYuNDc0ODcgMTMuNzY3N0w1Ljc2Nzc3IDE0LjQ3NDhMNCAxMi43MDcxTDIuMjMyMjMgMTQuNDc0OEwxLjUyNTEzIDEzLjc2NzdMMy4yOTI4OSAxMkwxLjUyNTEzIDEwLjIzMjJMMi4yMzIyMyA5LjUyNTA5TDQgMTEuMjkyOUw1Ljc2Nzc3IDkuNTI1MDlaTTcuMTE4MDIgNS4zMjk4OEM3LjAxNDQyIDUuMDgyNjggNi44Mzk3MyA0Ljg3MTgzIDYuNjE2MTIgNC43MjQwNkM2LjM5MjUgNC41NzYyOSA2LjEzMDA0IDQuNDk4MjYgNS44NjIwMiA0LjQ5OTg4QzUuNjc5MzUgNC40OTg5OSA1LjQ5ODM5IDQuNTM1MDUgNS4zMzAwMiA0LjYwNTg4QzUuMDAzMjggNC43NDMyMyA0Ljc0MzM3IDUuMDAzMTQgNC42MDYwMiA1LjMyOTg4QzQuNTM1ODggNS40OTQ3OCA0LjQ5ODk3IDUuNjcxOTEgNC40OTc0MSA1Ljg1MTFDNC40OTU4NiA2LjAzMDMgNC41Mjk2NyA2LjIwODA0IDQuNTk2OTMgNi4zNzQxNEM0LjY2NDE5IDYuNTQwMjQgNC43NjM1NiA2LjY5MTQzIDQuODg5MzYgNi44MTkwNkM1LjAxNTE2IDYuOTQ2NjkgNS4xNjQ5IDcuMDQ4MjMgNS4zMzAwMiA3LjExNzg4QzUuNDk4NjcgNy4xODg0OCA1LjY3OTY4IDcuMjI0ODQgNS44NjI1MiA3LjIyNDg0QzYuMDQ1MzUgNy4yMjQ4NCA2LjIyNjM2IDcuMTg4NDggNi4zOTUwMiA3LjExNzg4QzYuNjQyMDEgNy4wMTM4OCA2Ljg1MjcgNi44MzkxMyA3LjAwMDU4IDYuNjE1NjNDNy4xNDg0NSA2LjM5MjEzIDcuMjI2ODkgNi4xMjk4NyA3LjIyNjAyIDUuODYxODhDNy4yMjY1NSA1LjY3OTA1IDcuMTg5OCA1LjQ5ODAzIDcuMTE4MDIgNS4zMjk4OFpNNi4zNjUwMiA2LjA3NDg4QzYuMzM3NjYgNi4xMzkzNyA2LjI5ODI5IDYuMTk4MDggNi4yNDkwMiA2LjI0Nzg4QzYuMTk5MDggNi4yOTcyNCA2LjE0MDQyIDYuMzM2OTEgNi4wNzYwMiA2LjM2NDg4QzYuMDA4NTQgNi4zOTI5NyA1LjkzNjExIDYuNDA3MjUgNS44NjMwMiA2LjQwNjg4QzUuNzg5OTEgNi40MDc0NCA1LjcxNzQ0IDYuMzkzMTUgNS42NTAwMiA2LjM2NDg4QzUuNTg1NDEgNi4zMzcyOSA1LjUyNjY4IDYuMjk3NTcgNS40NzcwMiA2LjI0Nzg4QzUuNDI2OTEgNi4xOTg1NiA1LjM4NzEzIDYuMTM5NzUgNS4zNjAwMiA2LjA3NDg4QzUuMzA0MDEgNS45Mzg0IDUuMzA0MDEgNS43ODUzNiA1LjM2MDAyIDUuNjQ4ODhDNS40MTUzNiA1LjUxODQ2IDUuNTE5NDEgNS40MTQ3NyA1LjY1MDAyIDUuMzU5ODhDNS43MTczNyA1LjMzMTI2IDUuNzg5ODQgNS4zMTY2MyA1Ljg2MzAyIDUuMzE2ODhDNS45MzYxOCA1LjMxNjg1IDYuMDA4NiA1LjMzMTQ3IDYuMDc2MDIgNS4zNTk4OEM2LjE0MDM3IDUuMzg3NDkgNi4xOTkwNCA1LjQyNjgyIDYuMjQ5MDIgNS40NzU4OEM2LjI5Nzg2IDUuNTI2MDMgNi4zMzcxNiA1LjU4NDY1IDYuMzY1MDIgNS42NDg4OEM2LjM5MzQgNS43MTYzIDYuNDA4MDIgNS43ODg3MiA2LjQwODAyIDUuODYxODhDNi40MDgwMiA1LjkzNTAzIDYuMzkzNCA2LjAwNzQ1IDYuMzY1MDIgNi4wNzQ4OFpNMTQgM0gxMFY0SDE0VjNaIiBmaWxsPSIjNDI0MjQyIi8+Cjwvc3ZnPgo=")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.variable:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xLjUgNEwxIDQuNVYxMi41TDEuNSAxM0g0VjEySDJWNUg0VjRIMS41Wk0xNC41IDEzTDE1IDEyLjVMMTUgNC41TDE0LjUgNEgxMlY1TDE0IDVMMTQgMTJIMTJWMTNIMTQuNVpNOC43OTY5MyA1TDQuMjk2OTMgN0w0IDcuNDU2OTFWOS45NTY5MUw0LjI0Mjc1IDEwLjM4NTdMNi43NDI3NSAxMS44ODU3TDcuMjAzMDcgMTEuOTEzOEwxMS43MDMxIDkuOTEzODFMMTIgOS40NTY5MVY2Ljk1NjkxTDExLjc1NzIgNi41MjgxNkw5LjI1NzI1IDUuMDI4MTZMOC43OTY5MyA1Wk01IDguMzRWOS42NzM4MUw2LjUgMTAuNTczOFY5LjI0TDUgOC4zNFpNNy41IDkuMjgxODRWMTAuNjg3NUwxMSA5LjEzMTk3VjcuNzI2MjlMNy41IDkuMjgxODRaTTEwLjQxNzggNi44OTA3MUw4Ljk2NTU5IDYuMDE5MzZMNS41ODIxNiA3LjUyMzExTDcuMDM0NDEgOC4zOTQ0NUwxMC40MTc4IDYuODkwNzFaIiBmaWxsPSIjMDA3QUNDIi8+Cjwvc3ZnPgo=")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.class:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0zLjM1MzU2IDYuNjQ2NDJMMi4wNjA2NiA1LjM1MzUzTDUuMzUzNTYgMi4wNjA2NUw2LjY0NjQ1IDMuMzUzNTRMMy4zNTM1NiA2LjY0NjQyWk01IDFMMSA0Ljk5OTk4VjUuNzA3MDhMMyA3LjcwNzA3SDMuNzA3MTFMNC44NTM1NSA2LjU2MDYzVjEyLjM1MzVMNS4zNTM1NSAxMi44NTM1SDEwLjAwOTdWMTMuMzc0MUwxMS4zNDMgMTQuNzA3NEgxMi4wNTAxTDE0LjcxNjggMTIuMDQwN1YxMS4zMzM2TDEzLjM4MzUgMTAuMDAwM0gxMi42NzYzTDEwLjgyMzEgMTEuODUzNUg1Ljg1MzU1VjcuODkzNTVIMTAuMDA5N1Y4LjM3NDAxTDExLjM0MyA5LjcwNzM0SDEyLjA1MDFMMTQuNzE2OCA3LjA0MDY4VjYuMzMzNTdMMTMuMzgzNSA1LjAwMDI0SDEyLjY3NjNMMTAuODYzIDYuODEzNTZINS44NTM1NVY1LjU2MDY0TDcuNzA3MTEgMy43MDcwOVYyLjk5OTk5TDUuNzA3MTEgMUg1Wk0xMS4wNzAzIDguMDIwNDZMMTEuNjk2NiA4LjY0NjY4TDEzLjY1NjEgNi42ODcxM0wxMy4wMjk5IDYuMDYwOUwxMS4wNzAzIDguMDIwNDZaTTExLjA3MDMgMTMuMDIwNUwxMS42OTY2IDEzLjY0NjdMMTMuNjU2MSAxMS42ODcyTDEzLjAyOTkgMTEuMDYxTDExLjA3MDMgMTMuMDIwNVoiIGZpbGw9IiNENjdFMDAiLz4KPC9zdmc+Cg==")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.interface:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMS41IDVDMTAuMTE5MyA1IDkgNi4xMTkyOSA5IDcuNUM5IDguODgwNzEgMTAuMTE5MyAxMCAxMS41IDEwQzEyLjg4MDcgMTAgMTQgOC44ODA3MSAxNCA3LjVDMTQgNi4xMTkyOSAxMi44ODA3IDUgMTEuNSA1Wk04LjAzNTQ0IDhDOC4yNzgwNiA5LjY5NjE1IDkuNzM2NzYgMTEgMTEuNSAxMUMxMy40MzMgMTEgMTUgOS40MzMgMTUgNy41QzE1IDUuNTY3IDEzLjQzMyA0IDExLjUgNEM5LjczNjc2IDQgOC4yNzgwNiA1LjMwMzg1IDguMDM1NDQgN0g0LjkzNjk5QzQuNzE0OTcgNi4xMzczOSAzLjkzMTkyIDUuNSAzIDUuNUMxLjg5NTQzIDUuNSAxIDYuMzk1NDMgMSA3LjVDMSA4LjYwNDU3IDEuODk1NDMgOS41IDMgOS41QzMuOTMxOTIgOS41IDQuNzE0OTcgOC44NjI2MSA0LjkzNjk5IDhIOC4wMzU0NFoiIGZpbGw9IiMwMDdBQ0MiLz4KPC9zdmc+Cg==")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.struct:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0yIDJMMSAzVjZMMiA3SDE0TDE1IDZWM0wxNCAySDJaTTIgM0gzSDEzSDE0VjRWNVY2SDEzSDNIMlY1VjRWM1pNMSAxMEwyIDlINUw2IDEwVjEzTDUgMTRIMkwxIDEzVjEwWk0zIDEwSDJWMTFWMTJWMTNIM0g0SDVWMTJWMTFWMTBINEgzWk0xMCAxMEwxMSA5SDE0TDE1IDEwVjEzTDE0IDE0SDExTDEwIDEzVjEwWk0xMiAxMEgxMVYxMVYxMlYxM0gxMkgxM0gxNFYxMlYxMVYxMEgxM0gxMloiIGZpbGw9IiM0MjQyNDIiLz4KPC9zdmc+Cg==")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.type-parameter:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMSA2SDEwVjUuNUMxMCA1LjIyMzg2IDkuNzc2MTYgNSA5LjUwMDAxIDVIOC40NzkwMlYxMC41QzguNDc5MDIgMTAuNzc2MSA4LjcwMjg4IDExIDguOTc5MDIgMTFIOS40NzkwMlYxMkg2LjQ3OTAyVjExSDYuOTc5MDJDNy4yNTUxNiAxMSA3LjQ3OTAyIDEwLjc3NjEgNy40NzkwMiAxMC41VjVINi41MDAwMUM2LjIyMzg3IDUgNi4wMDAwMSA1LjIyMzg2IDYuMDAwMDEgNS41VjZINS4wMDAwMVY0SDExVjZaTTEzLjkxNDIgOC4wNDgxTDEyLjQ1MTkgNi41ODU4MUwxMy4xNTkgNS44Nzg3MUwxNC45NzQ5IDcuNjk0NTRWOC40MDE2NUwxMy4yMDcxIDEwLjE2OTRMMTIuNSA5LjQ2MjMxTDEzLjkxNDIgOC4wNDgxWk0zLjU0ODEgOS40NjIzTDIuMDg1ODEgOC4wMDAwMkwzLjUwMDAyIDYuNTg1ODFMMi43OTI5MSA1Ljg3ODdMMS4wMjUxNSA3LjY0NjQ3VjguMzUzNTdMMi44NDEgMTAuMTY5NEwzLjU0ODEgOS40NjIzWiIgZmlsbD0iIzQyNDI0MiIvPgo8L3N2Zz4K")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.module:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik02IDIuOTgzNjFWMi45NzE4NFYySDUuOTEwODNDNS41OTc0MyAyIDUuMjk0MDcgMi4wNjE2MSA1LjAwMTI4IDIuMTg0NzNDNC43MDgxOCAyLjMwNzk4IDQuNDQ5NDIgMi40ODQ3NCA0LjIyNTc4IDIuNzE0OThDNC4wMDMxMSAyLjk0NDIyIDMuODM3OTIgMy4xOTQ5OCAzLjczMjgyIDMuNDY3NjZMMy43MzIzMyAzLjQ2ODk4QzMuNjMzODIgMy43MzUyIDMuNTY4MTQgNC4wMTIwMSAzLjUzNTMzIDQuMjk5MTdMMy41MzUxOSA0LjMwMDUzQzMuNTA2NzggNC41ODA1IDMuNDk4NyA0Ljg2ODQ0IDMuNTEwODQgNS4xNjQyOEMzLjUyMjcyIDUuNDUzNzkgMy41Mjg2NiA1Ljc0MzI5IDMuNTI4NjYgNi4wMzI3OUMzLjUyODY2IDYuMjM1NTYgMy40ODk3NCA2LjQyNTk0IDMuNDEyIDYuNjA1MDdMMy40MTE2IDYuNjA2MDFDMy4zMzY4NyA2Ljc4Mjk2IDMuMjM0MjMgNi45Mzg2NiAzLjEwMzE3IDcuMDczNTlDMi45NzY0NCA3LjIwNDA1IDIuODI0NjYgNy4zMTA1NSAyLjY0NjcyIDcuMzkyNUMyLjQ3MDYgNy40Njk1NCAyLjI4NDk3IDcuNTA4MiAyLjA4OTE3IDcuNTA4MkgyVjcuNlY4LjRWOC40OTE4SDIuMDg5MTdDMi4yODQ2NSA4LjQ5MTggMi40NzAwMSA4LjUzMjM4IDIuNjQ2MDEgOC42MTMzNEwyLjY0NzQyIDguNjEzOTZDMi44MjQ1NyA4LjY5MTU3IDIuOTc1NzcgOC43OTc2MiAzLjEwMjIxIDguOTMxNjFMMy4xMDQxMiA4LjkzMzUyQzMuMjM0MjggOS4wNjM3IDMuMzM2NTkgOS4yMTg3MSAzLjQxMTI5IDkuMzk5NDJMMy40MTIwMSA5LjQwMTA4QzMuNDg5ODYgOS41ODA0NyAzLjUyODY2IDkuNzY4ODMgMy41Mjg2NiA5Ljk2NzIxQzMuNTI4NjYgMTAuMjU2NyAzLjUyMjcyIDEwLjU0NjIgMy41MTA4NCAxMC44MzU3QzMuNDk4NyAxMS4xMzE2IDMuNTA2NzcgMTEuNDIxNSAzLjUzNTE2IDExLjcwNTVMMy41MzUzNSAxMS43MDcyQzMuNTY4MTkgMTEuOTkwMyAzLjYzMzg3IDEyLjI2NSAzLjczMjMyIDEyLjUzMUwzLjczMjgzIDEyLjUzMjNDMy44Mzc5MyAxMi44MDUgNC4wMDMxMSAxMy4wNTU4IDQuMjI1NzggMTMuMjg1QzQuNDQ5NDIgMTMuNTE1MyA0LjcwODE4IDEzLjY5MiA1LjAwMTI4IDEzLjgxNTNDNS4yOTQwNyAxMy45Mzg0IDUuNTk3NDMgMTQgNS45MTA4MyAxNEg2VjEzLjJWMTMuMDE2NEg1LjkxMDgzQzUuNzEwOTUgMTMuMDE2NCA1LjUyMzQ2IDEyLjk3NzcgNS4zNDc2MyAxMi45MDA4QzUuMTczOTYgMTIuODE5MSA1LjAyMTk0IDEyLjcxMjYgNC44OTA4NiAxMi41ODE4QzQuNzYzODYgMTIuNDQ2OSA0LjY2MTA0IDEyLjI5MTEgNC41ODIyMyAxMi4xMTM3QzQuNTA4MzggMTEuOTM0NiA0LjQ3MTM0IDExLjc0NCA0LjQ3MTM0IDExLjU0MUM0LjQ3MTM0IDExLjMxMjcgNC40NzUzIDExLjA4ODUgNC40ODMyMSAxMC44Njg2QzQuNDkxMjUgMTAuNjQxMSA0LjQ5MTI3IDEwLjQxOTUgNC40ODMyNCAxMC4yMDM5QzQuNDc5MTQgOS45ODI0NiA0LjQ2MDg0IDkuNzY4ODMgNC40MjgyMyA5LjU2MzEyQzQuMzk1MTMgOS4zNTAyNCA0LjMzOTIxIDkuMTQ3NTcgNC4yNjAzOSA4Ljk1NTM2QzQuMTgwOTEgOC43NjE1NyA0LjA3MjU4IDguNTc3NDYgMy45MzYxNiA4LjQwMjk4QzMuODIzNDUgOC4yNTg4MSAzLjY4NTM4IDguMTI0NjIgMy41MjI4MyA4QzMuNjg1MzggNy44NzUzOCAzLjgyMzQ1IDcuNzQxMTkgMy45MzYxNiA3LjU5NzAyQzQuMDcyNTggNy40MjI1NCA0LjE4MDkxIDcuMjM4NDMgNC4yNjAzOSA3LjA0NDY0QzQuMzM5MTMgNi44NTI2MyA0LjM5NTEzIDYuNjUxNzUgNC40MjgyNiA2LjQ0Mjg1QzQuNDYwODIgNi4yMzMzIDQuNDc5MTQgNi4wMTk3MyA0LjQ4MzI0IDUuODAyMTlDNC40OTEyNyA1LjU4MjYyIDQuNDkxMjUgNS4zNjEwNSA0LjQ4MzIxIDUuMTM3NDlDNC40NzUzIDQuOTEzNCA0LjQ3MTM0IDQuNjg3MjUgNC40NzEzNCA0LjQ1OTAyQzQuNDcxMzQgNC4yNjAxOSA0LjUwODMzIDQuMDcxNTIgNC41ODIzOCAzLjg5MjA1QzQuNjYxMzUgMy43MTAzNCA0Ljc2NDIxIDMuNTU0NzUgNC44OTA4NiAzLjQyNDM3QzUuMDIxOTMgMy4yODk0MiA1LjE3NDYxIDMuMTgyNzUgNS4zNDgwMiAzLjEwNTEzQzUuNTIzOCAzLjAyNDI3IDUuNzExMTMgMi45ODM2MSA1LjkxMDgzIDIuOTgzNjFINlpNMTAgMTMuMDE2NFYxMy4wMjgyVjE0SDEwLjA4OTJDMTAuNDAyNiAxNCAxMC43MDU5IDEzLjkzODQgMTAuOTk4NyAxMy44MTUzQzExLjI5MTggMTMuNjkyIDExLjU1MDYgMTMuNTE1MyAxMS43NzQyIDEzLjI4NUMxMS45OTY5IDEzLjA1NTggMTIuMTYyMSAxMi44MDUgMTIuMjY3MiAxMi41MzIzTDEyLjI2NzcgMTIuNTMxQzEyLjM2NjIgMTIuMjY0OCAxMi40MzE5IDExLjk4OCAxMi40NjQ3IDExLjcwMDhMMTIuNDY0OCAxMS42OTk1QzEyLjQ5MzIgMTEuNDE5NSAxMi41MDEzIDExLjEzMTYgMTIuNDg5MiAxMC44MzU3QzEyLjQ3NzMgMTAuNTQ2MiAxMi40NzEzIDEwLjI1NjcgMTIuNDcxMyA5Ljk2NzIxQzEyLjQ3MTMgOS43NjQ0NCAxMi41MTAzIDkuNTc0MDYgMTIuNTg4IDkuMzk0OTNMMTIuNTg4NCA5LjM5Mzk5QzEyLjY2MzEgOS4yMTcwNCAxMi43NjU4IDkuMDYxMzQgMTIuODk2OCA4LjkyNjQyQzEzLjAyMzYgOC43OTU5NSAxMy4xNzUzIDguNjg5NDUgMTMuMzUzMyA4LjYwNzVDMTMuNTI5NCA4LjUzMDQ2IDEzLjcxNSA4LjQ5MTggMTMuOTEwOCA4LjQ5MThIMTRWOC40VjcuNlY3LjUwODJIMTMuOTEwOEMxMy43MTUzIDcuNTA4MiAxMy41MyA3LjQ2NzYyIDEzLjM1NCA3LjM4NjY2TDEzLjM1MjYgNy4zODYwNEMxMy4xNzU0IDcuMzA4NDQgMTMuMDI0MiA3LjIwMjM4IDEyLjg5NzggNy4wNjgzOUwxMi44OTU5IDcuMDY2NDhDMTIuNzY1NyA2LjkzNjMgMTIuNjYzNCA2Ljc4MTI5IDEyLjU4ODcgNi42MDA1OEwxMi41ODggNi41OTg5MkMxMi41MTAxIDYuNDE5NTMgMTIuNDcxMyA2LjIzMTE3IDEyLjQ3MTMgNi4wMzI3OUMxMi40NzEzIDUuNzQzMjkgMTIuNDc3MyA1LjQ1Mzc5IDEyLjQ4OTIgNS4xNjQyOEMxMi41MDEzIDQuODY4NDIgMTIuNDkzMiA0LjU3ODQ4IDEyLjQ2NDggNC4yOTQ1NEwxMi40NjQ2IDQuMjkyODVDMTIuNDMxOCA0LjAwOTcxIDEyLjM2NjEgMy43MzUwMiAxMi4yNjc3IDMuNDY4OTdMMTIuMjY3MiAzLjQ2NzY2QzEyLjE2MjEgMy4xOTQ5OSAxMS45OTY5IDIuOTQ0MjIgMTEuNzc0MiAyLjcxNDk4QzExLjU1MDYgMi40ODQ3NCAxMS4yOTE4IDIuMzA3OTggMTAuOTk4NyAyLjE4NDczQzEwLjcwNTkgMi4wNjE2MSAxMC40MDI2IDIgMTAuMDg5MiAySDEwVjIuOFYyLjk4MzYxSDEwLjA4OTJDMTAuMjg5MSAyLjk4MzYxIDEwLjQ3NjUgMy4wMjIzIDEwLjY1MjQgMy4wOTkxN0MxMC44MjYgMy4xODA5MiAxMC45NzgxIDMuMjg3MzYgMTEuMTA5MSAzLjQxODIzQzExLjIzNjEgMy41NTMwNSAxMS4zMzkgMy43MDg4OSAxMS40MTc4IDMuODg2MjhDMTEuNDkxNiA0LjA2NTQgMTEuNTI4NyA0LjI1NTk2IDExLjUyODcgNC40NTkwMkMxMS41Mjg3IDQuNjg3MjcgMTEuNTI0NyA0LjkxMTQ1IDExLjUxNjggNS4xMzE0MkMxMS41MDg4IDUuMzU4OTQgMTEuNTA4NyA1LjU4MDQ5IDExLjUxNjggNS43OTYwNUMxMS41MjA5IDYuMDE3NTQgMTEuNTM5MiA2LjIzMTE3IDExLjU3MTggNi40MzY4OEMxMS42MDQ5IDYuNjQ5NzYgMTEuNjYwOCA2Ljg1MjQzIDExLjczOTYgNy4wNDQ2NEMxMS44MTkxIDcuMjM4NDMgMTEuOTI3NCA3LjQyMjU0IDEyLjA2MzggNy41OTcwMkMxMi4xNzY1IDcuNzQxMTkgMTIuMzE0NiA3Ljg3NTM4IDEyLjQ3NzIgOEMxMi4zMTQ2IDguMTI0NjIgMTIuMTc2NSA4LjI1ODgxIDEyLjA2MzggOC40MDI5OEMxMS45Mjc0IDguNTc3NDYgMTEuODE5MSA4Ljc2MTU3IDExLjczOTYgOC45NTUzNkMxMS42NjA5IDkuMTQ3MzcgMTEuNjA0OSA5LjM0ODI1IDExLjU3MTcgOS41NTcxNUMxMS41MzkyIDkuNzY2NyAxMS41MjA5IDkuOTgwMjcgMTEuNTE2OCAxMC4xOTc4QzExLjUwODcgMTAuNDE3NCAxMS41MDg3IDEwLjYzODkgMTEuNTE2OCAxMC44NjI1QzExLjUyNDcgMTEuMDg2NiAxMS41Mjg3IDExLjMxMjggMTEuNTI4NyAxMS41NDFDMTEuNTI4NyAxMS43Mzk4IDExLjQ5MTcgMTEuOTI4NSAxMS40MTc2IDEyLjEwNzlDMTEuMzM4NiAxMi4yODk3IDExLjIzNTggMTIuNDQ1MiAxMS4xMDkxIDEyLjU3NTZDMTAuOTc4MSAxMi43MTA2IDEwLjgyNTQgMTIuODE3MyAxMC42NTIgMTIuODk0OUMxMC40NzYyIDEyLjk3NTcgMTAuMjg4OSAxMy4wMTY0IDEwLjA4OTIgMTMuMDE2NEgxMFoiIGZpbGw9IiM0MjQyNDIiLz4KPC9zdmc+Cg==")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.property:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTIuODA3MjMgMTQuOTc1NEMyLjU3MTE5IDE0Ljk3MjEgMi4zMzgyNiAxNC45MjExIDIuMTIyNDcgMTQuODI1NEMxLjkwNjY3IDE0LjcyOTcgMS43MTI0OCAxNC41OTEzIDEuNTUxNTggMTQuNDE4NkMxLjIzODUgMTQuMTMzNCAxLjA0NDMzIDEzLjc0MDggMS4wMDc3NSAxMy4zMTg5QzAuOTY2MjI1IDEyLjg4MjggMS4wOTI2OSAxMi40NDczIDEuMzYxMzMgMTIuMTAxM0MyLjU2Nzc5IDEwLjgyODkgNC45NDczIDguNDQ5NCA2LjY3ODExIDYuNzU0NzlDNi4zMDk4MyA1Ljc1ODg3IDYuMzI3MDQgNC42NjEyNyA2LjcyNjM3IDMuNjc3MzlDNy4wNTQ3NCAyLjg1ODc2IDcuNjM4NjkgMi4xNjgwNSA4LjM5MTI5IDEuNzA4MDdDOC45ODE3IDEuMzE3MDYgOS42NjAzMSAxLjA3OTQ0IDEwLjM2NTcgMS4wMTY3M0MxMS4wNzExIDAuOTU0MDIyIDExLjc4MDkgMS4wNjgxOSAxMi40MzExIDEuMzQ4OTJMMTMuMDQ4MiAxLjYxNjJMMTAuMTgyNCA0LjU2NzM4TDExLjQzNzEgNS44MjU4MkwxNC4zODA5IDIuOTQ4ODdMMTQuNjQ4MiAzLjU2Nzg4QzE0Ljg3MzUgNC4wODk3NiAxNC45OTMgNC42NTExOSAxNC45OTk3IDUuMjE5NjFDMTUuMDA2NCA1Ljc4ODAyIDE0LjkwMDIgNi4zNTIxMSAxNC42ODcyIDYuODc5MTVDMTQuNDc2IDcuNDAwMjkgMTQuMTYyMyA3Ljg3MzY4IDEzLjc2NDcgOC4yNzEyMkMxMy41Mzk0IDguNDkxNjkgMTMuMjkwNCA4LjY4NjUzIDEzLjAyMjIgOC44NTIxOEMxMi40NjczIDkuMjIyNzUgMTEuODMyNCA5LjQ1NjM2IDExLjE2OTcgOS41MzM4QzEwLjUwNjkgOS42MTEyNCA5LjgzNTIxIDkuNTMwMyA5LjIwOTgyIDkuMjk3NjRDOC4xMTE5NCAxMC40MTEzIDUuMzcxNDIgMTMuMTcwNCAzLjg5MTE5IDE0LjU1MjJDMy41OTQyNiAxNC44MjE5IDMuMjA4MzIgMTQuOTcyNiAyLjgwNzIzIDE0Ljk3NTRaTTEwLjc0NDggMS45MjgwMkMxMC4wODcgMS45MjYzNyA5LjQ0MzU5IDIuMTIwMTggOC44OTYxNCAyLjQ4NDg1QzguNjgyNjUgMi42MTUyIDguNDg0MzcgMi43Njg5NyA4LjMwNDk4IDIuOTQzM0M3LjgyNzg5IDMuNDI0MjMgNy41MDkyNiA0LjAzOTUzIDcuMzkxODIgNC43MDY2OUM3LjI3NDM3IDUuMzczODUgNy4zNjM3NCA2LjA2MDk4IDcuNjQ3OTIgNi42NzU5MUw3Ljc4MzQyIDYuOTcyODhMNy41NTA0OCA3LjIwMDI1QzUuODEyMjQgOC44OTY3MiAzLjI4MTQ2IDExLjQyMDEgMi4wNjQ3OSAxMi43MDQ1QzEuOTU2NDYgMTIuODY1OCAxLjkxMDEyIDEzLjA2MDggMS45MzQzNSAxMy4yNTM1QzEuOTU4NTcgMTMuNDQ2MyAyLjA1MTcxIDEzLjYyMzggMi4xOTY1NyAxMy43NTMyQzIuMjgwMDUgMTMuODQ2MiAyLjM4MTc3IDEzLjkyMTEgMi40OTU0MSAxMy45NzMxQzIuNTk1NTcgMTQuMDE4NCAyLjcwMzgzIDE0LjA0MyAyLjgxMzczIDE0LjA0NTVDMi45ODA2NCAxNC4wNDEzIDMuMTQwNDQgMTMuOTc3IDMuMjYzODMgMTMuODY0NkM0LjgzNjg3IDEyLjM5NjQgNy44NzYyMiA5LjMyNjQxIDguNzY4MDcgOC40MjQzNUw4Ljk5NzMgOC4xOTMyNkw5LjI5MjQyIDguMzI3ODNDOS44MDYxOCA4LjU2NzMyIDEwLjM3MzEgOC42Njk4NSAxMC45MzgyIDguNjI1NDVDMTEuNTAzMyA4LjU4MTA2IDEyLjA0NzMgOC4zOTEyNSAxMi41MTc0IDguMDc0NDdDMTIuNzMxMyA3Ljk0MjYgMTIuOTI5NiA3Ljc4Njk0IDEzLjEwODUgNy42MTA0NUMxMy40MTgzIDcuMzAxNTMgMTMuNjYzMSA2LjkzMzc0IDEzLjgyODYgNi41Mjg3NEMxMy45OTQgNi4xMjM3NSAxNC4wNzY3IDUuNjg5NzQgMTQuMDcxOSA1LjI1MjI4QzE0LjA3MTkgNS4wMzY2MiAxNC4wNTA1IDQuODIxNDggMTQuMDA3OCA0LjYxMDA3TDExLjQzMDYgNy4xMjUwOEw4Ljg3OTQ0IDQuNTc3NTlMMTEuMzk0NCAxLjk4ODM0QzExLjE4MDQgMS45NDY3NCAxMC45NjI4IDEuOTI2NTMgMTAuNzQ0OCAxLjkyODAyWiIgZmlsbD0iIzQyNDI0MiIvPgo8L3N2Zz4K")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.unit:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik00IDFMMyAyVjE0TDQgMTVIMTJMMTMgMTRWMkwxMiAxSDRaTTQgM1YySDEyVjE0SDRWMTNINlYxMkg0VjEwSDhWOUg0VjdINlY2SDRWNEg4VjNINFoiIGZpbGw9IiM0MjQyNDIiLz4KPC9zdmc+Cg==")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.constant:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik00IDZIMTJWN0g0VjZaTTEyIDlINFYxMEgxMlY5WiIgZmlsbD0iIzQyNDI0MiIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTEgNEwyIDNIMTRMMTUgNFYxMkwxNCAxM0gyTDEgMTJWNFpNMiA0VjEySDE0VjRIMloiIGZpbGw9IiM0MjQyNDIiLz4KPC9zdmc+Cg==")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.enum:before,.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.value:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik04IDJMNyAzVjZIOFYzSDE0VjhIMTBWOUgxNEwxNSA4VjNMMTQgMkg4Wk05IDhMOCA3SDdIMkwxIDhWMTNMMiAxNEg4TDkgMTNWOVY4Wk04IDlWOEg3SDJWMTNIOFY5Wk05IDYuNTg1NzlMOS40MTQyMSA3SDEzVjZIOVY2LjU4NTc5Wk0xMyA0SDlWNUgxM1Y0Wk03IDlIM1YxMEg3VjlaTTMgMTFIN1YxMkgzVjExWiIgZmlsbD0iI0Q2N0UwMCIvPgo8L3N2Zz4K")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.enum-member:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03IDNMOCAySDE0TDE1IDNWOEwxNCA5SDEwVjhIMTRWM0g4VjZIN1YzWk04IDdMOSA4VjlWMTNMOCAxNEgyTDEgMTNWOEwyIDdIN0g4Wk04IDhWOVYxM0gyVjhIN0g4Wk05LjQxNDIxIDdMOSA2LjU4NTc5VjZIMTNWN0g5LjQxNDIxWk05IDRIMTNWNUg5VjRaTTcgMTBIM1YxMUg3VjEwWiIgZmlsbD0iIzAwN0FDQyIvPgo8L3N2Zz4K")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.keyword:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTE1IDRIMTBWM0gxNVY0Wk0xNCA3SDEyVjhIMTRWN1pNMTAgN0gxVjhIMTBWN1pNMTIgMTNIMVYxNEgxMlYxM1pNNyAxMEgxVjExSDdWMTBaTTE1IDEwSDEwVjExSDE1VjEwWk04IDJWNUgxVjJIOFpNNyAzSDJWNEg3VjNaIiBmaWxsPSIjNDI0MjQyIi8+Cjwvc3ZnPgo=")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.text:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03LjIyMjg5IDEwLjkzM0M3LjU0ODYzIDExLjEyNTQgNy45MjE2MyAxMS4yMjMxIDguMjk5ODkgMTEuMjE1QzguNjM3NzcgMTEuMjIxOCA4Ljk3MjU0IDExLjE0OTIgOS4yNzcyMSAxMS4wMDNDOS41ODE4OCAxMC44NTY3IDkuODQ3OTIgMTAuNjQwOSAxMC4wNTM5IDEwLjM3M0MxMC41MDkxIDkuNzY1MTkgMTAuNzQwMiA5LjAxODY3IDEwLjcwNzkgOC4yNTk5OEMxMC43NDEyIDcuNTg2MjIgMTAuNTM3NCA2LjkyMjEgMTAuMTMxOSA2LjM4Mjk4QzkuOTM1NzUgNi4xNDE2MSA5LjY4NTc3IDUuOTQ5NTcgOS40MDIgNS44MjIyOEM5LjExODI0IDUuNjk0OTggOC44MDg1OCA1LjYzNTk3IDguNDk3ODkgNS42NDk5N0M4LjA3NTIyIDUuNjQ2OTkgNy42NTk5NCA1Ljc2MDg1IDcuMjk3ODkgNS45Nzg5OEM3LjE4MzA0IDYuMDQ4MDcgNy4wNzQ5IDYuMTI3NzUgNi45NzQ4OSA2LjIxNjk4VjMuNDc0OThINS45ODM4OVYxMS4xSDYuOTc4ODlWMTAuNzU2QzcuMDU1MTYgMTAuODIxNyA3LjEzNjc3IDEwLjg4MDkgNy4yMjI4OSAxMC45MzNaTTcuODQ5ODEgNi43MDAwNkM4LjAzNTk4IDYuNjIxMDUgOC4yMzgwNyA2LjU4Njc3IDguNDM5ODkgNi41OTk5OEM4LjYxMjU3IDYuNTk0NTIgOC43ODQwNCA2LjYzMDU0IDguOTM5OTQgNi43MDUwMUM5LjA5NTgzIDYuNzc5NDggOS4yMzE2MSA2Ljg5MDIzIDkuMzM1ODkgNy4wMjc5OEM5LjU5MjUzIDcuMzkwNTMgOS43MTg0IDcuODI5NTEgOS42OTI4OSA4LjI3Mjk3QzkuNzE5NzIgOC43OTc0OCA5LjU3OTY5IDkuMzE3MDEgOS4yOTI4OSA5Ljc1Njk4QzkuMTg4MjIgOS45MTUyNyA5LjA0NTQ2IDEwLjA0NDcgOC44Nzc3MyAxMC4xMzM1QzguNzA5OTkgMTAuMjIyMyA4LjUyMjY0IDEwLjI2NzUgOC4zMzI4OSAxMC4yNjVDOC4xNDkzNCAxMC4yNzMyIDcuOTY2MyAxMC4yNCA3Ljc5NzM0IDEwLjE2NzhDNy42MjgzOCAxMC4wOTU2IDcuNDc3ODQgOS45ODYyOCA3LjM1Njg5IDkuODQ3OTdDNy4xMDE1MiA5LjU1OTU3IDYuOTY1MDEgOS4xODUwNiA2Ljk3NDg5IDguNzk5OThWOC4xOTk5OEM2Ljk2Mjk5IDcuNzgzMzIgNy4xMDI2MyA3LjM3NjUgNy4zNjc4OSA3LjA1NDk4QzcuNDk4NTggNi45MDA2NCA3LjY2MzY0IDYuNzc5MDggNy44NDk4MSA2LjcwMDA2Wk0zLjI4OTAyIDUuNjc0OTlDMi45NzAxMSA1LjY3OTMzIDIuNjUzODggNS43MzQgMi4zNTIwMiA1LjgzNjk5QzIuMDY0MTcgNS45MjI5MyAxLjc5MzQ3IDYuMDU4MjggMS41NTIwMiA2LjIzNjk5TDEuNDUyMDIgNi4zMTM5OVY3LjUxMzk5TDEuODc1MDIgNy4xNTQ5OUMyLjI0NTc5IDYuODA0NzggMi43MzEzMyA2LjYwMTQ2IDMuMjQxMDIgNi41ODI5OUMzLjM2NTkzIDYuNTcxNjQgMy40OTE3IDYuNTkxNDcgMy42MDcwNiA2LjY0MDY4QzMuNzIyNDMgNi42ODk5IDMuODIzNzcgNi43NjY5NyAzLjkwMjAyIDYuODY0OTlDNC4wNTIyIDcuMDk3MSA0LjEzMjM5IDcuMzY3NTQgNC4xMzMwMiA3LjY0Mzk5TDIuOTAwMDIgNy44MjQ5OUMyLjM5NDM1IDcuODc3ODEgMS45MTUyNSA4LjA3NzcyIDEuNTIyMDIgOC4zOTk5OUMxLjM2Njk3IDguNTUxODEgMS4yNDMzOSA4LjczMjcxIDEuMTU4MzUgOC45MzIzNUMxLjA3MzMxIDkuMTMxOTkgMS4wMjg0OCA5LjM0NjQ0IDEuMDI2NDQgOS41NjM0M0MxLjAyNDQgOS43ODA0MiAxLjA2NTE3IDkuOTk1NjggMS4xNDY0NCAxMC4xOTY5QzEuMjI3NyAxMC4zOTgxIDEuMzQ3ODYgMTAuNTgxMyAxLjUwMDAyIDEwLjczNkMxLjY2ODcgMTAuODkwNCAxLjg2NjIyIDExLjAxIDIuMDgxMjUgMTEuMDg3OUMyLjI5NjI3IDExLjE2NTkgMi41MjQ1NiAxMS4yMDA1IDIuNzUzMDIgMTEuMTlDMy4xNDcgMTEuMTkzMSAzLjUzMjc4IDExLjA3NzQgMy44NjAwMiAxMC44NThDMy45NjE1MyAxMC43ODk3IDQuMDU3MiAxMC43MTMxIDQuMTQ2MDIgMTAuNjI5VjExLjA3M0g1LjA4NzAyVjcuNzE0OTlDNS4xMjEzNyA3LjE3NDIyIDQuOTU0MyA2LjYzOTg4IDQuNjE4MDIgNi4yMTQ5OUM0LjQ0OTc5IDYuMDMyODUgNC4yNDM0OCA1Ljg5MDAzIDQuMDEzNzggNS43OTY3QzMuNzg0MDcgNS43MDMzNiAzLjUzNjYxIDUuNjYxODEgMy4yODkwMiA1LjY3NDk5Wk00LjE0NjAyIDguNzE1OTlDNC4xNjU2NCA5LjEzNDM1IDQuMDI1OTIgOS41NDQ1OSAzLjc1NTAyIDkuODY0QzMuNjM2ODkgMTAuMDAwNSAzLjQ4OTk4IDEwLjEwOTIgMy4zMjQ4NiAxMC4xODIxQzMuMTU5NzMgMTAuMjU1MSAyLjk4MDQ5IDEwLjI5MDYgMi44MDAwMiAxMC4yODZDMi42OTA0OSAxMC4yOTQ1IDIuNTgwMzUgMTAuMjgxMiAyLjQ3NTk5IDEwLjI0NjlDMi4zNzE2MyAxMC4yMTI1IDIuMjc1MTEgMTAuMTU3OSAyLjE5MjAyIDEwLjA4NkMyLjA2MDc5IDkuOTM0NTUgMS45ODg1NiA5Ljc0MDg4IDEuOTg4NTYgOS41NDA0OUMxLjk4ODU2IDkuMzQwMTEgMi4wNjA3OSA5LjE0NjQ0IDIuMTkyMDIgOC45OTQ5OUMyLjQ3MzIyIDguODIxMzEgMi43OTIzMyA4LjcxODM3IDMuMTIyMDIgOC42OTQ5OUw0LjE0MjAyIDguNTQ2OTlMNC4xNDYwMiA4LjcxNTk5Wk0xMi40NTg4IDExLjAzMjVDMTIuNzY2IDExLjE2MzggMTMuMDk4MyAxMS4yMjYxIDEzLjQzMjIgMTEuMjE1QzEzLjkyNyAxMS4yMjcgMTQuNDE1MyAxMS4xMDA2IDE0Ljg0MjIgMTAuODVMMTQuOTY1MiAxMC43NzVMMTQuOTc4MiAxMC43NjhWOS42MTUwNEwxNC41MzIyIDkuOTM1MDRDMTQuMjE2IDEwLjE1OTIgMTMuODM1NiAxMC4yNzQ3IDEzLjQ0ODIgMTAuMjY0QzEzLjI0OTcgMTAuMjcxOSAxMy4wNTIgMTAuMjM0MiAxMi44NzAzIDEwLjE1MzhDMTIuNjg4NiAxMC4wNzMzIDEyLjUyNzggOS45NTIzMiAxMi40MDAyIDkuODAwMDRDMTIuMTE0NCA5LjQyNDUzIDExLjk3MjUgOC45NTkxMSAxMi4wMDAyIDguNDg4MDRDMTEuOTczNyA3Ljk4NzMyIDEyLjEzNTIgNy40OTQ3NSAxMi40NTMyIDcuMTA3MDRDMTIuNTkzNCA2Ljk0MTA1IDEyLjc2OTUgNi44MDkxNCAxMi45NjgyIDYuNzIxM0MxMy4xNjcgNi42MzM0NiAxMy4zODMxIDYuNTkyIDEzLjYwMDIgNi42MDAwNEMxMy45NDM5IDYuNTk4NDQgMTQuMjgwOCA2LjY5NTI1IDE0LjU3MTIgNi44NzkwNEwxNS4wMDAyIDcuMTQ0MDRWNS45NzAwNEwxNC44MzEyIDUuODk3MDRDMTQuNDYyNiA1LjczNDMyIDE0LjA2NDEgNS42NTAyIDEzLjY2MTIgNS42NTAwNEMxMy4yOTk5IDUuNjM5OTEgMTIuOTQwNiA1LjcwNzYyIDEyLjYwNzggNS44NDg1OUMxMi4yNzQ5IDUuOTg5NTYgMTEuOTc2MyA2LjIwMDQ4IDExLjczMjIgNi40NjcwNEMxMS4yMjYxIDcuMDI2ODMgMTAuOTU4MSA3Ljc2MTg2IDEwLjk4NTIgOC41MTYwNEMxMC45NTY3IDkuMjIzNDYgMTEuMTk1NSA5LjkxNTY5IDExLjY1NDIgMTAuNDU1QzExLjg3NjkgMTAuNzA0IDEyLjE1MTYgMTAuOTAxMiAxMi40NTg4IDExLjAzMjVaIiBmaWxsPSIjNDI0MjQyIi8+Cjwvc3ZnPgo=")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.color:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik02LjYgMTEuNzY3M0M3LjMyODcxIDExLjAzODMgNy4zMjg3MSA5Ljg1NjM4IDYuNiA5LjEyNzQyQzUuODcwODMgOC4zOTg0NSA0LjY4OTEzIDguMzk4NDUgMy45NTk5NiA5LjEyNzQyQzIuOTE4MTIgMTAuMjI0OSAxLjEwNDExIDkuOTM5MDEgMS4wMTI5IDguNDI4NTNDMS4wMDQzNCA4LjI4Njc5IDEgOC4xNDM5IDEgOEMxIDQuMTMzOTkgNC4xMzQwNSAxIDggMUMxMS44NjYgMSAxNSA0LjEzMzk5IDE1IDhDMTUgMTEuODY2IDExLjg2NiAxNSA4IDE1QzcuNzk3NzQgMTUgNy41OTc0OSAxNC45OTE0IDcuMzk5NTkgMTQuOTc0NkM1LjgwNjQ2IDE0LjgzOTMgNS40OTg2IDEyLjkyNjMgNi42IDExLjc2NzNaTTYuOTY2NzUgMTMuNTQzNEM2LjkwMjUxIDEzLjI0NjQgNi45ODgyMSAxMi44MTUgNy4zMTgxOSAxMi40NjMyQzguNDI2MjkgMTEuMzQyOSA4LjQyMjY0IDkuNTM2MjMgNy4zMDcyMyA4LjQyMDQzTDcuMzA3MDEgOC40MjAyMUM2LjE4NzM0IDcuMzAwODUgNC4zNzI2MiA3LjMwMDg1IDMuMjUyOTUgOC40MjAyMUwzLjI0MzcxIDguNDI5NDVMMy4yMzQ3MSA4LjQzODkzQzIuOTM5MDMgOC43NTA0IDIuNTcwOTEgOC44MjU5OSAyLjMzMjUgOC43NzY2OEMyLjIxOTM2IDguNzUzMjggMi4xNTAyMSA4LjcwNjY3IDIuMTA5NzkgOC42NjE2MUMyLjA3MzkzIDguNjIxNjIgMi4wMjE0NiA4LjU0MDE2IDIuMDExMDggOC4zNjgyNkMyLjAwMzczIDguMjQ2NTYgMiA4LjEyMzc4IDIgOEMyIDQuNjg2MjggNC42ODYzMyAyIDggMkMxMS4zMTM3IDIgMTQgNC42ODYyOCAxNCA4QzE0IDExLjMxMzcgMTEuMzEzNyAxNCA4IDE0QzcuODI2MDIgMTQgNy42NTQgMTMuOTkyNiA3LjQ4NDIxIDEzLjk3ODJDNy4yODk5MiAxMy45NjE3IDcuMTg0ODggMTMuODk4NyA3LjEyNDE0IDEzLjg0MjlDNy4wNTgzMSAxMy43ODI0IDYuOTk3NjcgMTMuNjg2NCA2Ljk2Njc1IDEzLjU0MzRaTTUgNkM1LjU1MjI4IDYgNiA1LjU1MjI4IDYgNUM2IDQuNDQ3NzIgNS41NTIyOCA0IDUgNEM0LjQ0NzcyIDQgNCA0LjQ0NzcyIDQgNUM0IDUuNTUyMjggNC40NDc3MiA2IDUgNlpNMTIgMTFDMTIgMTEuNTUyMyAxMS41NTIzIDEyIDExIDEyQzEwLjQ0NzcgMTIgMTAgMTEuNTUyMyAxMCAxMUMxMCAxMC40NDc3IDEwLjQ0NzcgMTAgMTEgMTBDMTEuNTUyMyAxMCAxMiAxMC40NDc3IDEyIDExWk04IDVDOC41NTIyOCA1IDkgNC41NTIyOCA5IDRDOSAzLjQ0NzcyIDguNTUyMjggMyA4IDNDNy40NDc3MiAzIDcgMy40NDc3MiA3IDRDNyA0LjU1MjI4IDcuNDQ3NzIgNSA4IDVaTTEzIDhDMTMgOC41NTIyOCAxMi41NTIzIDkgMTIgOUMxMS40NDc3IDkgMTEgOC41NTIyOCAxMSA4QzExIDcuNDQ3NzIgMTEuNDQ3NyA3IDEyIDdDMTIuNTUyMyA3IDEzIDcuNDQ3NzIgMTMgOFpNMTEgNkMxMS41NTIzIDYgMTIgNS41NTIyOCAxMiA1QzEyIDQuNDQ3NzIgMTEuNTUyMyA0IDExIDRDMTAuNDQ3NyA0IDEwIDQuNDQ3NzIgMTAgNUMxMCA1LjU1MjI4IDEwLjQ0NzcgNiAxMSA2WiIgZmlsbD0iIzQyNDI0MiIvPgo8L3N2Zz4K")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.file:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik00IDFMMyAyVjE0TDQgMTVIMTNMMTQgMTRWNUwxMy43MDcxIDQuMjkyODlMMTAuNzA3MSAxLjI5Mjg5TDEwIDFINFpNNCAxNFYyTDkgMlY2SDEzVjE0SDRaTTEzIDVMMTAgMlY1TDEzIDVaIiBmaWxsPSIjNDI0MjQyIi8+Cjwvc3ZnPgo=")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.reference:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik04LjA2MDY1IDMuODUzNTZMNS45MTQyMSA2TDUuMjA3MSA1LjI5Mjg5TDYuNDk5OTkgNEgzLjVDMy4xMDIxOCA0IDIuNzIwNjQgNC4xNTgwNCAyLjQzOTM0IDQuNDM5MzRDMi4xNTgwNCA0LjcyMDY1IDIgNS4xMDIxOCAyIDUuNUMyIDUuODk3ODMgMi4xNTgwNCA2LjI3OTM2IDIuNDM5MzQgNi41NjA2NkMyLjcyMDY0IDYuODQxOTcgMy4xMDIxOCA3IDMuNSA3SDRWOEgzLjVDMi44MzY5NiA4IDIuMjAxMDcgNy43MzY2MSAxLjczMjIzIDcuMjY3NzdDMS4yNjMzOSA2Ljc5ODkzIDEgNi4xNjMwNSAxIDUuNUMxIDQuODM2OTYgMS4yNjMzOSA0LjIwMTA4IDEuNzMyMjMgMy43MzIyNEMyLjIwMTA3IDMuMjYzNCAyLjgzNjk2IDMgMy41IDNINi40OTk5OUw2LjQ5OTk5IDNINi40OTk5Nkw2IDIuNTAwMDRWMi41MDAwMUw1LjIwNzEgMS43MDcxMUw1LjkxNDIxIDFMOC4wNjA2NSAzLjE0NjQ1TDguMDYwNjUgMy44NTM1NlpNNSA2LjUwMDAzTDUuOTE0MjEgNy40MTQyNEw2IDcuMzI4NDVWMTRIMTRWN0gxMFYzSDkuMDYwNjVWMi43MzIyN0w4LjMyODM4IDJIMTEuMkwxMS41IDIuMUwxNC45IDUuNkwxNSA2VjE0LjVMMTQuNSAxNUg1LjVMNSAxNC41VjkuMDAwMDNWNi41MDAwM1pNMTEgM1Y2SDEzLjkwMzJMMTEgM1oiIGZpbGw9IiM0MjQyNDIiLz4KPC9zdmc+Cg==")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.snippet:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0yLjUgMUwyIDEuNVYxM0gzVjJIMTRWMTNIMTVWMS41TDE0LjUgMUgyLjVaTTIgMTVWMTRIM1YxNUgyWk01IDE0LjAwMDFINFYxNS4wMDAxSDVWMTQuMDAwMVpNNiAxNC4wMDAxSDdWMTUuMDAwMUg2VjE0LjAwMDFaTTkgMTQuMDAwMUg4VjE1LjAwMDFIOVYxNC4wMDAxWk0xMCAxNC4wMDAxSDExVjE1LjAwMDFIMTBWMTQuMDAwMVpNMTUgMTUuMDAwMVYxNC4wMDAxSDE0VjE1LjAwMDFIMTVaTTEyIDE0LjAwMDFIMTNWMTUuMDAwMUgxMlYxNC4wMDAxWiIgZmlsbD0iIzQyNDI0MiIvPgo8L3N2Zz4K")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.customcolor:before{background-image:none}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon.folder:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xLjAxMDg3IDIuNUwxLjUxMDg3IDJINi41MDcxM0w2Ljg2MDY4IDIuMTQ2NDVMNy43MTM0OSAyLjk5OTI1SDE0LjUwMTFMMTUuMDAxMSAzLjQ5OTI1VjguOTk1MTJMMTQuOTkwMyA5LjAwNTk5VjEzLjUwMjFMMTQuNDkwMyAxNC4wMDIxSDEuNUwxIDEzLjUwMjFWNi41MDczNUwxLjAxMDg3IDYuNDk2NDhWMi41Wk0xNC4wMDExIDMuOTk5MjVWNS4wMDMxMUg3LjUwMDVMNy4xNDY5NSA1LjE0OTU2TDYuMjg5MTUgNi4wMDczNUgyLjAxMDg3VjNINi4zMDAwMkw3LjE1MjgzIDMuODUyOEw3LjUwNjM4IDMuOTk5MjVIMTQuMDAxMVpNNi40OTYyNiA3LjAwNzM1SDIuMDEwODdWNy40OTU4OEgxLjk5OTYzVjExLjQ5MjlIMlYxMy4wMDIxSDEzLjk5MDNWMTEuNDkyOUgxMy45OTA2VjcuNDk1ODhIMTMuOTkwM1Y2LjAwMzExSDcuNzA3NjFMNi44NDk4MSA2Ljg2MDlMNi40OTYyNiA3LjAwNzM1WiIgZmlsbD0iIzQyNDI0MiIvPgo8L3N2Zz4K")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.customcolor .colorspan{margin:0 0 0 .3em;border:.1em solid #000;width:.7em;height:.7em;display:inline-block}.monaco-editor .suggest-widget .details{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;cursor:default}.monaco-editor .suggest-widget .details.no-docs{display:none}.monaco-editor .suggest-widget.docs-below .details{border-top-width:0}.monaco-editor .suggest-widget .details>.monaco-scrollable-element{-ms-flex:1;flex:1}.monaco-editor .suggest-widget .details>.monaco-scrollable-element>.body{position:absolute;box-sizing:border-box;height:100%;width:100%}.monaco-editor .suggest-widget .details>.monaco-scrollable-element>.body>.header>.type{-ms-flex:2;flex:2;overflow:hidden;text-overflow:ellipsis;opacity:.7;word-break:break-all;margin:0 24px 0 0;padding:4px 0 12px 5px}.monaco-editor .suggest-widget .details>.monaco-scrollable-element>.body>.docs{margin:0;padding:4px 5px;white-space:pre-wrap}.monaco-editor .suggest-widget .details>.monaco-scrollable-element>.body>.docs.markdown-docs{padding:0;white-space:normal}.monaco-editor .suggest-widget .details>.monaco-scrollable-element>.body>.docs.markdown-docs>div,.monaco-editor .suggest-widget .details>.monaco-scrollable-element>.body>.docs.markdown-docs>span:not(:empty){padding:4px 5px}.monaco-editor .suggest-widget .details>.monaco-scrollable-element>.body>.docs.markdown-docs>div>p:first-child{margin-top:0}.monaco-editor .suggest-widget .details>.monaco-scrollable-element>.body>.docs.markdown-docs>div>p:last-child{margin-bottom:0}.monaco-editor .suggest-widget .details>.monaco-scrollable-element>.body>.docs .code{white-space:pre-wrap;word-wrap:break-word}.monaco-editor .suggest-widget .details>.monaco-scrollable-element>.body>p:empty{display:none}.monaco-editor .suggest-widget .details code{border-radius:3px;padding:0 .4em}.monaco-editor.hc-black .suggest-widget .details>.monaco-scrollable-element>.body>.header>.close,.monaco-editor.vs-dark .suggest-widget .details>.monaco-scrollable-element>.body>.header>.close{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03Ljk5OTk4IDguNzA3MDhMMTEuNjQ2NCAxMi4zNTM1TDEyLjM1MzUgMTEuNjQ2NEw4LjcwNzA4IDcuOTk5OThMMTIuMzUzNSA0LjM1MzUzTDExLjY0NjQgMy42NDY0Mkw3Ljk5OTk4IDcuMjkyODdMNC4zNTM1MyAzLjY0NjQyTDMuNjQ2NDIgNC4zNTM1M0w3LjI5Mjg3IDcuOTk5OThMMy42NDY0MiAxMS42NDY0TDQuMzUzNTMgMTIuMzUzNUw3Ljk5OTk4IDguNzA3MDhaIiBmaWxsPSIjQzVDNUM1Ii8+Cjwvc3ZnPgo=")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row>.contents>.main>.readMore,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row>.contents>.main>.readMore{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0zIDcuNUMzIDQuNDYyNDMgNS40NjI0MyAyIDguNSAyQzExLjUzNzYgMiAxNCA0LjQ2MjQzIDE0IDcuNUMxNCAxMC41Mzc2IDExLjUzNzYgMTMgOC41IDEzQzUuNDYyNDMgMTMgMyAxMC41Mzc2IDMgNy41Wk0yIDcuNUMyIDMuOTEwMTUgNC45MTAxNSAxIDguNSAxQzEyLjA4OTkgMSAxNSAzLjkxMDE1IDE1IDcuNUMxNSAxMS4wODk5IDEyLjA4OTkgMTQgOC41IDE0QzQuOTEwMTUgMTQgMiAxMS4wODk5IDIgNy41Wk04IDRWNUg5VjRIOFpNOCA2TDggMTBIOUw5IDZIOFoiIGZpbGw9IiNDNUM1QzUiLz4KPC9zdmc+Cg==")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.constructor:before,.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.function:before,.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.method:before,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.constructor:before,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.function:before,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.method:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0yIDQuODU3NDlMMi40ODU1IDRMNy40ODU1IDFIOC41MTQ1TDEzLjUxNDUgNEwxNCA0Ljg1NzQ5VjEwLjg1NzVMMTMuNTE0NSAxMS43MTVMOC41MTQ1IDE0LjcxNUg3LjQ4NTVMMi40ODU1IDExLjcxNUwyIDEwLjg1NzVWNC44NTc0OVpNNy41IDEzLjU1NzVMMyAxMC44NTc1VjUuNjk5NzVMNy41IDguMTU0M1YxMy41NTc1Wk04LjUgMTMuNTU3NUwxMyAxMC44NTc1VjUuNjk5NzVMOC41IDguMTU0M1YxMy41NTc1Wk04IDEuODU3NDlMMy4yNTkxMyA0LjcwMjAxTDggNy4yODc5NEwxMi43NDA5IDQuNzAyMDFMOCAxLjg1NzQ5WiIgZmlsbD0iI0IxODBENyIvPgo8L3N2Zz4K")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.field:before,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.field:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xIDYuMzk0NDNMMS41NTI3OSA1LjVMOC41NTI3OSAySDkuNDQ3MjFMMTQuNDQ3MiA0LjVMMTUgNS4zOTQ0M1Y5Ljg5NDQzTDE0LjQ0NzIgMTAuNzg4OUw3LjQ0NzIxIDE0LjI4ODlINi41NTI3OUwxLjU1Mjc5IDExLjc4ODlMMSAxMC44OTQ0VjYuMzk0NDNaTTYuNSAxMy4xNDQ0TDIgMTAuODk0NFY3LjE3MDk0TDYuNSA5LjIxNjM5VjEzLjE0NDRaTTcuNSAxMy4xNDQ0TDE0IDkuODk0NDNWNi4xNzk1NEw3LjUgOS4yMTI4N1YxMy4xNDQ0Wk05IDIuODk0NDNMMi4zMzcyOCA2LjIyNTc5TDYuOTk3MjUgOC4zNDM5NkwxMy42NzA2IDUuMjI5NzNMOSAyLjg5NDQzWiIgZmlsbD0iIzc1QkVGRiIvPgo8L3N2Zz4K")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.event:before,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.event:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03LjQxMzU0IDEuNTU5OTZMOC4zMTE1MiAxSDExLjYwNTZMMTIuNDI0IDIuNTc0NjVMMTAuMjM1NiA2SDEyLjAxNzRMMTIuNzM2MyA3LjY5NTEyTDUuNjE5NDMgMTVMNC4wMTY3NSAxMy44MzdMNi4xMTk0MyAxMEg0Ljg5Nzk4TDQgOC41NTk5Nkw3LjQxMzU0IDEuNTU5OTZaTTcuNzgwMzMgOUw0LjkwMDU0IDE0LjMwNDlMMTIuMDE3NCA3SDguMzExNTJMMTEuNjA1NiAySDguMzExNTJMNC44OTc5OCA5SDcuNzgwMzNaIiBmaWxsPSIjRDY3RTAwIi8+Cjwvc3ZnPgo=")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.operator:before,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.operator:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0yLjg3Mjg5IDEuMTAwMjNDMy4yMDc2OCAxLjIzNTc5IDMuNDc1NDUgMS40OTggMy42MTgwMiAxLjgyOTg4QzMuNjkwMzIgMS45OTk1OSAzLjcyNjc1IDIuMTgyNDIgMy43MjUwMiAyLjM2Njg4QzMuNzI2MTcgMi41NDk5OSAzLjY4OTc1IDIuNzMxNCAzLjYxODAyIDIuODk5ODhDMy41MTI5OSAzLjE0NTY3IDMuMzM3ODIgMy4zNTUwMyAzLjExNDQyIDMuNTAxNzdDMi44OTEwMiAzLjY0ODUxIDIuNjI5MyAzLjcyNjEyIDIuMzYyMDIgMy43MjQ4OEMyLjE3OTI0IDMuNzI1OTIgMS45OTgxOCAzLjY4OTUxIDEuODMwMDIgMy42MTc4OEMxLjU4Mjk4IDMuNTE0MDYgMS4zNzIyNyAzLjMzOTMyIDEuMjI0NTMgMy4xMTU3NUMxLjA3NjggMi44OTIxOSAwLjk5ODY2NiAyLjYyOTg0IDEuMDAwMDIgMi4zNjE4OEMwLjk5OTEzIDIuMTc5MjEgMS4wMzUxOSAxLjk5ODI1IDEuMTA2MDIgMS44Mjk4OEMxLjI0MzM3IDEuNTAzMTQgMS41MDMyOCAxLjI0MzIzIDEuODMwMDIgMS4xMDU4OEMyLjE2MzMyIDAuOTY2NjkyIDIuNTM4MDkgMC45NjQ2NjEgMi44NzI4OSAxLjEwMDIzWk0yLjU3NTAyIDIuODY0ODhDMi43MDU0IDIuODA5MTMgMi44MDkyNyAyLjcwNTI2IDIuODY1MDIgMi41NzQ4OEMyLjg5MjkgMi41MDgzOCAyLjkwNzE4IDIuNDM2OTggMi45MDcwMiAyLjM2NDg4QzIuOTA4MTMgMi4yNjU0IDIuODgyMTUgMi4xNjc1IDIuODMxODUgMi4wODE2N0MyLjc4MTU2IDEuOTk1ODQgMi43MDg4NCAxLjkyNTMxIDIuNjIxNTEgMS44Nzc2N0MyLjUzNDE4IDEuODMwMDIgMi40MzU1MyAxLjgwNzA1IDIuMzM2MTQgMS44MTEyMUMyLjIzNjc0IDEuODE1MzcgMi4xNDAzNSAxLjg0NjUgMi4wNTczMSAxLjkwMTI4QzEuOTc0MjYgMS45NTYwNiAxLjkwNzcgMi4wMzI0MSAxLjg2NDc1IDIuMTIyMTVDMS44MjE4IDIuMjExODggMS44MDQwOSAyLjMxMTYxIDEuODEzNTIgMi40MTA2NUMxLjgyMjk0IDIuNTA5NjggMS44NTkxNSAyLjYwNDI4IDEuOTE4MjUgMi42ODQzQzEuOTc3MzYgMi43NjQzMyAyLjA1NzEzIDIuODI2NzUgMi4xNDkwMiAyLjg2NDg4QzIuMjg1NDkgMi45MjA4OSAyLjQzODU0IDIuOTIwODkgMi41NzUwMiAyLjg2NDg4Wk02LjQyOTk1IDEuMTA5NUwxLjEwOTY3IDYuNDI5NzdMMS43OTU1NyA3LjExNTY3TDcuMTE1ODQgMS43OTU0TDYuNDI5OTUgMS4xMDk1Wk0xMS41IDguOTk5OTlIMTIuNVYxMS41SDE1VjEyLjVIMTIuNVYxNUgxMS41VjEyLjVIOVYxMS41SDExLjVWOC45OTk5OVpNNS43Njc3NyA5LjUyNTA5TDYuNDc0ODcgMTAuMjMyMkw0LjcwNzExIDEyTDYuNDc0ODcgMTMuNzY3N0w1Ljc2Nzc3IDE0LjQ3NDhMNCAxMi43MDcxTDIuMjMyMjMgMTQuNDc0OEwxLjUyNTEzIDEzLjc2NzdMMy4yOTI4OSAxMkwxLjUyNTEzIDEwLjIzMjJMMi4yMzIyMyA5LjUyNTA5TDQgMTEuMjkyOUw1Ljc2Nzc3IDkuNTI1MDlaTTcuMTE4MDIgNS4zMjk4OEM3LjAxNDQyIDUuMDgyNjggNi44Mzk3MyA0Ljg3MTgzIDYuNjE2MTIgNC43MjQwNkM2LjM5MjUgNC41NzYyOSA2LjEzMDA0IDQuNDk4MjYgNS44NjIwMiA0LjQ5OTg4QzUuNjc5MzUgNC40OTg5OSA1LjQ5ODM5IDQuNTM1MDUgNS4zMzAwMiA0LjYwNTg4QzUuMDAzMjggNC43NDMyMyA0Ljc0MzM3IDUuMDAzMTQgNC42MDYwMiA1LjMyOTg4QzQuNTM1ODggNS40OTQ3OCA0LjQ5ODk3IDUuNjcxOTEgNC40OTc0MSA1Ljg1MTFDNC40OTU4NiA2LjAzMDMgNC41Mjk2NyA2LjIwODA0IDQuNTk2OTMgNi4zNzQxNEM0LjY2NDE5IDYuNTQwMjQgNC43NjM1NiA2LjY5MTQzIDQuODg5MzYgNi44MTkwNkM1LjAxNTE2IDYuOTQ2NjkgNS4xNjQ5IDcuMDQ4MjMgNS4zMzAwMiA3LjExNzg4QzUuNDk4NjcgNy4xODg0OCA1LjY3OTY4IDcuMjI0ODQgNS44NjI1MiA3LjIyNDg0QzYuMDQ1MzUgNy4yMjQ4NCA2LjIyNjM2IDcuMTg4NDggNi4zOTUwMiA3LjExNzg4QzYuNjQyMDEgNy4wMTM4OCA2Ljg1MjcgNi44MzkxMyA3LjAwMDU4IDYuNjE1NjNDNy4xNDg0NSA2LjM5MjEzIDcuMjI2ODkgNi4xMjk4NyA3LjIyNjAyIDUuODYxODhDNy4yMjY1NSA1LjY3OTA1IDcuMTg5OCA1LjQ5ODAzIDcuMTE4MDIgNS4zMjk4OFpNNi4zNjUwMiA2LjA3NDg4QzYuMzM3NjYgNi4xMzkzNyA2LjI5ODI5IDYuMTk4MDggNi4yNDkwMiA2LjI0Nzg4QzYuMTk5MDggNi4yOTcyNCA2LjE0MDQyIDYuMzM2OTEgNi4wNzYwMiA2LjM2NDg4QzYuMDA4NTQgNi4zOTI5NyA1LjkzNjExIDYuNDA3MjUgNS44NjMwMiA2LjQwNjg4QzUuNzg5OTEgNi40MDc0NCA1LjcxNzQ0IDYuMzkzMTUgNS42NTAwMiA2LjM2NDg4QzUuNTg1NDEgNi4zMzcyOSA1LjUyNjY4IDYuMjk3NTcgNS40NzcwMiA2LjI0Nzg4QzUuNDI2OTEgNi4xOTg1NiA1LjM4NzEzIDYuMTM5NzUgNS4zNjAwMiA2LjA3NDg4QzUuMzA0MDEgNS45Mzg0IDUuMzA0MDEgNS43ODUzNiA1LjM2MDAyIDUuNjQ4ODhDNS40MTUzNiA1LjUxODQ2IDUuNTE5NDEgNS40MTQ3NyA1LjY1MDAyIDUuMzU5ODhDNS43MTczNyA1LjMzMTI2IDUuNzg5ODQgNS4zMTY2MyA1Ljg2MzAyIDUuMzE2ODhDNS45MzYxOCA1LjMxNjg1IDYuMDA4NiA1LjMzMTQ3IDYuMDc2MDIgNS4zNTk4OEM2LjE0MDM3IDUuMzg3NDkgNi4xOTkwNCA1LjQyNjgyIDYuMjQ5MDIgNS40NzU4OEM2LjI5Nzg2IDUuNTI2MDMgNi4zMzcxNyA1LjU4NDY1IDYuMzY1MDIgNS42NDg4OEM2LjM5MzQgNS43MTYzIDYuNDA4MDIgNS43ODg3MiA2LjQwODAyIDUuODYxODhDNi40MDgwMiA1LjkzNTAzIDYuMzkzNCA2LjAwNzQ1IDYuMzY1MDIgNi4wNzQ4OFpNMTQgM0gxMFY0SDE0VjNaIiBmaWxsPSIjQzVDNUM1Ii8+Cjwvc3ZnPgo=")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.variable:before,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.variable:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xLjUgNEwxIDQuNVYxMi41TDEuNSAxM0g0VjEySDJWNUg0VjRIMS41Wk0xNC41IDEzTDE1IDEyLjVMMTUgNC41TDE0LjUgNEgxMlY1TDE0IDVMMTQgMTJIMTJWMTNIMTQuNVpNOC43OTY5MyA1TDQuMjk2OTMgN0w0IDcuNDU2OTFWOS45NTY5MUw0LjI0Mjc1IDEwLjM4NTdMNi43NDI3NSAxMS44ODU3TDcuMjAzMDcgMTEuOTEzOEwxMS43MDMxIDkuOTEzODFMMTIgOS40NTY5MVY2Ljk1NjkxTDExLjc1NzIgNi41MjgxNkw5LjI1NzI1IDUuMDI4MTZMOC43OTY5MyA1Wk01IDguMzRWOS42NzM4MUw2LjUgMTAuNTczOFY5LjI0TDUgOC4zNFpNNy41IDkuMjgxODRWMTAuNjg3NUwxMSA5LjEzMTk3VjcuNzI2MjlMNy41IDkuMjgxODRaTTEwLjQxNzggNi44OTA3MUw4Ljk2NTU5IDYuMDE5MzZMNS41ODIxNiA3LjUyMzExTDcuMDM0NDEgOC4zOTQ0NUwxMC40MTc4IDYuODkwNzFaIiBmaWxsPSIjNzVCRUZGIi8+Cjwvc3ZnPgo=")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.class:before,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.class:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0zLjM1MzU2IDYuNjQ2NDJMMi4wNjA2NiA1LjM1MzUzTDUuMzUzNTYgMi4wNjA2NUw2LjY0NjQ1IDMuMzUzNTRMMy4zNTM1NiA2LjY0NjQyWk01IDFMMSA0Ljk5OTk4VjUuNzA3MDhMMyA3LjcwNzA3SDMuNzA3MTFMNC44NTM1NSA2LjU2MDYzVjEyLjM1MzVMNS4zNTM1NSAxMi44NTM1SDEwLjAwOTdWMTMuMzc0MUwxMS4zNDMgMTQuNzA3NEgxMi4wNTAxTDE0LjcxNjggMTIuMDQwN1YxMS4zMzM2TDEzLjM4MzUgMTAuMDAwM0gxMi42NzYzTDEwLjgyMzEgMTEuODUzNUg1Ljg1MzU1VjcuODkzNTVIMTAuMDA5N1Y4LjM3NDAxTDExLjM0MyA5LjcwNzM0SDEyLjA1MDFMMTQuNzE2OCA3LjA0MDY4VjYuMzMzNTdMMTMuMzgzNSA1LjAwMDI0SDEyLjY3NjNMMTAuODYzIDYuODEzNTZINS44NTM1NVY1LjU2MDY0TDcuNzA3MTEgMy43MDcwOVYyLjk5OTk5TDUuNzA3MTEgMUg1Wk0xMS4wNzAzIDguMDIwNDZMMTEuNjk2NiA4LjY0NjY4TDEzLjY1NjEgNi42ODcxM0wxMy4wMjk5IDYuMDYwOUwxMS4wNzAzIDguMDIwNDZaTTExLjA3MDMgMTMuMDIwNUwxMS42OTY2IDEzLjY0NjdMMTMuNjU2MSAxMS42ODcyTDEzLjAyOTkgMTEuMDYxTDExLjA3MDMgMTMuMDIwNVoiIGZpbGw9IiNFRTlEMjgiLz4KPC9zdmc+Cg==")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.interface:before,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.interface:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMS41IDVDMTAuMTE5MyA1IDkgNi4xMTkyOSA5IDcuNUM5IDguODgwNzEgMTAuMTE5MyAxMCAxMS41IDEwQzEyLjg4MDcgMTAgMTQgOC44ODA3MSAxNCA3LjVDMTQgNi4xMTkyOSAxMi44ODA3IDUgMTEuNSA1Wk04LjAzNTQ0IDhDOC4yNzgwNiA5LjY5NjE1IDkuNzM2NzYgMTEgMTEuNSAxMUMxMy40MzMgMTEgMTUgOS40MzMgMTUgNy41QzE1IDUuNTY3IDEzLjQzMyA0IDExLjUgNEM5LjczNjc2IDQgOC4yNzgwNiA1LjMwMzg1IDguMDM1NDQgN0g0LjkzNjk5QzQuNzE0OTcgNi4xMzczOSAzLjkzMTkyIDUuNSAzIDUuNUMxLjg5NTQzIDUuNSAxIDYuMzk1NDMgMSA3LjVDMSA4LjYwNDU3IDEuODk1NDMgOS41IDMgOS41QzMuOTMxOTIgOS41IDQuNzE0OTcgOC44NjI2MSA0LjkzNjk5IDhIOC4wMzU0NFoiIGZpbGw9IiM3NUJFRkYiLz4KPC9zdmc+Cg==")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.struct:before,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.struct:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0yIDJMMSAzVjZMMiA3SDE0TDE1IDZWM0wxNCAySDJaTTIgM0gzSDEzSDE0VjRWNVY2SDEzSDNIMlY1VjRWM1pNMSAxMEwyIDlINUw2IDEwVjEzTDUgMTRIMkwxIDEzVjEwWk0zIDEwSDJWMTFWMTJWMTNIM0g0SDVWMTJWMTFWMTBINEgzWk0xMCAxMEwxMSA5SDE0TDE1IDEwVjEzTDE0IDE0SDExTDEwIDEzVjEwWk0xMiAxMEgxMVYxMVYxMlYxM0gxMkgxM0gxNFYxMlYxMVYxMEgxM0gxMloiIGZpbGw9IiNDNUM1QzUiLz4KPC9zdmc+Cg==")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.type-parameter:before,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.type-parameter:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMSA2SDEwVjUuNUMxMCA1LjIyMzg2IDkuNzc2MTYgNSA5LjUwMDAxIDVIOC40NzkwMlYxMC41QzguNDc5MDIgMTAuNzc2MSA4LjcwMjg4IDExIDguOTc5MDIgMTFIOS40NzkwMlYxMkg2LjQ3OTAyVjExSDYuOTc5MDJDNy4yNTUxNiAxMSA3LjQ3OTAyIDEwLjc3NjEgNy40NzkwMiAxMC41VjVINi41MDAwMUM2LjIyMzg3IDUgNi4wMDAwMSA1LjIyMzg2IDYuMDAwMDEgNS41VjZINS4wMDAwMVY0SDExVjZaTTEzLjkxNDIgOC4wNDgxTDEyLjQ1MTkgNi41ODU4MUwxMy4xNTkgNS44Nzg3MUwxNC45NzQ5IDcuNjk0NTRWOC40MDE2NUwxMy4yMDcxIDEwLjE2OTRMMTIuNSA5LjQ2MjMxTDEzLjkxNDIgOC4wNDgxWk0zLjU0ODEgOS40NjIzTDIuMDg1ODEgOC4wMDAwMkwzLjUwMDAyIDYuNTg1ODFMMi43OTI5MSA1Ljg3ODdMMS4wMjUxNSA3LjY0NjQ3VjguMzUzNTdMMi44NDEgMTAuMTY5NEwzLjU0ODEgOS40NjIzWiIgZmlsbD0iI0M1QzVDNSIvPgo8L3N2Zz4K")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.module:before,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.module:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik02IDIuOTgzNjFWMi45NzE4NFYySDUuOTEwODNDNS41OTc0MyAyIDUuMjk0MDcgMi4wNjE2MSA1LjAwMTI4IDIuMTg0NzNDNC43MDgxOCAyLjMwNzk4IDQuNDQ5NDIgMi40ODQ3NCA0LjIyNTc4IDIuNzE0OThDNC4wMDMxMSAyLjk0NDIyIDMuODM3OTIgMy4xOTQ5OCAzLjczMjgyIDMuNDY3NjZMMy43MzIzMyAzLjQ2ODk4QzMuNjMzODIgMy43MzUyIDMuNTY4MTQgNC4wMTIwMSAzLjUzNTMzIDQuMjk5MTdMMy41MzUxOSA0LjMwMDUzQzMuNTA2NzggNC41ODA1IDMuNDk4NyA0Ljg2ODQ0IDMuNTEwODQgNS4xNjQyOEMzLjUyMjcyIDUuNDUzNzkgMy41Mjg2NiA1Ljc0MzI5IDMuNTI4NjYgNi4wMzI3OUMzLjUyODY2IDYuMjM1NTYgMy40ODk3NCA2LjQyNTk0IDMuNDEyIDYuNjA1MDdMMy40MTE2IDYuNjA2MDFDMy4zMzY4NyA2Ljc4Mjk2IDMuMjM0MjMgNi45Mzg2NiAzLjEwMzE3IDcuMDczNTlDMi45NzY0NCA3LjIwNDA1IDIuODI0NjYgNy4zMTA1NSAyLjY0NjcyIDcuMzkyNUMyLjQ3MDYgNy40Njk1NCAyLjI4NDk3IDcuNTA4MiAyLjA4OTE3IDcuNTA4MkgyVjcuNlY4LjRWOC40OTE4SDIuMDg5MTdDMi4yODQ2NSA4LjQ5MTggMi40NzAwMSA4LjUzMjM4IDIuNjQ2MDEgOC42MTMzNEwyLjY0NzQyIDguNjEzOTZDMi44MjQ1NyA4LjY5MTU3IDIuOTc1NzcgOC43OTc2MiAzLjEwMjIxIDguOTMxNjFMMy4xMDQxMiA4LjkzMzUyQzMuMjM0MjggOS4wNjM3IDMuMzM2NTkgOS4yMTg3MSAzLjQxMTI5IDkuMzk5NDJMMy40MTIwMSA5LjQwMTA4QzMuNDg5ODYgOS41ODA0NyAzLjUyODY2IDkuNzY4ODMgMy41Mjg2NiA5Ljk2NzIxQzMuNTI4NjYgMTAuMjU2NyAzLjUyMjcyIDEwLjU0NjIgMy41MTA4NCAxMC44MzU3QzMuNDk4NyAxMS4xMzE2IDMuNTA2NzcgMTEuNDIxNSAzLjUzNTE2IDExLjcwNTVMMy41MzUzNSAxMS43MDcyQzMuNTY4MTkgMTEuOTkwMyAzLjYzMzg3IDEyLjI2NSAzLjczMjMyIDEyLjUzMUwzLjczMjgzIDEyLjUzMjNDMy44Mzc5MyAxMi44MDUgNC4wMDMxMSAxMy4wNTU4IDQuMjI1NzggMTMuMjg1QzQuNDQ5NDIgMTMuNTE1MyA0LjcwODE4IDEzLjY5MiA1LjAwMTI4IDEzLjgxNTNDNS4yOTQwNyAxMy45Mzg0IDUuNTk3NDMgMTQgNS45MTA4MyAxNEg2VjEzLjJWMTMuMDE2NEg1LjkxMDgzQzUuNzEwOTUgMTMuMDE2NCA1LjUyMzQ2IDEyLjk3NzcgNS4zNDc2MyAxMi45MDA4QzUuMTczOTYgMTIuODE5MSA1LjAyMTk0IDEyLjcxMjYgNC44OTA4NiAxMi41ODE4QzQuNzYzODYgMTIuNDQ2OSA0LjY2MTA0IDEyLjI5MTEgNC41ODIyMyAxMi4xMTM3QzQuNTA4MzggMTEuOTM0NiA0LjQ3MTM0IDExLjc0NCA0LjQ3MTM0IDExLjU0MUM0LjQ3MTM0IDExLjMxMjcgNC40NzUzIDExLjA4ODUgNC40ODMyMSAxMC44Njg2QzQuNDkxMjUgMTAuNjQxMSA0LjQ5MTI3IDEwLjQxOTUgNC40ODMyNCAxMC4yMDM5QzQuNDc5MTQgOS45ODI0NiA0LjQ2MDg0IDkuNzY4ODMgNC40MjgyMyA5LjU2MzEyQzQuMzk1MTMgOS4zNTAyNCA0LjMzOTIxIDkuMTQ3NTcgNC4yNjAzOSA4Ljk1NTM2QzQuMTgwOTEgOC43NjE1NyA0LjA3MjU4IDguNTc3NDYgMy45MzYxNiA4LjQwMjk4QzMuODIzNDUgOC4yNTg4MSAzLjY4NTM4IDguMTI0NjIgMy41MjI4MyA4QzMuNjg1MzggNy44NzUzOCAzLjgyMzQ1IDcuNzQxMTkgMy45MzYxNiA3LjU5NzAyQzQuMDcyNTggNy40MjI1NCA0LjE4MDkxIDcuMjM4NDMgNC4yNjAzOSA3LjA0NDY0QzQuMzM5MTMgNi44NTI2MyA0LjM5NTEzIDYuNjUxNzUgNC40MjgyNiA2LjQ0Mjg1QzQuNDYwODIgNi4yMzMzIDQuNDc5MTQgNi4wMTk3MyA0LjQ4MzI0IDUuODAyMTlDNC40OTEyNyA1LjU4MjYyIDQuNDkxMjUgNS4zNjEwNSA0LjQ4MzIxIDUuMTM3NDlDNC40NzUzIDQuOTEzNCA0LjQ3MTM0IDQuNjg3MjUgNC40NzEzNCA0LjQ1OTAyQzQuNDcxMzQgNC4yNjAxOSA0LjUwODMzIDQuMDcxNTIgNC41ODIzOCAzLjg5MjA1QzQuNjYxMzUgMy43MTAzNCA0Ljc2NDIxIDMuNTU0NzUgNC44OTA4NiAzLjQyNDM3QzUuMDIxOTMgMy4yODk0MiA1LjE3NDYxIDMuMTgyNzUgNS4zNDgwMiAzLjEwNTEzQzUuNTIzOCAzLjAyNDI3IDUuNzExMTMgMi45ODM2MSA1LjkxMDgzIDIuOTgzNjFINlpNMTAgMTMuMDE2NFYxMy4wMjgyVjE0SDEwLjA4OTJDMTAuNDAyNiAxNCAxMC43MDU5IDEzLjkzODQgMTAuOTk4NyAxMy44MTUzQzExLjI5MTggMTMuNjkyIDExLjU1MDYgMTMuNTE1MyAxMS43NzQyIDEzLjI4NUMxMS45OTY5IDEzLjA1NTggMTIuMTYyMSAxMi44MDUgMTIuMjY3MiAxMi41MzIzTDEyLjI2NzcgMTIuNTMxQzEyLjM2NjIgMTIuMjY0OCAxMi40MzE5IDExLjk4OCAxMi40NjQ3IDExLjcwMDhMMTIuNDY0OCAxMS42OTk1QzEyLjQ5MzIgMTEuNDE5NSAxMi41MDEzIDExLjEzMTYgMTIuNDg5MiAxMC44MzU3QzEyLjQ3NzMgMTAuNTQ2MiAxMi40NzEzIDEwLjI1NjcgMTIuNDcxMyA5Ljk2NzIxQzEyLjQ3MTMgOS43NjQ0NCAxMi41MTAzIDkuNTc0MDYgMTIuNTg4IDkuMzk0OTNMMTIuNTg4NCA5LjM5Mzk5QzEyLjY2MzEgOS4yMTcwNCAxMi43NjU4IDkuMDYxMzQgMTIuODk2OCA4LjkyNjQyQzEzLjAyMzYgOC43OTU5NSAxMy4xNzUzIDguNjg5NDUgMTMuMzUzMyA4LjYwNzVDMTMuNTI5NCA4LjUzMDQ2IDEzLjcxNSA4LjQ5MTggMTMuOTEwOCA4LjQ5MThIMTRWOC40VjcuNlY3LjUwODJIMTMuOTEwOEMxMy43MTUzIDcuNTA4MiAxMy41MyA3LjQ2NzYyIDEzLjM1NCA3LjM4NjY2TDEzLjM1MjYgNy4zODYwNEMxMy4xNzU0IDcuMzA4NDQgMTMuMDI0MiA3LjIwMjM4IDEyLjg5NzggNy4wNjgzOUwxMi44OTU5IDcuMDY2NDhDMTIuNzY1NyA2LjkzNjMgMTIuNjYzNCA2Ljc4MTI5IDEyLjU4ODcgNi42MDA1OEwxMi41ODggNi41OTg5MkMxMi41MTAxIDYuNDE5NTMgMTIuNDcxMyA2LjIzMTE3IDEyLjQ3MTMgNi4wMzI3OUMxMi40NzEzIDUuNzQzMjkgMTIuNDc3MyA1LjQ1Mzc5IDEyLjQ4OTIgNS4xNjQyOEMxMi41MDEzIDQuODY4NDIgMTIuNDkzMiA0LjU3ODQ4IDEyLjQ2NDggNC4yOTQ1NEwxMi40NjQ2IDQuMjkyODVDMTIuNDMxOCA0LjAwOTcxIDEyLjM2NjEgMy43MzUwMiAxMi4yNjc3IDMuNDY4OTdMMTIuMjY3MiAzLjQ2NzY2QzEyLjE2MjEgMy4xOTQ5OSAxMS45OTY5IDIuOTQ0MjIgMTEuNzc0MiAyLjcxNDk4QzExLjU1MDYgMi40ODQ3NCAxMS4yOTE4IDIuMzA3OTggMTAuOTk4NyAyLjE4NDczQzEwLjcwNTkgMi4wNjE2MSAxMC40MDI2IDIgMTAuMDg5MiAySDEwVjIuOFYyLjk4MzYxSDEwLjA4OTJDMTAuMjg5MSAyLjk4MzYxIDEwLjQ3NjUgMy4wMjIzIDEwLjY1MjQgMy4wOTkxN0MxMC44MjYgMy4xODA5MiAxMC45NzgxIDMuMjg3MzYgMTEuMTA5MSAzLjQxODIzQzExLjIzNjEgMy41NTMwNSAxMS4zMzkgMy43MDg4OSAxMS40MTc4IDMuODg2MjhDMTEuNDkxNiA0LjA2NTQgMTEuNTI4NyA0LjI1NTk2IDExLjUyODcgNC40NTkwMkMxMS41Mjg3IDQuNjg3MjcgMTEuNTI0NyA0LjkxMTQ1IDExLjUxNjggNS4xMzE0MkMxMS41MDg4IDUuMzU4OTQgMTEuNTA4NyA1LjU4MDQ5IDExLjUxNjggNS43OTYwNUMxMS41MjA5IDYuMDE3NTQgMTEuNTM5MiA2LjIzMTE3IDExLjU3MTggNi40MzY4OEMxMS42MDQ5IDYuNjQ5NzYgMTEuNjYwOCA2Ljg1MjQzIDExLjczOTYgNy4wNDQ2NEMxMS44MTkxIDcuMjM4NDMgMTEuOTI3NCA3LjQyMjU0IDEyLjA2MzggNy41OTcwMkMxMi4xNzY1IDcuNzQxMTkgMTIuMzE0NiA3Ljg3NTM4IDEyLjQ3NzIgOEMxMi4zMTQ2IDguMTI0NjIgMTIuMTc2NSA4LjI1ODgxIDEyLjA2MzggOC40MDI5OEMxMS45Mjc0IDguNTc3NDYgMTEuODE5MSA4Ljc2MTU3IDExLjczOTYgOC45NTUzNkMxMS42NjA5IDkuMTQ3MzcgMTEuNjA0OSA5LjM0ODI1IDExLjU3MTcgOS41NTcxNUMxMS41MzkyIDkuNzY2NyAxMS41MjA5IDkuOTgwMjcgMTEuNTE2OCAxMC4xOTc4QzExLjUwODcgMTAuNDE3NCAxMS41MDg3IDEwLjYzODkgMTEuNTE2OCAxMC44NjI1QzExLjUyNDcgMTEuMDg2NiAxMS41Mjg3IDExLjMxMjggMTEuNTI4NyAxMS41NDFDMTEuNTI4NyAxMS43Mzk4IDExLjQ5MTcgMTEuOTI4NSAxMS40MTc2IDEyLjEwNzlDMTEuMzM4NiAxMi4yODk3IDExLjIzNTggMTIuNDQ1MiAxMS4xMDkxIDEyLjU3NTZDMTAuOTc4MSAxMi43MTA2IDEwLjgyNTQgMTIuODE3MyAxMC42NTIgMTIuODk0OUMxMC40NzYyIDEyLjk3NTcgMTAuMjg4OSAxMy4wMTY0IDEwLjA4OTIgMTMuMDE2NEgxMFoiIGZpbGw9IiNDNUM1QzUiLz4KPC9zdmc+Cg==")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.property:before,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.property:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTIuODA3MjMgMTQuOTc1NEMyLjU3MTE5IDE0Ljk3MjEgMi4zMzgyNiAxNC45MjExIDIuMTIyNDcgMTQuODI1NEMxLjkwNjY3IDE0LjcyOTcgMS43MTI0OCAxNC41OTEzIDEuNTUxNTggMTQuNDE4NkMxLjIzODUgMTQuMTMzNCAxLjA0NDMzIDEzLjc0MDggMS4wMDc3NSAxMy4zMTg5QzAuOTY2MjI1IDEyLjg4MjggMS4wOTI2OSAxMi40NDczIDEuMzYxMzMgMTIuMTAxM0MyLjU2Nzc5IDEwLjgyODkgNC45NDczIDguNDQ5NCA2LjY3ODExIDYuNzU0NzlDNi4zMDk4MyA1Ljc1ODg3IDYuMzI3MDQgNC42NjEyNyA2LjcyNjM3IDMuNjc3MzlDNy4wNTQ3NCAyLjg1ODc2IDcuNjM4NjkgMi4xNjgwNSA4LjM5MTI5IDEuNzA4MDdDOC45ODE3IDEuMzE3MDYgOS42NjAzMSAxLjA3OTQ0IDEwLjM2NTcgMS4wMTY3M0MxMS4wNzExIDAuOTU0MDIyIDExLjc4MDkgMS4wNjgxOSAxMi40MzExIDEuMzQ4OTJMMTMuMDQ4MiAxLjYxNjJMMTAuMTgyNCA0LjU2NzM4TDExLjQzNzEgNS44MjU4MkwxNC4zODA5IDIuOTQ4ODdMMTQuNjQ4MiAzLjU2Nzg4QzE0Ljg3MzUgNC4wODk3NiAxNC45OTMgNC42NTExOSAxNC45OTk3IDUuMjE5NjFDMTUuMDA2NCA1Ljc4ODAyIDE0LjkwMDIgNi4zNTIxMSAxNC42ODcyIDYuODc5MTVDMTQuNDc2IDcuNDAwMjkgMTQuMTYyMyA3Ljg3MzY4IDEzLjc2NDcgOC4yNzEyMkMxMy41Mzk0IDguNDkxNjkgMTMuMjkwNCA4LjY4NjUzIDEzLjAyMjIgOC44NTIxOEMxMi40NjczIDkuMjIyNzUgMTEuODMyNCA5LjQ1NjM2IDExLjE2OTcgOS41MzM4QzEwLjUwNjkgOS42MTEyNCA5LjgzNTIxIDkuNTMwMyA5LjIwOTgyIDkuMjk3NjRDOC4xMTE5NCAxMC40MTEzIDUuMzcxNDIgMTMuMTcwNCAzLjg5MTE5IDE0LjU1MjJDMy41OTQyNiAxNC44MjE5IDMuMjA4MzIgMTQuOTcyNiAyLjgwNzIzIDE0Ljk3NTRaTTEwLjc0NDggMS45MjgwMkMxMC4wODcgMS45MjYzNyA5LjQ0MzU5IDIuMTIwMTggOC44OTYxNCAyLjQ4NDg1QzguNjgyNjUgMi42MTUyIDguNDg0MzcgMi43Njg5NyA4LjMwNDk4IDIuOTQzM0M3LjgyNzg5IDMuNDI0MjMgNy41MDkyNiA0LjAzOTUzIDcuMzkxODIgNC43MDY2OUM3LjI3NDM3IDUuMzczODUgNy4zNjM3NCA2LjA2MDk4IDcuNjQ3OTIgNi42NzU5MUw3Ljc4MzQyIDYuOTcyODhMNy41NTA0OCA3LjIwMDI1QzUuODEyMjQgOC44OTY3MiAzLjI4MTQ2IDExLjQyMDEgMi4wNjQ3OSAxMi43MDQ1QzEuOTU2NDYgMTIuODY1OCAxLjkxMDEyIDEzLjA2MDggMS45MzQzNSAxMy4yNTM1QzEuOTU4NTcgMTMuNDQ2MyAyLjA1MTcxIDEzLjYyMzggMi4xOTY1NyAxMy43NTMyQzIuMjgwMDUgMTMuODQ2MiAyLjM4MTc3IDEzLjkyMTEgMi40OTU0MSAxMy45NzMxQzIuNTk1NTcgMTQuMDE4NCAyLjcwMzgzIDE0LjA0MyAyLjgxMzczIDE0LjA0NTVDMi45ODA2NCAxNC4wNDEzIDMuMTQwNDQgMTMuOTc3IDMuMjYzODMgMTMuODY0NkM0LjgzNjg3IDEyLjM5NjQgNy44NzYyMiA5LjMyNjQxIDguNzY4MDcgOC40MjQzNUw4Ljk5NzMgOC4xOTMyNkw5LjI5MjQyIDguMzI3ODNDOS44MDYxOCA4LjU2NzMyIDEwLjM3MzEgOC42Njk4NSAxMC45MzgyIDguNjI1NDVDMTEuNTAzMyA4LjU4MTA2IDEyLjA0NzMgOC4zOTEyNSAxMi41MTc0IDguMDc0NDdDMTIuNzMxMyA3Ljk0MjYgMTIuOTI5NiA3Ljc4Njk0IDEzLjEwODUgNy42MTA0NUMxMy40MTgzIDcuMzAxNTMgMTMuNjYzMSA2LjkzMzc0IDEzLjgyODYgNi41Mjg3NEMxMy45OTQgNi4xMjM3NSAxNC4wNzY3IDUuNjg5NzQgMTQuMDcxOSA1LjI1MjI4QzE0LjA3MTkgNS4wMzY2MiAxNC4wNTA1IDQuODIxNDggMTQuMDA3OCA0LjYxMDA3TDExLjQzMDYgNy4xMjUwOEw4Ljg3OTQ0IDQuNTc3NTlMMTEuMzk0NCAxLjk4ODM0QzExLjE4MDQgMS45NDY3NCAxMC45NjI4IDEuOTI2NTMgMTAuNzQ0OCAxLjkyODAyWiIgZmlsbD0iI0M1QzVDNSIvPgo8L3N2Zz4K")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.unit:before,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.unit:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik00IDFMMyAyVjE0TDQgMTVIMTJMMTMgMTRWMkwxMiAxSDRaTTQgM1YySDEyVjE0SDRWMTNINlYxMkg0VjEwSDhWOUg0VjdINlY2SDRWNEg4VjNINFoiIGZpbGw9IiNDNUM1QzUiLz4KPC9zdmc+Cg==")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.constant:before,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.constant:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik00IDZIMTJWN0g0VjZaTTEyIDlINFYxMEgxMlY5WiIgZmlsbD0iI0M1QzVDNSIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTEgNEwyIDNIMTRMMTUgNFYxMkwxNCAxM0gyTDEgMTJWNFpNMiA0VjEySDE0VjRIMloiIGZpbGw9IiNDNUM1QzUiLz4KPC9zdmc+Cg==")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.enum:before,.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.value:before,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.enum:before,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.value:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik04IDJMNyAzVjZIOFYzSDE0VjhIMTBWOUgxNEwxNSA4VjNMMTQgMkg4Wk05IDhMOCA3SDdIMkwxIDhWMTNMMiAxNEg4TDkgMTNWOVY4Wk04IDlWOEg3SDJWMTNIOFY5Wk05IDYuNTg1NzlMOS40MTQyMSA3SDEzVjZIOVY2LjU4NTc5Wk0xMyA0SDlWNUgxM1Y0Wk03IDlIM1YxMEg3VjlaTTMgMTFIN1YxMkgzVjExWiIgZmlsbD0iI0VFOUQyOCIvPgo8L3N2Zz4K")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.enum-member:before,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.enum-member:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03IDNMOCAySDE0TDE1IDNWOEwxNCA5SDEwVjhIMTRWM0g4VjZIN1YzWk04IDdMOSA4VjlWMTNMOCAxNEgyTDEgMTNWOEwyIDdIN0g4Wk04IDhWOVYxM0gyVjhIN0g4Wk05LjQxNDIxIDdMOSA2LjU4NTc5VjZIMTNWN0g5LjQxNDIxWk05IDRIMTNWNUg5VjRaTTcgMTBIM1YxMUg3VjEwWiIgZmlsbD0iIzc1QkVGRiIvPgo8L3N2Zz4K")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.keyword:before,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.keyword:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTE1IDRIMTBWM0gxNVY0Wk0xNCA3SDEyVjhIMTRWN1pNMTAgN0gxVjhIMTBWN1pNMTIgMTNIMVYxNEgxMlYxM1pNNyAxMEgxVjExSDdWMTBaTTE1IDEwSDEwVjExSDE1VjEwWk04IDJWNUgxVjJIOFpNNyAzSDJWNEg3VjNaIiBmaWxsPSIjQzVDNUM1Ii8+Cjwvc3ZnPgo=")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.text:before,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.text:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03LjIyMjg5IDEwLjkzM0M3LjU0ODYzIDExLjEyNTQgNy45MjE2MyAxMS4yMjMxIDguMjk5ODkgMTEuMjE1QzguNjM3NzcgMTEuMjIxOCA4Ljk3MjU0IDExLjE0OTIgOS4yNzcyMSAxMS4wMDNDOS41ODE4OCAxMC44NTY3IDkuODQ3OTIgMTAuNjQwOSAxMC4wNTM5IDEwLjM3M0MxMC41MDkxIDkuNzY1MTkgMTAuNzQwMiA5LjAxODY3IDEwLjcwNzkgOC4yNTk5OEMxMC43NDEyIDcuNTg2MjIgMTAuNTM3NCA2LjkyMjEgMTAuMTMxOSA2LjM4Mjk4QzkuOTM1NzUgNi4xNDE2MSA5LjY4NTc3IDUuOTQ5NTcgOS40MDIgNS44MjIyOEM5LjExODI0IDUuNjk0OTggOC44MDg1OCA1LjYzNTk3IDguNDk3ODkgNS42NDk5N0M4LjA3NTIyIDUuNjQ2OTkgNy42NTk5NCA1Ljc2MDg1IDcuMjk3ODkgNS45Nzg5OEM3LjE4MzA0IDYuMDQ4MDcgNy4wNzQ5IDYuMTI3NzUgNi45NzQ4OSA2LjIxNjk4VjMuNDc0OThINS45ODM4OVYxMS4xSDYuOTc4ODlWMTAuNzU2QzcuMDU1MTYgMTAuODIxNyA3LjEzNjc3IDEwLjg4MDkgNy4yMjI4OSAxMC45MzNaTTcuODQ5ODEgNi43MDAwNkM4LjAzNTk4IDYuNjIxMDUgOC4yMzgwNyA2LjU4Njc3IDguNDM5ODkgNi41OTk5OEM4LjYxMjU3IDYuNTk0NTIgOC43ODQwNCA2LjYzMDU0IDguOTM5OTQgNi43MDUwMUM5LjA5NTgzIDYuNzc5NDggOS4yMzE2MSA2Ljg5MDIzIDkuMzM1ODkgNy4wMjc5OEM5LjU5MjUzIDcuMzkwNTMgOS43MTg0IDcuODI5NTEgOS42OTI4OSA4LjI3Mjk3QzkuNzE5NzIgOC43OTc0OCA5LjU3OTY5IDkuMzE3MDEgOS4yOTI4OSA5Ljc1Njk4QzkuMTg4MjIgOS45MTUyNyA5LjA0NTQ2IDEwLjA0NDcgOC44Nzc3MyAxMC4xMzM1QzguNzA5OTkgMTAuMjIyMyA4LjUyMjY0IDEwLjI2NzUgOC4zMzI4OSAxMC4yNjVDOC4xNDkzNCAxMC4yNzMyIDcuOTY2MyAxMC4yNCA3Ljc5NzM0IDEwLjE2NzhDNy42MjgzOCAxMC4wOTU2IDcuNDc3ODQgOS45ODYyOCA3LjM1Njg5IDkuODQ3OTdDNy4xMDE1MiA5LjU1OTU3IDYuOTY1MDEgOS4xODUwNiA2Ljk3NDg5IDguNzk5OThWOC4xOTk5OEM2Ljk2Mjk5IDcuNzgzMzIgNy4xMDI2MyA3LjM3NjUgNy4zNjc4OSA3LjA1NDk4QzcuNDk4NTggNi45MDA2NCA3LjY2MzY0IDYuNzc5MDggNy44NDk4MSA2LjcwMDA2Wk0zLjI4OTAyIDUuNjc0OTlDMi45NzAxMSA1LjY3OTMzIDIuNjUzODggNS43MzQgMi4zNTIwMiA1LjgzNjk5QzIuMDY0MTcgNS45MjI5MyAxLjc5MzQ3IDYuMDU4MjggMS41NTIwMiA2LjIzNjk5TDEuNDUyMDIgNi4zMTM5OVY3LjUxMzk5TDEuODc1MDIgNy4xNTQ5OUMyLjI0NTc5IDYuODA0NzggMi43MzEzMyA2LjYwMTQ2IDMuMjQxMDIgNi41ODI5OUMzLjM2NTkzIDYuNTcxNjQgMy40OTE3IDYuNTkxNDcgMy42MDcwNiA2LjY0MDY4QzMuNzIyNDMgNi42ODk5IDMuODIzNzcgNi43NjY5NyAzLjkwMjAyIDYuODY0OTlDNC4wNTIyIDcuMDk3MSA0LjEzMjM5IDcuMzY3NTQgNC4xMzMwMiA3LjY0Mzk5TDIuOTAwMDIgNy44MjQ5OUMyLjM5NDM1IDcuODc3ODEgMS45MTUyNSA4LjA3NzcyIDEuNTIyMDIgOC4zOTk5OUMxLjM2Njk3IDguNTUxODEgMS4yNDMzOSA4LjczMjcxIDEuMTU4MzUgOC45MzIzNUMxLjA3MzMxIDkuMTMxOTkgMS4wMjg0OCA5LjM0NjQ0IDEuMDI2NDQgOS41NjM0M0MxLjAyNDQgOS43ODA0MiAxLjA2NTE3IDkuOTk1NjggMS4xNDY0NCAxMC4xOTY5QzEuMjI3NyAxMC4zOTgxIDEuMzQ3ODYgMTAuNTgxMyAxLjUwMDAyIDEwLjczNkMxLjY2ODcgMTAuODkwNCAxLjg2NjIyIDExLjAxIDIuMDgxMjUgMTEuMDg3OUMyLjI5NjI3IDExLjE2NTkgMi41MjQ1NiAxMS4yMDA1IDIuNzUzMDIgMTEuMTlDMy4xNDcgMTEuMTkzMSAzLjUzMjc4IDExLjA3NzQgMy44NjAwMiAxMC44NThDMy45NjE1MyAxMC43ODk3IDQuMDU3MiAxMC43MTMxIDQuMTQ2MDIgMTAuNjI5VjExLjA3M0g1LjA4NzAyVjcuNzE0OTlDNS4xMjEzNyA3LjE3NDIyIDQuOTU0MyA2LjYzOTg4IDQuNjE4MDIgNi4yMTQ5OUM0LjQ0OTc5IDYuMDMyODUgNC4yNDM0OCA1Ljg5MDAzIDQuMDEzNzggNS43OTY3QzMuNzg0MDcgNS43MDMzNiAzLjUzNjYxIDUuNjYxODEgMy4yODkwMiA1LjY3NDk5Wk00LjE0NjAyIDguNzE1OTlDNC4xNjU2NCA5LjEzNDM1IDQuMDI1OTIgOS41NDQ1OSAzLjc1NTAyIDkuODY0QzMuNjM2ODkgMTAuMDAwNSAzLjQ4OTk4IDEwLjEwOTIgMy4zMjQ4NiAxMC4xODIxQzMuMTU5NzMgMTAuMjU1MSAyLjk4MDQ5IDEwLjI5MDYgMi44MDAwMiAxMC4yODZDMi42OTA0OSAxMC4yOTQ1IDIuNTgwMzUgMTAuMjgxMiAyLjQ3NTk5IDEwLjI0NjlDMi4zNzE2MyAxMC4yMTI1IDIuMjc1MTEgMTAuMTU3OSAyLjE5MjAyIDEwLjA4NkMyLjA2MDc5IDkuOTM0NTUgMS45ODg1NiA5Ljc0MDg4IDEuOTg4NTYgOS41NDA0OUMxLjk4ODU2IDkuMzQwMTEgMi4wNjA3OSA5LjE0NjQ0IDIuMTkyMDIgOC45OTQ5OUMyLjQ3MzIyIDguODIxMzEgMi43OTIzMyA4LjcxODM3IDMuMTIyMDIgOC42OTQ5OUw0LjE0MjAyIDguNTQ2OTlMNC4xNDYwMiA4LjcxNTk5Wk0xMi40NTg4IDExLjAzMjVDMTIuNzY2IDExLjE2MzggMTMuMDk4MyAxMS4yMjYxIDEzLjQzMjIgMTEuMjE1QzEzLjkyNyAxMS4yMjcgMTQuNDE1MyAxMS4xMDA2IDE0Ljg0MjIgMTAuODVMMTQuOTY1MiAxMC43NzVMMTQuOTc4MiAxMC43NjhWOS42MTUwNEwxNC41MzIyIDkuOTM1MDRDMTQuMjE2IDEwLjE1OTIgMTMuODM1NiAxMC4yNzQ3IDEzLjQ0ODIgMTAuMjY0QzEzLjI0OTcgMTAuMjcxOSAxMy4wNTIgMTAuMjM0MiAxMi44NzAzIDEwLjE1MzhDMTIuNjg4NiAxMC4wNzMzIDEyLjUyNzggOS45NTIzMiAxMi40MDAyIDkuODAwMDRDMTIuMTE0NCA5LjQyNDUzIDExLjk3MjUgOC45NTkxMSAxMi4wMDAyIDguNDg4MDRDMTEuOTczNyA3Ljk4NzMyIDEyLjEzNTIgNy40OTQ3NSAxMi40NTMyIDcuMTA3MDRDMTIuNTkzNCA2Ljk0MTA1IDEyLjc2OTUgNi44MDkxNCAxMi45NjgyIDYuNzIxM0MxMy4xNjcgNi42MzM0NiAxMy4zODMxIDYuNTkyIDEzLjYwMDIgNi42MDAwNEMxMy45NDM5IDYuNTk4NDQgMTQuMjgwOCA2LjY5NTI1IDE0LjU3MTIgNi44NzkwNEwxNS4wMDAyIDcuMTQ0MDRWNS45NzAwNEwxNC44MzEyIDUuODk3MDRDMTQuNDYyNiA1LjczNDMyIDE0LjA2NDEgNS42NTAyIDEzLjY2MTIgNS42NTAwNEMxMy4yOTk5IDUuNjM5OTEgMTIuOTQwNiA1LjcwNzYyIDEyLjYwNzggNS44NDg1OUMxMi4yNzQ5IDUuOTg5NTYgMTEuOTc2MyA2LjIwMDQ4IDExLjczMjIgNi40NjcwNEMxMS4yMjYxIDcuMDI2ODMgMTAuOTU4MSA3Ljc2MTg2IDEwLjk4NTIgOC41MTYwNEMxMC45NTY3IDkuMjIzNDYgMTEuMTk1NSA5LjkxNTY5IDExLjY1NDIgMTAuNDU1QzExLjg3NjkgMTAuNzA0IDEyLjE1MTYgMTAuOTAxMiAxMi40NTg4IDExLjAzMjVaIiBmaWxsPSIjQzVDNUM1Ii8+Cjwvc3ZnPgo=")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.color:before,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.color:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik02LjYgMTEuNzY3M0M3LjMyODcxIDExLjAzODMgNy4zMjg3MSA5Ljg1NjM4IDYuNiA5LjEyNzQyQzUuODcwODMgOC4zOTg0NSA0LjY4OTEzIDguMzk4NDUgMy45NTk5NiA5LjEyNzQyQzIuOTE4MTIgMTAuMjI0OSAxLjEwNDExIDkuOTM5MDEgMS4wMTI5IDguNDI4NTNDMS4wMDQzNCA4LjI4Njc5IDEgOC4xNDM5IDEgOEMxIDQuMTMzOTkgNC4xMzQwNSAxIDggMUMxMS44NjYgMSAxNSA0LjEzMzk5IDE1IDhDMTUgMTEuODY2IDExLjg2NiAxNSA4IDE1QzcuNzk3NzQgMTUgNy41OTc0OSAxNC45OTE0IDcuMzk5NTkgMTQuOTc0NkM1LjgwNjQ2IDE0LjgzOTMgNS40OTg2IDEyLjkyNjMgNi42IDExLjc2NzNaTTYuOTY2NzUgMTMuNTQzNEM2LjkwMjUxIDEzLjI0NjQgNi45ODgyMSAxMi44MTUgNy4zMTgxOSAxMi40NjMyQzguNDI2MjkgMTEuMzQyOSA4LjQyMjY0IDkuNTM2MjMgNy4zMDcyMyA4LjQyMDQzTDcuMzA3MDEgOC40MjAyMUM2LjE4NzM0IDcuMzAwODUgNC4zNzI2MiA3LjMwMDg1IDMuMjUyOTUgOC40MjAyMUwzLjI0MzcxIDguNDI5NDVMMy4yMzQ3MSA4LjQzODkzQzIuOTM5MDMgOC43NTA0IDIuNTcwOTEgOC44MjU5OSAyLjMzMjUgOC43NzY2OEMyLjIxOTM2IDguNzUzMjggMi4xNTAyMSA4LjcwNjY3IDIuMTA5NzkgOC42NjE2MUMyLjA3MzkzIDguNjIxNjIgMi4wMjE0NiA4LjU0MDE2IDIuMDExMDggOC4zNjgyNkMyLjAwMzczIDguMjQ2NTYgMiA4LjEyMzc4IDIgOEMyIDQuNjg2MjggNC42ODYzMyAyIDggMkMxMS4zMTM3IDIgMTQgNC42ODYyOCAxNCA4QzE0IDExLjMxMzcgMTEuMzEzNyAxNCA4IDE0QzcuODI2MDIgMTQgNy42NTQgMTMuOTkyNiA3LjQ4NDIxIDEzLjk3ODJDNy4yODk5MiAxMy45NjE3IDcuMTg0ODggMTMuODk4NyA3LjEyNDE0IDEzLjg0MjlDNy4wNTgzMSAxMy43ODI0IDYuOTk3NjcgMTMuNjg2NCA2Ljk2Njc1IDEzLjU0MzRaTTUgNkM1LjU1MjI4IDYgNiA1LjU1MjI4IDYgNUM2IDQuNDQ3NzIgNS41NTIyOCA0IDUgNEM0LjQ0NzcyIDQgNCA0LjQ0NzcyIDQgNUM0IDUuNTUyMjggNC40NDc3MiA2IDUgNlpNMTIgMTFDMTIgMTEuNTUyMyAxMS41NTIzIDEyIDExIDEyQzEwLjQ0NzcgMTIgMTAgMTEuNTUyMyAxMCAxMUMxMCAxMC40NDc3IDEwLjQ0NzcgMTAgMTEgMTBDMTEuNTUyMyAxMCAxMiAxMC40NDc3IDEyIDExWk04IDVDOC41NTIyOCA1IDkgNC41NTIyOCA5IDRDOSAzLjQ0NzcyIDguNTUyMjggMyA4IDNDNy40NDc3MiAzIDcgMy40NDc3MiA3IDRDNyA0LjU1MjI4IDcuNDQ3NzIgNSA4IDVaTTEzIDhDMTMgOC41NTIyOCAxMi41NTIzIDkgMTIgOUMxMS40NDc3IDkgMTEgOC41NTIyOCAxMSA4QzExIDcuNDQ3NzIgMTEuNDQ3NyA3IDEyIDdDMTIuNTUyMyA3IDEzIDcuNDQ3NzIgMTMgOFpNMTEgNkMxMS41NTIzIDYgMTIgNS41NTIyOCAxMiA1QzEyIDQuNDQ3NzIgMTEuNTUyMyA0IDExIDRDMTAuNDQ3NyA0IDEwIDQuNDQ3NzIgMTAgNUMxMCA1LjU1MjI4IDEwLjQ0NzcgNiAxMSA2WiIgZmlsbD0iI0M1QzVDNSIvPgo8L3N2Zz4K")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.file:before,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.file:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik00IDFMMyAyVjE0TDQgMTVIMTNMMTQgMTRWNUwxMy43MDcxIDQuMjkyODlMMTAuNzA3MSAxLjI5Mjg5TDEwIDFINFpNNCAxNFYyTDkgMlY2SDEzVjE0SDRaTTEzIDVMMTAgMlY1TDEzIDVaIiBmaWxsPSIjQzVDNUM1Ii8+Cjwvc3ZnPgo=")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.reference:before,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.reference:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik04LjA2MDY1IDMuODUzNTZMNS45MTQyMSA2TDUuMjA3MSA1LjI5Mjg5TDYuNDk5OTkgNEgzLjVDMy4xMDIxOCA0IDIuNzIwNjQgNC4xNTgwNCAyLjQzOTM0IDQuNDM5MzRDMi4xNTgwNCA0LjcyMDY1IDIgNS4xMDIxOCAyIDUuNUMyIDUuODk3ODMgMi4xNTgwNCA2LjI3OTM2IDIuNDM5MzQgNi41NjA2NkMyLjcyMDY0IDYuODQxOTcgMy4xMDIxOCA3IDMuNSA3SDRWOEgzLjVDMi44MzY5NiA4IDIuMjAxMDcgNy43MzY2MSAxLjczMjIzIDcuMjY3NzdDMS4yNjMzOSA2Ljc5ODkzIDEgNi4xNjMwNSAxIDUuNUMxIDQuODM2OTYgMS4yNjMzOSA0LjIwMTA4IDEuNzMyMjMgMy43MzIyNEMyLjIwMTA3IDMuMjYzNCAyLjgzNjk2IDMgMy41IDNINi40OTk5OUw2LjQ5OTk5IDNINi40OTk5Nkw2IDIuNTAwMDRWMi41MDAwMUw1LjIwNzEgMS43MDcxMUw1LjkxNDIxIDFMOC4wNjA2NSAzLjE0NjQ1TDguMDYwNjUgMy44NTM1NlpNNSA2LjUwMDAzTDUuOTE0MjEgNy40MTQyNEw2IDcuMzI4NDVWMTRIMTRWN0gxMFYzSDkuMDYwNjVWMi43MzIyN0w4LjMyODM4IDJIMTEuMkwxMS41IDIuMUwxNC45IDUuNkwxNSA2VjE0LjVMMTQuNSAxNUg1LjVMNSAxNC41VjkuMDAwMDNWNi41MDAwM1pNMTEgM1Y2SDEzLjkwMzJMMTEgM1oiIGZpbGw9IiNDNUM1QzUiLz4KPC9zdmc+Cg==")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.snippet:before,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.snippet:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0yLjUgMUwyIDEuNVYxM0gzVjJIMTRWMTNIMTVWMS41TDE0LjUgMUgyLjVaTTIgMTVWMTRIM1YxNUgyWk01IDE0LjAwMDFINFYxNS4wMDAxSDVWMTQuMDAwMVpNNiAxNC4wMDAxSDdWMTUuMDAwMUg2VjE0LjAwMDFaTTkgMTQuMDAwMUg4VjE1LjAwMDFIOVYxNC4wMDAxWk0xMCAxNC4wMDAxSDExVjE1LjAwMDFIMTBWMTQuMDAwMVpNMTUgMTUuMDAwMVYxNC4wMDAxSDE0VjE1LjAwMDFIMTVaTTEyIDE0LjAwMDFIMTNWMTUuMDAwMUgxMlYxNC4wMDAxWiIgZmlsbD0iI0M1QzVDNSIvPgo8L3N2Zz4K")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.customcolor:before,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.customcolor:before{background-image:none}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .suggest-icon.folder:before,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .suggest-icon.folder:before{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xLjAxMDg3IDIuNUwxLjUxMDg3IDJINi41MDcxM0w2Ljg2MDY4IDIuMTQ2NDVMNy43MTM0OSAyLjk5OTI1SDE0LjUwMTFMMTUuMDAxMSAzLjQ5OTI1VjguOTk1MTJMMTQuOTkwMyA5LjAwNTk5VjEzLjUwMjFMMTQuNDkwMyAxNC4wMDIxSDEuNUwxIDEzLjUwMjFWNi41MDczNUwxLjAxMDg3IDYuNDk2NDhWMi41Wk0xNC4wMDExIDMuOTk5MjVWNS4wMDMxMUg3LjUwMDVMNy4xNDY5NSA1LjE0OTU2TDYuMjg5MTUgNi4wMDczNUgyLjAxMDg3VjNINi4zMDAwMkw3LjE1MjgzIDMuODUyOEw3LjUwNjM4IDMuOTk5MjVIMTQuMDAxMVpNNi40OTYyNiA3LjAwNzM1SDIuMDEwODdWNy40OTU4OEgxLjk5OTYzVjExLjQ5MjlIMlYxMy4wMDIxSDEzLjk5MDNWMTEuNDkyOUgxMy45OTA2VjcuNDk1ODhIMTMuOTkwM1Y2LjAwMzExSDcuNzA3NjFMNi44NDk4MSA2Ljg2MDlMNi40OTYyNiA3LjAwNzM1WiIgZmlsbD0iI0M1QzVDNSIvPgo8L3N2Zz4K")}.monaco-editor{font-family:-apple-system,BlinkMacSystemFont,Segoe WPC,Segoe UI,HelveticaNeue-Light,Ubuntu,Droid Sans,sans-serif}.monaco-editor.hc-black .monaco-menu .monaco-action-bar.vertical .action-menu-item:focus .action-label,.monaco-editor.vs-dark .monaco-menu .monaco-action-bar.vertical .action-menu-item:focus .action-label,.monaco-menu .monaco-action-bar.vertical .action-item .action-menu-item:focus .action-label{stroke-width:1.2px}.monaco-editor-hover p{margin:0}.monaco-editor.hc-black{-ms-high-contrast-adjust:none}@media screen and (-ms-high-contrast:active){.monaco-editor.vs-dark .view-overlays .current-line,.monaco-editor.vs .view-overlays .current-line{border-color:windowtext!important;border-left:0;border-right:0}.monaco-editor.vs-dark .cursor,.monaco-editor.vs .cursor{background-color:windowtext!important}.monaco-editor.vs-dark .dnd-target,.monaco-editor.vs .dnd-target{border-color:windowtext!important}.monaco-editor.vs-dark .selected-text,.monaco-editor.vs .selected-text{background-color:highlight!important}.monaco-editor.vs-dark .view-line,.monaco-editor.vs .view-line{-ms-high-contrast-adjust:none}.monaco-editor.vs-dark .view-line span,.monaco-editor.vs .view-line span{color:windowtext!important}.monaco-editor.vs-dark .view-line span.inline-selected-text,.monaco-editor.vs .view-line span.inline-selected-text{color:highlighttext!important}.monaco-editor.vs-dark .view-overlays,.monaco-editor.vs .view-overlays{-ms-high-contrast-adjust:none}.monaco-editor.vs-dark .reference-decoration,.monaco-editor.vs-dark .selectionHighlight,.monaco-editor.vs-dark .wordHighlight,.monaco-editor.vs-dark .wordHighlightStrong,.monaco-editor.vs .reference-decoration,.monaco-editor.vs .selectionHighlight,.monaco-editor.vs .wordHighlight,.monaco-editor.vs .wordHighlightStrong{border:2px dotted highlight!important;background:transparent!important;box-sizing:border-box}.monaco-editor.vs-dark .rangeHighlight,.monaco-editor.vs .rangeHighlight{background:transparent!important;border:1px dotted activeborder!important;box-sizing:border-box}.monaco-editor.vs-dark .bracket-match,.monaco-editor.vs .bracket-match{border-color:windowtext!important;background:transparent!important}.monaco-editor.vs-dark .currentFindMatch,.monaco-editor.vs-dark .findMatch,.monaco-editor.vs .currentFindMatch,.monaco-editor.vs .findMatch{border:2px dotted activeborder!important;background:transparent!important;box-sizing:border-box}.monaco-editor.vs-dark .find-widget,.monaco-editor.vs .find-widget{border:1px solid windowtext}.monaco-editor.vs-dark .monaco-list .monaco-list-row,.monaco-editor.vs .monaco-list .monaco-list-row{-ms-high-contrast-adjust:none;color:windowtext!important}.monaco-editor.vs-dark .monaco-list .monaco-list-row.focused,.monaco-editor.vs .monaco-list .monaco-list-row.focused{color:highlighttext!important;background-color:highlight!important}.monaco-editor.vs-dark .monaco-list .monaco-list-row:hover,.monaco-editor.vs .monaco-list .monaco-list-row:hover{background:transparent!important;border:1px solid highlight;box-sizing:border-box}.monaco-editor.vs-dark .monaco-tree .monaco-tree-row,.monaco-editor.vs .monaco-tree .monaco-tree-row{-ms-high-contrast-adjust:none;color:windowtext!important}.monaco-editor.vs-dark .monaco-tree .monaco-tree-row.focused,.monaco-editor.vs-dark .monaco-tree .monaco-tree-row.selected,.monaco-editor.vs .monaco-tree .monaco-tree-row.focused,.monaco-editor.vs .monaco-tree .monaco-tree-row.selected{color:highlighttext!important;background-color:highlight!important}.monaco-editor.vs-dark .monaco-tree .monaco-tree-row:hover,.monaco-editor.vs .monaco-tree .monaco-tree-row:hover{background:transparent!important;border:1px solid highlight;box-sizing:border-box}.monaco-editor.vs-dark .monaco-scrollable-element>.scrollbar,.monaco-editor.vs .monaco-scrollable-element>.scrollbar{-ms-high-contrast-adjust:none;background:background!important;border:1px solid windowtext;box-sizing:border-box}.monaco-editor.vs-dark .monaco-scrollable-element>.scrollbar>.slider,.monaco-editor.vs .monaco-scrollable-element>.scrollbar>.slider{background:windowtext!important}.monaco-editor.vs-dark .monaco-scrollable-element>.scrollbar>.slider.active,.monaco-editor.vs-dark .monaco-scrollable-element>.scrollbar>.slider:hover,.monaco-editor.vs .monaco-scrollable-element>.scrollbar>.slider.active,.monaco-editor.vs .monaco-scrollable-element>.scrollbar>.slider:hover{background:highlight!important}.monaco-editor.vs-dark .decorationsOverviewRuler,.monaco-editor.vs .decorationsOverviewRuler{opacity:0}.monaco-editor.vs-dark .minimap,.monaco-editor.vs .minimap{display:none}.monaco-editor.vs-dark .squiggly-d-error,.monaco-editor.vs .squiggly-d-error{background:transparent!important;border-bottom:4px double #e47777}.monaco-editor.vs-dark .squiggly-b-info,.monaco-editor.vs-dark .squiggly-c-warning,.monaco-editor.vs .squiggly-b-info,.monaco-editor.vs .squiggly-c-warning{border-bottom:4px double #71b771}.monaco-editor.vs-dark .squiggly-a-hint,.monaco-editor.vs .squiggly-a-hint{border-bottom:4px double #6c6c6c}.monaco-editor.vs-dark .monaco-menu .monaco-action-bar.vertical .action-menu-item:focus .action-label,.monaco-editor.vs .monaco-menu .monaco-action-bar.vertical .action-menu-item:focus .action-label{-ms-high-contrast-adjust:none;color:highlighttext!important;background-color:highlight!important}.monaco-editor.vs-dark .monaco-menu .monaco-action-bar.vertical .action-menu-item:hover .action-label,.monaco-editor.vs .monaco-menu .monaco-action-bar.vertical .action-menu-item:hover .action-label{-ms-high-contrast-adjust:none;background:transparent!important;border:1px solid highlight;box-sizing:border-box}.monaco-diff-editor.vs-dark .diffOverviewRuler,.monaco-diff-editor.vs .diffOverviewRuler{display:none}.monaco-editor.vs-dark .line-delete,.monaco-editor.vs-dark .line-insert,.monaco-editor.vs .line-delete,.monaco-editor.vs .line-insert{background:transparent!important;border:1px solid highlight!important;box-sizing:border-box}.monaco-editor.vs-dark .char-delete,.monaco-editor.vs-dark .char-insert,.monaco-editor.vs .char-delete,.monaco-editor.vs .char-insert{background:transparent!important}}.monaco-diff-editor .diffOverview{z-index:9}.monaco-diff-editor.vs .diffOverview{background:rgba(0,0,0,.03)}.monaco-diff-editor.vs-dark .diffOverview{background:hsla(0,0%,100%,.01)}.monaco-diff-editor .diffViewport{box-shadow:inset 0 0 1px 0 #b9b9b9;background:rgba(0,0,0,.1)}.monaco-diff-editor.hc-black .diffViewport,.monaco-diff-editor.vs-dark .diffViewport{background:hsla(0,0%,100%,.1)}.monaco-scrollable-element.modified-in-monaco-diff-editor.vs-dark .scrollbar,.monaco-scrollable-element.modified-in-monaco-diff-editor.vs .scrollbar{background:transparent}.monaco-scrollable-element.modified-in-monaco-diff-editor.hc-black .scrollbar{background:none}.monaco-scrollable-element.modified-in-monaco-diff-editor .slider{z-index:10}.modified-in-monaco-diff-editor .slider.active{background:hsla(0,0%,67%,.4)}.modified-in-monaco-diff-editor.hc-black .slider.active{background:none}.monaco-diff-editor .delete-sign,.monaco-diff-editor .insert-sign,.monaco-editor .delete-sign,.monaco-editor .insert-sign{background-size:60%;opacity:.7;background-repeat:no-repeat;background-position:75%;background-size:11px 11px}.monaco-diff-editor.hc-black .delete-sign,.monaco-diff-editor.hc-black .insert-sign,.monaco-editor.hc-black .delete-sign,.monaco-editor.hc-black .insert-sign{opacity:1}.monaco-diff-editor .insert-sign,.monaco-editor .insert-sign{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTE0IDdWOEg4VjE0SDdWOEgxVjdIN1YxSDhWN0gxNFoiIGZpbGw9IiM0MjQyNDIiLz4KPC9zdmc+Cg==")}.monaco-diff-editor .delete-sign,.monaco-editor .delete-sign{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTE1IDhIMVY3SDE1VjhaIiBmaWxsPSIjNDI0MjQyIi8+Cjwvc3ZnPgo=")}.monaco-diff-editor.hc-black .insert-sign,.monaco-diff-editor.vs-dark .insert-sign,.monaco-editor.hc-black .insert-sign,.monaco-editor.vs-dark .insert-sign{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTE0IDdWOEg4VjE0SDdWOEgxVjdIN1YxSDhWN0gxNFoiIGZpbGw9IiNDNUM1QzUiLz4KPC9zdmc+Cg==")}.monaco-diff-editor.hc-black .delete-sign,.monaco-diff-editor.vs-dark .delete-sign,.monaco-editor.hc-black .delete-sign,.monaco-editor.vs-dark .delete-sign{background-image:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTE1IDhIMVY3SDE1VjhaIiBmaWxsPSIjQzVDNUM1Ii8+Cjwvc3ZnPgo=")}.monaco-editor .inline-added-margin-view-zone,.monaco-editor .inline-deleted-margin-view-zone{text-align:right}.monaco-editor .diagonal-fill{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAChJREFUKFNjOH/+fAMDDgCSu3Dhwn9c8gwwBTgNGR4KQP4HhQOhsAIAZCBTkhtqePcAAAAASUVORK5CYII=")}.monaco-editor.vs-dark .diagonal-fill{opacity:.2}.monaco-editor.hc-black .diagonal-fill{background:none}.monaco-editor .view-zones .view-lines .view-line span{display:inline-block}.monaco-editor .margin-view-zones .inline-deleted-margin-view-zone .lightbulb-glyph{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMS42NzA4IDguNjU4MDZDMTEuMzMxOSA4Ljk5MTYgMTEuMDcxNiA5LjM2Mjc4IDEwLjg4ODYgOS43NzE3MkMxMC43MTA1IDEwLjE3OTIgMTAuNjIxIDEwLjYyMTkgMTAuNjIxIDExLjEwMDlWMTIuNzAxMkMxMC42MjEgMTIuODgwNyAxMC41ODcyIDEzLjA1MDMgMTAuNTE4OSAxMy4yMDkxQzEwLjQ1MTMgMTMuMzY2MSAxMC4zNTg2IDEzLjUwMzggMTAuMjQwNyAxMy42MjEzQzEwLjEyMjggMTMuNzM4OCA5Ljk4NDY0IDEzLjgzMTEgOS44MjcyMyAxMy44OTg0QzkuNjY4MDYgMTMuOTY2MyA5LjQ5ODA2IDE0IDkuMzE4MjMgMTRINy43MTIwNUM3LjUzMjIzIDE0IDcuMzYyMjMgMTMuOTY2MyA3LjIwMzA2IDEzLjg5ODRDNy4wNDU2NCAxMy44MzExIDYuOTA3NTMgMTMuNzM4OCA2Ljc4OTYxIDEzLjYyMTNDNi42NzE2OCAxMy41MDM4IDYuNTc4OTUgMTMuMzY2MSA2LjUxMTQxIDEzLjIwOTFDNi40NDMxMSAxMy4wNTAzIDYuNDA5MjcgMTIuODgwNyA2LjQwOTI3IDEyLjcwMTJWMTEuMTAwOUM2LjQwOTI3IDEwLjYyMiA2LjMxNzcyIDEwLjE3OTUgNi4xMzU1MyA5Ljc3MjA5QzUuOTU2ODMgOS4zNjMzNiA1LjY5ODMyIDguOTkxNTYgNS4zNTk1MyA4LjY1ODA2QzQuOTI0NjggOC4yMjkwMyA0LjU4ODk2IDcuNzUwMDMgNC4zNTM2MSA3LjIyMTM0QzQuMTE3NTYgNi42OTEwNyA0IDYuMTE2NzIgNCA1LjQ5OTUzQzQgNS4wODY2NCA0LjA1MzQyIDQuNjg4MDIgNC4xNjA0OCA0LjMwMzk3QzQuMjY3MjggMy45MjA4OSA0LjQxOTA3IDMuNTYyODYgNC42MTU5NSAzLjIzMDE4QzQuODEyNTcgMi44OTM3NyA1LjA0Nzc3IDIuNTg5MTEgNS4zMjE0NiAyLjMxNjQxQzUuNTk1MDMgMi4wNDM4MyA1Ljg5ODU4IDEuODA5NTMgNi4yMzE5NSAxLjYxMzY0QzYuNTY5NzkgMS40MTc2NCA2LjkzMTQ2IDEuMjY2MiA3LjMxNTc4IDEuMTU5ODNDNy43MDEwNiAxLjA1MzIgOC4xMDA5NCAxIDguNTE1MTQgMUM4LjkyOTM0IDEgOS4zMjkyMyAxLjA1MzIgOS43MTQ1MSAxLjE1OTgzQzEwLjA5ODggMS4yNjYyIDEwLjQ1OCAxLjQxNzM5IDEwLjc5MTggMS42MTM1MUMxMS4xMjk0IDEuODA5MzggMTEuNDM1MSAyLjA0MzcgMTEuNzA4OCAyLjMxNjQxQzExLjk4MjUgMi41ODkxIDEyLjIxNzcgMi44OTM3NiAxMi40MTQzIDMuMjMwMTZDMTIuNjExMiAzLjU2Mjg1IDEyLjc2MyAzLjkyMDg4IDEyLjg2OTggNC4zMDM5N0MxMi45NzY5IDQuNjg4MDIgMTMuMDMwMyA1LjA4NjY0IDEzLjAzMDMgNS40OTk1M0MxMy4wMzAzIDYuMTE2NzIgMTIuOTEyNyA2LjY5MTA3IDEyLjY3NjcgNy4yMjEzNEMxMi40NDEzIDcuNzUwMDMgMTIuMTA1NiA4LjIyOTAzIDExLjY3MDggOC42NTgwNlpNOS42MjE2MiAxMC41SDcuNDA4NjdWMTIuNzAxMkM3LjQwODY3IDEyLjc4MjMgNy40MzcyIDEyLjg1MTIgNy40OTg4OCAxMi45MTI3QzcuNTYwNTggMTIuOTc0MSA3LjYzMDA3IDEzLjAwMjggNy43MTIwNSAxMy4wMDI4SDkuMzE4MjNDOS40MDAyMiAxMy4wMDI4IDkuNDY5NzEgMTIuOTc0MSA5LjUzMTQgMTIuOTEyN0M5LjU5MzA5IDEyLjg1MTIgOS42MjE2MiAxMi43ODIzIDkuNjIxNjIgMTIuNzAxMlYxMC41WiIgZmlsbD0iIzQyNDI0MiIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTExLjY3MDggOC42NTgwNkMxMS4zMzE5IDguOTkxNiAxMS4wNzE2IDkuMzYyNzggMTAuODg4NiA5Ljc3MTcyQzEwLjcxMDUgMTAuMTc5MiAxMC42MjEgMTAuNjIxOSAxMC42MjEgMTEuMTAwOVYxMi43MDEyQzEwLjYyMSAxMi44ODA3IDEwLjU4NzIgMTMuMDUwMyAxMC41MTg5IDEzLjIwOTFDMTAuNDUxMyAxMy4zNjYxIDEwLjM1ODYgMTMuNTAzOCAxMC4yNDA3IDEzLjYyMTNDMTAuMTIyOCAxMy43Mzg4IDkuOTg0NjQgMTMuODMxMSA5LjgyNzIzIDEzLjg5ODRDOS42NjgwNiAxMy45NjYzIDkuNDk4MDYgMTQgOS4zMTgyMyAxNEg3LjcxMjA1QzcuNTMyMjMgMTQgNy4zNjIyMyAxMy45NjYzIDcuMjAzMDYgMTMuODk4NEM3LjA0NTY0IDEzLjgzMTEgNi45MDc1MyAxMy43Mzg4IDYuNzg5NjEgMTMuNjIxM0M2LjY3MTY4IDEzLjUwMzggNi41Nzg5NSAxMy4zNjYxIDYuNTExNDEgMTMuMjA5MUM2LjQ0MzExIDEzLjA1MDMgNi40MDkyNyAxMi44ODA3IDYuNDA5MjcgMTIuNzAxMlYxMS4xMDA5QzYuNDA5MjcgMTAuNjIyIDYuMzE3NzIgMTAuMTc5NSA2LjEzNTUzIDkuNzcyMDlDNS45NTY4MyA5LjM2MzM2IDUuNjk4MzIgOC45OTE1NiA1LjM1OTUzIDguNjU4MDZDNC45MjQ2OCA4LjIyOTAzIDQuNTg4OTYgNy43NTAwMyA0LjM1MzYxIDcuMjIxMzRDNC4xMTc1NiA2LjY5MTA3IDQgNi4xMTY3MiA0IDUuNDk5NTNDNCA1LjA4NjY0IDQuMDUzNDIgNC42ODgwMiA0LjE2MDQ4IDQuMzAzOTdDNC4yNjcyOCAzLjkyMDg5IDQuNDE5MDcgMy41NjI4NiA0LjYxNTk1IDMuMjMwMThDNC44MTI1NyAyLjg5Mzc3IDUuMDQ3NzcgMi41ODkxMSA1LjMyMTQ2IDIuMzE2NDFDNS41OTUwMyAyLjA0MzgzIDUuODk4NTggMS44MDk1MyA2LjIzMTk1IDEuNjEzNjRDNi41Njk3OSAxLjQxNzY0IDYuOTMxNDYgMS4yNjYyIDcuMzE1NzggMS4xNTk4M0M3LjcwMTA2IDEuMDUzMiA4LjEwMDk0IDEgOC41MTUxNCAxQzguOTI5MzQgMSA5LjMyOTIzIDEuMDUzMiA5LjcxNDUxIDEuMTU5ODNDMTAuMDk4OCAxLjI2NjIgMTAuNDU4IDEuNDE3MzkgMTAuNzkxOCAxLjYxMzUxQzExLjEyOTQgMS44MDkzOCAxMS40MzUxIDIuMDQzNyAxMS43MDg4IDIuMzE2NDFDMTEuOTgyNSAyLjU4OTEgMTIuMjE3NyAyLjg5Mzc2IDEyLjQxNDMgMy4yMzAxNkMxMi42MTEyIDMuNTYyODUgMTIuNzYzIDMuOTIwODggMTIuODY5OCA0LjMwMzk3QzEyLjk3NjkgNC42ODgwMiAxMy4wMzAzIDUuMDg2NjQgMTMuMDMwMyA1LjQ5OTUzQzEzLjAzMDMgNi4xMTY3MiAxMi45MTI3IDYuNjkxMDcgMTIuNjc2NyA3LjIyMTM0QzEyLjQ0MTMgNy43NTAwMyAxMi4xMDU2IDguMjI5MDMgMTEuNjcwOCA4LjY1ODA2Wk05LjYyMTYyIDEwLjVINy40MDg2N1YxMi43MDEyQzcuNDA4NjcgMTIuNzgyMyA3LjQzNzIgMTIuODUxMiA3LjQ5ODg4IDEyLjkxMjdDNy41NjA1OCAxMi45NzQxIDcuNjMwMDcgMTMuMDAyOCA3LjcxMjA1IDEzLjAwMjhIOS4zMTgyM0M5LjQwMDIyIDEzLjAwMjggOS40Njk3MSAxMi45NzQxIDkuNTMxNCAxMi45MTI3QzkuNTkzMDkgMTIuODUxMiA5LjYyMTYyIDEyLjc4MjMgOS42MjE2MiAxMi43MDEyVjEwLjVaIiBmaWxsPSIjNDI0MjQyIi8+Cjwvc3ZnPgo=") 50% no-repeat}.monaco-editor.hc-dark .margin-view-zones .inline-deleted-margin-view-zone .lightbulb-glyph,.monaco-editor.vs-dark .margin-view-zones .inline-deleted-margin-view-zone .lightbulb-glyph{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMS42NzA4IDguNjU4MDZDMTEuMzMxOSA4Ljk5MTYgMTEuMDcxNiA5LjM2Mjc4IDEwLjg4ODYgOS43NzE3MkMxMC43MTA1IDEwLjE3OTIgMTAuNjIxIDEwLjYyMTkgMTAuNjIxIDExLjEwMDlWMTIuNzAxMkMxMC42MjEgMTIuODgwNyAxMC41ODcyIDEzLjA1MDMgMTAuNTE4OSAxMy4yMDkxQzEwLjQ1MTMgMTMuMzY2MSAxMC4zNTg2IDEzLjUwMzggMTAuMjQwNyAxMy42MjEzQzEwLjEyMjggMTMuNzM4OCA5Ljk4NDY0IDEzLjgzMTEgOS44MjcyMyAxMy44OTg0QzkuNjY4MDYgMTMuOTY2MyA5LjQ5ODA2IDE0IDkuMzE4MjMgMTRINy43MTIwNUM3LjUzMjIzIDE0IDcuMzYyMjMgMTMuOTY2MyA3LjIwMzA2IDEzLjg5ODRDNy4wNDU2NCAxMy44MzExIDYuOTA3NTMgMTMuNzM4OCA2Ljc4OTYxIDEzLjYyMTNDNi42NzE2OCAxMy41MDM4IDYuNTc4OTUgMTMuMzY2MSA2LjUxMTQxIDEzLjIwOTFDNi40NDMxMSAxMy4wNTAzIDYuNDA5MjcgMTIuODgwNyA2LjQwOTI3IDEyLjcwMTJWMTEuMTAwOUM2LjQwOTI3IDEwLjYyMiA2LjMxNzcyIDEwLjE3OTUgNi4xMzU1MyA5Ljc3MjA5QzUuOTU2ODMgOS4zNjMzNiA1LjY5ODMyIDguOTkxNTYgNS4zNTk1MyA4LjY1ODA2QzQuOTI0NjggOC4yMjkwMyA0LjU4ODk2IDcuNzUwMDMgNC4zNTM2MSA3LjIyMTM0QzQuMTE3NTYgNi42OTEwNyA0IDYuMTE2NzIgNCA1LjQ5OTUzQzQgNS4wODY2NCA0LjA1MzQyIDQuNjg4MDIgNC4xNjA0OCA0LjMwMzk3QzQuMjY3MjggMy45MjA4OSA0LjQxOTA3IDMuNTYyODYgNC42MTU5NSAzLjIzMDE4QzQuODEyNTcgMi44OTM3NyA1LjA0Nzc3IDIuNTg5MTEgNS4zMjE0NiAyLjMxNjQxQzUuNTk1MDMgMi4wNDM4MyA1Ljg5ODU4IDEuODA5NTMgNi4yMzE5NSAxLjYxMzY0QzYuNTY5NzkgMS40MTc2NCA2LjkzMTQ2IDEuMjY2MiA3LjMxNTc4IDEuMTU5ODNDNy43MDEwNiAxLjA1MzIgOC4xMDA5NCAxIDguNTE1MTQgMUM4LjkyOTM0IDEgOS4zMjkyMyAxLjA1MzIgOS43MTQ1MSAxLjE1OTgzQzEwLjA5ODggMS4yNjYyIDEwLjQ1OCAxLjQxNzM5IDEwLjc5MTggMS42MTM1MUMxMS4xMjk0IDEuODA5MzggMTEuNDM1MSAyLjA0MzcgMTEuNzA4OCAyLjMxNjQxQzExLjk4MjUgMi41ODkxIDEyLjIxNzcgMi44OTM3NiAxMi40MTQzIDMuMjMwMTZDMTIuNjExMiAzLjU2Mjg1IDEyLjc2MyAzLjkyMDg4IDEyLjg2OTggNC4zMDM5N0MxMi45NzY5IDQuNjg4MDIgMTMuMDMwMyA1LjA4NjY0IDEzLjAzMDMgNS40OTk1M0MxMy4wMzAzIDYuMTE2NzIgMTIuOTEyNyA2LjY5MTA3IDEyLjY3NjcgNy4yMjEzNEMxMi40NDEzIDcuNzUwMDMgMTIuMTA1NiA4LjIyOTAzIDExLjY3MDggOC42NTgwNlpNOS42MjE2MiAxMC41SDcuNDA4NjdWMTIuNzAxMkM3LjQwODY3IDEyLjc4MjMgNy40MzcyIDEyLjg1MTIgNy40OTg4OCAxMi45MTI3QzcuNTYwNTggMTIuOTc0MSA3LjYzMDA3IDEzLjAwMjggNy43MTIwNSAxMy4wMDI4SDkuMzE4MjNDOS40MDAyMiAxMy4wMDI4IDkuNDY5NzEgMTIuOTc0MSA5LjUzMTQgMTIuOTEyN0M5LjU5MzA5IDEyLjg1MTIgOS42MjE2MiAxMi43ODIzIDkuNjIxNjIgMTIuNzAxMlYxMC41WiIgZmlsbD0iI0MyQzJDMiIvPgo8L3N2Zz4K") 50% no-repeat}.monaco-editor .margin-view-zones .lightbulb-glyph:hover{cursor:pointer}.monaco-diff-editor .diff-review-line-number{text-align:right;display:inline-block}.monaco-diff-editor .diff-review{position:absolute;-webkit-user-select:none;-ms-user-select:none;-moz-user-select:none;-o-user-select:none;user-select:none}.monaco-diff-editor .diff-review-summary{padding-left:10px}.monaco-diff-editor .diff-review-shadow{position:absolute}.monaco-diff-editor .diff-review-row{white-space:pre}.monaco-diff-editor .diff-review-table{display:table;min-width:100%}.monaco-diff-editor .diff-review-row{display:table-row;width:100%}.monaco-diff-editor .diff-review-cell{display:table-cell}.monaco-diff-editor .diff-review-spacer{display:inline-block;width:10px}.monaco-diff-editor .diff-review-actions{display:inline-block;position:absolute;right:10px;top:2px}.monaco-diff-editor .diff-review-actions .action-label{width:16px;height:16px;margin:2px 0}.monaco-diff-editor .action-label.icon.close-diff-review{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik04LjAwMDAxIDguNzA3MTFMMTEuNjQ2NSAxMi4zNTM2TDEyLjM1MzYgMTEuNjQ2NUw4LjcwNzExIDguMDAwMDFMMTIuMzUzNiA0LjM1MzU2TDExLjY0NjUgMy42NDY0NUw4LjAwMDAxIDcuMjkyOUw0LjM1MzU2IDMuNjQ2NDVMMy42NDY0NSA0LjM1MzU2TDcuMjkyOSA4LjAwMDAxTDMuNjQ2NDUgMTEuNjQ2NUw0LjM1MzU2IDEyLjM1MzZMOC4wMDAwMSA4LjcwNzExWiIgZmlsbD0iIzQyNDI0MiIvPgo8L3N2Zz4K") 50% no-repeat}.monaco-diff-editor.hc-black .action-label.icon.close-diff-review,.monaco-diff-editor.vs-dark .action-label.icon.close-diff-review{background:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik04LjAwMDAxIDguNzA3MTFMMTEuNjQ2NSAxMi4zNTM2TDEyLjM1MzYgMTEuNjQ2NUw4LjcwNzExIDguMDAwMDFMMTIuMzUzNiA0LjM1MzU2TDExLjY0NjUgMy42NDY0NUw4LjAwMDAxIDcuMjkyOUw0LjM1MzU2IDMuNjQ2NDVMMy42NDY0NSA0LjM1MzU2TDcuMjkyOSA4LjAwMDAxTDMuNjQ2NDUgMTEuNjQ2NUw0LjM1MzU2IDEyLjM1MzZMOC4wMDAwMSA4LjcwNzExWiIgZmlsbD0iI0M1QzVDNSIvPgo8L3N2Zz4K") 50% no-repeat}.context-view .monaco-menu{min-width:130px}.context-view-block{position:fixed;left:0;top:0;z-index:-1;width:100%;height:100%}.monaco-menu .monaco-action-bar.vertical{margin-left:0;overflow:visible}.monaco-menu .monaco-action-bar.vertical .actions-container{display:block}.monaco-menu .monaco-action-bar.vertical .action-item{padding:0;transform:none;display:-ms-flexbox;display:flex}.monaco-menu .monaco-action-bar.vertical .action-item.active{transform:none}.monaco-menu .monaco-action-bar.vertical .action-menu-item{-ms-flex:1 1 auto;flex:1 1 auto;display:-ms-flexbox;display:flex;height:2em;-ms-flex-align:center;align-items:center;position:relative}.monaco-menu .monaco-action-bar.vertical .action-label{-ms-flex:1 1 auto;flex:1 1 auto;text-decoration:none;padding:0 1em;background:none;font-size:12px;line-height:1}.monaco-menu .monaco-action-bar.vertical .keybinding,.monaco-menu .monaco-action-bar.vertical .submenu-indicator{display:inline-block;-ms-flex:2 1 auto;flex:2 1 auto;padding:0 1em;text-align:right;font-size:12px;line-height:1}.monaco-menu .monaco-action-bar.vertical .submenu-indicator{height:100%;-webkit-mask:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTQuNTIwNTEgMTIuMzY0M0w5Ljg3NzkzIDdMNC41MjA1MSAxLjYzNTc0Mkw1LjEzNTc0IDEuMDIwNTA3OEwxMS4xMjIxIDdMNS4xMzU3NCAxMi45Nzk1TDQuNTIwNTEgMTIuMzY0M1oiIGZpbGw9ImJsYWNrIi8+Cjwvc3ZnPgo=") no-repeat 90% 50%/13px 13px;mask:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTQuNTIwNTEgMTIuMzY0M0w5Ljg3NzkzIDdMNC41MjA1MSAxLjYzNTc0Mkw1LjEzNTc0IDEuMDIwNTA3OEwxMS4xMjIxIDdMNS4xMzU3NCAxMi45Nzk1TDQuNTIwNTEgMTIuMzY0M1oiIGZpbGw9ImJsYWNrIi8+Cjwvc3ZnPgo=") no-repeat 90% 50%/13px 13px}.monaco-menu .monaco-action-bar.vertical .action-item.disabled .keybinding,.monaco-menu .monaco-action-bar.vertical .action-item.disabled .submenu-indicator{opacity:.4}.monaco-menu .monaco-action-bar.vertical .action-label:not(.separator){display:inline-block;-o-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;margin:0}.monaco-menu .monaco-action-bar.vertical .action-item{position:static;overflow:visible}.monaco-menu .monaco-action-bar.vertical .action-item .monaco-submenu{position:absolute}.monaco-menu .monaco-action-bar.vertical .action-label.separator{padding:.5em 0 0;margin-bottom:.5em;width:100%}.monaco-menu .monaco-action-bar.vertical .action-label.separator.text{padding:.7em 1em .1em;font-weight:700;opacity:1}.monaco-menu .monaco-action-bar.vertical .action-label:hover{color:inherit}.monaco-menu .monaco-action-bar.vertical .menu-item-check{position:absolute;visibility:hidden;-webkit-mask:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xNC40MzE1IDMuMzIzMkw1Ljk2MTUxIDEzLjMyMzJMNS4xNzA4IDEzLjI4NzRMMS44MjA4IDguNTE3NEwyLjYzOTE1IDcuOTQyNjhMNS42MTY5NyAxMi4xODI3TDEzLjY2ODQgMi42NzY4OEwxNC40MzE1IDMuMzIzMloiIGZpbGw9IiNDNUM1QzUiLz4KPC9zdmc+Cg==") no-repeat 50% 56%/15px 15px;mask:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xNC40MzE1IDMuMzIzMkw1Ljk2MTUxIDEzLjMyMzJMNS4xNzA4IDEzLjI4NzRMMS44MjA4IDguNTE3NEwyLjYzOTE1IDcuOTQyNjhMNS42MTY5NyAxMi4xODI3TDEzLjY2ODQgMi42NzY4OEwxNC40MzE1IDMuMzIzMloiIGZpbGw9IiNDNUM1QzUiLz4KPC9zdmc+Cg==") no-repeat 50% 56%/15px 15px;width:1em;height:100%}.monaco-menu .monaco-action-bar.vertical .action-menu-item.checked .menu-item-check{visibility:visible}.context-view.monaco-menu-container{outline:0;border:none;animation:fadeIn 83ms linear}.context-view.monaco-menu-container .monaco-action-bar.vertical:focus,.context-view.monaco-menu-container .monaco-action-bar.vertical :focus,.context-view.monaco-menu-container :focus{outline:0}.monaco-menu .monaco-action-bar.vertical .action-item{border:thin solid transparent}.hc-black .context-view.monaco-menu-container{box-shadow:none}.hc-black .monaco-menu .monaco-action-bar.vertical .action-item.focused{background:none}.menubar{display:-ms-flexbox;display:flex;-ms-flex-negative:1;flex-shrink:1;box-sizing:border-box;height:30px;overflow:hidden;-ms-flex-wrap:wrap;flex-wrap:wrap}.fullscreen .menubar{margin:0;padding:0 5px}.menubar>.menubar-menu-button{-ms-flex-align:center;align-items:center;box-sizing:border-box;padding:0 8px;cursor:default;-webkit-app-region:no-drag;zoom:1;white-space:nowrap;outline:0}.menubar .menubar-menu-items-holder{position:absolute;left:0;opacity:1;z-index:2000}.menubar .menubar-menu-items-holder.monaco-menu-container{outline:0;border:none}.menubar .menubar-menu-items-holder.monaco-menu-container :focus{outline:0}.menubar .toolbar-toggle-more{background-position:50%;background-repeat:no-repeat;background-size:14px;width:20px;height:100%;display:inline-block;padding:0;-webkit-mask:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTQgOEM0IDguMTk3NzggMy45NDEzNSA4LjM5MTEyIDMuODMxNDcgOC41NTU1N0MzLjcyMTU5IDguNzIwMDIgMy41NjU0MSA4Ljg0ODE5IDMuMzgyNjggOC45MjM4OEMzLjE5OTk2IDguOTk5NTcgMi45OTg4OSA5LjAxOTM3IDIuODA0OTEgOC45ODA3OUMyLjYxMDkzIDguOTQyMiAyLjQzMjc1IDguODQ2OTYgMi4yOTI4OSA4LjcwNzExQzIuMTUzMDQgOC41NjcyNSAyLjA1NzggOC4zODkwNyAyLjAxOTIyIDguMTk1MDlDMS45ODA2MyA4LjAwMTExIDIuMDAwNDMgNy44MDAwNCAyLjA3NjEyIDcuNjE3MzJDMi4xNTE4MSA3LjQzNDU5IDIuMjc5OTggNy4yNzg0MSAyLjQ0NDQzIDcuMTY4NTNDMi42MDg4OCA3LjA1ODY1IDIuODAyMjIgNyAzIDdDMy4yNjUyMiA3IDMuNTE5NTcgNy4xMDUzNiAzLjcwNzExIDcuMjkyODlDMy44OTQ2NCA3LjQ4MDQzIDQgNy43MzQ3OCA0IDhaIiBmaWxsPSIjQzVDNUM1Ii8+CjxwYXRoIGQ9Ik05IDhDOSA4LjE5Nzc4IDguOTQxMzUgOC4zOTExMiA4LjgzMTQ3IDguNTU1NTdDOC43MjE1OSA4LjcyMDAyIDguNTY1NDEgOC44NDgxOSA4LjM4MjY4IDguOTIzODhDOC4xOTk5NiA4Ljk5OTU3IDcuOTk4ODkgOS4wMTkzNyA3LjgwNDkxIDguOTgwNzlDNy42MTA5MyA4Ljk0MjIgNy40MzI3NSA4Ljg0Njk2IDcuMjkyODkgOC43MDcxMUM3LjE1MzA0IDguNTY3MjUgNy4wNTc4IDguMzg5MDcgNy4wMTkyMiA4LjE5NTA5QzYuOTgwNjMgOC4wMDExMSA3LjAwMDQzIDcuODAwMDQgNy4wNzYxMiA3LjYxNzMyQzcuMTUxODEgNy40MzQ1OSA3LjI3OTk4IDcuMjc4NDEgNy40NDQ0MyA3LjE2ODUzQzcuNjA4ODggNy4wNTg2NSA3LjgwMjIyIDcgOCA3QzguMjY1MjIgNyA4LjUxOTU3IDcuMTA1MzYgOC43MDcxMSA3LjI5Mjg5QzguODk0NjQgNy40ODA0MyA5IDcuNzM0NzggOSA4WiIgZmlsbD0iI0M1QzVDNSIvPgo8cGF0aCBkPSJNMTQgOEMxNCA4LjE5Nzc4IDEzLjk0MTQgOC4zOTExMiAxMy44MzE1IDguNTU1NTdDMTMuNzIxNiA4LjcyMDAyIDEzLjU2NTQgOC44NDgxOSAxMy4zODI3IDguOTIzODhDMTMuMiA4Ljk5OTU3IDEyLjk5ODkgOS4wMTkzNyAxMi44MDQ5IDguOTgwNzlDMTIuNjEwOSA4Ljk0MjIgMTIuNDMyNyA4Ljg0Njk2IDEyLjI5MjkgOC43MDcxMUMxMi4xNTMgOC41NjcyNSAxMi4wNTc4IDguMzg5MDcgMTIuMDE5MiA4LjE5NTA5QzExLjk4MDYgOC4wMDExMSAxMi4wMDA0IDcuODAwMDQgMTIuMDc2MSA3LjYxNzMyQzEyLjE1MTggNy40MzQ1OSAxMi4yOCA3LjI3ODQxIDEyLjQ0NDQgNy4xNjg1M0MxMi42MDg5IDcuMDU4NjUgMTIuODAyMiA3IDEzIDdDMTMuMjY1MiA3IDEzLjUxOTYgNy4xMDUzNiAxMy43MDcxIDcuMjkyODlDMTMuODk0NiA3LjQ4MDQzIDE0IDcuNzM0NzggMTQgOFoiIGZpbGw9IiNDNUM1QzUiLz4KPC9zdmc+Cg==") no-repeat 50% 55%/14px 14px;mask:url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTQgOEM0IDguMTk3NzggMy45NDEzNSA4LjM5MTEyIDMuODMxNDcgOC41NTU1N0MzLjcyMTU5IDguNzIwMDIgMy41NjU0MSA4Ljg0ODE5IDMuMzgyNjggOC45MjM4OEMzLjE5OTk2IDguOTk5NTcgMi45OTg4OSA5LjAxOTM3IDIuODA0OTEgOC45ODA3OUMyLjYxMDkzIDguOTQyMiAyLjQzMjc1IDguODQ2OTYgMi4yOTI4OSA4LjcwNzExQzIuMTUzMDQgOC41NjcyNSAyLjA1NzggOC4zODkwNyAyLjAxOTIyIDguMTk1MDlDMS45ODA2MyA4LjAwMTExIDIuMDAwNDMgNy44MDAwNCAyLjA3NjEyIDcuNjE3MzJDMi4xNTE4MSA3LjQzNDU5IDIuMjc5OTggNy4yNzg0MSAyLjQ0NDQzIDcuMTY4NTNDMi42MDg4OCA3LjA1ODY1IDIuODAyMjIgNyAzIDdDMy4yNjUyMiA3IDMuNTE5NTcgNy4xMDUzNiAzLjcwNzExIDcuMjkyODlDMy44OTQ2NCA3LjQ4MDQzIDQgNy43MzQ3OCA0IDhaIiBmaWxsPSIjQzVDNUM1Ii8+CjxwYXRoIGQ9Ik05IDhDOSA4LjE5Nzc4IDguOTQxMzUgOC4zOTExMiA4LjgzMTQ3IDguNTU1NTdDOC43MjE1OSA4LjcyMDAyIDguNTY1NDEgOC44NDgxOSA4LjM4MjY4IDguOTIzODhDOC4xOTk5NiA4Ljk5OTU3IDcuOTk4ODkgOS4wMTkzNyA3LjgwNDkxIDguOTgwNzlDNy42MTA5MyA4Ljk0MjIgNy40MzI3NSA4Ljg0Njk2IDcuMjkyODkgOC43MDcxMUM3LjE1MzA0IDguNTY3MjUgNy4wNTc4IDguMzg5MDcgNy4wMTkyMiA4LjE5NTA5QzYuOTgwNjMgOC4wMDExMSA3LjAwMDQzIDcuODAwMDQgNy4wNzYxMiA3LjYxNzMyQzcuMTUxODEgNy40MzQ1OSA3LjI3OTk4IDcuMjc4NDEgNy40NDQ0MyA3LjE2ODUzQzcuNjA4ODggNy4wNTg2NSA3LjgwMjIyIDcgOCA3QzguMjY1MjIgNyA4LjUxOTU3IDcuMTA1MzYgOC43MDcxMSA3LjI5Mjg5QzguODk0NjQgNy40ODA0MyA5IDcuNzM0NzggOSA4WiIgZmlsbD0iI0M1QzVDNSIvPgo8cGF0aCBkPSJNMTQgOEMxNCA4LjE5Nzc4IDEzLjk0MTQgOC4zOTExMiAxMy44MzE1IDguNTU1NTdDMTMuNzIxNiA4LjcyMDAyIDEzLjU2NTQgOC44NDgxOSAxMy4zODI3IDguOTIzODhDMTMuMiA4Ljk5OTU3IDEyLjk5ODkgOS4wMTkzNyAxMi44MDQ5IDguOTgwNzlDMTIuNjEwOSA4Ljk0MjIgMTIuNDMyNyA4Ljg0Njk2IDEyLjI5MjkgOC43MDcxMUMxMi4xNTMgOC41NjcyNSAxMi4wNTc4IDguMzg5MDcgMTIuMDE5MiA4LjE5NTA5QzExLjk4MDYgOC4wMDExMSAxMi4wMDA0IDcuODAwMDQgMTIuMDc2MSA3LjYxNzMyQzEyLjE1MTggNy40MzQ1OSAxMi4yOCA3LjI3ODQxIDEyLjQ0NDQgNy4xNjg1M0MxMi42MDg5IDcuMDU4NjUgMTIuODAyMiA3IDEzIDdDMTMuMjY1MiA3IDEzLjUxOTYgNy4xMDUzNiAxMy43MDcxIDcuMjkyODlDMTMuODk0NiA3LjQ4MDQzIDE0IDcuNzM0NzggMTQgOFoiIGZpbGw9IiNDNUM1QzUiLz4KPC9zdmc+Cg==") no-repeat 50% 55%/14px 14px}.context-view{position:absolute;z-index:2000}.rule-view .el-card{margin-top:24px;min-height:150px}.rule-view .page-title .el-breadcrumb{text-transform:none}.resources-view .el-table{margin-top:24px}.resources-view .status-wrapper{padding:0;list-style-type:none}.resources-view .status-wrapper .status-item{padding:2px 6px}.resources-view .status-wrapper .status-item>span{margin-right:12px}.resources-view .el-form-item__content{clear:both}.resources-view .expand-column .cell{opacity:0}.topic-metrics .sub-tip{font-size:14px;color:#9e9e9f;text-transform:none;margin-right:10px}.topic-metrics .el-table{margin-top:24px}.topic-metrics .el-table .expand-header{height:32px;line-height:32px;margin-bottom:20px}.topic-metrics .el-table .topic-qos-radio{float:right}.topic-metrics .el-table .message-card{height:112px;border-radius:4px;padding:6px 12px}.topic-metrics .el-table .message-card .message-card--body{font-size:28px;height:80px;line-height:80px;text-align:center}.topic-metrics .el-table .message-card .message-rate{float:right}.alarms-view .table-title{margin:24px 0 20px;font-size:16px}.alarms-view .table-title .table-oper{float:right}.alarms-view .el-table{margin-bottom:32px}.alarms-view .details{margin-right:5px;color:#a7a7a7;cursor:pointer}.plugins-view .el-card.plugin-config,.plugins-view .el-table{margin-top:24px}.plugins-view .el-row{margin-top:20px}.plugins-view .oper{min-width:50px;font-size:14px;margin-bottom:4px}.plugins-view .tutorial{margin-left:5px;color:#a7a7a7}.plugins-view .tutorial:hover{color:#34c388}.plugin-manage .page-title{text-transform:none}.plugin-manage .el-card{margin-top:24px;min-height:150px}.plugin-manage .el-card .config-null{text-align:center;margin:20px auto}.plugin-manage .el-input.input-radius,.plugin-manage .el-textarea.input-radius{width:100%}.auth-clientid-table .el-form-item__error,.auth-username-table .el-form-item__error{display:none}.generate-jwt .monaco-container{height:200px}.generate-jwt .el-date-editor.el-input,.generate-jwt .el-date-editor.el-input__inner,.generate-jwt .el-select{width:100%}.generate-jwt .el-table{margin-top:40px}.generate-jwt .jwt-payload-desc{font-size:14px;padding:6px;border-radius:4px;line-height:1.4;margin:16px 0}.modules-view .el-table{margin-top:24px}.modules-view .oper{min-width:50px;font-size:14px;margin-bottom:4px}.listeners-view .el-table{margin-top:24px}.websocket-view .el-form-item--small.el-form-item{margin-bottom:2px}.websocket-view .check-area .el-form-item__content{line-height:20px!important}.websocket-view .operation-area{margin-top:10px!important}.websocket-view .el-input .el-input--medium{margin-bottom:10px!important}.websocket-view .el-select{width:100%}.websocket-view .refresh-btn{font-size:12px;margin-left:8px;cursor:pointer}.websocket-view .connect-state{display:inline-block;margin-left:20px;font-size:14px;color:#a7a7a7}.websocket-view .connect-state span{margin-left:4px}.websocket-view .el-table{margin-top:5px;border-width:0!important}.websocket-view .el-card{margin-top:24px}.websocket-view .el-checkbox,.websocket-view .el-input{margin:5px 0 20px}.http-api{margin-top:0!important}.http-api .link-disabled{cursor:not-allowed}.http-api .el-card{margin-top:24px}.http-api .el-table{border-width:0!important}.http-api .refresh-btn{cursor:pointer;font-size:16px;padding:0!important}.http-api .response-container{line-height:1.5}.http-api .response-container h3{font-size:14px!important}.http-api .response-container a{margin-left:12px}.applications-view .el-date-editor,.applications-view .el-select{width:100%}.applications-view .el-table{margin-top:24px}.applications-view .el-row{margin-top:20px}.applications-view .search-btn{margin-left:8px}.applications-view .el-breadcrumb{margin-top:10px;margin-bottom:20px}.applications-view .el-date-picker{max-width:600px!important}.applications-view .el-form-item--medium .el-form-item__content{line-height:38px}.app-info .el-input.is-disabled .el-input__inner{cursor:text}.users-view .el-table{margin-top:24px}.users-view .change-password{text-align:left}.settings-view .el-card{margin-top:24px}.settings-view .el-switch.is-checked .el-switch__core{background-color:#42d885;border-color:#42d885}.settings-view .confirm-btn .el-form-item{margin-bottom:4px!important}.help-view{width:80%}.help-view .help-item h3{font-size:16px}.help-view .help-item p{color:#b0b0b0;line-height:1.8}.help-view .help-item a{margin-right:16px}.help-view .help-item .follow-link{display:inline-block;width:64px;height:52px;text-align:center;line-height:52px;background:#232429;color:#9ea3b1;margin-bottom:20px}.help-view .help-item .follow-link .iconfont{font-size:24px}.help-view .el-divider{margin:30px 0;background-color:#2b2c30}@media (max-width:996px){.help-view{width:100%}}.not-found{text-align:center;padding:50px}.not-found p{margin-top:30px;font-size:20px}.not-found a{margin-right:20px}.not-found a:hover{text-decoration:underline}@font-face{font-family:element-icons;src:url(/static/fonts/element-icons.535877f.woff) format("woff"),url(/static/fonts/element-icons.732389d.ttf) format("truetype");font-weight:400;font-style:normal}[class*=" el-icon-"],[class^=el-icon-]{font-family:element-icons!important;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;vertical-align:baseline;display:inline-block;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.el-icon-ice-cream-round:before{content:"\E6A0"}.el-icon-ice-cream-square:before{content:"\E6A3"}.el-icon-lollipop:before{content:"\E6A4"}.el-icon-potato-strips:before{content:"\E6A5"}.el-icon-milk-tea:before{content:"\E6A6"}.el-icon-ice-drink:before{content:"\E6A7"}.el-icon-ice-tea:before{content:"\E6A9"}.el-icon-coffee:before{content:"\E6AA"}.el-icon-orange:before{content:"\E6AB"}.el-icon-pear:before{content:"\E6AC"}.el-icon-apple:before{content:"\E6AD"}.el-icon-cherry:before{content:"\E6AE"}.el-icon-watermelon:before{content:"\E6AF"}.el-icon-grape:before{content:"\E6B0"}.el-icon-refrigerator:before{content:"\E6B1"}.el-icon-goblet-square-full:before{content:"\E6B2"}.el-icon-goblet-square:before{content:"\E6B3"}.el-icon-goblet-full:before{content:"\E6B4"}.el-icon-goblet:before{content:"\E6B5"}.el-icon-cold-drink:before{content:"\E6B6"}.el-icon-coffee-cup:before{content:"\E6B8"}.el-icon-water-cup:before{content:"\E6B9"}.el-icon-hot-water:before{content:"\E6BA"}.el-icon-ice-cream:before{content:"\E6BB"}.el-icon-dessert:before{content:"\E6BC"}.el-icon-sugar:before{content:"\E6BD"}.el-icon-tableware:before{content:"\E6BE"}.el-icon-burger:before{content:"\E6BF"}.el-icon-knife-fork:before{content:"\E6C1"}.el-icon-fork-spoon:before{content:"\E6C2"}.el-icon-chicken:before{content:"\E6C3"}.el-icon-food:before{content:"\E6C4"}.el-icon-dish-1:before{content:"\E6C5"}.el-icon-dish:before{content:"\E6C6"}.el-icon-moon-night:before{content:"\E6EE"}.el-icon-moon:before{content:"\E6F0"}.el-icon-cloudy-and-sunny:before{content:"\E6F1"}.el-icon-partly-cloudy:before{content:"\E6F2"}.el-icon-cloudy:before{content:"\E6F3"}.el-icon-sunny:before{content:"\E6F6"}.el-icon-sunset:before{content:"\E6F7"}.el-icon-sunrise-1:before{content:"\E6F8"}.el-icon-sunrise:before{content:"\E6F9"}.el-icon-heavy-rain:before{content:"\E6FA"}.el-icon-lightning:before{content:"\E6FB"}.el-icon-light-rain:before{content:"\E6FC"}.el-icon-wind-power:before{content:"\E6FD"}.el-icon-baseball:before{content:"\E712"}.el-icon-soccer:before{content:"\E713"}.el-icon-football:before{content:"\E715"}.el-icon-basketball:before{content:"\E716"}.el-icon-ship:before{content:"\E73F"}.el-icon-truck:before{content:"\E740"}.el-icon-bicycle:before{content:"\E741"}.el-icon-mobile-phone:before{content:"\E6D3"}.el-icon-service:before{content:"\E6D4"}.el-icon-key:before{content:"\E6E2"}.el-icon-unlock:before{content:"\E6E4"}.el-icon-lock:before{content:"\E6E5"}.el-icon-watch:before{content:"\E6FE"}.el-icon-watch-1:before{content:"\E6FF"}.el-icon-timer:before{content:"\E702"}.el-icon-alarm-clock:before{content:"\E703"}.el-icon-map-location:before{content:"\E704"}.el-icon-delete-location:before{content:"\E705"}.el-icon-add-location:before{content:"\E706"}.el-icon-location-information:before{content:"\E707"}.el-icon-location-outline:before{content:"\E708"}.el-icon-location:before{content:"\E79E"}.el-icon-place:before{content:"\E709"}.el-icon-discover:before{content:"\E70A"}.el-icon-first-aid-kit:before{content:"\E70B"}.el-icon-trophy-1:before{content:"\E70C"}.el-icon-trophy:before{content:"\E70D"}.el-icon-medal:before{content:"\E70E"}.el-icon-medal-1:before{content:"\E70F"}.el-icon-stopwatch:before{content:"\E710"}.el-icon-mic:before{content:"\E711"}.el-icon-copy-document:before{content:"\E718"}.el-icon-full-screen:before{content:"\E719"}.el-icon-switch-button:before{content:"\E71B"}.el-icon-aim:before{content:"\E71C"}.el-icon-crop:before{content:"\E71D"}.el-icon-odometer:before{content:"\E71E"}.el-icon-time:before{content:"\E71F"}.el-icon-bangzhu:before{content:"\E724"}.el-icon-close-notification:before{content:"\E726"}.el-icon-microphone:before{content:"\E727"}.el-icon-turn-off-microphone:before{content:"\E728"}.el-icon-position:before{content:"\E729"}.el-icon-postcard:before{content:"\E72A"}.el-icon-message:before{content:"\E72B"}.el-icon-chat-line-square:before{content:"\E72D"}.el-icon-chat-dot-square:before{content:"\E72E"}.el-icon-chat-dot-round:before{content:"\E72F"}.el-icon-chat-square:before{content:"\E730"}.el-icon-chat-line-round:before{content:"\E731"}.el-icon-chat-round:before{content:"\E732"}.el-icon-set-up:before{content:"\E733"}.el-icon-turn-off:before{content:"\E734"}.el-icon-open:before{content:"\E735"}.el-icon-connection:before{content:"\E736"}.el-icon-link:before{content:"\E737"}.el-icon-cpu:before{content:"\E738"}.el-icon-thumb:before{content:"\E739"}.el-icon-female:before{content:"\E73A"}.el-icon-male:before{content:"\E73B"}.el-icon-guide:before{content:"\E73C"}.el-icon-news:before{content:"\E73E"}.el-icon-price-tag:before{content:"\E744"}.el-icon-discount:before{content:"\E745"}.el-icon-wallet:before{content:"\E747"}.el-icon-coin:before{content:"\E748"}.el-icon-money:before{content:"\E749"}.el-icon-bank-card:before{content:"\E74A"}.el-icon-box:before{content:"\E74B"}.el-icon-present:before{content:"\E74C"}.el-icon-sell:before{content:"\E6D5"}.el-icon-sold-out:before{content:"\E6D6"}.el-icon-shopping-bag-2:before{content:"\E74D"}.el-icon-shopping-bag-1:before{content:"\E74E"}.el-icon-shopping-cart-2:before{content:"\E74F"}.el-icon-shopping-cart-1:before{content:"\E750"}.el-icon-shopping-cart-full:before{content:"\E751"}.el-icon-smoking:before{content:"\E752"}.el-icon-no-smoking:before{content:"\E753"}.el-icon-house:before{content:"\E754"}.el-icon-table-lamp:before{content:"\E755"}.el-icon-school:before{content:"\E756"}.el-icon-office-building:before{content:"\E757"}.el-icon-toilet-paper:before{content:"\E758"}.el-icon-notebook-2:before{content:"\E759"}.el-icon-notebook-1:before{content:"\E75A"}.el-icon-files:before{content:"\E75B"}.el-icon-collection:before{content:"\E75C"}.el-icon-receiving:before{content:"\E75D"}.el-icon-suitcase-1:before{content:"\E760"}.el-icon-suitcase:before{content:"\E761"}.el-icon-film:before{content:"\E763"}.el-icon-collection-tag:before{content:"\E765"}.el-icon-data-analysis:before{content:"\E766"}.el-icon-pie-chart:before{content:"\E767"}.el-icon-data-board:before{content:"\E768"}.el-icon-data-line:before{content:"\E76D"}.el-icon-reading:before{content:"\E769"}.el-icon-magic-stick:before{content:"\E76A"}.el-icon-coordinate:before{content:"\E76B"}.el-icon-mouse:before{content:"\E76C"}.el-icon-brush:before{content:"\E76E"}.el-icon-headset:before{content:"\E76F"}.el-icon-umbrella:before{content:"\E770"}.el-icon-scissors:before{content:"\E771"}.el-icon-mobile:before{content:"\E773"}.el-icon-attract:before{content:"\E774"}.el-icon-monitor:before{content:"\E775"}.el-icon-search:before{content:"\E778"}.el-icon-takeaway-box:before{content:"\E77A"}.el-icon-paperclip:before{content:"\E77D"}.el-icon-printer:before{content:"\E77E"}.el-icon-document-add:before{content:"\E782"}.el-icon-document:before{content:"\E785"}.el-icon-document-checked:before{content:"\E786"}.el-icon-document-copy:before{content:"\E787"}.el-icon-document-delete:before{content:"\E788"}.el-icon-document-remove:before{content:"\E789"}.el-icon-tickets:before{content:"\E78B"}.el-icon-folder-checked:before{content:"\E77F"}.el-icon-folder-delete:before{content:"\E780"}.el-icon-folder-remove:before{content:"\E781"}.el-icon-folder-add:before{content:"\E783"}.el-icon-folder-opened:before{content:"\E784"}.el-icon-folder:before{content:"\E78A"}.el-icon-edit-outline:before{content:"\E764"}.el-icon-edit:before{content:"\E78C"}.el-icon-date:before{content:"\E78E"}.el-icon-c-scale-to-original:before{content:"\E7C6"}.el-icon-view:before{content:"\E6CE"}.el-icon-loading:before{content:"\E6CF"}.el-icon-rank:before{content:"\E6D1"}.el-icon-sort-down:before{content:"\E7C4"}.el-icon-sort-up:before{content:"\E7C5"}.el-icon-sort:before{content:"\E6D2"}.el-icon-finished:before{content:"\E6CD"}.el-icon-refresh-left:before{content:"\E6C7"}.el-icon-refresh-right:before{content:"\E6C8"}.el-icon-refresh:before{content:"\E6D0"}.el-icon-video-play:before{content:"\E7C0"}.el-icon-video-pause:before{content:"\E7C1"}.el-icon-d-arrow-right:before{content:"\E6DC"}.el-icon-d-arrow-left:before{content:"\E6DD"}.el-icon-arrow-up:before{content:"\E6E1"}.el-icon-arrow-down:before{content:"\E6DF"}.el-icon-arrow-right:before{content:"\E6E0"}.el-icon-arrow-left:before{content:"\E6DE"}.el-icon-top-right:before{content:"\E6E7"}.el-icon-top-left:before{content:"\E6E8"}.el-icon-top:before{content:"\E6E6"}.el-icon-bottom:before{content:"\E6EB"}.el-icon-right:before{content:"\E6E9"}.el-icon-back:before{content:"\E6EA"}.el-icon-bottom-right:before{content:"\E6EC"}.el-icon-bottom-left:before{content:"\E6ED"}.el-icon-caret-top:before{content:"\E78F"}.el-icon-caret-bottom:before{content:"\E790"}.el-icon-caret-right:before{content:"\E791"}.el-icon-caret-left:before{content:"\E792"}.el-icon-d-caret:before{content:"\E79A"}.el-icon-share:before{content:"\E793"}.el-icon-menu:before{content:"\E798"}.el-icon-s-grid:before{content:"\E7A6"}.el-icon-s-check:before{content:"\E7A7"}.el-icon-s-data:before{content:"\E7A8"}.el-icon-s-opportunity:before{content:"\E7AA"}.el-icon-s-custom:before{content:"\E7AB"}.el-icon-s-claim:before{content:"\E7AD"}.el-icon-s-finance:before{content:"\E7AE"}.el-icon-s-comment:before{content:"\E7AF"}.el-icon-s-flag:before{content:"\E7B0"}.el-icon-s-marketing:before{content:"\E7B1"}.el-icon-s-shop:before{content:"\E7B4"}.el-icon-s-open:before{content:"\E7B5"}.el-icon-s-management:before{content:"\E7B6"}.el-icon-s-ticket:before{content:"\E7B7"}.el-icon-s-release:before{content:"\E7B8"}.el-icon-s-home:before{content:"\E7B9"}.el-icon-s-promotion:before{content:"\E7BA"}.el-icon-s-operation:before{content:"\E7BB"}.el-icon-s-unfold:before{content:"\E7BC"}.el-icon-s-fold:before{content:"\E7A9"}.el-icon-s-platform:before{content:"\E7BD"}.el-icon-s-order:before{content:"\E7BE"}.el-icon-s-cooperation:before{content:"\E7BF"}.el-icon-bell:before{content:"\E725"}.el-icon-message-solid:before{content:"\E799"}.el-icon-video-camera:before{content:"\E772"}.el-icon-video-camera-solid:before{content:"\E796"}.el-icon-camera:before{content:"\E779"}.el-icon-camera-solid:before{content:"\E79B"}.el-icon-download:before{content:"\E77C"}.el-icon-upload2:before{content:"\E77B"}.el-icon-upload:before{content:"\E7C3"}.el-icon-picture-outline-round:before{content:"\E75F"}.el-icon-picture-outline:before{content:"\E75E"}.el-icon-picture:before{content:"\E79F"}.el-icon-close:before{content:"\E6DB"}.el-icon-check:before{content:"\E6DA"}.el-icon-plus:before{content:"\E6D9"}.el-icon-minus:before{content:"\E6D8"}.el-icon-help:before{content:"\E73D"}.el-icon-s-help:before{content:"\E7B3"}.el-icon-circle-close:before{content:"\E78D"}.el-icon-circle-check:before{content:"\E720"}.el-icon-circle-plus-outline:before{content:"\E723"}.el-icon-remove-outline:before{content:"\E722"}.el-icon-zoom-out:before{content:"\E776"}.el-icon-zoom-in:before{content:"\E777"}.el-icon-error:before{content:"\E79D"}.el-icon-success:before{content:"\E79C"}.el-icon-circle-plus:before{content:"\E7A0"}.el-icon-remove:before{content:"\E7A2"}.el-icon-info:before{content:"\E7A1"}.el-icon-question:before{content:"\E7A4"}.el-icon-warning-outline:before{content:"\E6C9"}.el-icon-warning:before{content:"\E7A3"}.el-icon-goods:before{content:"\E7C2"}.el-icon-s-goods:before{content:"\E7B2"}.el-icon-star-off:before{content:"\E717"}.el-icon-star-on:before{content:"\E797"}.el-icon-more-outline:before{content:"\E6CC"}.el-icon-more:before{content:"\E794"}.el-icon-phone-outline:before{content:"\E6CB"}.el-icon-phone:before{content:"\E795"}.el-icon-user:before{content:"\E6E3"}.el-icon-user-solid:before{content:"\E7A5"}.el-icon-setting:before{content:"\E6CA"}.el-icon-s-tools:before{content:"\E7AC"}.el-icon-delete:before{content:"\E6D7"}.el-icon-delete-solid:before{content:"\E7C9"}.el-icon-eleme:before{content:"\E7C7"}.el-icon-platform-eleme:before{content:"\E7CA"}.el-icon-loading{animation:rotating 2s linear infinite}.el-icon--right{margin-left:5px}.el-icon--left{margin-right:5px}@keyframes rotating{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.el-pagination{white-space:nowrap;padding:2px 5px;color:#303133;font-weight:700}.el-pagination:after,.el-pagination:before{display:table;content:""}.el-pagination:after{clear:both}.el-pagination button,.el-pagination span:not([class*=suffix]){display:inline-block;font-size:13px;min-width:35.5px;height:28px;line-height:28px;vertical-align:top;box-sizing:border-box}.el-pagination .el-input__inner{text-align:center;-moz-appearance:textfield;line-height:normal}.el-pagination .el-input__suffix{right:0;transform:scale(.8)}.el-pagination .el-select .el-input{width:100px;margin:0 5px}.el-pagination .el-select .el-input .el-input__inner{padding-right:25px;border-radius:3px}.el-pagination button{border:none;padding:0 6px;background:transparent}.el-pagination button:focus{outline:none}.el-pagination button:hover{color:#42d885}.el-pagination button:disabled{color:#c0c4cc;background-color:#fff;cursor:not-allowed}.el-pagination .btn-next,.el-pagination .btn-prev{background:50% no-repeat;background-size:16px;background-color:#fff;cursor:pointer;margin:0;color:#303133}.el-pagination .btn-next .el-icon,.el-pagination .btn-prev .el-icon{display:block;font-size:12px;font-weight:700}.el-pagination .btn-prev{padding-right:12px}.el-pagination .btn-next{padding-left:12px}.el-pagination .el-pager li.disabled{color:#c0c4cc;cursor:not-allowed}.el-pagination--small .btn-next,.el-pagination--small .btn-prev,.el-pagination--small .el-pager li,.el-pagination--small .el-pager li.btn-quicknext,.el-pagination--small .el-pager li.btn-quickprev,.el-pagination--small .el-pager li:last-child{border-color:transparent;font-size:12px;line-height:22px;height:22px;min-width:22px}.el-pagination--small .arrow.disabled{visibility:hidden}.el-pagination--small .more:before,.el-pagination--small li.more:before{line-height:24px}.el-pagination--small button,.el-pagination--small span:not([class*=suffix]){height:22px;line-height:22px}.el-pagination--small .el-pagination__editor,.el-pagination--small .el-pagination__editor.el-input .el-input__inner{height:22px}.el-pagination__sizes{margin:0 10px 0 0;font-weight:400;color:#606266}.el-pagination__sizes .el-input .el-input__inner{font-size:13px;padding-left:8px}.el-pagination__sizes .el-input .el-input__inner:hover{border-color:#42d885}.el-pagination__total{margin-right:10px;font-weight:400;color:#606266}.el-pagination__jump{margin-left:24px;font-weight:400;color:#606266}.el-pagination__jump .el-input__inner{padding:0 3px}.el-pagination__rightwrapper{float:right}.el-pagination__editor{line-height:18px;padding:0 2px;height:28px;text-align:center;margin:0 2px;box-sizing:border-box;border-radius:3px}.el-pagination__editor.el-input{width:50px}.el-pagination__editor.el-input .el-input__inner{height:28px}.el-pagination__editor .el-input__inner::-webkit-inner-spin-button,.el-pagination__editor .el-input__inner::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.el-pagination.is-background .btn-next,.el-pagination.is-background .btn-prev,.el-pagination.is-background .el-pager li{margin:0 5px;background-color:#f4f4f5;color:#606266;min-width:30px;border-radius:2px}.el-pagination.is-background .btn-next.disabled,.el-pagination.is-background .btn-prev.disabled,.el-pagination.is-background .el-pager li.disabled{color:#c0c4cc}.el-pagination.is-background .btn-next,.el-pagination.is-background .btn-prev{padding:0}.el-pagination.is-background .btn-next:disabled,.el-pagination.is-background .btn-prev:disabled{color:#c0c4cc}.el-pagination.is-background .el-pager li:not(.disabled):hover{color:#42d885}.el-pagination.is-background .el-pager li:not(.disabled).active{background-color:#42d885;color:#fff}.el-pagination.is-background.el-pagination--small .btn-next,.el-pagination.is-background.el-pagination--small .btn-prev,.el-pagination.is-background.el-pagination--small .el-pager li{margin:0 3px;min-width:22px}.el-pager{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;list-style:none;display:inline-block;vertical-align:top;font-size:0;padding:0;margin:0}.el-pager .more:before{line-height:30px}.el-pager li{padding:0 4px;background:#fff;vertical-align:top;display:inline-block;font-size:13px;min-width:35.5px;height:28px;line-height:28px;cursor:pointer;box-sizing:border-box;text-align:center;margin:0}.el-pager li.btn-quicknext,.el-pager li.btn-quickprev{line-height:28px;color:#303133}.el-pager li.btn-quicknext.disabled,.el-pager li.btn-quickprev.disabled{color:#c0c4cc}.el-pager li.btn-quicknext:hover,.el-pager li.btn-quickprev:hover{cursor:pointer}.el-pager li.active+li{border-left:0}.el-pager li:hover{color:#42d885}.el-pager li.active{color:#42d885;cursor:default}.el-dialog{position:relative;margin:0 auto 50px;background:#fff;border-radius:2px;box-shadow:0 1px 3px rgba(0,0,0,.3);box-sizing:border-box;width:50%}.el-dialog.is-fullscreen{width:100%;margin-top:0;margin-bottom:0;height:100%;overflow:auto}.el-dialog__wrapper{position:fixed;top:0;right:0;bottom:0;left:0;overflow:auto;margin:0}.el-dialog__header{padding:20px;padding-bottom:10px}.el-dialog__headerbtn{position:absolute;top:20px;right:20px;padding:0;background:transparent;border:none;outline:none;cursor:pointer;font-size:16px}.el-dialog__headerbtn .el-dialog__close{color:#909399}.el-dialog__headerbtn:focus .el-dialog__close,.el-dialog__headerbtn:hover .el-dialog__close{color:#42d885}.el-dialog__title{line-height:24px;font-size:18px;color:#303133}.el-dialog__body{padding:30px 20px;color:#606266;font-size:14px;word-break:break-all}.el-dialog__footer{padding:20px;padding-top:10px;text-align:right;box-sizing:border-box}.el-dialog--center{text-align:center}.el-dialog--center .el-dialog__body{text-align:initial;padding:25px 25px 30px}.el-dialog--center .el-dialog__footer{text-align:inherit}.dialog-fade-enter-active{animation:dialog-fade-in .3s}.dialog-fade-leave-active{animation:dialog-fade-out .3s}@keyframes dialog-fade-in{0%{transform:translate3d(0,-20px,0);opacity:0}to{transform:translateZ(0);opacity:1}}@keyframes dialog-fade-out{0%{transform:translateZ(0);opacity:1}to{transform:translate3d(0,-20px,0);opacity:0}}.el-autocomplete{position:relative;display:inline-block}.el-autocomplete-suggestion{margin:5px 0;box-shadow:0 2px 12px 0 rgba(0,0,0,.1);border-radius:4px;border:1px solid #e4e7ed;box-sizing:border-box;background-color:#fff}.el-autocomplete-suggestion__wrap{max-height:280px;padding:10px 0;box-sizing:border-box}.el-autocomplete-suggestion__list{margin:0;padding:0}.el-autocomplete-suggestion li{padding:0 20px;margin:0;line-height:34px;cursor:pointer;color:#606266;font-size:14px;list-style:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.el-autocomplete-suggestion li.highlighted,.el-autocomplete-suggestion li:hover{background-color:#f5f7fa}.el-autocomplete-suggestion li.divider{margin-top:6px;border-top:1px solid #000}.el-autocomplete-suggestion li.divider:last-child{margin-bottom:-6px}.el-autocomplete-suggestion.is-loading li{text-align:center;height:100px;line-height:100px;font-size:20px;color:#999}.el-autocomplete-suggestion.is-loading li:after{display:inline-block;content:"";height:100%;vertical-align:middle}.el-autocomplete-suggestion.is-loading li:hover{background-color:#fff}.el-autocomplete-suggestion.is-loading .el-icon-loading{vertical-align:middle}.el-dropdown{display:inline-block;position:relative;color:#606266;font-size:14px}.el-dropdown .el-button-group{display:block}.el-dropdown .el-button-group .el-button{float:none}.el-dropdown .el-dropdown__caret-button{padding-left:5px;padding-right:5px;position:relative;border-left:none}.el-dropdown .el-dropdown__caret-button:before{content:"";position:absolute;display:block;width:1px;top:5px;bottom:5px;left:0;background:hsla(0,0%,100%,.5)}.el-dropdown .el-dropdown__caret-button.el-button--default:before{background:rgba(220,223,230,.5)}.el-dropdown .el-dropdown__caret-button:hover:before{top:0;bottom:0}.el-dropdown .el-dropdown__caret-button .el-dropdown__icon{padding-left:0}.el-dropdown__icon{font-size:12px;margin:0 3px}.el-dropdown .el-dropdown-selfdefine:focus:active,.el-dropdown .el-dropdown-selfdefine:focus:not(.focusing){outline-width:0}.el-dropdown-menu{position:absolute;top:0;left:0;z-index:10;padding:10px 0;margin:5px 0;background-color:#fff;border:1px solid #ebeef5;border-radius:4px;box-shadow:0 2px 12px 0 rgba(0,0,0,.1)}.el-dropdown-menu__item{list-style:none;line-height:36px;padding:0 20px;margin:0;font-size:14px;color:#606266;cursor:pointer;outline:none}.el-dropdown-menu__item:focus,.el-dropdown-menu__item:not(.is-disabled):hover{background-color:#ecfbf3;color:#68e09d}.el-dropdown-menu__item i{margin-right:5px}.el-dropdown-menu__item--divided{position:relative;margin-top:6px;border-top:1px solid #ebeef5}.el-dropdown-menu__item--divided:before{content:"";height:6px;display:block;margin:0 -20px;background-color:#fff}.el-dropdown-menu__item.is-disabled{cursor:default;color:#bbb;pointer-events:none}.el-dropdown-menu--medium{padding:6px 0}.el-dropdown-menu--medium .el-dropdown-menu__item{line-height:30px;padding:0 17px;font-size:14px}.el-dropdown-menu--medium .el-dropdown-menu__item.el-dropdown-menu__item--divided{margin-top:6px}.el-dropdown-menu--medium .el-dropdown-menu__item.el-dropdown-menu__item--divided:before{height:6px;margin:0 -17px}.el-dropdown-menu--small{padding:6px 0}.el-dropdown-menu--small .el-dropdown-menu__item{line-height:27px;padding:0 15px;font-size:13px}.el-dropdown-menu--small .el-dropdown-menu__item.el-dropdown-menu__item--divided{margin-top:4px}.el-dropdown-menu--small .el-dropdown-menu__item.el-dropdown-menu__item--divided:before{height:4px;margin:0 -15px}.el-dropdown-menu--mini{padding:3px 0}.el-dropdown-menu--mini .el-dropdown-menu__item{line-height:24px;padding:0 10px;font-size:12px}.el-dropdown-menu--mini .el-dropdown-menu__item.el-dropdown-menu__item--divided{margin-top:3px}.el-dropdown-menu--mini .el-dropdown-menu__item.el-dropdown-menu__item--divided:before{height:3px;margin:0 -10px}.el-menu{border-right:1px solid #e6e6e6;list-style:none;position:relative;margin:0;padding-left:0;background-color:#fff}.el-menu:after,.el-menu:before{display:table;content:""}.el-menu:after{clear:both}.el-menu.el-menu--horizontal{border-bottom:1px solid #e6e6e6}.el-menu--horizontal{border-right:none}.el-menu--horizontal>.el-menu-item{float:left;height:60px;line-height:60px;margin:0;border-bottom:2px solid transparent;color:#909399}.el-menu--horizontal>.el-menu-item a,.el-menu--horizontal>.el-menu-item a:hover{color:inherit}.el-menu--horizontal>.el-menu-item:not(.is-disabled):focus,.el-menu--horizontal>.el-menu-item:not(.is-disabled):hover{background-color:#fff}.el-menu--horizontal>.el-submenu{float:left}.el-menu--horizontal>.el-submenu:focus,.el-menu--horizontal>.el-submenu:hover{outline:none}.el-menu--horizontal>.el-submenu:focus .el-submenu__title,.el-menu--horizontal>.el-submenu:hover .el-submenu__title{color:#303133}.el-menu--horizontal>.el-submenu.is-active .el-submenu__title{border-bottom:2px solid #42d885;color:#303133}.el-menu--horizontal>.el-submenu .el-submenu__title{height:60px;line-height:60px;border-bottom:2px solid transparent;color:#909399}.el-menu--horizontal>.el-submenu .el-submenu__title:hover{background-color:#fff}.el-menu--horizontal>.el-submenu .el-submenu__icon-arrow{position:static;vertical-align:middle;margin-left:8px;margin-top:-3px}.el-menu--horizontal .el-menu .el-menu-item,.el-menu--horizontal .el-menu .el-submenu__title{background-color:#fff;float:none;height:36px;line-height:36px;padding:0 10px;color:#909399}.el-menu--horizontal .el-menu .el-menu-item.is-active,.el-menu--horizontal .el-menu .el-submenu.is-active>.el-submenu__title{color:#303133}.el-menu--horizontal .el-menu-item:not(.is-disabled):focus,.el-menu--horizontal .el-menu-item:not(.is-disabled):hover{outline:none;color:#303133}.el-menu--horizontal>.el-menu-item.is-active{border-bottom:2px solid #42d885;color:#303133}.el-menu--collapse{width:64px}.el-menu--collapse>.el-menu-item [class^=el-icon-],.el-menu--collapse>.el-submenu>.el-submenu__title [class^=el-icon-]{margin:0;vertical-align:middle;width:24px;text-align:center}.el-menu--collapse>.el-menu-item .el-submenu__icon-arrow,.el-menu--collapse>.el-submenu>.el-submenu__title .el-submenu__icon-arrow{display:none}.el-menu--collapse>.el-menu-item span,.el-menu--collapse>.el-submenu>.el-submenu__title span{height:0;width:0;overflow:hidden;visibility:hidden;display:inline-block}.el-menu--collapse>.el-menu-item.is-active i{color:inherit}.el-menu--collapse .el-menu .el-submenu{min-width:200px}.el-menu--collapse .el-submenu{position:relative}.el-menu--collapse .el-submenu .el-menu{position:absolute;margin-left:5px;top:0;left:100%;z-index:10;border:1px solid #e4e7ed;border-radius:2px;box-shadow:0 2px 12px 0 rgba(0,0,0,.1)}.el-menu--collapse .el-submenu.is-opened>.el-submenu__title .el-submenu__icon-arrow{transform:none}.el-menu--popup{z-index:100;min-width:200px;border:none;padding:5px 0;border-radius:2px;box-shadow:0 2px 12px 0 rgba(0,0,0,.1)}.el-menu--popup-bottom-start{margin-top:5px}.el-menu--popup-right-start{margin-left:5px;margin-right:5px}.el-menu-item{height:56px;line-height:56px;font-size:14px;color:#303133;padding:0 20px;list-style:none;cursor:pointer;position:relative;transition:border-color .3s,background-color .3s,color .3s;box-sizing:border-box;white-space:nowrap}.el-menu-item *{vertical-align:middle}.el-menu-item i{color:#909399}.el-menu-item:focus,.el-menu-item:hover{outline:none;background-color:#ecfbf3}.el-menu-item.is-disabled{opacity:.25;cursor:not-allowed;background:none!important}.el-menu-item [class^=el-icon-]{margin-right:5px;width:24px;text-align:center;font-size:18px;vertical-align:middle}.el-menu-item.is-active{color:#42d885}.el-menu-item.is-active i{color:inherit}.el-submenu{list-style:none;margin:0;padding-left:0}.el-submenu__title{height:56px;line-height:56px;font-size:14px;color:#303133;padding:0 20px;list-style:none;cursor:pointer;position:relative;transition:border-color .3s,background-color .3s,color .3s;box-sizing:border-box;white-space:nowrap}.el-submenu__title *{vertical-align:middle}.el-submenu__title i{color:#909399}.el-submenu__title:focus,.el-submenu__title:hover{outline:none;background-color:#ecfbf3}.el-submenu__title.is-disabled{opacity:.25;cursor:not-allowed;background:none!important}.el-submenu__title:hover{background-color:#ecfbf3}.el-submenu .el-menu{border:none}.el-submenu .el-menu-item{height:50px;line-height:50px;padding:0 45px;min-width:200px}.el-submenu__icon-arrow{position:absolute;top:50%;right:20px;margin-top:-7px;transition:transform .3s;font-size:12px}.el-submenu.is-active .el-submenu__title{border-bottom-color:#42d885}.el-submenu.is-opened>.el-submenu__title .el-submenu__icon-arrow{transform:rotate(180deg)}.el-submenu.is-disabled .el-menu-item,.el-submenu.is-disabled .el-submenu__title{opacity:.25;cursor:not-allowed;background:none!important}.el-submenu [class^=el-icon-]{vertical-align:middle;margin-right:5px;width:24px;text-align:center;font-size:18px}.el-menu-item-group>ul{padding:0}.el-menu-item-group__title{padding:7px 0 7px 20px;line-height:normal;font-size:12px;color:#909399}.horizontal-collapse-transition .el-submenu__title .el-submenu__icon-arrow{transition:.2s;opacity:0}.el-radio-group{display:inline-block;line-height:1;vertical-align:middle;font-size:0}.el-radio-button,.el-radio-button__inner{position:relative;display:inline-block;outline:none}.el-radio-button__inner{line-height:1;white-space:nowrap;vertical-align:middle;background:#fff;border:1px solid #dcdfe6;font-weight:500;border-left:0;color:#606266;-webkit-appearance:none;text-align:center;box-sizing:border-box;margin:0;cursor:pointer;transition:all .3s cubic-bezier(.645,.045,.355,1);padding:12px 20px;font-size:14px;border-radius:0}.el-radio-button__inner.is-round{padding:12px 20px}.el-radio-button__inner:hover{color:#42d885}.el-radio-button__inner [class*=el-icon-]{line-height:.9}.el-radio-button__inner [class*=el-icon-]+span{margin-left:5px}.el-radio-button:first-child .el-radio-button__inner{border-left:1px solid #dcdfe6;border-radius:4px 0 0 4px;box-shadow:none!important}.el-radio-button__orig-radio{opacity:0;outline:none;position:absolute;z-index:-1}.el-radio-button__orig-radio:checked+.el-radio-button__inner{color:#fff;background-color:#42d885;border-color:#42d885;box-shadow:-1px 0 0 0 #42d885}.el-radio-button__orig-radio:disabled+.el-radio-button__inner{color:#c0c4cc;cursor:not-allowed;background-image:none;background-color:#fff;border-color:#ebeef5;box-shadow:none}.el-radio-button__orig-radio:disabled:checked+.el-radio-button__inner{background-color:#f2f6fc}.el-radio-button:last-child .el-radio-button__inner{border-radius:0 4px 4px 0}.el-radio-button:first-child:last-child .el-radio-button__inner{border-radius:4px}.el-radio-button--medium .el-radio-button__inner{padding:10px 20px;font-size:14px;border-radius:0}.el-radio-button--medium .el-radio-button__inner.is-round{padding:10px 20px}.el-radio-button--small .el-radio-button__inner{padding:9px 15px;font-size:12px;border-radius:0}.el-radio-button--small .el-radio-button__inner.is-round{padding:9px 15px}.el-radio-button--mini .el-radio-button__inner{padding:7px 15px;font-size:12px;border-radius:0}.el-radio-button--mini .el-radio-button__inner.is-round{padding:7px 15px}.el-radio-button:focus:not(.is-focus):not(:active):not(.is-disabled){box-shadow:0 0 2px 2px #42d885}.el-switch{display:-ms-inline-flexbox;display:inline-flex;-ms-flex-align:center;align-items:center;position:relative;font-size:14px;line-height:20px;height:20px;vertical-align:middle}.el-switch.is-disabled .el-switch__core,.el-switch.is-disabled .el-switch__label{cursor:not-allowed}.el-switch__label{transition:.2s;height:20px;display:inline-block;font-size:14px;font-weight:500;cursor:pointer;vertical-align:middle;color:#303133}.el-switch__label.is-active{color:#42d885}.el-switch__label--left{margin-right:10px}.el-switch__label--right{margin-left:10px}.el-switch__label *{line-height:1;font-size:14px;display:inline-block}.el-switch__input{position:absolute;width:0;height:0;opacity:0;margin:0}.el-switch__core{margin:0;display:inline-block;position:relative;width:40px;height:20px;border:1px solid #dcdfe6;outline:none;border-radius:10px;box-sizing:border-box;background:#dcdfe6;cursor:pointer;transition:border-color .3s,background-color .3s;vertical-align:middle}.el-switch__core:after{content:"";position:absolute;top:1px;left:1px;border-radius:100%;transition:all .3s;width:16px;height:16px;background-color:#fff}.el-switch.is-checked .el-switch__core{border-color:#42d885;background-color:#42d885}.el-switch.is-checked .el-switch__core:after{left:100%;margin-left:-17px}.el-switch.is-disabled{opacity:.6}.el-switch--wide .el-switch__label.el-switch__label--left span{left:10px}.el-switch--wide .el-switch__label.el-switch__label--right span{right:10px}.el-switch .label-fade-enter,.el-switch .label-fade-leave-active{opacity:0}.el-select-dropdown{position:absolute;z-index:1001;border:1px solid #e4e7ed;border-radius:4px;background-color:#fff;box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-sizing:border-box;margin:5px 0}.el-select-dropdown.is-multiple .el-select-dropdown__item.selected{color:#42d885;background-color:#fff}.el-select-dropdown.is-multiple .el-select-dropdown__item.selected.hover{background-color:#f5f7fa}.el-select-dropdown.is-multiple .el-select-dropdown__item.selected:after{position:absolute;right:20px;font-family:element-icons;content:"\E6DA";font-size:12px;font-weight:700;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.el-select-dropdown .el-scrollbar.is-empty .el-select-dropdown__list{padding:0}.el-select-dropdown__empty{padding:10px 0;margin:0;text-align:center;color:#999;font-size:14px}.el-select-dropdown__wrap{max-height:274px}.el-select-dropdown__list{list-style:none;padding:6px 0;margin:0;box-sizing:border-box}.el-select-dropdown__item{font-size:14px;padding:0 20px;position:relative;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#606266;height:34px;line-height:34px;box-sizing:border-box;cursor:pointer}.el-select-dropdown__item.is-disabled{color:#c0c4cc;cursor:not-allowed}.el-select-dropdown__item.is-disabled:hover{background-color:#fff}.el-select-dropdown__item.hover,.el-select-dropdown__item:hover{background-color:#f5f7fa}.el-select-dropdown__item.selected{color:#42d885;font-weight:700}.el-select-group{margin:0;padding:0}.el-select-group__wrap{position:relative;list-style:none;margin:0;padding:0}.el-select-group__wrap:not(:last-of-type){padding-bottom:24px}.el-select-group__wrap:not(:last-of-type):after{content:"";position:absolute;display:block;left:20px;right:20px;bottom:12px;height:1px;background:#e4e7ed}.el-select-group__title{padding-left:20px;font-size:12px;color:#909399;line-height:30px}.el-select-group .el-select-dropdown__item{padding-left:20px}.el-select{display:inline-block;position:relative}.el-select .el-select__tags>span{display:contents}.el-select:hover .el-input__inner{border-color:#c0c4cc}.el-select .el-input__inner{cursor:pointer;padding-right:35px}.el-select .el-input__inner:focus{border-color:#42d885}.el-select .el-input .el-select__caret{color:#c0c4cc;font-size:14px;transition:transform .3s;transform:rotate(180deg);cursor:pointer}.el-select .el-input .el-select__caret.is-reverse{transform:rotate(0deg)}.el-select .el-input .el-select__caret.is-show-close{font-size:14px;text-align:center;transform:rotate(180deg);border-radius:100%;color:#c0c4cc;transition:color .2s cubic-bezier(.645,.045,.355,1)}.el-select .el-input .el-select__caret.is-show-close:hover{color:#909399}.el-select .el-input.is-disabled .el-input__inner{cursor:not-allowed}.el-select .el-input.is-disabled .el-input__inner:hover{border-color:#e4e7ed}.el-select .el-input.is-focus .el-input__inner{border-color:#42d885}.el-select>.el-input{display:block}.el-select__input{border:none;outline:none;padding:0;margin-left:15px;color:#666;font-size:14px;-webkit-appearance:none;-moz-appearance:none;appearance:none;height:28px;background-color:transparent}.el-select__input.is-mini{height:14px}.el-select__close{cursor:pointer;position:absolute;top:8px;z-index:1000;right:25px;color:#c0c4cc;line-height:18px;font-size:14px}.el-select__close:hover{color:#909399}.el-select__tags{position:absolute;line-height:normal;white-space:normal;z-index:1;top:50%;transform:translateY(-50%);display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-wrap:wrap;flex-wrap:wrap}.el-select .el-tag__close{margin-top:-2px}.el-select .el-tag{box-sizing:border-box;border-color:transparent;margin:2px 0 2px 6px;background-color:#f0f2f5}.el-select .el-tag__close.el-icon-close{background-color:#c0c4cc;right:-7px;top:0;color:#fff}.el-select .el-tag__close.el-icon-close:hover{background-color:#909399}.el-select .el-tag__close.el-icon-close:before{display:block;transform:translateY(.5px)}.el-table{position:relative;overflow:hidden;box-sizing:border-box;-ms-flex:1;flex:1;width:100%;max-width:100%;background-color:#fff;font-size:14px;color:#606266}.el-table__empty-block{min-height:60px;text-align:center;width:100%;height:100%;display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center;-ms-flex-align:center;align-items:center}.el-table__empty-text{line-height:60px;width:50%;color:#909399}.el-table__expand-column .cell{padding:0;text-align:center}.el-table__expand-icon{position:relative;cursor:pointer;color:#666;font-size:12px;transition:transform .2s ease-in-out;height:20px}.el-table__expand-icon--expanded{transform:rotate(90deg)}.el-table__expand-icon>.el-icon{position:absolute;left:50%;top:50%;margin-left:-5px;margin-top:-5px}.el-table__expanded-cell{background-color:#fff}.el-table__expanded-cell[class*=cell]{padding:20px 50px}.el-table__expanded-cell:hover{background-color:transparent!important}.el-table__placeholder{display:inline-block;width:20px}.el-table__append-wrapper{overflow:hidden}.el-table--fit{border-right:0;border-bottom:0}.el-table--fit td.gutter,.el-table--fit th.gutter{border-right-width:1px}.el-table--scrollable-x .el-table__body-wrapper{overflow-x:auto}.el-table--scrollable-y .el-table__body-wrapper{overflow-y:auto}.el-table thead{color:#909399;font-weight:500}.el-table thead.is-group th{background:#f5f7fa}.el-table td,.el-table th{padding:12px 0;min-width:0;box-sizing:border-box;text-overflow:ellipsis;vertical-align:middle;position:relative;text-align:left}.el-table td.is-center,.el-table th.is-center{text-align:center}.el-table td.is-right,.el-table th.is-right{text-align:right}.el-table td.gutter,.el-table th.gutter{width:15px;border-right-width:0;border-bottom-width:0;padding:0}.el-table td.is-hidden>*,.el-table th.is-hidden>*{visibility:hidden}.el-table--medium td,.el-table--medium th{padding:10px 0}.el-table--small{font-size:12px}.el-table--small td,.el-table--small th{padding:8px 0}.el-table--mini{font-size:12px}.el-table--mini td,.el-table--mini th{padding:6px 0}.el-table tr{background-color:#fff}.el-table tr input[type=checkbox]{margin:0}.el-table td,.el-table th.is-leaf{border-bottom:1px solid #ebeef5}.el-table th.is-sortable{cursor:pointer}.el-table th{white-space:nowrap;overflow:hidden;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:#fff}.el-table th div{padding-left:10px;padding-right:10px;line-height:40px;overflow:hidden;white-space:nowrap}.el-table th>.cell,.el-table th div{display:inline-block;box-sizing:border-box;text-overflow:ellipsis}.el-table th>.cell{position:relative;word-wrap:normal;vertical-align:middle;width:100%}.el-table th>.cell.highlight{color:#42d885}.el-table th.required>div:before{display:inline-block;content:"";width:8px;height:8px;border-radius:50%;background:#ff4d51;margin-right:5px;vertical-align:middle}.el-table td div{box-sizing:border-box}.el-table td.gutter{width:0}.el-table .cell{box-sizing:border-box;overflow:hidden;text-overflow:ellipsis;white-space:normal;word-break:break-all;line-height:23px;padding-left:10px;padding-right:10px}.el-table .cell.el-tooltip{white-space:nowrap;min-width:50px}.el-table--border,.el-table--group{border:1px solid #ebeef5}.el-table--border:after,.el-table--group:after,.el-table:before{content:"";position:absolute;background-color:#ebeef5;z-index:1}.el-table--border:after,.el-table--group:after{top:0;right:0;width:1px;height:100%}.el-table:before{left:0;bottom:0;width:100%;height:1px}.el-table--border{border-right:none;border-bottom:none}.el-table--border.el-loading-parent--relative{border-color:transparent}.el-table--border td,.el-table--border th{border-right:1px solid #ebeef5}.el-table--border td:first-child .cell,.el-table--border th:first-child .cell{padding-left:10px}.el-table--border th.gutter:last-of-type{border-bottom:1px solid #ebeef5;border-bottom-width:1px}.el-table--border th{border-bottom:1px solid #ebeef5}.el-table--hidden{visibility:hidden}.el-table__fixed,.el-table__fixed-right{position:absolute;top:0;left:0;overflow-x:hidden;overflow-y:hidden;box-shadow:0 0 10px rgba(0,0,0,.12)}.el-table__fixed-right:before,.el-table__fixed:before{content:"";position:absolute;left:0;bottom:0;width:100%;height:1px;background-color:#ebeef5;z-index:4}.el-table__fixed-right-patch{position:absolute;top:-1px;right:0;background-color:#fff;border-bottom:1px solid #ebeef5}.el-table__fixed-right{top:0;left:auto;right:0}.el-table__fixed-right .el-table__fixed-body-wrapper,.el-table__fixed-right .el-table__fixed-footer-wrapper,.el-table__fixed-right .el-table__fixed-header-wrapper{left:auto;right:0}.el-table__fixed-header-wrapper{position:absolute;left:0;top:0;z-index:3}.el-table__fixed-footer-wrapper{position:absolute;left:0;bottom:0;z-index:3}.el-table__fixed-footer-wrapper tbody td{border-top:1px solid #ebeef5;background-color:#f5f7fa;color:#606266}.el-table__fixed-body-wrapper{position:absolute;left:0;top:37px;overflow:hidden;z-index:3}.el-table__body-wrapper,.el-table__footer-wrapper,.el-table__header-wrapper{width:100%}.el-table__footer-wrapper{margin-top:-1px}.el-table__footer-wrapper td{border-top:1px solid #ebeef5}.el-table__body,.el-table__footer,.el-table__header{table-layout:fixed;border-collapse:separate}.el-table__footer-wrapper,.el-table__header-wrapper{overflow:hidden}.el-table__footer-wrapper tbody td,.el-table__header-wrapper tbody td{background-color:#f5f7fa;color:#606266}.el-table__body-wrapper{overflow:hidden;position:relative}.el-table__body-wrapper.is-scrolling-left~.el-table__fixed,.el-table__body-wrapper.is-scrolling-none~.el-table__fixed,.el-table__body-wrapper.is-scrolling-none~.el-table__fixed-right,.el-table__body-wrapper.is-scrolling-right~.el-table__fixed-right{box-shadow:none}.el-table__body-wrapper .el-table--border.is-scrolling-right~.el-table__fixed-right{border-left:1px solid #ebeef5}.el-table__body-wrapper .el-table--border.is-scrolling-left~.el-table__fixed{border-right:1px solid #ebeef5}.el-table .caret-wrapper{display:-ms-inline-flexbox;display:inline-flex;-ms-flex-direction:column;flex-direction:column;-ms-flex-align:center;align-items:center;height:34px;width:24px;vertical-align:middle;cursor:pointer;overflow:initial;position:relative}.el-table .sort-caret{width:0;height:0;border:5px solid transparent;position:absolute;left:7px}.el-table .sort-caret.ascending{border-bottom-color:#c0c4cc;top:5px}.el-table .sort-caret.descending{border-top-color:#c0c4cc;bottom:7px}.el-table .ascending .sort-caret.ascending{border-bottom-color:#42d885}.el-table .descending .sort-caret.descending{border-top-color:#42d885}.el-table .hidden-columns{visibility:hidden;position:absolute;z-index:-1}.el-table--striped .el-table__body tr.el-table__row--striped td{background:#fafafa}.el-table--striped .el-table__body tr.el-table__row--striped.current-row td{background-color:#ecfbf3}.el-table__body tr.hover-row.current-row>td,.el-table__body tr.hover-row.el-table__row--striped.current-row>td,.el-table__body tr.hover-row.el-table__row--striped>td,.el-table__body tr.hover-row>td{background-color:#f5f7fa}.el-table__body tr.current-row>td{background-color:#ecfbf3}.el-table__column-resize-proxy{position:absolute;left:200px;top:0;bottom:0;width:0;border-left:1px solid #ebeef5;z-index:10}.el-table__column-filter-trigger{display:inline-block;line-height:34px;cursor:pointer}.el-table__column-filter-trigger i{color:#909399;font-size:12px;transform:scale(.75)}.el-table--enable-row-transition .el-table__body td{transition:background-color .25s ease}.el-table--enable-row-hover .el-table__body tr:hover>td{background-color:#f5f7fa}.el-table--fluid-height .el-table__fixed,.el-table--fluid-height .el-table__fixed-right{bottom:0;overflow:hidden}.el-table [class*=el-table__row--level] .el-table__expand-icon{display:inline-block;width:20px;line-height:20px;height:20px;text-align:center;margin-right:3px}.el-table-column--selection .cell{padding-left:14px;padding-right:14px}.el-table-filter{border:1px solid #ebeef5;border-radius:2px;background-color:#fff;box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-sizing:border-box;margin:2px 0}.el-table-filter__list{padding:5px 0;margin:0;list-style:none;min-width:100px}.el-table-filter__list-item{line-height:36px;padding:0 10px;cursor:pointer;font-size:14px}.el-table-filter__list-item:hover{background-color:#ecfbf3;color:#68e09d}.el-table-filter__list-item.is-active{background-color:#42d885;color:#fff}.el-table-filter__content{min-width:100px}.el-table-filter__bottom{border-top:1px solid #ebeef5;padding:8px}.el-table-filter__bottom button{background:transparent;border:none;color:#606266;cursor:pointer;font-size:13px;padding:0 3px}.el-table-filter__bottom button:hover{color:#42d885}.el-table-filter__bottom button:focus{outline:none}.el-table-filter__bottom button.is-disabled{color:#c0c4cc;cursor:not-allowed}.el-table-filter__wrap{max-height:280px}.el-table-filter__checkbox-group{padding:10px}.el-table-filter__checkbox-group label.el-checkbox{display:block;margin-right:5px;margin-bottom:8px;margin-left:5px}.el-table-filter__checkbox-group .el-checkbox:last-child{margin-bottom:0}.el-date-table{font-size:12px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.el-date-table.is-week-mode .el-date-table__row:hover div{background-color:#f2f6fc}.el-date-table.is-week-mode .el-date-table__row:hover td.available:hover{color:#606266}.el-date-table.is-week-mode .el-date-table__row:hover td:first-child div{margin-left:5px;border-top-left-radius:15px;border-bottom-left-radius:15px}.el-date-table.is-week-mode .el-date-table__row:hover td:last-child div{margin-right:5px;border-top-right-radius:15px;border-bottom-right-radius:15px}.el-date-table.is-week-mode .el-date-table__row.current div{background-color:#f2f6fc}.el-date-table td{width:32px;height:30px;padding:4px 0;box-sizing:border-box;text-align:center;cursor:pointer;position:relative}.el-date-table td div{height:30px;padding:3px 0;box-sizing:border-box}.el-date-table td span{width:24px;height:24px;display:block;margin:0 auto;line-height:24px;position:absolute;left:50%;transform:translateX(-50%);border-radius:50%}.el-date-table td.next-month,.el-date-table td.prev-month{color:#c0c4cc}.el-date-table td.today{position:relative}.el-date-table td.today span{color:#42d885;font-weight:700}.el-date-table td.today.end-date span,.el-date-table td.today.start-date span{color:#fff}.el-date-table td.available:hover{color:#42d885}.el-date-table td.in-range div,.el-date-table td.in-range div:hover{background-color:#f2f6fc}.el-date-table td.current:not(.disabled) span{color:#fff;background-color:#42d885}.el-date-table td.end-date div,.el-date-table td.start-date div{color:#fff}.el-date-table td.end-date span,.el-date-table td.start-date span{background-color:#42d885}.el-date-table td.start-date div{margin-left:5px;border-top-left-radius:15px;border-bottom-left-radius:15px}.el-date-table td.end-date div{margin-right:5px;border-top-right-radius:15px;border-bottom-right-radius:15px}.el-date-table td.disabled div{background-color:#f5f7fa;opacity:1;cursor:not-allowed;color:#c0c4cc}.el-date-table td.selected div{margin-left:5px;margin-right:5px;background-color:#f2f6fc;border-radius:15px}.el-date-table td.selected div:hover{background-color:#f2f6fc}.el-date-table td.selected span{background-color:#42d885;color:#fff;border-radius:15px}.el-date-table td.week{font-size:80%;color:#606266}.el-date-table th{padding:5px;color:#606266;font-weight:400;border-bottom:1px solid #ebeef5}.el-month-table{font-size:12px;margin:-1px;border-collapse:collapse}.el-month-table td{text-align:center;padding:8px 0;cursor:pointer}.el-month-table td div{height:48px;padding:6px 0;box-sizing:border-box}.el-month-table td.today .cell{color:#42d885;font-weight:700}.el-month-table td.today.end-date .cell,.el-month-table td.today.start-date .cell{color:#fff}.el-month-table td.disabled .cell{background-color:#f5f7fa;cursor:not-allowed;color:#c0c4cc}.el-month-table td.disabled .cell:hover{color:#c0c4cc}.el-month-table td .cell{width:60px;height:36px;display:block;line-height:36px;color:#606266;margin:0 auto;border-radius:18px}.el-month-table td .cell:hover{color:#42d885}.el-month-table td.in-range div,.el-month-table td.in-range div:hover{background-color:#f2f6fc}.el-month-table td.end-date div,.el-month-table td.start-date div{color:#fff}.el-month-table td.end-date .cell,.el-month-table td.start-date .cell{color:#fff;background-color:#42d885}.el-month-table td.start-date div{border-top-left-radius:24px;border-bottom-left-radius:24px}.el-month-table td.end-date div{border-top-right-radius:24px;border-bottom-right-radius:24px}.el-month-table td.current:not(.disabled) .cell{color:#42d885}.el-year-table{font-size:12px;margin:-1px;border-collapse:collapse}.el-year-table .el-icon{color:#303133}.el-year-table td{text-align:center;padding:20px 3px;cursor:pointer}.el-year-table td.today .cell{color:#42d885;font-weight:700}.el-year-table td.disabled .cell{background-color:#f5f7fa;cursor:not-allowed;color:#c0c4cc}.el-year-table td.disabled .cell:hover{color:#c0c4cc}.el-year-table td .cell{width:48px;height:32px;display:block;line-height:32px;color:#606266;margin:0 auto}.el-year-table td .cell:hover,.el-year-table td.current:not(.disabled) .cell{color:#42d885}.el-date-range-picker{width:646px}.el-date-range-picker.has-sidebar{width:756px}.el-date-range-picker table{table-layout:fixed;width:100%}.el-date-range-picker .el-picker-panel__body{min-width:513px}.el-date-range-picker .el-picker-panel__content{margin:0}.el-date-range-picker__header{position:relative;text-align:center;height:28px}.el-date-range-picker__header [class*=arrow-left]{float:left}.el-date-range-picker__header [class*=arrow-right]{float:right}.el-date-range-picker__header div{font-size:16px;font-weight:500;margin-right:50px}.el-date-range-picker__content{float:left;width:50%;box-sizing:border-box;margin:0;padding:16px}.el-date-range-picker__content.is-left{border-right:1px solid #e4e4e4}.el-date-range-picker__content .el-date-range-picker__header div{margin-left:50px;margin-right:50px}.el-date-range-picker__editors-wrap{box-sizing:border-box;display:table-cell}.el-date-range-picker__editors-wrap.is-right{text-align:right}.el-date-range-picker__time-header{position:relative;border-bottom:1px solid #e4e4e4;font-size:12px;padding:8px 5px 5px;display:table;width:100%;box-sizing:border-box}.el-date-range-picker__time-header>.el-icon-arrow-right{font-size:20px;vertical-align:middle;display:table-cell;color:#303133}.el-date-range-picker__time-picker-wrap{position:relative;display:table-cell;padding:0 5px}.el-date-range-picker__time-picker-wrap .el-picker-panel{position:absolute;top:13px;right:0;z-index:1;background:#fff}.el-date-picker{width:322px}.el-date-picker.has-sidebar.has-time{width:434px}.el-date-picker.has-sidebar{width:438px}.el-date-picker.has-time .el-picker-panel__body-wrapper{position:relative}.el-date-picker .el-picker-panel__content{width:292px}.el-date-picker table{table-layout:fixed;width:100%}.el-date-picker__editor-wrap{position:relative;display:table-cell;padding:0 5px}.el-date-picker__time-header{position:relative;border-bottom:1px solid #e4e4e4;font-size:12px;padding:8px 5px 5px;display:table;width:100%;box-sizing:border-box}.el-date-picker__header{margin:12px;text-align:center}.el-date-picker__header--bordered{margin-bottom:0;padding-bottom:12px;border-bottom:1px solid #ebeef5}.el-date-picker__header--bordered+.el-picker-panel__content{margin-top:0}.el-date-picker__header-label{font-size:16px;font-weight:500;padding:0 5px;line-height:22px;text-align:center;cursor:pointer;color:#606266}.el-date-picker__header-label.active,.el-date-picker__header-label:hover{color:#42d885}.el-date-picker__prev-btn{float:left}.el-date-picker__next-btn{float:right}.el-date-picker__time-wrap{padding:10px;text-align:center}.el-date-picker__time-label{float:left;cursor:pointer;line-height:30px;margin-left:10px}.time-select{margin:5px 0;min-width:0}.time-select .el-picker-panel__content{max-height:200px;margin:0}.time-select-item{padding:8px 10px;font-size:14px;line-height:20px}.time-select-item.selected:not(.disabled){color:#42d885;font-weight:700}.time-select-item.disabled{color:#e4e7ed;cursor:not-allowed}.time-select-item:hover{background-color:#f5f7fa;font-weight:700;cursor:pointer}.el-date-editor{position:relative;display:inline-block;text-align:left}.el-date-editor.el-input,.el-date-editor.el-input__inner{width:220px}.el-date-editor--monthrange.el-input,.el-date-editor--monthrange.el-input__inner{width:300px}.el-date-editor--daterange.el-input,.el-date-editor--daterange.el-input__inner,.el-date-editor--timerange.el-input,.el-date-editor--timerange.el-input__inner{width:350px}.el-date-editor--datetimerange.el-input,.el-date-editor--datetimerange.el-input__inner{width:400px}.el-date-editor--dates .el-input__inner{text-overflow:ellipsis;white-space:nowrap}.el-date-editor .el-icon-circle-close{cursor:pointer}.el-date-editor .el-range__icon{font-size:14px;margin-left:-5px;color:#c0c4cc;float:left;line-height:32px}.el-date-editor .el-range-input{-webkit-appearance:none;-moz-appearance:none;appearance:none;border:none;outline:none;display:inline-block;height:100%;margin:0;padding:0;width:39%;text-align:center;font-size:14px;color:#606266}.el-date-editor .el-range-input::-webkit-input-placeholder{color:#c0c4cc}.el-date-editor .el-range-input::-ms-input-placeholder{color:#c0c4cc}.el-date-editor .el-range-input::placeholder{color:#c0c4cc}.el-date-editor .el-range-separator{display:inline-block;height:100%;padding:0 5px;margin:0;text-align:center;line-height:32px;font-size:14px;width:5%;color:#303133}.el-date-editor .el-range__close-icon{font-size:14px;color:#c0c4cc;width:25px;display:inline-block;float:right;line-height:32px}.el-range-editor.el-input__inner{display:-ms-inline-flexbox;display:inline-flex;-ms-flex-align:center;align-items:center;padding:3px 10px}.el-range-editor .el-range-input{line-height:1}.el-range-editor.is-active,.el-range-editor.is-active:hover{border-color:#42d885}.el-range-editor--medium.el-input__inner{height:36px}.el-range-editor--medium .el-range-separator{line-height:28px;font-size:14px}.el-range-editor--medium .el-range-input{font-size:14px}.el-range-editor--medium .el-range__close-icon,.el-range-editor--medium .el-range__icon{line-height:28px}.el-range-editor--small.el-input__inner{height:32px}.el-range-editor--small .el-range-separator{line-height:24px;font-size:13px}.el-range-editor--small .el-range-input{font-size:13px}.el-range-editor--small .el-range__close-icon,.el-range-editor--small .el-range__icon{line-height:24px}.el-range-editor--mini.el-input__inner{height:28px}.el-range-editor--mini .el-range-separator{line-height:20px;font-size:12px}.el-range-editor--mini .el-range-input{font-size:12px}.el-range-editor--mini .el-range__close-icon,.el-range-editor--mini .el-range__icon{line-height:20px}.el-range-editor.is-disabled{background-color:#f5f7fa;border-color:#e4e7ed;color:#c0c4cc;cursor:not-allowed}.el-range-editor.is-disabled:focus,.el-range-editor.is-disabled:hover{border-color:#e4e7ed}.el-range-editor.is-disabled input{background-color:#f5f7fa;color:#c0c4cc;cursor:not-allowed}.el-range-editor.is-disabled input::-webkit-input-placeholder{color:#c0c4cc}.el-range-editor.is-disabled input::-ms-input-placeholder{color:#c0c4cc}.el-range-editor.is-disabled input::placeholder{color:#c0c4cc}.el-range-editor.is-disabled .el-range-separator{color:#c0c4cc}.el-picker-panel{color:#606266;border:1px solid #e4e7ed;box-shadow:0 2px 12px 0 rgba(0,0,0,.1);background:#fff;border-radius:4px;line-height:30px;margin:5px 0}.el-picker-panel__body-wrapper:after,.el-picker-panel__body:after{content:"";display:table;clear:both}.el-picker-panel__content{position:relative;margin:15px}.el-picker-panel__footer{border-top:1px solid #e4e4e4;padding:4px;text-align:right;background-color:#fff;position:relative;font-size:0}.el-picker-panel__shortcut{display:block;width:100%;border:0;background-color:transparent;line-height:28px;font-size:14px;color:#606266;padding-left:12px;text-align:left;outline:none;cursor:pointer}.el-picker-panel__shortcut:hover{color:#42d885}.el-picker-panel__shortcut.active{background-color:#e6f1fe;color:#42d885}.el-picker-panel__btn{border:1px solid #dcdcdc;color:#333;line-height:24px;border-radius:2px;padding:0 20px;cursor:pointer;background-color:transparent;outline:none;font-size:12px}.el-picker-panel__btn[disabled]{color:#ccc;cursor:not-allowed}.el-picker-panel__icon-btn{font-size:12px;color:#303133;border:0;background:transparent;cursor:pointer;outline:none;margin-top:8px}.el-picker-panel__icon-btn:hover{color:#42d885}.el-picker-panel__icon-btn.is-disabled{color:#bbb}.el-picker-panel__icon-btn.is-disabled:hover{cursor:not-allowed}.el-picker-panel__link-btn{vertical-align:middle}.el-picker-panel [slot=sidebar],.el-picker-panel__sidebar{position:absolute;top:0;bottom:0;width:110px;border-right:1px solid #e4e4e4;box-sizing:border-box;padding-top:6px;background-color:#fff;overflow:auto}.el-picker-panel [slot=sidebar]+.el-picker-panel__body,.el-picker-panel__sidebar+.el-picker-panel__body{margin-left:110px}.el-time-spinner.has-seconds .el-time-spinner__wrapper{width:33.3%}.el-time-spinner__wrapper{max-height:190px;overflow:auto;display:inline-block;width:50%;vertical-align:top;position:relative}.el-time-spinner__wrapper .el-scrollbar__wrap:not(.el-scrollbar__wrap--hidden-default){padding-bottom:15px}.el-time-spinner__wrapper.is-arrow{box-sizing:border-box;text-align:center;overflow:hidden}.el-time-spinner__wrapper.is-arrow .el-time-spinner__list{transform:translateY(-32px)}.el-time-spinner__wrapper.is-arrow .el-time-spinner__item:hover:not(.disabled):not(.active){background:#fff;cursor:default}.el-time-spinner__arrow{font-size:12px;color:#909399;position:absolute;left:0;width:100%;z-index:1;text-align:center;height:30px;line-height:30px;cursor:pointer}.el-time-spinner__arrow:hover{color:#42d885}.el-time-spinner__arrow.el-icon-arrow-up{top:10px}.el-time-spinner__arrow.el-icon-arrow-down{bottom:10px}.el-time-spinner__input.el-input{width:70%}.el-time-spinner__input.el-input .el-input__inner,.el-time-spinner__list{padding:0;text-align:center}.el-time-spinner__list{margin:0;list-style:none}.el-time-spinner__list:after,.el-time-spinner__list:before{content:"";display:block;width:100%;height:80px}.el-time-spinner__item{height:32px;line-height:32px;font-size:12px;color:#606266}.el-time-spinner__item:hover:not(.disabled):not(.active){background:#f5f7fa;cursor:pointer}.el-time-spinner__item.active:not(.disabled){color:#303133;font-weight:700}.el-time-spinner__item.disabled{color:#c0c4cc;cursor:not-allowed}.el-time-panel{margin:5px 0;border:1px solid #e4e7ed;background-color:#fff;box-shadow:0 2px 12px 0 rgba(0,0,0,.1);border-radius:2px;position:absolute;width:180px;left:0;z-index:1000;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;box-sizing:content-box}.el-time-panel__content{font-size:0;position:relative;overflow:hidden}.el-time-panel__content:after,.el-time-panel__content:before{content:"";top:50%;position:absolute;margin-top:-15px;height:32px;z-index:-1;left:0;right:0;box-sizing:border-box;padding-top:6px;text-align:left;border-top:1px solid #e4e7ed;border-bottom:1px solid #e4e7ed}.el-time-panel__content:after{left:50%;margin-left:12%;margin-right:12%}.el-time-panel__content:before{padding-left:50%;margin-right:12%;margin-left:12%}.el-time-panel__content.has-seconds:after{left:66.66667%}.el-time-panel__content.has-seconds:before{padding-left:33.33333%}.el-time-panel__footer{border-top:1px solid #e4e4e4;padding:4px;height:36px;line-height:25px;text-align:right;box-sizing:border-box}.el-time-panel__btn{border:none;line-height:28px;padding:0 5px;margin:0 5px;cursor:pointer;background-color:transparent;outline:none;font-size:12px;color:#303133}.el-time-panel__btn.confirm{font-weight:800;color:#42d885}.el-time-range-picker{width:354px;overflow:visible}.el-time-range-picker__content{position:relative;text-align:center;padding:10px}.el-time-range-picker__cell{box-sizing:border-box;margin:0;padding:4px 7px 7px;width:50%;display:inline-block}.el-time-range-picker__header{margin-bottom:5px;text-align:center;font-size:14px}.el-time-range-picker__body{border-radius:2px;border:1px solid #e4e7ed}.el-popover{position:absolute;background:#fff;min-width:150px;border-radius:4px;border:1px solid #ebeef5;padding:12px;z-index:2000;color:#606266;line-height:1.4;text-align:justify;font-size:14px;box-shadow:0 2px 12px 0 rgba(0,0,0,.1);word-break:break-all}.el-popover--plain{padding:18px 20px}.el-popover__title{color:#303133;font-size:16px;line-height:1;margin-bottom:12px}.el-popover:focus,.el-popover:focus:active,.el-popover__reference:focus:hover,.el-popover__reference:focus:not(.focusing){outline-width:0}.v-modal-enter{animation:v-modal-in .2s ease}.v-modal-leave{animation:v-modal-out .2s ease forwards}@keyframes v-modal-in{0%{opacity:0}}@keyframes v-modal-out{to{opacity:0}}.v-modal{position:fixed;left:0;top:0;width:100%;height:100%;opacity:.5;background:#000}.el-popup-parent--hidden{overflow:hidden}.el-message-box{display:inline-block;width:420px;padding-bottom:10px;vertical-align:middle;background-color:#fff;border-radius:4px;border:1px solid #ebeef5;font-size:18px;box-shadow:0 2px 12px 0 rgba(0,0,0,.1);text-align:left;overflow:hidden;-webkit-backface-visibility:hidden;backface-visibility:hidden}.el-message-box__wrapper{position:fixed;top:0;bottom:0;left:0;right:0;text-align:center}.el-message-box__wrapper:after{content:"";display:inline-block;height:100%;width:0;vertical-align:middle}.el-message-box__header{position:relative;padding:15px;padding-bottom:10px}.el-message-box__title{padding-left:0;margin-bottom:0;font-size:18px;line-height:1;color:#303133}.el-message-box__headerbtn{position:absolute;top:15px;right:15px;padding:0;border:none;outline:none;background:transparent;font-size:16px;cursor:pointer}.el-message-box__headerbtn .el-message-box__close{color:#909399}.el-message-box__headerbtn:focus .el-message-box__close,.el-message-box__headerbtn:hover .el-message-box__close{color:#42d885}.el-message-box__content{position:relative;padding:10px 15px;color:#606266;font-size:14px}.el-message-box__input{padding-top:15px}.el-message-box__input input.invalid,.el-message-box__input input.invalid:focus{border-color:#ff6d6d}.el-message-box__status{position:absolute;top:50%;transform:translateY(-50%);font-size:24px!important}.el-message-box__status:before{padding-left:1px}.el-message-box__status+.el-message-box__message{padding-left:36px;padding-right:12px}.el-message-box__status.el-icon-success{color:#42d885}.el-message-box__status.el-icon-info{color:#909399}.el-message-box__status.el-icon-warning{color:#f9c855}.el-message-box__status.el-icon-error{color:#ff6d6d}.el-message-box__message{margin:0}.el-message-box__message p{margin:0;line-height:24px}.el-message-box__errormsg{color:#ff6d6d;font-size:12px;min-height:18px;margin-top:2px}.el-message-box__btns{padding:5px 15px 0;text-align:right}.el-message-box__btns button:nth-child(2){margin-left:10px}.el-message-box__btns-reverse{-ms-flex-direction:row-reverse;flex-direction:row-reverse}.el-message-box--center{padding-bottom:30px}.el-message-box--center .el-message-box__header{padding-top:30px}.el-message-box--center .el-message-box__title{position:relative;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center}.el-message-box--center .el-message-box__status{position:relative;top:auto;padding-right:5px;text-align:center;transform:translateY(-1px)}.el-message-box--center .el-message-box__message{margin-left:0}.el-message-box--center .el-message-box__btns,.el-message-box--center .el-message-box__content{text-align:center}.el-message-box--center .el-message-box__content{padding-left:27px;padding-right:27px}.msgbox-fade-enter-active{animation:msgbox-fade-in .3s}.msgbox-fade-leave-active{animation:msgbox-fade-out .3s}@keyframes msgbox-fade-in{0%{transform:translate3d(0,-20px,0);opacity:0}to{transform:translateZ(0);opacity:1}}@keyframes msgbox-fade-out{0%{transform:translateZ(0);opacity:1}to{transform:translate3d(0,-20px,0);opacity:0}}.el-breadcrumb{font-size:14px;line-height:1}.el-breadcrumb:after,.el-breadcrumb:before{display:table;content:""}.el-breadcrumb:after{clear:both}.el-breadcrumb__separator{margin:0 9px;font-weight:700;color:#c0c4cc}.el-breadcrumb__separator[class*=icon]{margin:0 6px;font-weight:400}.el-breadcrumb__item{float:left}.el-breadcrumb__inner{color:#606266}.el-breadcrumb__inner.is-link,.el-breadcrumb__inner a{font-weight:700;text-decoration:none;transition:color .2s cubic-bezier(.645,.045,.355,1);color:#303133}.el-breadcrumb__inner.is-link:hover,.el-breadcrumb__inner a:hover{color:#42d885;cursor:pointer}.el-breadcrumb__item:last-child .el-breadcrumb__inner,.el-breadcrumb__item:last-child .el-breadcrumb__inner:hover,.el-breadcrumb__item:last-child .el-breadcrumb__inner a,.el-breadcrumb__item:last-child .el-breadcrumb__inner a:hover{font-weight:400;color:#606266;cursor:text}.el-breadcrumb__item:last-child .el-breadcrumb__separator{display:none}.el-form--label-left .el-form-item__label{text-align:left}.el-form--label-top .el-form-item__label{float:none;display:inline-block;text-align:left;padding:0 0 10px}.el-form--inline .el-form-item{display:inline-block;margin-right:10px;vertical-align:top}.el-form--inline .el-form-item__label{float:none;display:inline-block}.el-form--inline .el-form-item__content{display:inline-block;vertical-align:top}.el-form--inline.el-form--label-top .el-form-item__content{display:block}.el-form-item{margin-bottom:22px}.el-form-item:after,.el-form-item:before{display:table;content:""}.el-form-item:after{clear:both}.el-form-item .el-form-item{margin-bottom:0}.el-form-item .el-input__validateIcon{display:none}.el-form-item--medium .el-form-item__content,.el-form-item--medium .el-form-item__label{line-height:36px}.el-form-item--small .el-form-item__content,.el-form-item--small .el-form-item__label{line-height:32px}.el-form-item--small.el-form-item{margin-bottom:18px}.el-form-item--small .el-form-item__error{padding-top:2px}.el-form-item--mini .el-form-item__content,.el-form-item--mini .el-form-item__label{line-height:28px}.el-form-item--mini.el-form-item{margin-bottom:18px}.el-form-item--mini .el-form-item__error{padding-top:1px}.el-form-item__label-wrap{float:left}.el-form-item__label-wrap .el-form-item__label{display:inline-block;float:none}.el-form-item__label{text-align:right;vertical-align:middle;float:left;font-size:14px;color:#606266;line-height:40px;padding:0 12px 0 0;box-sizing:border-box}.el-form-item__content{line-height:40px;position:relative;font-size:14px}.el-form-item__content:after,.el-form-item__content:before{display:table;content:""}.el-form-item__content:after{clear:both}.el-form-item__content .el-input-group{vertical-align:top}.el-form-item__error{color:#ff6d6d;font-size:12px;line-height:1;padding-top:4px;position:absolute;top:100%;left:0}.el-form-item__error--inline{position:relative;top:auto;left:auto;display:inline-block;margin-left:10px}.el-form-item.is-required:not(.is-no-asterisk) .el-form-item__label-wrap>.el-form-item__label:before,.el-form-item.is-required:not(.is-no-asterisk)>.el-form-item__label:before{content:"*";color:#ff6d6d;margin-right:4px}.el-form-item.is-error .el-input__inner,.el-form-item.is-error .el-input__inner:focus,.el-form-item.is-error .el-textarea__inner,.el-form-item.is-error .el-textarea__inner:focus{border-color:#ff6d6d}.el-form-item.is-error .el-input-group__append .el-input__inner,.el-form-item.is-error .el-input-group__prepend .el-input__inner{border-color:transparent}.el-form-item.is-error .el-input__validateIcon{color:#ff6d6d}.el-form-item--feedback .el-input__validateIcon{display:inline-block}.el-tabs__header{padding:0;position:relative;margin:0 0 15px}.el-tabs__active-bar{position:absolute;bottom:0;left:0;height:2px;background-color:#42d885;z-index:1;transition:transform .3s cubic-bezier(.645,.045,.355,1);list-style:none}.el-tabs__new-tab{float:right;border:1px solid #d3dce6;height:18px;width:18px;line-height:18px;margin:12px 0 9px 10px;border-radius:3px;text-align:center;font-size:12px;color:#d3dce6;cursor:pointer;transition:all .15s}.el-tabs__new-tab .el-icon-plus{transform:scale(.8)}.el-tabs__new-tab:hover{color:#42d885}.el-tabs__nav-wrap{overflow:hidden;margin-bottom:-1px;position:relative}.el-tabs__nav-wrap:after{content:"";position:absolute;left:0;bottom:0;width:100%;height:2px;background-color:#e4e7ed;z-index:1}.el-tabs__nav-wrap.is-scrollable{padding:0 20px;box-sizing:border-box}.el-tabs__nav-scroll{overflow:hidden}.el-tabs__nav-next,.el-tabs__nav-prev{position:absolute;cursor:pointer;line-height:44px;font-size:12px;color:#909399}.el-tabs__nav-next{right:0}.el-tabs__nav-prev{left:0}.el-tabs__nav{white-space:nowrap;position:relative;transition:transform .3s;float:left;z-index:2}.el-tabs__nav.is-stretch{min-width:100%;display:-ms-flexbox;display:flex}.el-tabs__nav.is-stretch>*{-ms-flex:1;flex:1;text-align:center}.el-tabs__item{padding:0 20px;height:40px;box-sizing:border-box;line-height:40px;display:inline-block;list-style:none;font-size:14px;font-weight:500;color:#303133;position:relative}.el-tabs__item:focus,.el-tabs__item:focus:active{outline:none}.el-tabs__item:focus.is-active.is-focus:not(:active){box-shadow:inset 0 0 2px 2px #42d885;border-radius:3px}.el-tabs__item .el-icon-close{border-radius:50%;text-align:center;transition:all .3s cubic-bezier(.645,.045,.355,1);margin-left:5px}.el-tabs__item .el-icon-close:before{transform:scale(.9);display:inline-block}.el-tabs__item .el-icon-close:hover{background-color:#c0c4cc;color:#fff}.el-tabs__item.is-active{color:#42d885}.el-tabs__item:hover{color:#42d885;cursor:pointer}.el-tabs__item.is-disabled{color:#c0c4cc;cursor:default}.el-tabs__content{overflow:hidden;position:relative}.el-tabs--card>.el-tabs__header{border-bottom:1px solid #e4e7ed}.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap:after{content:none}.el-tabs--card>.el-tabs__header .el-tabs__nav{border:1px solid #e4e7ed;border-bottom:none;border-radius:4px 4px 0 0;box-sizing:border-box}.el-tabs--card>.el-tabs__header .el-tabs__active-bar{display:none}.el-tabs--card>.el-tabs__header .el-tabs__item .el-icon-close{position:relative;font-size:12px;width:0;height:14px;vertical-align:middle;line-height:15px;overflow:hidden;top:-1px;right:-2px;transform-origin:100% 50%}.el-tabs--card>.el-tabs__header .el-tabs__item{border-bottom:1px solid transparent;border-left:1px solid #e4e7ed;transition:color .3s cubic-bezier(.645,.045,.355,1),padding .3s cubic-bezier(.645,.045,.355,1)}.el-tabs--card>.el-tabs__header .el-tabs__item:first-child{border-left:none}.el-tabs--card>.el-tabs__header .el-tabs__item.is-closable:hover{padding-left:13px;padding-right:13px}.el-tabs--card>.el-tabs__header .el-tabs__item.is-closable:hover .el-icon-close{width:14px}.el-tabs--card>.el-tabs__header .el-tabs__item.is-active{border-bottom-color:#fff}.el-tabs--card>.el-tabs__header .el-tabs__item.is-active.is-closable{padding-left:20px;padding-right:20px}.el-tabs--card>.el-tabs__header .el-tabs__item.is-active.is-closable .el-icon-close{width:14px}.el-tabs--border-card{background:#fff;border:1px solid #dcdfe6;box-shadow:0 2px 4px 0 rgba(0,0,0,.12),0 0 6px 0 rgba(0,0,0,.04)}.el-tabs--border-card>.el-tabs__content{padding:15px}.el-tabs--border-card>.el-tabs__header{background-color:#f5f7fa;border-bottom:1px solid #e4e7ed;margin:0}.el-tabs--border-card>.el-tabs__header .el-tabs__nav-wrap:after{content:none}.el-tabs--border-card>.el-tabs__header .el-tabs__item{transition:all .3s cubic-bezier(.645,.045,.355,1);border:1px solid transparent;margin-top:-1px;color:#909399}.el-tabs--border-card>.el-tabs__header .el-tabs__item+.el-tabs__item,.el-tabs--border-card>.el-tabs__header .el-tabs__item:first-child{margin-left:-1px}.el-tabs--border-card>.el-tabs__header .el-tabs__item.is-active{color:#42d885;background-color:#fff;border-right-color:#dcdfe6;border-left-color:#dcdfe6}.el-tabs--border-card>.el-tabs__header .el-tabs__item:not(.is-disabled):hover{color:#42d885}.el-tabs--border-card>.el-tabs__header .el-tabs__item.is-disabled{color:#c0c4cc}.el-tabs--border-card>.el-tabs__header .is-scrollable .el-tabs__item:first-child{margin-left:0}.el-tabs--bottom .el-tabs__item.is-bottom:nth-child(2),.el-tabs--bottom .el-tabs__item.is-top:nth-child(2),.el-tabs--top .el-tabs__item.is-bottom:nth-child(2),.el-tabs--top .el-tabs__item.is-top:nth-child(2){padding-left:0}.el-tabs--bottom .el-tabs__item.is-bottom:last-child,.el-tabs--bottom .el-tabs__item.is-top:last-child,.el-tabs--top .el-tabs__item.is-bottom:last-child,.el-tabs--top .el-tabs__item.is-top:last-child{padding-right:0}.el-tabs--bottom.el-tabs--border-card>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--bottom.el-tabs--card>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--bottom .el-tabs--left>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--bottom .el-tabs--right>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--top.el-tabs--border-card>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--top.el-tabs--card>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--top .el-tabs--left>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--top .el-tabs--right>.el-tabs__header .el-tabs__item:nth-child(2){padding-left:20px}.el-tabs--bottom.el-tabs--border-card>.el-tabs__header .el-tabs__item:last-child,.el-tabs--bottom.el-tabs--card>.el-tabs__header .el-tabs__item:last-child,.el-tabs--bottom .el-tabs--left>.el-tabs__header .el-tabs__item:last-child,.el-tabs--bottom .el-tabs--right>.el-tabs__header .el-tabs__item:last-child,.el-tabs--top.el-tabs--border-card>.el-tabs__header .el-tabs__item:last-child,.el-tabs--top.el-tabs--card>.el-tabs__header .el-tabs__item:last-child,.el-tabs--top .el-tabs--left>.el-tabs__header .el-tabs__item:last-child,.el-tabs--top .el-tabs--right>.el-tabs__header .el-tabs__item:last-child{padding-right:20px}.el-tabs--bottom .el-tabs__header.is-bottom{margin-bottom:0;margin-top:10px}.el-tabs--bottom.el-tabs--border-card .el-tabs__header.is-bottom{border-bottom:0;border-top:1px solid #dcdfe6}.el-tabs--bottom.el-tabs--border-card .el-tabs__nav-wrap.is-bottom{margin-top:-1px;margin-bottom:0}.el-tabs--bottom.el-tabs--border-card .el-tabs__item.is-bottom:not(.is-active){border:1px solid transparent}.el-tabs--bottom.el-tabs--border-card .el-tabs__item.is-bottom{margin:0 -1px -1px}.el-tabs--left,.el-tabs--right{overflow:hidden}.el-tabs--left .el-tabs__header.is-left,.el-tabs--left .el-tabs__header.is-right,.el-tabs--left .el-tabs__nav-scroll,.el-tabs--left .el-tabs__nav-wrap.is-left,.el-tabs--left .el-tabs__nav-wrap.is-right,.el-tabs--right .el-tabs__header.is-left,.el-tabs--right .el-tabs__header.is-right,.el-tabs--right .el-tabs__nav-scroll,.el-tabs--right .el-tabs__nav-wrap.is-left,.el-tabs--right .el-tabs__nav-wrap.is-right{height:100%}.el-tabs--left .el-tabs__active-bar.is-left,.el-tabs--left .el-tabs__active-bar.is-right,.el-tabs--right .el-tabs__active-bar.is-left,.el-tabs--right .el-tabs__active-bar.is-right{top:0;bottom:auto;width:2px;height:auto}.el-tabs--left .el-tabs__nav-wrap.is-left,.el-tabs--left .el-tabs__nav-wrap.is-right,.el-tabs--right .el-tabs__nav-wrap.is-left,.el-tabs--right .el-tabs__nav-wrap.is-right{margin-bottom:0}.el-tabs--left .el-tabs__nav-wrap.is-left>.el-tabs__nav-next,.el-tabs--left .el-tabs__nav-wrap.is-left>.el-tabs__nav-prev,.el-tabs--left .el-tabs__nav-wrap.is-right>.el-tabs__nav-next,.el-tabs--left .el-tabs__nav-wrap.is-right>.el-tabs__nav-prev,.el-tabs--right .el-tabs__nav-wrap.is-left>.el-tabs__nav-next,.el-tabs--right .el-tabs__nav-wrap.is-left>.el-tabs__nav-prev,.el-tabs--right .el-tabs__nav-wrap.is-right>.el-tabs__nav-next,.el-tabs--right .el-tabs__nav-wrap.is-right>.el-tabs__nav-prev{height:30px;line-height:30px;width:100%;text-align:center;cursor:pointer}.el-tabs--left .el-tabs__nav-wrap.is-left>.el-tabs__nav-next i,.el-tabs--left .el-tabs__nav-wrap.is-left>.el-tabs__nav-prev i,.el-tabs--left .el-tabs__nav-wrap.is-right>.el-tabs__nav-next i,.el-tabs--left .el-tabs__nav-wrap.is-right>.el-tabs__nav-prev i,.el-tabs--right .el-tabs__nav-wrap.is-left>.el-tabs__nav-next i,.el-tabs--right .el-tabs__nav-wrap.is-left>.el-tabs__nav-prev i,.el-tabs--right .el-tabs__nav-wrap.is-right>.el-tabs__nav-next i,.el-tabs--right .el-tabs__nav-wrap.is-right>.el-tabs__nav-prev i{transform:rotate(90deg)}.el-tabs--left .el-tabs__nav-wrap.is-left>.el-tabs__nav-prev,.el-tabs--left .el-tabs__nav-wrap.is-right>.el-tabs__nav-prev,.el-tabs--right .el-tabs__nav-wrap.is-left>.el-tabs__nav-prev,.el-tabs--right .el-tabs__nav-wrap.is-right>.el-tabs__nav-prev{left:auto;top:0}.el-tabs--left .el-tabs__nav-wrap.is-left>.el-tabs__nav-next,.el-tabs--left .el-tabs__nav-wrap.is-right>.el-tabs__nav-next,.el-tabs--right .el-tabs__nav-wrap.is-left>.el-tabs__nav-next,.el-tabs--right .el-tabs__nav-wrap.is-right>.el-tabs__nav-next{right:auto;bottom:0}.el-tabs--left .el-tabs__nav-wrap.is-left.is-scrollable,.el-tabs--left .el-tabs__nav-wrap.is-right.is-scrollable,.el-tabs--right .el-tabs__nav-wrap.is-left.is-scrollable,.el-tabs--right .el-tabs__nav-wrap.is-right.is-scrollable{padding:30px 0}.el-tabs--left .el-tabs__nav-wrap.is-left:after,.el-tabs--left .el-tabs__nav-wrap.is-right:after,.el-tabs--right .el-tabs__nav-wrap.is-left:after,.el-tabs--right .el-tabs__nav-wrap.is-right:after{height:100%;width:2px;bottom:auto;top:0}.el-tabs--left .el-tabs__nav.is-left,.el-tabs--left .el-tabs__nav.is-right,.el-tabs--right .el-tabs__nav.is-left,.el-tabs--right .el-tabs__nav.is-right{float:none}.el-tabs--left .el-tabs__item.is-left,.el-tabs--left .el-tabs__item.is-right,.el-tabs--right .el-tabs__item.is-left,.el-tabs--right .el-tabs__item.is-right{display:block}.el-tabs--left .el-tabs__header.is-left{float:left;margin-bottom:0;margin-right:10px}.el-tabs--left .el-tabs__nav-wrap.is-left{margin-right:-1px}.el-tabs--left .el-tabs__active-bar.is-left,.el-tabs--left .el-tabs__nav-wrap.is-left:after{left:auto;right:0}.el-tabs--left .el-tabs__item.is-left{text-align:right}.el-tabs--left.el-tabs--card .el-tabs__active-bar.is-left{display:none}.el-tabs--left.el-tabs--card .el-tabs__item.is-left{border-left:none;border-right:1px solid #e4e7ed;border-bottom:none;border-top:1px solid #e4e7ed;text-align:left}.el-tabs--left.el-tabs--card .el-tabs__item.is-left:first-child{border-right:1px solid #e4e7ed;border-top:none}.el-tabs--left.el-tabs--card .el-tabs__item.is-left.is-active{border:1px solid #e4e7ed;border-right-color:#fff;border-left:none;border-bottom:none}.el-tabs--left.el-tabs--card .el-tabs__item.is-left.is-active:first-child{border-top:none}.el-tabs--left.el-tabs--card .el-tabs__item.is-left.is-active:last-child{border-bottom:none}.el-tabs--left.el-tabs--card .el-tabs__nav{border-radius:4px 0 0 4px;border-bottom:1px solid #e4e7ed;border-right:none}.el-tabs--left.el-tabs--card .el-tabs__new-tab{float:none}.el-tabs--left.el-tabs--border-card .el-tabs__header.is-left{border-right:1px solid #dfe4ed}.el-tabs--left.el-tabs--border-card .el-tabs__item.is-left{border:1px solid transparent;margin:-1px 0 -1px -1px}.el-tabs--left.el-tabs--border-card .el-tabs__item.is-left.is-active{border-color:transparent;border-top-color:#d1dbe5;border-bottom-color:#d1dbe5}.el-tabs--right .el-tabs__header.is-right{float:right;margin-bottom:0;margin-left:10px}.el-tabs--right .el-tabs__nav-wrap.is-right{margin-left:-1px}.el-tabs--right .el-tabs__nav-wrap.is-right:after{left:0;right:auto}.el-tabs--right .el-tabs__active-bar.is-right{left:0}.el-tabs--right.el-tabs--card .el-tabs__active-bar.is-right{display:none}.el-tabs--right.el-tabs--card .el-tabs__item.is-right{border-bottom:none;border-top:1px solid #e4e7ed}.el-tabs--right.el-tabs--card .el-tabs__item.is-right:first-child{border-left:1px solid #e4e7ed;border-top:none}.el-tabs--right.el-tabs--card .el-tabs__item.is-right.is-active{border:1px solid #e4e7ed;border-left-color:#fff;border-right:none;border-bottom:none}.el-tabs--right.el-tabs--card .el-tabs__item.is-right.is-active:first-child{border-top:none}.el-tabs--right.el-tabs--card .el-tabs__item.is-right.is-active:last-child{border-bottom:none}.el-tabs--right.el-tabs--card .el-tabs__nav{border-radius:0 4px 4px 0;border-bottom:1px solid #e4e7ed;border-left:none}.el-tabs--right.el-tabs--border-card .el-tabs__header.is-right{border-left:1px solid #dfe4ed}.el-tabs--right.el-tabs--border-card .el-tabs__item.is-right{border:1px solid transparent;margin:-1px -1px -1px 0}.el-tabs--right.el-tabs--border-card .el-tabs__item.is-right.is-active{border-color:transparent;border-top-color:#d1dbe5;border-bottom-color:#d1dbe5}.slideInLeft-transition,.slideInRight-transition{display:inline-block}.slideInRight-enter{animation:slideInRight-enter .3s}.slideInRight-leave{position:absolute;left:0;right:0;animation:slideInRight-leave .3s}.slideInLeft-enter{animation:slideInLeft-enter .3s}.slideInLeft-leave{position:absolute;left:0;right:0;animation:slideInLeft-leave .3s}@keyframes slideInRight-enter{0%{opacity:0;transform-origin:0 0;transform:translateX(100%)}to{opacity:1;transform-origin:0 0;transform:translateX(0)}}@keyframes slideInRight-leave{0%{transform-origin:0 0;transform:translateX(0);opacity:1}to{transform-origin:0 0;transform:translateX(100%);opacity:0}}@keyframes slideInLeft-enter{0%{opacity:0;transform-origin:0 0;transform:translateX(-100%)}to{opacity:1;transform-origin:0 0;transform:translateX(0)}}@keyframes slideInLeft-leave{0%{transform-origin:0 0;transform:translateX(0);opacity:1}to{transform-origin:0 0;transform:translateX(-100%);opacity:0}}.el-tree{position:relative;cursor:default;background:#fff;color:#606266}.el-tree__empty-block{position:relative;min-height:60px;text-align:center;width:100%;height:100%}.el-tree__empty-text{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);color:#909399}.el-tree__drop-indicator{position:absolute;left:0;right:0;height:1px;background-color:#42d885}.el-tree-node{white-space:nowrap;outline:none}.el-tree-node:focus>.el-tree-node__content{background-color:#f5f7fa}.el-tree-node.is-drop-inner>.el-tree-node__content .el-tree-node__label{background-color:#42d885;color:#fff}.el-tree-node__content{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;height:26px;cursor:pointer}.el-tree-node__content>.el-tree-node__expand-icon{padding:6px}.el-tree-node__content>.el-checkbox{margin-right:8px}.el-tree-node__content:hover{background-color:#f5f7fa}.el-tree.is-dragging .el-tree-node__content{cursor:move}.el-tree.is-dragging .el-tree-node__content *{pointer-events:none}.el-tree.is-dragging.is-drop-not-allow .el-tree-node__content{cursor:not-allowed}.el-tree-node__expand-icon{cursor:pointer;color:#c0c4cc;font-size:12px;transform:rotate(0deg);transition:transform .3s ease-in-out}.el-tree-node__expand-icon.expanded{transform:rotate(90deg)}.el-tree-node__expand-icon.is-leaf{color:transparent;cursor:default}.el-tree-node__label{font-size:14px}.el-tree-node__loading-icon{margin-right:8px;font-size:14px;color:#c0c4cc}.el-tree-node>.el-tree-node__children{overflow:hidden;background-color:transparent}.el-tree-node.is-expanded>.el-tree-node__children{display:block}.el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content{background-color:#f0fcf5}.el-alert{width:100%;padding:8px 16px;margin:0;box-sizing:border-box;border-radius:4px;position:relative;background-color:#fff;overflow:hidden;opacity:1;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;transition:opacity .2s}.el-alert.is-light .el-alert__closebtn{color:#c0c4cc}.el-alert.is-dark .el-alert__closebtn,.el-alert.is-dark .el-alert__description{color:#fff}.el-alert.is-center{-ms-flex-pack:center;justify-content:center}.el-alert--success.is-light{background-color:#ecfbf3;color:#42d885}.el-alert--success.is-light .el-alert__description{color:#42d885}.el-alert--success.is-dark{background-color:#42d885;color:#fff}.el-alert--info.is-light{background-color:#f4f4f5;color:#909399}.el-alert--info.is-dark{background-color:#909399;color:#fff}.el-alert--info .el-alert__description{color:#909399}.el-alert--warning.is-light{background-color:#fefaee;color:#f9c855}.el-alert--warning.is-light .el-alert__description{color:#f9c855}.el-alert--warning.is-dark{background-color:#f9c855;color:#fff}.el-alert--error.is-light{background-color:#fff0f0;color:#ff6d6d}.el-alert--error.is-light .el-alert__description{color:#ff6d6d}.el-alert--error.is-dark{background-color:#ff6d6d;color:#fff}.el-alert__content{display:table-cell;padding:0 8px}.el-alert__icon{font-size:16px;width:16px}.el-alert__icon.is-big{font-size:28px;width:28px}.el-alert__title{font-size:13px;line-height:18px}.el-alert__title.is-bold{font-weight:700}.el-alert .el-alert__description{font-size:12px;margin:5px 0 0}.el-alert__closebtn{font-size:12px;opacity:1;position:absolute;top:12px;right:15px;cursor:pointer}.el-alert__closebtn.is-customed{font-style:normal;font-size:13px;top:9px}.el-alert-fade-enter,.el-alert-fade-leave-active{opacity:0}.el-notification{display:-ms-flexbox;display:flex;width:330px;padding:14px 26px 14px 13px;border-radius:8px;box-sizing:border-box;border:1px solid #ebeef5;position:fixed;background-color:#fff;box-shadow:0 2px 12px 0 rgba(0,0,0,.1);transition:opacity .3s,transform .3s,left .3s,right .3s,top .4s,bottom .3s;overflow:hidden}.el-notification.right{right:16px}.el-notification.left{left:16px}.el-notification__group{margin-left:13px;margin-right:8px}.el-notification__title{font-weight:700;font-size:16px;color:#303133;margin:0}.el-notification__content{font-size:14px;line-height:21px;margin:6px 0 0;color:#606266;text-align:justify}.el-notification__content p{margin:0}.el-notification__icon{height:24px;width:24px;font-size:24px}.el-notification__closeBtn{position:absolute;top:18px;right:15px;cursor:pointer;color:#909399;font-size:16px}.el-notification__closeBtn:hover{color:#606266}.el-notification .el-icon-success{color:#42d885}.el-notification .el-icon-error{color:#ff6d6d}.el-notification .el-icon-info{color:#909399}.el-notification .el-icon-warning{color:#f9c855}.el-notification-fade-enter.right{right:0;transform:translateX(100%)}.el-notification-fade-enter.left{left:0;transform:translateX(-100%)}.el-notification-fade-leave-active{opacity:0}.el-input-number{position:relative;display:inline-block;width:180px;line-height:38px}.el-input-number .el-input{display:block}.el-input-number .el-input__inner{-webkit-appearance:none;padding-left:50px;padding-right:50px;text-align:center}.el-input-number__decrease,.el-input-number__increase{position:absolute;z-index:1;top:1px;width:40px;height:auto;text-align:center;background:#f5f7fa;color:#606266;cursor:pointer;font-size:13px}.el-input-number__decrease:hover,.el-input-number__increase:hover{color:#42d885}.el-input-number__decrease:hover:not(.is-disabled)~.el-input .el-input__inner:not(.is-disabled),.el-input-number__increase:hover:not(.is-disabled)~.el-input .el-input__inner:not(.is-disabled){border-color:#42d885}.el-input-number__decrease.is-disabled,.el-input-number__increase.is-disabled{color:#c0c4cc;cursor:not-allowed}.el-input-number__increase{right:1px;border-radius:0 4px 4px 0;border-left:1px solid #dcdfe6}.el-input-number__decrease{left:1px;border-radius:4px 0 0 4px;border-right:1px solid #dcdfe6}.el-input-number.is-disabled .el-input-number__decrease,.el-input-number.is-disabled .el-input-number__increase{border-color:#e4e7ed;color:#e4e7ed}.el-input-number.is-disabled .el-input-number__decrease:hover,.el-input-number.is-disabled .el-input-number__increase:hover{color:#e4e7ed;cursor:not-allowed}.el-input-number--medium{width:200px;line-height:34px}.el-input-number--medium .el-input-number__decrease,.el-input-number--medium .el-input-number__increase{width:36px;font-size:14px}.el-input-number--medium .el-input__inner{padding-left:43px;padding-right:43px}.el-input-number--small{width:130px;line-height:30px}.el-input-number--small .el-input-number__decrease,.el-input-number--small .el-input-number__increase{width:32px;font-size:13px}.el-input-number--small .el-input-number__decrease [class*=el-icon],.el-input-number--small .el-input-number__increase [class*=el-icon]{transform:scale(.9)}.el-input-number--small .el-input__inner{padding-left:39px;padding-right:39px}.el-input-number--mini{width:130px;line-height:26px}.el-input-number--mini .el-input-number__decrease,.el-input-number--mini .el-input-number__increase{width:28px;font-size:12px}.el-input-number--mini .el-input-number__decrease [class*=el-icon],.el-input-number--mini .el-input-number__increase [class*=el-icon]{transform:scale(.8)}.el-input-number--mini .el-input__inner{padding-left:35px;padding-right:35px}.el-input-number.is-without-controls .el-input__inner{padding-left:15px;padding-right:15px}.el-input-number.is-controls-right .el-input__inner{padding-left:15px;padding-right:50px}.el-input-number.is-controls-right .el-input-number__decrease,.el-input-number.is-controls-right .el-input-number__increase{height:auto;line-height:19px}.el-input-number.is-controls-right .el-input-number__decrease [class*=el-icon],.el-input-number.is-controls-right .el-input-number__increase [class*=el-icon]{transform:scale(.8)}.el-input-number.is-controls-right .el-input-number__increase{border-radius:0 4px 0 0;border-bottom:1px solid #dcdfe6}.el-input-number.is-controls-right .el-input-number__decrease{right:1px;bottom:1px;top:auto;left:auto;border-right:none;border-left:1px solid #dcdfe6;border-radius:0 0 4px 0}.el-input-number.is-controls-right[class*=medium] [class*=decrease],.el-input-number.is-controls-right[class*=medium] [class*=increase]{line-height:17px}.el-input-number.is-controls-right[class*=small] [class*=decrease],.el-input-number.is-controls-right[class*=small] [class*=increase]{line-height:15px}.el-input-number.is-controls-right[class*=mini] [class*=decrease],.el-input-number.is-controls-right[class*=mini] [class*=increase]{line-height:13px}.el-tooltip:focus:hover,.el-tooltip:focus:not(.focusing){outline-width:0}.el-tooltip__popper{position:absolute;border-radius:4px;padding:10px;z-index:2000;font-size:12px;line-height:1.2;min-width:10px;word-wrap:break-word}.el-tooltip__popper .popper__arrow,.el-tooltip__popper .popper__arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.el-tooltip__popper .popper__arrow{border-width:6px}.el-tooltip__popper .popper__arrow:after{content:" ";border-width:5px}.el-tooltip__popper[x-placement^=top]{margin-bottom:12px}.el-tooltip__popper[x-placement^=top] .popper__arrow{bottom:-6px;border-top-color:#303133;border-bottom-width:0}.el-tooltip__popper[x-placement^=top] .popper__arrow:after{bottom:1px;margin-left:-5px;border-top-color:#303133;border-bottom-width:0}.el-tooltip__popper[x-placement^=bottom]{margin-top:12px}.el-tooltip__popper[x-placement^=bottom] .popper__arrow{top:-6px;border-top-width:0;border-bottom-color:#303133}.el-tooltip__popper[x-placement^=bottom] .popper__arrow:after{top:1px;margin-left:-5px;border-top-width:0;border-bottom-color:#303133}.el-tooltip__popper[x-placement^=right]{margin-left:12px}.el-tooltip__popper[x-placement^=right] .popper__arrow{left:-6px;border-right-color:#303133;border-left-width:0}.el-tooltip__popper[x-placement^=right] .popper__arrow:after{bottom:-5px;left:1px;border-right-color:#303133;border-left-width:0}.el-tooltip__popper[x-placement^=left]{margin-right:12px}.el-tooltip__popper[x-placement^=left] .popper__arrow{right:-6px;border-right-width:0;border-left-color:#303133}.el-tooltip__popper[x-placement^=left] .popper__arrow:after{right:1px;bottom:-5px;margin-left:-5px;border-right-width:0;border-left-color:#303133}.el-tooltip__popper.is-dark{background:#303133;color:#fff}.el-tooltip__popper.is-light{background:#fff;border:1px solid #303133}.el-tooltip__popper.is-light[x-placement^=top] .popper__arrow{border-top-color:#303133}.el-tooltip__popper.is-light[x-placement^=top] .popper__arrow:after{border-top-color:#fff}.el-tooltip__popper.is-light[x-placement^=bottom] .popper__arrow{border-bottom-color:#303133}.el-tooltip__popper.is-light[x-placement^=bottom] .popper__arrow:after{border-bottom-color:#fff}.el-tooltip__popper.is-light[x-placement^=left] .popper__arrow{border-left-color:#303133}.el-tooltip__popper.is-light[x-placement^=left] .popper__arrow:after{border-left-color:#fff}.el-tooltip__popper.is-light[x-placement^=right] .popper__arrow{border-right-color:#303133}.el-tooltip__popper.is-light[x-placement^=right] .popper__arrow:after{border-right-color:#fff}.el-slider:after,.el-slider:before{display:table;content:""}.el-slider:after{clear:both}.el-slider__runway{width:100%;height:6px;margin:16px 0;background-color:#e4e7ed;border-radius:3px;position:relative;cursor:pointer;vertical-align:middle}.el-slider__runway.show-input{margin-right:160px;width:auto}.el-slider__runway.disabled{cursor:default}.el-slider__runway.disabled .el-slider__bar{background-color:#c0c4cc}.el-slider__runway.disabled .el-slider__button{border-color:#c0c4cc}.el-slider__runway.disabled .el-slider__button-wrapper.dragging,.el-slider__runway.disabled .el-slider__button-wrapper.hover,.el-slider__runway.disabled .el-slider__button-wrapper:hover{cursor:not-allowed}.el-slider__runway.disabled .el-slider__button.dragging,.el-slider__runway.disabled .el-slider__button.hover,.el-slider__runway.disabled .el-slider__button:hover{transform:scale(1)}.el-slider__runway.disabled .el-slider__button.dragging,.el-slider__runway.disabled .el-slider__button.hover,.el-slider__runway.disabled .el-slider__button:hover{cursor:not-allowed}.el-slider__input{float:right;margin-top:3px;width:130px}.el-slider__input.el-input-number--mini{margin-top:5px}.el-slider__input.el-input-number--medium{margin-top:0}.el-slider__input.el-input-number--large{margin-top:-2px}.el-slider__bar{height:6px;background-color:#42d885;border-top-left-radius:3px;border-bottom-left-radius:3px;position:absolute}.el-slider__button-wrapper{height:36px;width:36px;position:absolute;z-index:1001;top:-15px;transform:translateX(-50%);background-color:transparent;text-align:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;line-height:normal}.el-slider__button-wrapper:after{content:"";height:100%}.el-slider__button-wrapper .el-tooltip,.el-slider__button-wrapper:after{display:inline-block;vertical-align:middle}.el-slider__button-wrapper.hover,.el-slider__button-wrapper:hover{cursor:grab}.el-slider__button-wrapper.dragging{cursor:grabbing}.el-slider__button{width:16px;height:16px;border:2px solid #42d885;background-color:#fff;border-radius:50%;transition:.2s;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.el-slider__button.dragging,.el-slider__button.hover,.el-slider__button:hover{transform:scale(1.2)}.el-slider__button.hover,.el-slider__button:hover{cursor:grab}.el-slider__button.dragging{cursor:grabbing}.el-slider__stop{position:absolute;height:6px;width:6px;border-radius:100%;background-color:#fff;transform:translateX(-50%)}.el-slider__marks{top:0;left:12px;width:18px;height:100%}.el-slider__marks-text{position:absolute;transform:translateX(-50%);font-size:14px;color:#909399;margin-top:15px}.el-slider.is-vertical{position:relative}.el-slider.is-vertical .el-slider__runway{width:6px;height:100%;margin:0 16px}.el-slider.is-vertical .el-slider__bar{width:6px;height:auto;border-radius:0 0 3px 3px}.el-slider.is-vertical .el-slider__button-wrapper{top:auto;left:-15px;transform:translateY(50%)}.el-slider.is-vertical .el-slider__stop{transform:translateY(50%)}.el-slider.is-vertical.el-slider--with-input{padding-bottom:58px}.el-slider.is-vertical.el-slider--with-input .el-slider__input{overflow:visible;float:none;position:absolute;bottom:22px;width:36px;margin-top:15px}.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input__inner{text-align:center;padding-left:5px;padding-right:5px}.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__decrease,.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__increase{top:32px;margin-top:-1px;border:1px solid #dcdfe6;line-height:20px;box-sizing:border-box;transition:border-color .2s cubic-bezier(.645,.045,.355,1)}.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__decrease{width:18px;right:18px;border-bottom-left-radius:4px}.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__increase{width:19px;border-bottom-right-radius:4px}.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__increase~.el-input .el-input__inner{border-bottom-left-radius:0;border-bottom-right-radius:0}.el-slider.is-vertical.el-slider--with-input .el-slider__input:hover .el-input-number__decrease,.el-slider.is-vertical.el-slider--with-input .el-slider__input:hover .el-input-number__increase{border-color:#c0c4cc}.el-slider.is-vertical.el-slider--with-input .el-slider__input:active .el-input-number__decrease,.el-slider.is-vertical.el-slider--with-input .el-slider__input:active .el-input-number__increase{border-color:#42d885}.el-slider.is-vertical .el-slider__marks-text{margin-top:0;left:15px;transform:translateY(50%)}.el-loading-parent--relative{position:relative!important}.el-loading-parent--hidden{overflow:hidden!important}.el-loading-mask{position:absolute;z-index:2000;background-color:hsla(0,0%,100%,.9);margin:0;top:0;right:0;bottom:0;left:0;transition:opacity .3s}.el-loading-mask.is-fullscreen{position:fixed}.el-loading-mask.is-fullscreen .el-loading-spinner{margin-top:-25px}.el-loading-mask.is-fullscreen .el-loading-spinner .circular{height:50px;width:50px}.el-loading-spinner{top:50%;margin-top:-21px;width:100%;text-align:center;position:absolute}.el-loading-spinner .el-loading-text{color:#42d885;margin:3px 0;font-size:14px}.el-loading-spinner .circular{height:42px;width:42px;animation:loading-rotate 2s linear infinite}.el-loading-spinner .path{animation:loading-dash 1.5s ease-in-out infinite;stroke-dasharray:90,150;stroke-dashoffset:0;stroke-width:2;stroke:#42d885;stroke-linecap:round}.el-loading-spinner i{color:#42d885}.el-loading-fade-enter,.el-loading-fade-leave-active{opacity:0}@keyframes loading-rotate{to{transform:rotate(1turn)}}@keyframes loading-dash{0%{stroke-dasharray:1,200;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-40px}to{stroke-dasharray:90,150;stroke-dashoffset:-120px}}.el-row{position:relative;box-sizing:border-box}.el-row:after,.el-row:before{display:table;content:""}.el-row:after{clear:both}.el-row--flex{display:-ms-flexbox;display:flex}.el-row--flex:after,.el-row--flex:before{display:none}.el-row--flex.is-justify-center{-ms-flex-pack:center;justify-content:center}.el-row--flex.is-justify-end{-ms-flex-pack:end;justify-content:flex-end}.el-row--flex.is-justify-space-between{-ms-flex-pack:justify;justify-content:space-between}.el-row--flex.is-justify-space-around{-ms-flex-pack:distribute;justify-content:space-around}.el-row--flex.is-align-middle{-ms-flex-align:center;align-items:center}.el-row--flex.is-align-bottom{-ms-flex-align:end;align-items:flex-end}[class*=el-col-]{float:left;box-sizing:border-box}.el-col-0{display:none;width:0}.el-col-offset-0{margin-left:0}.el-col-pull-0{position:relative;right:0}.el-col-push-0{position:relative;left:0}.el-col-1{width:4.16667%}.el-col-offset-1{margin-left:4.16667%}.el-col-pull-1{position:relative;right:4.16667%}.el-col-push-1{position:relative;left:4.16667%}.el-col-2{width:8.33333%}.el-col-offset-2{margin-left:8.33333%}.el-col-pull-2{position:relative;right:8.33333%}.el-col-push-2{position:relative;left:8.33333%}.el-col-3{width:12.5%}.el-col-offset-3{margin-left:12.5%}.el-col-pull-3{position:relative;right:12.5%}.el-col-push-3{position:relative;left:12.5%}.el-col-4{width:16.66667%}.el-col-offset-4{margin-left:16.66667%}.el-col-pull-4{position:relative;right:16.66667%}.el-col-push-4{position:relative;left:16.66667%}.el-col-5{width:20.83333%}.el-col-offset-5{margin-left:20.83333%}.el-col-pull-5{position:relative;right:20.83333%}.el-col-push-5{position:relative;left:20.83333%}.el-col-6{width:25%}.el-col-offset-6{margin-left:25%}.el-col-pull-6{position:relative;right:25%}.el-col-push-6{position:relative;left:25%}.el-col-7{width:29.16667%}.el-col-offset-7{margin-left:29.16667%}.el-col-pull-7{position:relative;right:29.16667%}.el-col-push-7{position:relative;left:29.16667%}.el-col-8{width:33.33333%}.el-col-offset-8{margin-left:33.33333%}.el-col-pull-8{position:relative;right:33.33333%}.el-col-push-8{position:relative;left:33.33333%}.el-col-9{width:37.5%}.el-col-offset-9{margin-left:37.5%}.el-col-pull-9{position:relative;right:37.5%}.el-col-push-9{position:relative;left:37.5%}.el-col-10{width:41.66667%}.el-col-offset-10{margin-left:41.66667%}.el-col-pull-10{position:relative;right:41.66667%}.el-col-push-10{position:relative;left:41.66667%}.el-col-11{width:45.83333%}.el-col-offset-11{margin-left:45.83333%}.el-col-pull-11{position:relative;right:45.83333%}.el-col-push-11{position:relative;left:45.83333%}.el-col-12{width:50%}.el-col-offset-12{margin-left:50%}.el-col-pull-12{position:relative;right:50%}.el-col-push-12{position:relative;left:50%}.el-col-13{width:54.16667%}.el-col-offset-13{margin-left:54.16667%}.el-col-pull-13{position:relative;right:54.16667%}.el-col-push-13{position:relative;left:54.16667%}.el-col-14{width:58.33333%}.el-col-offset-14{margin-left:58.33333%}.el-col-pull-14{position:relative;right:58.33333%}.el-col-push-14{position:relative;left:58.33333%}.el-col-15{width:62.5%}.el-col-offset-15{margin-left:62.5%}.el-col-pull-15{position:relative;right:62.5%}.el-col-push-15{position:relative;left:62.5%}.el-col-16{width:66.66667%}.el-col-offset-16{margin-left:66.66667%}.el-col-pull-16{position:relative;right:66.66667%}.el-col-push-16{position:relative;left:66.66667%}.el-col-17{width:70.83333%}.el-col-offset-17{margin-left:70.83333%}.el-col-pull-17{position:relative;right:70.83333%}.el-col-push-17{position:relative;left:70.83333%}.el-col-18{width:75%}.el-col-offset-18{margin-left:75%}.el-col-pull-18{position:relative;right:75%}.el-col-push-18{position:relative;left:75%}.el-col-19{width:79.16667%}.el-col-offset-19{margin-left:79.16667%}.el-col-pull-19{position:relative;right:79.16667%}.el-col-push-19{position:relative;left:79.16667%}.el-col-20{width:83.33333%}.el-col-offset-20{margin-left:83.33333%}.el-col-pull-20{position:relative;right:83.33333%}.el-col-push-20{position:relative;left:83.33333%}.el-col-21{width:87.5%}.el-col-offset-21{margin-left:87.5%}.el-col-pull-21{position:relative;right:87.5%}.el-col-push-21{position:relative;left:87.5%}.el-col-22{width:91.66667%}.el-col-offset-22{margin-left:91.66667%}.el-col-pull-22{position:relative;right:91.66667%}.el-col-push-22{position:relative;left:91.66667%}.el-col-23{width:95.83333%}.el-col-offset-23{margin-left:95.83333%}.el-col-pull-23{position:relative;right:95.83333%}.el-col-push-23{position:relative;left:95.83333%}.el-col-24{width:100%}.el-col-offset-24{margin-left:100%}.el-col-pull-24{position:relative;right:100%}.el-col-push-24{position:relative;left:100%}@media only screen and (max-width:767px){.el-col-xs-0{display:none;width:0}.el-col-xs-offset-0{margin-left:0}.el-col-xs-pull-0{position:relative;right:0}.el-col-xs-push-0{position:relative;left:0}.el-col-xs-1{width:4.16667%}.el-col-xs-offset-1{margin-left:4.16667%}.el-col-xs-pull-1{position:relative;right:4.16667%}.el-col-xs-push-1{position:relative;left:4.16667%}.el-col-xs-2{width:8.33333%}.el-col-xs-offset-2{margin-left:8.33333%}.el-col-xs-pull-2{position:relative;right:8.33333%}.el-col-xs-push-2{position:relative;left:8.33333%}.el-col-xs-3{width:12.5%}.el-col-xs-offset-3{margin-left:12.5%}.el-col-xs-pull-3{position:relative;right:12.5%}.el-col-xs-push-3{position:relative;left:12.5%}.el-col-xs-4{width:16.66667%}.el-col-xs-offset-4{margin-left:16.66667%}.el-col-xs-pull-4{position:relative;right:16.66667%}.el-col-xs-push-4{position:relative;left:16.66667%}.el-col-xs-5{width:20.83333%}.el-col-xs-offset-5{margin-left:20.83333%}.el-col-xs-pull-5{position:relative;right:20.83333%}.el-col-xs-push-5{position:relative;left:20.83333%}.el-col-xs-6{width:25%}.el-col-xs-offset-6{margin-left:25%}.el-col-xs-pull-6{position:relative;right:25%}.el-col-xs-push-6{position:relative;left:25%}.el-col-xs-7{width:29.16667%}.el-col-xs-offset-7{margin-left:29.16667%}.el-col-xs-pull-7{position:relative;right:29.16667%}.el-col-xs-push-7{position:relative;left:29.16667%}.el-col-xs-8{width:33.33333%}.el-col-xs-offset-8{margin-left:33.33333%}.el-col-xs-pull-8{position:relative;right:33.33333%}.el-col-xs-push-8{position:relative;left:33.33333%}.el-col-xs-9{width:37.5%}.el-col-xs-offset-9{margin-left:37.5%}.el-col-xs-pull-9{position:relative;right:37.5%}.el-col-xs-push-9{position:relative;left:37.5%}.el-col-xs-10{width:41.66667%}.el-col-xs-offset-10{margin-left:41.66667%}.el-col-xs-pull-10{position:relative;right:41.66667%}.el-col-xs-push-10{position:relative;left:41.66667%}.el-col-xs-11{width:45.83333%}.el-col-xs-offset-11{margin-left:45.83333%}.el-col-xs-pull-11{position:relative;right:45.83333%}.el-col-xs-push-11{position:relative;left:45.83333%}.el-col-xs-12{width:50%}.el-col-xs-offset-12{margin-left:50%}.el-col-xs-pull-12{position:relative;right:50%}.el-col-xs-push-12{position:relative;left:50%}.el-col-xs-13{width:54.16667%}.el-col-xs-offset-13{margin-left:54.16667%}.el-col-xs-pull-13{position:relative;right:54.16667%}.el-col-xs-push-13{position:relative;left:54.16667%}.el-col-xs-14{width:58.33333%}.el-col-xs-offset-14{margin-left:58.33333%}.el-col-xs-pull-14{position:relative;right:58.33333%}.el-col-xs-push-14{position:relative;left:58.33333%}.el-col-xs-15{width:62.5%}.el-col-xs-offset-15{margin-left:62.5%}.el-col-xs-pull-15{position:relative;right:62.5%}.el-col-xs-push-15{position:relative;left:62.5%}.el-col-xs-16{width:66.66667%}.el-col-xs-offset-16{margin-left:66.66667%}.el-col-xs-pull-16{position:relative;right:66.66667%}.el-col-xs-push-16{position:relative;left:66.66667%}.el-col-xs-17{width:70.83333%}.el-col-xs-offset-17{margin-left:70.83333%}.el-col-xs-pull-17{position:relative;right:70.83333%}.el-col-xs-push-17{position:relative;left:70.83333%}.el-col-xs-18{width:75%}.el-col-xs-offset-18{margin-left:75%}.el-col-xs-pull-18{position:relative;right:75%}.el-col-xs-push-18{position:relative;left:75%}.el-col-xs-19{width:79.16667%}.el-col-xs-offset-19{margin-left:79.16667%}.el-col-xs-pull-19{position:relative;right:79.16667%}.el-col-xs-push-19{position:relative;left:79.16667%}.el-col-xs-20{width:83.33333%}.el-col-xs-offset-20{margin-left:83.33333%}.el-col-xs-pull-20{position:relative;right:83.33333%}.el-col-xs-push-20{position:relative;left:83.33333%}.el-col-xs-21{width:87.5%}.el-col-xs-offset-21{margin-left:87.5%}.el-col-xs-pull-21{position:relative;right:87.5%}.el-col-xs-push-21{position:relative;left:87.5%}.el-col-xs-22{width:91.66667%}.el-col-xs-offset-22{margin-left:91.66667%}.el-col-xs-pull-22{position:relative;right:91.66667%}.el-col-xs-push-22{position:relative;left:91.66667%}.el-col-xs-23{width:95.83333%}.el-col-xs-offset-23{margin-left:95.83333%}.el-col-xs-pull-23{position:relative;right:95.83333%}.el-col-xs-push-23{position:relative;left:95.83333%}.el-col-xs-24{width:100%}.el-col-xs-offset-24{margin-left:100%}.el-col-xs-pull-24{position:relative;right:100%}.el-col-xs-push-24{position:relative;left:100%}}@media only screen and (min-width:768px){.el-col-sm-0{display:none;width:0}.el-col-sm-offset-0{margin-left:0}.el-col-sm-pull-0{position:relative;right:0}.el-col-sm-push-0{position:relative;left:0}.el-col-sm-1{width:4.16667%}.el-col-sm-offset-1{margin-left:4.16667%}.el-col-sm-pull-1{position:relative;right:4.16667%}.el-col-sm-push-1{position:relative;left:4.16667%}.el-col-sm-2{width:8.33333%}.el-col-sm-offset-2{margin-left:8.33333%}.el-col-sm-pull-2{position:relative;right:8.33333%}.el-col-sm-push-2{position:relative;left:8.33333%}.el-col-sm-3{width:12.5%}.el-col-sm-offset-3{margin-left:12.5%}.el-col-sm-pull-3{position:relative;right:12.5%}.el-col-sm-push-3{position:relative;left:12.5%}.el-col-sm-4{width:16.66667%}.el-col-sm-offset-4{margin-left:16.66667%}.el-col-sm-pull-4{position:relative;right:16.66667%}.el-col-sm-push-4{position:relative;left:16.66667%}.el-col-sm-5{width:20.83333%}.el-col-sm-offset-5{margin-left:20.83333%}.el-col-sm-pull-5{position:relative;right:20.83333%}.el-col-sm-push-5{position:relative;left:20.83333%}.el-col-sm-6{width:25%}.el-col-sm-offset-6{margin-left:25%}.el-col-sm-pull-6{position:relative;right:25%}.el-col-sm-push-6{position:relative;left:25%}.el-col-sm-7{width:29.16667%}.el-col-sm-offset-7{margin-left:29.16667%}.el-col-sm-pull-7{position:relative;right:29.16667%}.el-col-sm-push-7{position:relative;left:29.16667%}.el-col-sm-8{width:33.33333%}.el-col-sm-offset-8{margin-left:33.33333%}.el-col-sm-pull-8{position:relative;right:33.33333%}.el-col-sm-push-8{position:relative;left:33.33333%}.el-col-sm-9{width:37.5%}.el-col-sm-offset-9{margin-left:37.5%}.el-col-sm-pull-9{position:relative;right:37.5%}.el-col-sm-push-9{position:relative;left:37.5%}.el-col-sm-10{width:41.66667%}.el-col-sm-offset-10{margin-left:41.66667%}.el-col-sm-pull-10{position:relative;right:41.66667%}.el-col-sm-push-10{position:relative;left:41.66667%}.el-col-sm-11{width:45.83333%}.el-col-sm-offset-11{margin-left:45.83333%}.el-col-sm-pull-11{position:relative;right:45.83333%}.el-col-sm-push-11{position:relative;left:45.83333%}.el-col-sm-12{width:50%}.el-col-sm-offset-12{margin-left:50%}.el-col-sm-pull-12{position:relative;right:50%}.el-col-sm-push-12{position:relative;left:50%}.el-col-sm-13{width:54.16667%}.el-col-sm-offset-13{margin-left:54.16667%}.el-col-sm-pull-13{position:relative;right:54.16667%}.el-col-sm-push-13{position:relative;left:54.16667%}.el-col-sm-14{width:58.33333%}.el-col-sm-offset-14{margin-left:58.33333%}.el-col-sm-pull-14{position:relative;right:58.33333%}.el-col-sm-push-14{position:relative;left:58.33333%}.el-col-sm-15{width:62.5%}.el-col-sm-offset-15{margin-left:62.5%}.el-col-sm-pull-15{position:relative;right:62.5%}.el-col-sm-push-15{position:relative;left:62.5%}.el-col-sm-16{width:66.66667%}.el-col-sm-offset-16{margin-left:66.66667%}.el-col-sm-pull-16{position:relative;right:66.66667%}.el-col-sm-push-16{position:relative;left:66.66667%}.el-col-sm-17{width:70.83333%}.el-col-sm-offset-17{margin-left:70.83333%}.el-col-sm-pull-17{position:relative;right:70.83333%}.el-col-sm-push-17{position:relative;left:70.83333%}.el-col-sm-18{width:75%}.el-col-sm-offset-18{margin-left:75%}.el-col-sm-pull-18{position:relative;right:75%}.el-col-sm-push-18{position:relative;left:75%}.el-col-sm-19{width:79.16667%}.el-col-sm-offset-19{margin-left:79.16667%}.el-col-sm-pull-19{position:relative;right:79.16667%}.el-col-sm-push-19{position:relative;left:79.16667%}.el-col-sm-20{width:83.33333%}.el-col-sm-offset-20{margin-left:83.33333%}.el-col-sm-pull-20{position:relative;right:83.33333%}.el-col-sm-push-20{position:relative;left:83.33333%}.el-col-sm-21{width:87.5%}.el-col-sm-offset-21{margin-left:87.5%}.el-col-sm-pull-21{position:relative;right:87.5%}.el-col-sm-push-21{position:relative;left:87.5%}.el-col-sm-22{width:91.66667%}.el-col-sm-offset-22{margin-left:91.66667%}.el-col-sm-pull-22{position:relative;right:91.66667%}.el-col-sm-push-22{position:relative;left:91.66667%}.el-col-sm-23{width:95.83333%}.el-col-sm-offset-23{margin-left:95.83333%}.el-col-sm-pull-23{position:relative;right:95.83333%}.el-col-sm-push-23{position:relative;left:95.83333%}.el-col-sm-24{width:100%}.el-col-sm-offset-24{margin-left:100%}.el-col-sm-pull-24{position:relative;right:100%}.el-col-sm-push-24{position:relative;left:100%}}@media only screen and (min-width:992px){.el-col-md-0{display:none;width:0}.el-col-md-offset-0{margin-left:0}.el-col-md-pull-0{position:relative;right:0}.el-col-md-push-0{position:relative;left:0}.el-col-md-1{width:4.16667%}.el-col-md-offset-1{margin-left:4.16667%}.el-col-md-pull-1{position:relative;right:4.16667%}.el-col-md-push-1{position:relative;left:4.16667%}.el-col-md-2{width:8.33333%}.el-col-md-offset-2{margin-left:8.33333%}.el-col-md-pull-2{position:relative;right:8.33333%}.el-col-md-push-2{position:relative;left:8.33333%}.el-col-md-3{width:12.5%}.el-col-md-offset-3{margin-left:12.5%}.el-col-md-pull-3{position:relative;right:12.5%}.el-col-md-push-3{position:relative;left:12.5%}.el-col-md-4{width:16.66667%}.el-col-md-offset-4{margin-left:16.66667%}.el-col-md-pull-4{position:relative;right:16.66667%}.el-col-md-push-4{position:relative;left:16.66667%}.el-col-md-5{width:20.83333%}.el-col-md-offset-5{margin-left:20.83333%}.el-col-md-pull-5{position:relative;right:20.83333%}.el-col-md-push-5{position:relative;left:20.83333%}.el-col-md-6{width:25%}.el-col-md-offset-6{margin-left:25%}.el-col-md-pull-6{position:relative;right:25%}.el-col-md-push-6{position:relative;left:25%}.el-col-md-7{width:29.16667%}.el-col-md-offset-7{margin-left:29.16667%}.el-col-md-pull-7{position:relative;right:29.16667%}.el-col-md-push-7{position:relative;left:29.16667%}.el-col-md-8{width:33.33333%}.el-col-md-offset-8{margin-left:33.33333%}.el-col-md-pull-8{position:relative;right:33.33333%}.el-col-md-push-8{position:relative;left:33.33333%}.el-col-md-9{width:37.5%}.el-col-md-offset-9{margin-left:37.5%}.el-col-md-pull-9{position:relative;right:37.5%}.el-col-md-push-9{position:relative;left:37.5%}.el-col-md-10{width:41.66667%}.el-col-md-offset-10{margin-left:41.66667%}.el-col-md-pull-10{position:relative;right:41.66667%}.el-col-md-push-10{position:relative;left:41.66667%}.el-col-md-11{width:45.83333%}.el-col-md-offset-11{margin-left:45.83333%}.el-col-md-pull-11{position:relative;right:45.83333%}.el-col-md-push-11{position:relative;left:45.83333%}.el-col-md-12{width:50%}.el-col-md-offset-12{margin-left:50%}.el-col-md-pull-12{position:relative;right:50%}.el-col-md-push-12{position:relative;left:50%}.el-col-md-13{width:54.16667%}.el-col-md-offset-13{margin-left:54.16667%}.el-col-md-pull-13{position:relative;right:54.16667%}.el-col-md-push-13{position:relative;left:54.16667%}.el-col-md-14{width:58.33333%}.el-col-md-offset-14{margin-left:58.33333%}.el-col-md-pull-14{position:relative;right:58.33333%}.el-col-md-push-14{position:relative;left:58.33333%}.el-col-md-15{width:62.5%}.el-col-md-offset-15{margin-left:62.5%}.el-col-md-pull-15{position:relative;right:62.5%}.el-col-md-push-15{position:relative;left:62.5%}.el-col-md-16{width:66.66667%}.el-col-md-offset-16{margin-left:66.66667%}.el-col-md-pull-16{position:relative;right:66.66667%}.el-col-md-push-16{position:relative;left:66.66667%}.el-col-md-17{width:70.83333%}.el-col-md-offset-17{margin-left:70.83333%}.el-col-md-pull-17{position:relative;right:70.83333%}.el-col-md-push-17{position:relative;left:70.83333%}.el-col-md-18{width:75%}.el-col-md-offset-18{margin-left:75%}.el-col-md-pull-18{position:relative;right:75%}.el-col-md-push-18{position:relative;left:75%}.el-col-md-19{width:79.16667%}.el-col-md-offset-19{margin-left:79.16667%}.el-col-md-pull-19{position:relative;right:79.16667%}.el-col-md-push-19{position:relative;left:79.16667%}.el-col-md-20{width:83.33333%}.el-col-md-offset-20{margin-left:83.33333%}.el-col-md-pull-20{position:relative;right:83.33333%}.el-col-md-push-20{position:relative;left:83.33333%}.el-col-md-21{width:87.5%}.el-col-md-offset-21{margin-left:87.5%}.el-col-md-pull-21{position:relative;right:87.5%}.el-col-md-push-21{position:relative;left:87.5%}.el-col-md-22{width:91.66667%}.el-col-md-offset-22{margin-left:91.66667%}.el-col-md-pull-22{position:relative;right:91.66667%}.el-col-md-push-22{position:relative;left:91.66667%}.el-col-md-23{width:95.83333%}.el-col-md-offset-23{margin-left:95.83333%}.el-col-md-pull-23{position:relative;right:95.83333%}.el-col-md-push-23{position:relative;left:95.83333%}.el-col-md-24{width:100%}.el-col-md-offset-24{margin-left:100%}.el-col-md-pull-24{position:relative;right:100%}.el-col-md-push-24{position:relative;left:100%}}@media only screen and (min-width:1200px){.el-col-lg-0{display:none;width:0}.el-col-lg-offset-0{margin-left:0}.el-col-lg-pull-0{position:relative;right:0}.el-col-lg-push-0{position:relative;left:0}.el-col-lg-1{width:4.16667%}.el-col-lg-offset-1{margin-left:4.16667%}.el-col-lg-pull-1{position:relative;right:4.16667%}.el-col-lg-push-1{position:relative;left:4.16667%}.el-col-lg-2{width:8.33333%}.el-col-lg-offset-2{margin-left:8.33333%}.el-col-lg-pull-2{position:relative;right:8.33333%}.el-col-lg-push-2{position:relative;left:8.33333%}.el-col-lg-3{width:12.5%}.el-col-lg-offset-3{margin-left:12.5%}.el-col-lg-pull-3{position:relative;right:12.5%}.el-col-lg-push-3{position:relative;left:12.5%}.el-col-lg-4{width:16.66667%}.el-col-lg-offset-4{margin-left:16.66667%}.el-col-lg-pull-4{position:relative;right:16.66667%}.el-col-lg-push-4{position:relative;left:16.66667%}.el-col-lg-5{width:20.83333%}.el-col-lg-offset-5{margin-left:20.83333%}.el-col-lg-pull-5{position:relative;right:20.83333%}.el-col-lg-push-5{position:relative;left:20.83333%}.el-col-lg-6{width:25%}.el-col-lg-offset-6{margin-left:25%}.el-col-lg-pull-6{position:relative;right:25%}.el-col-lg-push-6{position:relative;left:25%}.el-col-lg-7{width:29.16667%}.el-col-lg-offset-7{margin-left:29.16667%}.el-col-lg-pull-7{position:relative;right:29.16667%}.el-col-lg-push-7{position:relative;left:29.16667%}.el-col-lg-8{width:33.33333%}.el-col-lg-offset-8{margin-left:33.33333%}.el-col-lg-pull-8{position:relative;right:33.33333%}.el-col-lg-push-8{position:relative;left:33.33333%}.el-col-lg-9{width:37.5%}.el-col-lg-offset-9{margin-left:37.5%}.el-col-lg-pull-9{position:relative;right:37.5%}.el-col-lg-push-9{position:relative;left:37.5%}.el-col-lg-10{width:41.66667%}.el-col-lg-offset-10{margin-left:41.66667%}.el-col-lg-pull-10{position:relative;right:41.66667%}.el-col-lg-push-10{position:relative;left:41.66667%}.el-col-lg-11{width:45.83333%}.el-col-lg-offset-11{margin-left:45.83333%}.el-col-lg-pull-11{position:relative;right:45.83333%}.el-col-lg-push-11{position:relative;left:45.83333%}.el-col-lg-12{width:50%}.el-col-lg-offset-12{margin-left:50%}.el-col-lg-pull-12{position:relative;right:50%}.el-col-lg-push-12{position:relative;left:50%}.el-col-lg-13{width:54.16667%}.el-col-lg-offset-13{margin-left:54.16667%}.el-col-lg-pull-13{position:relative;right:54.16667%}.el-col-lg-push-13{position:relative;left:54.16667%}.el-col-lg-14{width:58.33333%}.el-col-lg-offset-14{margin-left:58.33333%}.el-col-lg-pull-14{position:relative;right:58.33333%}.el-col-lg-push-14{position:relative;left:58.33333%}.el-col-lg-15{width:62.5%}.el-col-lg-offset-15{margin-left:62.5%}.el-col-lg-pull-15{position:relative;right:62.5%}.el-col-lg-push-15{position:relative;left:62.5%}.el-col-lg-16{width:66.66667%}.el-col-lg-offset-16{margin-left:66.66667%}.el-col-lg-pull-16{position:relative;right:66.66667%}.el-col-lg-push-16{position:relative;left:66.66667%}.el-col-lg-17{width:70.83333%}.el-col-lg-offset-17{margin-left:70.83333%}.el-col-lg-pull-17{position:relative;right:70.83333%}.el-col-lg-push-17{position:relative;left:70.83333%}.el-col-lg-18{width:75%}.el-col-lg-offset-18{margin-left:75%}.el-col-lg-pull-18{position:relative;right:75%}.el-col-lg-push-18{position:relative;left:75%}.el-col-lg-19{width:79.16667%}.el-col-lg-offset-19{margin-left:79.16667%}.el-col-lg-pull-19{position:relative;right:79.16667%}.el-col-lg-push-19{position:relative;left:79.16667%}.el-col-lg-20{width:83.33333%}.el-col-lg-offset-20{margin-left:83.33333%}.el-col-lg-pull-20{position:relative;right:83.33333%}.el-col-lg-push-20{position:relative;left:83.33333%}.el-col-lg-21{width:87.5%}.el-col-lg-offset-21{margin-left:87.5%}.el-col-lg-pull-21{position:relative;right:87.5%}.el-col-lg-push-21{position:relative;left:87.5%}.el-col-lg-22{width:91.66667%}.el-col-lg-offset-22{margin-left:91.66667%}.el-col-lg-pull-22{position:relative;right:91.66667%}.el-col-lg-push-22{position:relative;left:91.66667%}.el-col-lg-23{width:95.83333%}.el-col-lg-offset-23{margin-left:95.83333%}.el-col-lg-pull-23{position:relative;right:95.83333%}.el-col-lg-push-23{position:relative;left:95.83333%}.el-col-lg-24{width:100%}.el-col-lg-offset-24{margin-left:100%}.el-col-lg-pull-24{position:relative;right:100%}.el-col-lg-push-24{position:relative;left:100%}}@media only screen and (min-width:1920px){.el-col-xl-0{display:none;width:0}.el-col-xl-offset-0{margin-left:0}.el-col-xl-pull-0{position:relative;right:0}.el-col-xl-push-0{position:relative;left:0}.el-col-xl-1{width:4.16667%}.el-col-xl-offset-1{margin-left:4.16667%}.el-col-xl-pull-1{position:relative;right:4.16667%}.el-col-xl-push-1{position:relative;left:4.16667%}.el-col-xl-2{width:8.33333%}.el-col-xl-offset-2{margin-left:8.33333%}.el-col-xl-pull-2{position:relative;right:8.33333%}.el-col-xl-push-2{position:relative;left:8.33333%}.el-col-xl-3{width:12.5%}.el-col-xl-offset-3{margin-left:12.5%}.el-col-xl-pull-3{position:relative;right:12.5%}.el-col-xl-push-3{position:relative;left:12.5%}.el-col-xl-4{width:16.66667%}.el-col-xl-offset-4{margin-left:16.66667%}.el-col-xl-pull-4{position:relative;right:16.66667%}.el-col-xl-push-4{position:relative;left:16.66667%}.el-col-xl-5{width:20.83333%}.el-col-xl-offset-5{margin-left:20.83333%}.el-col-xl-pull-5{position:relative;right:20.83333%}.el-col-xl-push-5{position:relative;left:20.83333%}.el-col-xl-6{width:25%}.el-col-xl-offset-6{margin-left:25%}.el-col-xl-pull-6{position:relative;right:25%}.el-col-xl-push-6{position:relative;left:25%}.el-col-xl-7{width:29.16667%}.el-col-xl-offset-7{margin-left:29.16667%}.el-col-xl-pull-7{position:relative;right:29.16667%}.el-col-xl-push-7{position:relative;left:29.16667%}.el-col-xl-8{width:33.33333%}.el-col-xl-offset-8{margin-left:33.33333%}.el-col-xl-pull-8{position:relative;right:33.33333%}.el-col-xl-push-8{position:relative;left:33.33333%}.el-col-xl-9{width:37.5%}.el-col-xl-offset-9{margin-left:37.5%}.el-col-xl-pull-9{position:relative;right:37.5%}.el-col-xl-push-9{position:relative;left:37.5%}.el-col-xl-10{width:41.66667%}.el-col-xl-offset-10{margin-left:41.66667%}.el-col-xl-pull-10{position:relative;right:41.66667%}.el-col-xl-push-10{position:relative;left:41.66667%}.el-col-xl-11{width:45.83333%}.el-col-xl-offset-11{margin-left:45.83333%}.el-col-xl-pull-11{position:relative;right:45.83333%}.el-col-xl-push-11{position:relative;left:45.83333%}.el-col-xl-12{width:50%}.el-col-xl-offset-12{margin-left:50%}.el-col-xl-pull-12{position:relative;right:50%}.el-col-xl-push-12{position:relative;left:50%}.el-col-xl-13{width:54.16667%}.el-col-xl-offset-13{margin-left:54.16667%}.el-col-xl-pull-13{position:relative;right:54.16667%}.el-col-xl-push-13{position:relative;left:54.16667%}.el-col-xl-14{width:58.33333%}.el-col-xl-offset-14{margin-left:58.33333%}.el-col-xl-pull-14{position:relative;right:58.33333%}.el-col-xl-push-14{position:relative;left:58.33333%}.el-col-xl-15{width:62.5%}.el-col-xl-offset-15{margin-left:62.5%}.el-col-xl-pull-15{position:relative;right:62.5%}.el-col-xl-push-15{position:relative;left:62.5%}.el-col-xl-16{width:66.66667%}.el-col-xl-offset-16{margin-left:66.66667%}.el-col-xl-pull-16{position:relative;right:66.66667%}.el-col-xl-push-16{position:relative;left:66.66667%}.el-col-xl-17{width:70.83333%}.el-col-xl-offset-17{margin-left:70.83333%}.el-col-xl-pull-17{position:relative;right:70.83333%}.el-col-xl-push-17{position:relative;left:70.83333%}.el-col-xl-18{width:75%}.el-col-xl-offset-18{margin-left:75%}.el-col-xl-pull-18{position:relative;right:75%}.el-col-xl-push-18{position:relative;left:75%}.el-col-xl-19{width:79.16667%}.el-col-xl-offset-19{margin-left:79.16667%}.el-col-xl-pull-19{position:relative;right:79.16667%}.el-col-xl-push-19{position:relative;left:79.16667%}.el-col-xl-20{width:83.33333%}.el-col-xl-offset-20{margin-left:83.33333%}.el-col-xl-pull-20{position:relative;right:83.33333%}.el-col-xl-push-20{position:relative;left:83.33333%}.el-col-xl-21{width:87.5%}.el-col-xl-offset-21{margin-left:87.5%}.el-col-xl-pull-21{position:relative;right:87.5%}.el-col-xl-push-21{position:relative;left:87.5%}.el-col-xl-22{width:91.66667%}.el-col-xl-offset-22{margin-left:91.66667%}.el-col-xl-pull-22{position:relative;right:91.66667%}.el-col-xl-push-22{position:relative;left:91.66667%}.el-col-xl-23{width:95.83333%}.el-col-xl-offset-23{margin-left:95.83333%}.el-col-xl-pull-23{position:relative;right:95.83333%}.el-col-xl-push-23{position:relative;left:95.83333%}.el-col-xl-24{width:100%}.el-col-xl-offset-24{margin-left:100%}.el-col-xl-pull-24{position:relative;right:100%}.el-col-xl-push-24{position:relative;left:100%}}.el-upload{display:inline-block;text-align:center;cursor:pointer;outline:none}.el-upload__input{display:none}.el-upload__tip{font-size:12px;color:#606266;margin-top:7px}.el-upload iframe{position:absolute;z-index:-1;top:0;left:0;opacity:0;filter:alpha(opacity=0)}.el-upload--picture-card{background-color:#fbfdff;border:1px dashed #c0ccda;border-radius:6px;box-sizing:border-box;width:148px;height:148px;cursor:pointer;line-height:146px;vertical-align:top}.el-upload--picture-card i{font-size:28px;color:#8c939d}.el-upload--picture-card:hover,.el-upload:focus{border-color:#42d885;color:#42d885}.el-upload:focus .el-upload-dragger{border-color:#42d885}.el-upload-dragger{background-color:#fff;border:1px dashed #d9d9d9;border-radius:6px;box-sizing:border-box;width:360px;height:180px;text-align:center;cursor:pointer;position:relative;overflow:hidden}.el-upload-dragger .el-icon-upload{font-size:67px;color:#c0c4cc;margin:40px 0 16px;line-height:50px}.el-upload-dragger+.el-upload__tip{text-align:center}.el-upload-dragger~.el-upload__files{border-top:1px solid #dcdfe6;margin-top:7px;padding-top:5px}.el-upload-dragger .el-upload__text{color:#606266;font-size:14px;text-align:center}.el-upload-dragger .el-upload__text em{color:#42d885;font-style:normal}.el-upload-dragger:hover{border-color:#42d885}.el-upload-dragger.is-dragover{background-color:rgba(32,159,255,.06);border:2px dashed #42d885}.el-upload-list{margin:0;padding:0;list-style:none}.el-upload-list__item{transition:all .5s cubic-bezier(.55,0,.1,1);font-size:14px;color:#606266;line-height:1.8;margin-top:5px;position:relative;box-sizing:border-box;border-radius:4px;width:100%}.el-upload-list__item .el-progress{position:absolute;top:20px;width:100%}.el-upload-list__item .el-progress__text{position:absolute;right:0;top:-13px}.el-upload-list__item .el-progress-bar{margin-right:0;padding-right:0}.el-upload-list__item:first-child{margin-top:10px}.el-upload-list__item .el-icon-upload-success{color:#42d885}.el-upload-list__item .el-icon-close{display:none;position:absolute;top:5px;right:5px;cursor:pointer;opacity:.75;color:#606266}.el-upload-list__item .el-icon-close:hover{opacity:1}.el-upload-list__item .el-icon-close-tip{display:none;position:absolute;top:5px;right:5px;font-size:12px;cursor:pointer;opacity:1;color:#42d885}.el-upload-list__item:hover{background-color:#f5f7fa}.el-upload-list__item:hover .el-icon-close{display:inline-block}.el-upload-list__item:hover .el-progress__text{display:none}.el-upload-list__item.is-success .el-upload-list__item-status-label{display:block}.el-upload-list__item.is-success .el-upload-list__item-name:focus,.el-upload-list__item.is-success .el-upload-list__item-name:hover{color:#42d885;cursor:pointer}.el-upload-list__item.is-success:focus:not(:hover) .el-icon-close-tip{display:inline-block}.el-upload-list__item.is-success:active,.el-upload-list__item.is-success:not(.focusing):focus{outline-width:0}.el-upload-list__item.is-success:active .el-icon-close-tip,.el-upload-list__item.is-success:focus .el-upload-list__item-status-label,.el-upload-list__item.is-success:hover .el-upload-list__item-status-label,.el-upload-list__item.is-success:not(.focusing):focus .el-icon-close-tip{display:none}.el-upload-list.is-disabled .el-upload-list__item:hover .el-upload-list__item-status-label{display:block}.el-upload-list__item-name{color:#606266;display:block;margin-right:40px;overflow:hidden;padding-left:4px;text-overflow:ellipsis;transition:color .3s;white-space:nowrap}.el-upload-list__item-name [class^=el-icon]{height:100%;margin-right:7px;color:#909399;line-height:inherit}.el-upload-list__item-status-label{position:absolute;right:5px;top:0;line-height:inherit;display:none}.el-upload-list__item-delete{position:absolute;right:10px;top:0;font-size:12px;color:#606266;display:none}.el-upload-list__item-delete:hover{color:#42d885}.el-upload-list--picture-card{margin:0;display:inline;vertical-align:top}.el-upload-list--picture-card .el-upload-list__item{overflow:hidden;background-color:#fff;border:1px solid #c0ccda;border-radius:6px;box-sizing:border-box;width:148px;height:148px;margin:0 8px 8px 0;display:inline-block}.el-upload-list--picture-card .el-upload-list__item .el-icon-check,.el-upload-list--picture-card .el-upload-list__item .el-icon-circle-check{color:#fff}.el-upload-list--picture-card .el-upload-list__item .el-icon-close,.el-upload-list--picture-card .el-upload-list__item:hover .el-upload-list__item-status-label{display:none}.el-upload-list--picture-card .el-upload-list__item:hover .el-progress__text{display:block}.el-upload-list--picture-card .el-upload-list__item-name{display:none}.el-upload-list--picture-card .el-upload-list__item-thumbnail{width:100%;height:100%}.el-upload-list--picture-card .el-upload-list__item-status-label{position:absolute;right:-15px;top:-6px;width:40px;height:24px;background:#13ce66;text-align:center;transform:rotate(45deg);box-shadow:0 0 1pc 1px rgba(0,0,0,.2)}.el-upload-list--picture-card .el-upload-list__item-status-label i{font-size:12px;margin-top:11px;transform:rotate(-45deg)}.el-upload-list--picture-card .el-upload-list__item-actions{position:absolute;width:100%;height:100%;left:0;top:0;cursor:default;text-align:center;color:#fff;opacity:0;font-size:20px;background-color:rgba(0,0,0,.5);transition:opacity .3s}.el-upload-list--picture-card .el-upload-list__item-actions:after{display:inline-block;content:"";height:100%;vertical-align:middle}.el-upload-list--picture-card .el-upload-list__item-actions span{display:none;cursor:pointer}.el-upload-list--picture-card .el-upload-list__item-actions span+span{margin-left:15px}.el-upload-list--picture-card .el-upload-list__item-actions .el-upload-list__item-delete{position:static;font-size:inherit;color:inherit}.el-upload-list--picture-card .el-upload-list__item-actions:hover{opacity:1}.el-upload-list--picture-card .el-upload-list__item-actions:hover span{display:inline-block}.el-upload-list--picture-card .el-progress{top:50%;left:50%;transform:translate(-50%,-50%);bottom:auto;width:126px}.el-upload-list--picture-card .el-progress .el-progress__text{top:50%}.el-upload-list--picture .el-upload-list__item{overflow:hidden;z-index:0;background-color:#fff;border:1px solid #c0ccda;border-radius:6px;box-sizing:border-box;margin-top:10px;padding:10px 10px 10px 90px;height:92px}.el-upload-list--picture .el-upload-list__item .el-icon-check,.el-upload-list--picture .el-upload-list__item .el-icon-circle-check{color:#fff}.el-upload-list--picture .el-upload-list__item:hover .el-upload-list__item-status-label{background:transparent;box-shadow:none;top:-2px;right:-12px}.el-upload-list--picture .el-upload-list__item:hover .el-progress__text{display:block}.el-upload-list--picture .el-upload-list__item.is-success .el-upload-list__item-name{line-height:70px;margin-top:0}.el-upload-list--picture .el-upload-list__item.is-success .el-upload-list__item-name i{display:none}.el-upload-list--picture .el-upload-list__item-thumbnail{vertical-align:middle;display:inline-block;width:70px;height:70px;float:left;position:relative;z-index:1;margin-left:-80px;background-color:#fff}.el-upload-list--picture .el-upload-list__item-name{display:block;margin-top:20px}.el-upload-list--picture .el-upload-list__item-name i{font-size:70px;line-height:1;position:absolute;left:9px;top:10px}.el-upload-list--picture .el-upload-list__item-status-label{position:absolute;right:-17px;top:-7px;width:46px;height:26px;background:#13ce66;text-align:center;transform:rotate(45deg);box-shadow:0 1px 1px #ccc}.el-upload-list--picture .el-upload-list__item-status-label i{font-size:12px;margin-top:12px;transform:rotate(-45deg)}.el-upload-list--picture .el-progress{position:relative;top:-7px}.el-upload-cover{position:absolute;left:0;top:0;width:100%;height:100%;overflow:hidden;z-index:10;cursor:default}.el-upload-cover:after{display:inline-block;content:"";height:100%;vertical-align:middle}.el-upload-cover img{display:block;width:100%;height:100%}.el-upload-cover__label{position:absolute;right:-15px;top:-6px;width:40px;height:24px;background:#13ce66;text-align:center;transform:rotate(45deg);box-shadow:0 0 1pc 1px rgba(0,0,0,.2)}.el-upload-cover__label i{font-size:12px;margin-top:11px;transform:rotate(-45deg);color:#fff}.el-upload-cover__progress{display:inline-block;vertical-align:middle;position:static;width:243px}.el-upload-cover__progress+.el-upload__inner{opacity:0}.el-upload-cover__content{position:absolute;top:0;left:0;width:100%;height:100%}.el-upload-cover__interact{position:absolute;bottom:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,.72);text-align:center}.el-upload-cover__interact .btn{display:inline-block;color:#fff;font-size:14px;cursor:pointer;vertical-align:middle;transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1);margin-top:60px}.el-upload-cover__interact .btn i{margin-top:0}.el-upload-cover__interact .btn span{opacity:0;transition:opacity .15s linear}.el-upload-cover__interact .btn:not(:first-child){margin-left:35px}.el-upload-cover__interact .btn:hover{transform:translateY(-13px)}.el-upload-cover__interact .btn:hover span{opacity:1}.el-upload-cover__interact .btn i{color:#fff;display:block;font-size:24px;line-height:inherit;margin:0 auto 5px}.el-upload-cover__title{position:absolute;bottom:0;left:0;background-color:#fff;height:36px;width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:400;text-align:left;padding:0 10px;margin:0;line-height:36px;font-size:14px;color:#303133}.el-upload-cover+.el-upload__inner{opacity:0;position:relative;z-index:1}.el-progress{position:relative;line-height:1}.el-progress__text{font-size:14px;color:#606266;display:inline-block;vertical-align:middle;margin-left:10px;line-height:1}.el-progress__text i{vertical-align:middle;display:block}.el-progress--circle,.el-progress--dashboard{display:inline-block}.el-progress--circle .el-progress__text,.el-progress--dashboard .el-progress__text{position:absolute;top:50%;left:0;width:100%;text-align:center;margin:0;transform:translateY(-50%)}.el-progress--circle .el-progress__text i,.el-progress--dashboard .el-progress__text i{vertical-align:middle;display:inline-block}.el-progress--without-text .el-progress__text{display:none}.el-progress--without-text .el-progress-bar{padding-right:0;margin-right:0;display:block}.el-progress--text-inside .el-progress-bar{padding-right:0;margin-right:0}.el-progress.is-success .el-progress-bar__inner{background-color:#42d885}.el-progress.is-success .el-progress__text{color:#42d885}.el-progress.is-warning .el-progress-bar__inner{background-color:#f9c855}.el-progress.is-warning .el-progress__text{color:#f9c855}.el-progress.is-exception .el-progress-bar__inner{background-color:#ff6d6d}.el-progress.is-exception .el-progress__text{color:#ff6d6d}.el-progress-bar{padding-right:50px;display:inline-block;vertical-align:middle;width:100%;margin-right:-55px;box-sizing:border-box}.el-progress-bar__outer{height:6px;border-radius:100px;background-color:#ebeef5;overflow:hidden;position:relative;vertical-align:middle}.el-progress-bar__inner{position:absolute;left:0;top:0;height:100%;background-color:#42d885;text-align:right;border-radius:100px;line-height:1;white-space:nowrap;transition:width .6s ease}.el-progress-bar__inner:after{display:inline-block;content:"";height:100%;vertical-align:middle}.el-progress-bar__innerText{display:inline-block;vertical-align:middle;color:#fff;font-size:12px;margin:0 5px}@keyframes progress{0%{background-position:0 0}to{background-position:32px 0}}.el-time-spinner{width:100%;white-space:nowrap}.el-spinner{display:inline-block;vertical-align:middle}.el-spinner-inner{animation:rotate 2s linear infinite;width:50px;height:50px}.el-spinner-inner .path{stroke:#ececec;stroke-linecap:round;animation:dash 1.5s ease-in-out infinite}@keyframes rotate{to{transform:rotate(1turn)}}@keyframes dash{0%{stroke-dasharray:1,150;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-35}to{stroke-dasharray:90,150;stroke-dashoffset:-124}}.el-message{min-width:380px;box-sizing:border-box;border-radius:4px;border:1px solid #ebeef5;position:fixed;left:50%;top:20px;transform:translateX(-50%);background-color:#edf2fc;transition:opacity .3s,transform .4s,top .4s;overflow:hidden;padding:15px 15px 15px 20px;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}.el-message.is-center{-ms-flex-pack:center;justify-content:center}.el-message.is-closable .el-message__content{padding-right:16px}.el-message p{margin:0}.el-message--info .el-message__content{color:#909399}.el-message--success{background-color:#ecfbf3;border-color:#d9f7e7}.el-message--success .el-message__content{color:#42d885}.el-message--warning{background-color:#fefaee;border-color:#fef4dd}.el-message--warning .el-message__content{color:#f9c855}.el-message--error{background-color:#fff0f0;border-color:#ffe2e2}.el-message--error .el-message__content{color:#ff6d6d}.el-message__icon{margin-right:10px}.el-message__content{padding:0;font-size:14px;line-height:1}.el-message__content:focus{outline-width:0}.el-message__closeBtn{position:absolute;top:50%;right:15px;transform:translateY(-50%);cursor:pointer;color:#c0c4cc;font-size:16px}.el-message__closeBtn:focus{outline-width:0}.el-message__closeBtn:hover{color:#909399}.el-message .el-icon-success{color:#42d885}.el-message .el-icon-error{color:#ff6d6d}.el-message .el-icon-info{color:#909399}.el-message .el-icon-warning{color:#f9c855}.el-message-fade-enter,.el-message-fade-leave-active{opacity:0;transform:translate(-50%,-100%)}.el-badge{position:relative;vertical-align:middle;display:inline-block}.el-badge__content{background-color:#ff6d6d;border-radius:10px;color:#fff;display:inline-block;font-size:12px;height:18px;line-height:18px;padding:0 6px;text-align:center;white-space:nowrap;border:1px solid #fff}.el-badge__content.is-fixed{position:absolute;top:0;right:10px;transform:translateY(-50%) translateX(100%)}.el-badge__content.is-fixed.is-dot{right:5px}.el-badge__content.is-dot{height:8px;width:8px;padding:0;right:0;border-radius:50%}.el-badge__content--primary,.el-badge__content--success{background-color:#42d885}.el-badge__content--warning{background-color:#f9c855}.el-badge__content--info{background-color:#909399}.el-badge__content--danger{background-color:#ff6d6d}.el-card{border-radius:4px;border:1px solid #ebeef5;background-color:#fff;overflow:hidden;color:#303133;transition:.3s}.el-card.is-always-shadow,.el-card.is-hover-shadow:focus,.el-card.is-hover-shadow:hover{box-shadow:0 2px 12px 0 rgba(0,0,0,.1)}.el-card__header{padding:18px 20px;border-bottom:1px solid #ebeef5;box-sizing:border-box}.el-card__body{padding:20px}.el-rate{height:20px;line-height:1}.el-rate:active,.el-rate:focus{outline-width:0}.el-rate__item{font-size:0;vertical-align:middle}.el-rate__icon,.el-rate__item{display:inline-block;position:relative}.el-rate__icon{font-size:18px;margin-right:6px;color:#c0c4cc;transition:.3s}.el-rate__icon.hover{transform:scale(1.15)}.el-rate__decimal,.el-rate__icon .path2{position:absolute;left:0;top:0}.el-rate__decimal{display:inline-block;overflow:hidden}.el-rate__text{font-size:14px;vertical-align:middle}.el-steps{display:-ms-flexbox;display:flex}.el-steps--simple{padding:13px 8%;border-radius:4px;background:#f5f7fa}.el-steps--horizontal{white-space:nowrap}.el-steps--vertical{height:100%;-ms-flex-flow:column;flex-flow:column}.el-step{position:relative;-ms-flex-negative:1;flex-shrink:1}.el-step:last-of-type .el-step__line{display:none}.el-step:last-of-type.is-flex{-ms-flex-preferred-size:auto!important;flex-basis:auto!important;-ms-flex-negative:0;flex-shrink:0;-ms-flex-positive:0;flex-grow:0}.el-step:last-of-type .el-step__description,.el-step:last-of-type .el-step__main{padding-right:0}.el-step__head{position:relative;width:100%}.el-step__head.is-process{color:#303133;border-color:#303133}.el-step__head.is-wait{color:#c0c4cc;border-color:#c0c4cc}.el-step__head.is-success{color:#42d885;border-color:#42d885}.el-step__head.is-error{color:#ff6d6d;border-color:#ff6d6d}.el-step__head.is-finish{color:#42d885;border-color:#42d885}.el-step__icon{position:relative;z-index:1;display:-ms-inline-flexbox;display:inline-flex;-ms-flex-pack:center;justify-content:center;-ms-flex-align:center;align-items:center;width:24px;height:24px;font-size:14px;box-sizing:border-box;background:#fff;transition:.15s ease-out}.el-step__icon.is-text{border-radius:50%;border:2px solid;border-color:inherit}.el-step__icon.is-icon{width:40px}.el-step__icon-inner{display:inline-block;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-align:center;font-weight:700;line-height:1;color:inherit}.el-step__icon-inner[class*=el-icon]:not(.is-status){font-size:25px;font-weight:400}.el-step__icon-inner.is-status{transform:translateY(1px)}.el-step__line{position:absolute;border-color:inherit;background-color:#c0c4cc}.el-step__line-inner{display:block;border-width:1px;border-style:solid;border-color:inherit;transition:.15s ease-out;box-sizing:border-box;width:0;height:0}.el-step__main{white-space:normal;text-align:left}.el-step__title{font-size:16px;line-height:38px}.el-step__title.is-process{font-weight:700;color:#303133}.el-step__title.is-wait{color:#c0c4cc}.el-step__title.is-success{color:#42d885}.el-step__title.is-error{color:#ff6d6d}.el-step__title.is-finish{color:#42d885}.el-step__description{padding-right:10%;margin-top:-5px;font-size:12px;line-height:20px;font-weight:400}.el-step__description.is-process{color:#303133}.el-step__description.is-wait{color:#c0c4cc}.el-step__description.is-success{color:#42d885}.el-step__description.is-error{color:#ff6d6d}.el-step__description.is-finish{color:#42d885}.el-step.is-horizontal{display:inline-block}.el-step.is-horizontal .el-step__line{height:2px;top:11px;left:0;right:0}.el-step.is-vertical{display:-ms-flexbox;display:flex}.el-step.is-vertical .el-step__head{-ms-flex-positive:0;flex-grow:0;width:24px}.el-step.is-vertical .el-step__main{padding-left:10px;-ms-flex-positive:1;flex-grow:1}.el-step.is-vertical .el-step__title{line-height:24px;padding-bottom:8px}.el-step.is-vertical .el-step__line{width:2px;top:0;bottom:0;left:11px}.el-step.is-vertical .el-step__icon.is-icon{width:24px}.el-step.is-center .el-step__head,.el-step.is-center .el-step__main{text-align:center}.el-step.is-center .el-step__description{padding-left:20%;padding-right:20%}.el-step.is-center .el-step__line{left:50%;right:-50%}.el-step.is-simple{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}.el-step.is-simple .el-step__head{width:auto;font-size:0;padding-right:10px}.el-step.is-simple .el-step__icon{background:transparent;width:16px;height:16px;font-size:12px}.el-step.is-simple .el-step__icon-inner[class*=el-icon]:not(.is-status){font-size:18px}.el-step.is-simple .el-step__icon-inner.is-status{transform:scale(.8) translateY(1px)}.el-step.is-simple .el-step__main{position:relative;display:-ms-flexbox;display:flex;-ms-flex-align:stretch;align-items:stretch;-ms-flex-positive:1;flex-grow:1}.el-step.is-simple .el-step__title{font-size:16px;line-height:20px}.el-step.is-simple:not(:last-of-type) .el-step__title{max-width:50%;word-break:break-all}.el-step.is-simple .el-step__arrow{-ms-flex-positive:1;flex-grow:1;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center}.el-step.is-simple .el-step__arrow:after,.el-step.is-simple .el-step__arrow:before{content:"";display:inline-block;position:absolute;height:15px;width:1px;background:#c0c4cc}.el-step.is-simple .el-step__arrow:before{transform:rotate(-45deg) translateY(-4px);transform-origin:0 0}.el-step.is-simple .el-step__arrow:after{transform:rotate(45deg) translateY(4px);transform-origin:100% 100%}.el-step.is-simple:last-of-type .el-step__arrow{display:none}.el-carousel{position:relative}.el-carousel--horizontal{overflow-x:hidden}.el-carousel--vertical{overflow-y:hidden}.el-carousel__container{position:relative;height:300px}.el-carousel__arrow{border:none;outline:none;padding:0;margin:0;height:36px;width:36px;cursor:pointer;transition:.3s;border-radius:50%;background-color:rgba(31,45,61,.11);color:#fff;position:absolute;top:50%;z-index:10;transform:translateY(-50%);text-align:center;font-size:12px}.el-carousel__arrow--left{left:16px}.el-carousel__arrow--right{right:16px}.el-carousel__arrow:hover{background-color:rgba(31,45,61,.23)}.el-carousel__arrow i{cursor:pointer}.el-carousel__indicators{position:absolute;list-style:none;margin:0;padding:0;z-index:2}.el-carousel__indicators--horizontal{bottom:0;left:50%;transform:translateX(-50%)}.el-carousel__indicators--vertical{right:0;top:50%;transform:translateY(-50%)}.el-carousel__indicators--outside{bottom:26px;text-align:center;position:static;transform:none}.el-carousel__indicators--outside .el-carousel__indicator:hover button{opacity:.64}.el-carousel__indicators--outside button{background-color:#c0c4cc;opacity:.24}.el-carousel__indicators--labels{left:0;right:0;transform:none;text-align:center}.el-carousel__indicators--labels .el-carousel__button{height:auto;width:auto;padding:2px 18px;font-size:12px}.el-carousel__indicators--labels .el-carousel__indicator{padding:6px 4px}.el-carousel__indicator{background-color:transparent;cursor:pointer}.el-carousel__indicator:hover button{opacity:.72}.el-carousel__indicator--horizontal{display:inline-block;padding:12px 4px}.el-carousel__indicator--vertical{padding:4px 12px}.el-carousel__indicator--vertical .el-carousel__button{width:2px;height:15px}.el-carousel__indicator.is-active button{opacity:1}.el-carousel__button{display:block;opacity:.48;width:30px;height:2px;background-color:#fff;border:none;outline:none;padding:0;margin:0;cursor:pointer;transition:.3s}.carousel-arrow-left-enter,.carousel-arrow-left-leave-active{transform:translateY(-50%) translateX(-10px);opacity:0}.carousel-arrow-right-enter,.carousel-arrow-right-leave-active{transform:translateY(-50%) translateX(10px);opacity:0}.el-carousel__item{position:absolute;top:0;left:0;width:100%;height:100%;display:inline-block;overflow:hidden;z-index:0}.el-carousel__item.is-active{z-index:2}.el-carousel__item--card,.el-carousel__item.is-animating{transition:transform .4s ease-in-out}.el-carousel__item--card{width:50%}.el-carousel__item--card.is-in-stage{cursor:pointer;z-index:1}.el-carousel__item--card.is-in-stage.is-hover .el-carousel__mask,.el-carousel__item--card.is-in-stage:hover .el-carousel__mask{opacity:.12}.el-carousel__item--card.is-active{z-index:2}.el-carousel__mask{position:absolute;width:100%;height:100%;top:0;left:0;background-color:#fff;opacity:.24;transition:.2s}.fade-in-linear-enter-active,.fade-in-linear-leave-active{transition:opacity .2s linear}.fade-in-linear-enter,.fade-in-linear-leave,.fade-in-linear-leave-active{opacity:0}.el-fade-in-linear-enter-active,.el-fade-in-linear-leave-active{transition:opacity .2s linear}.el-fade-in-linear-enter,.el-fade-in-linear-leave,.el-fade-in-linear-leave-active{opacity:0}.el-fade-in-enter-active,.el-fade-in-leave-active{transition:all .3s cubic-bezier(.55,0,.1,1)}.el-fade-in-enter,.el-fade-in-leave-active{opacity:0}.el-zoom-in-center-enter-active,.el-zoom-in-center-leave-active{transition:all .3s cubic-bezier(.55,0,.1,1)}.el-zoom-in-center-enter,.el-zoom-in-center-leave-active{opacity:0;transform:scaleX(0)}.el-zoom-in-top-enter-active,.el-zoom-in-top-leave-active{opacity:1;transform:scaleY(1);transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1);transform-origin:center top}.el-zoom-in-top-enter,.el-zoom-in-top-leave-active{opacity:0;transform:scaleY(0)}.el-zoom-in-bottom-enter-active,.el-zoom-in-bottom-leave-active{opacity:1;transform:scaleY(1);transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1);transform-origin:center bottom}.el-zoom-in-bottom-enter,.el-zoom-in-bottom-leave-active{opacity:0;transform:scaleY(0)}.el-zoom-in-left-enter-active,.el-zoom-in-left-leave-active{opacity:1;transform:scale(1);transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1);transform-origin:top left}.el-zoom-in-left-enter,.el-zoom-in-left-leave-active{opacity:0;transform:scale(.45)}.collapse-transition{transition:height .3s ease-in-out,padding-top .3s ease-in-out,padding-bottom .3s ease-in-out}.horizontal-collapse-transition{transition:width .3s ease-in-out,padding-left .3s ease-in-out,padding-right .3s ease-in-out}.el-list-enter-active,.el-list-leave-active{transition:all 1s}.el-list-enter,.el-list-leave-active{opacity:0;transform:translateY(-30px)}.el-opacity-transition{transition:opacity .3s cubic-bezier(.55,0,.1,1)}.el-collapse{border-top:1px solid #ebeef5;border-bottom:1px solid #ebeef5}.el-collapse-item.is-disabled .el-collapse-item__header{color:#bbb;cursor:not-allowed}.el-collapse-item__header{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;height:48px;line-height:48px;background-color:#fff;color:#303133;cursor:pointer;border-bottom:1px solid #ebeef5;font-size:13px;font-weight:500;transition:border-bottom-color .3s;outline:none}.el-collapse-item__arrow{margin:0 8px 0 auto;transition:transform .3s;font-weight:300}.el-collapse-item__arrow.is-active{transform:rotate(90deg)}.el-collapse-item__header.focusing:focus:not(:hover){color:#42d885}.el-collapse-item__header.is-active{border-bottom-color:transparent}.el-collapse-item__wrap{will-change:height;background-color:#fff;overflow:hidden;box-sizing:border-box;border-bottom:1px solid #ebeef5}.el-collapse-item__content{padding-bottom:25px;font-size:13px;color:#303133;line-height:1.769230769230769}.el-collapse-item:last-child{margin-bottom:-1px}.el-popper .popper__arrow,.el-popper .popper__arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.el-popper .popper__arrow{border-width:6px;filter:drop-shadow(0 2px 12px rgba(0,0,0,.03))}.el-popper .popper__arrow:after{content:" ";border-width:6px}.el-popper[x-placement^=top]{margin-bottom:12px}.el-popper[x-placement^=top] .popper__arrow{bottom:-6px;left:50%;margin-right:3px;border-top-color:#ebeef5;border-bottom-width:0}.el-popper[x-placement^=top] .popper__arrow:after{bottom:1px;margin-left:-6px;border-top-color:#fff;border-bottom-width:0}.el-popper[x-placement^=bottom]{margin-top:12px}.el-popper[x-placement^=bottom] .popper__arrow{top:-6px;left:50%;margin-right:3px;border-top-width:0;border-bottom-color:#ebeef5}.el-popper[x-placement^=bottom] .popper__arrow:after{top:1px;margin-left:-6px;border-top-width:0;border-bottom-color:#fff}.el-popper[x-placement^=right]{margin-left:12px}.el-popper[x-placement^=right] .popper__arrow{top:50%;left:-6px;margin-bottom:3px;border-right-color:#ebeef5;border-left-width:0}.el-popper[x-placement^=right] .popper__arrow:after{bottom:-6px;left:1px;border-right-color:#fff;border-left-width:0}.el-popper[x-placement^=left]{margin-right:12px}.el-popper[x-placement^=left] .popper__arrow{top:50%;right:-6px;margin-bottom:3px;border-right-width:0;border-left-color:#ebeef5}.el-popper[x-placement^=left] .popper__arrow:after{right:1px;bottom:-6px;margin-left:-6px;border-right-width:0;border-left-color:#fff}.el-tag{background-color:#ecfbf3;border:1px solid #d9f7e7;display:inline-block;height:32px;padding:0 10px;line-height:30px;font-size:12px;color:#42d885;border-radius:4px;box-sizing:border-box;white-space:nowrap}.el-tag.is-hit{border-color:#42d885}.el-tag .el-tag__close{color:#42d885}.el-tag .el-tag__close:hover{color:#fff;background-color:#42d885}.el-tag.el-tag--info{background-color:#f4f4f5;border-color:#e9e9eb;color:#909399}.el-tag.el-tag--info.is-hit{border-color:#909399}.el-tag.el-tag--info .el-tag__close{color:#909399}.el-tag.el-tag--info .el-tag__close:hover{color:#fff;background-color:#909399}.el-tag.el-tag--success{background-color:#ecfbf3;border-color:#d9f7e7;color:#42d885}.el-tag.el-tag--success.is-hit{border-color:#42d885}.el-tag.el-tag--success .el-tag__close{color:#42d885}.el-tag.el-tag--success .el-tag__close:hover{color:#fff;background-color:#42d885}.el-tag.el-tag--warning{background-color:#fefaee;border-color:#fef4dd;color:#f9c855}.el-tag.el-tag--warning.is-hit{border-color:#f9c855}.el-tag.el-tag--warning .el-tag__close{color:#f9c855}.el-tag.el-tag--warning .el-tag__close:hover{color:#fff;background-color:#f9c855}.el-tag.el-tag--danger{background-color:#fff0f0;border-color:#ffe2e2;color:#ff6d6d}.el-tag.el-tag--danger.is-hit{border-color:#ff6d6d}.el-tag.el-tag--danger .el-tag__close{color:#ff6d6d}.el-tag.el-tag--danger .el-tag__close:hover{color:#fff;background-color:#ff6d6d}.el-tag .el-icon-close{border-radius:50%;text-align:center;position:relative;cursor:pointer;font-size:12px;height:16px;width:16px;line-height:16px;vertical-align:middle;top:-1px;right:-5px}.el-tag .el-icon-close:before{display:block}.el-tag--dark{background-color:#42d885;color:#fff}.el-tag--dark,.el-tag--dark.is-hit{border-color:#42d885}.el-tag--dark .el-tag__close{color:#fff}.el-tag--dark .el-tag__close:hover{color:#fff;background-color:#68e09d}.el-tag--dark.el-tag--info{background-color:#909399;border-color:#909399;color:#fff}.el-tag--dark.el-tag--info.is-hit{border-color:#909399}.el-tag--dark.el-tag--info .el-tag__close{color:#fff}.el-tag--dark.el-tag--info .el-tag__close:hover{color:#fff;background-color:#a6a9ad}.el-tag--dark.el-tag--success{background-color:#42d885;border-color:#42d885;color:#fff}.el-tag--dark.el-tag--success.is-hit{border-color:#42d885}.el-tag--dark.el-tag--success .el-tag__close{color:#fff}.el-tag--dark.el-tag--success .el-tag__close:hover{color:#fff;background-color:#68e09d}.el-tag--dark.el-tag--warning{background-color:#f9c855;border-color:#f9c855;color:#fff}.el-tag--dark.el-tag--warning.is-hit{border-color:#f9c855}.el-tag--dark.el-tag--warning .el-tag__close{color:#fff}.el-tag--dark.el-tag--warning .el-tag__close:hover{color:#fff;background-color:#fad377}.el-tag--dark.el-tag--danger{background-color:#ff6d6d;border-color:#ff6d6d;color:#fff}.el-tag--dark.el-tag--danger.is-hit{border-color:#ff6d6d}.el-tag--dark.el-tag--danger .el-tag__close{color:#fff}.el-tag--dark.el-tag--danger .el-tag__close:hover{color:#fff;background-color:#ff8a8a}.el-tag--plain{background-color:#fff;border-color:#b3efce;color:#42d885}.el-tag--plain.is-hit{border-color:#42d885}.el-tag--plain .el-tag__close{color:#42d885}.el-tag--plain .el-tag__close:hover{color:#fff;background-color:#42d885}.el-tag--plain.el-tag--info{background-color:#fff;border-color:#d3d4d6;color:#909399}.el-tag--plain.el-tag--info.is-hit{border-color:#909399}.el-tag--plain.el-tag--info .el-tag__close{color:#909399}.el-tag--plain.el-tag--info .el-tag__close:hover{color:#fff;background-color:#909399}.el-tag--plain.el-tag--success{background-color:#fff;border-color:#b3efce;color:#42d885}.el-tag--plain.el-tag--success.is-hit{border-color:#42d885}.el-tag--plain.el-tag--success .el-tag__close{color:#42d885}.el-tag--plain.el-tag--success .el-tag__close:hover{color:#fff;background-color:#42d885}.el-tag--plain.el-tag--warning{background-color:#fff;border-color:#fde9bb;color:#f9c855}.el-tag--plain.el-tag--warning.is-hit{border-color:#f9c855}.el-tag--plain.el-tag--warning .el-tag__close{color:#f9c855}.el-tag--plain.el-tag--warning .el-tag__close:hover{color:#fff;background-color:#f9c855}.el-tag--plain.el-tag--danger{background-color:#fff;border-color:#ffc5c5;color:#ff6d6d}.el-tag--plain.el-tag--danger.is-hit{border-color:#ff6d6d}.el-tag--plain.el-tag--danger .el-tag__close{color:#ff6d6d}.el-tag--plain.el-tag--danger .el-tag__close:hover{color:#fff;background-color:#ff6d6d}.el-tag--medium{height:28px;line-height:26px}.el-tag--medium .el-icon-close{transform:scale(.8)}.el-tag--small{height:24px;padding:0 8px;line-height:22px}.el-tag--small .el-icon-close{transform:scale(.8)}.el-tag--mini{height:20px;padding:0 5px;line-height:19px}.el-tag--mini .el-icon-close{margin-left:-3px;transform:scale(.7)}.el-cascader{display:inline-block;position:relative;font-size:14px;line-height:40px}.el-cascader:not(.is-disabled):hover .el-input__inner{cursor:pointer;border-color:#c0c4cc}.el-cascader .el-input{cursor:pointer}.el-cascader .el-input .el-input__inner{text-overflow:ellipsis}.el-cascader .el-input .el-input__inner:focus{border-color:#42d885}.el-cascader .el-input .el-icon-arrow-down{transition:transform .3s;font-size:14px}.el-cascader .el-input .el-icon-arrow-down.is-reverse{transform:rotate(180deg)}.el-cascader .el-input .el-icon-circle-close:hover{color:#909399}.el-cascader .el-input.is-focus .el-input__inner{border-color:#42d885}.el-cascader--medium{font-size:14px;line-height:36px}.el-cascader--small{font-size:13px;line-height:32px}.el-cascader--mini{font-size:12px;line-height:28px}.el-cascader.is-disabled .el-cascader__label{z-index:2;color:#c0c4cc}.el-cascader__dropdown{margin:5px 0;font-size:14px;background:#fff;border:1px solid #e4e7ed;border-radius:4px;box-shadow:0 2px 12px 0 rgba(0,0,0,.1)}.el-cascader__tags{position:absolute;left:0;right:30px;top:50%;transform:translateY(-50%);display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;line-height:normal;text-align:left;box-sizing:border-box}.el-cascader__tags .el-tag{display:-ms-inline-flexbox;display:inline-flex;-ms-flex-align:center;align-items:center;max-width:100%;margin:2px 0 2px 6px;text-overflow:ellipsis;background:#f0f2f5}.el-cascader__tags .el-tag:not(.is-hit){border-color:transparent}.el-cascader__tags .el-tag>span{-ms-flex:1;flex:1;overflow:hidden;text-overflow:ellipsis}.el-cascader__tags .el-tag .el-icon-close{-ms-flex:none;flex:none;background-color:#c0c4cc;color:#fff}.el-cascader__tags .el-tag .el-icon-close:hover{background-color:#909399}.el-cascader__suggestion-panel{border-radius:4px}.el-cascader__suggestion-list{max-height:204px;margin:0;padding:6px 0;font-size:14px;color:#606266;text-align:center}.el-cascader__suggestion-item{display:-ms-flexbox;display:flex;-ms-flex-pack:justify;justify-content:space-between;-ms-flex-align:center;align-items:center;height:34px;padding:0 15px;text-align:left;outline:none;cursor:pointer}.el-cascader__suggestion-item:focus,.el-cascader__suggestion-item:hover{background:#f5f7fa}.el-cascader__suggestion-item.is-checked{color:#42d885;font-weight:700}.el-cascader__suggestion-item>span{margin-right:10px}.el-cascader__empty-text{margin:10px 0;color:#c0c4cc}.el-cascader__search-input{-ms-flex:1;flex:1;height:24px;min-width:60px;margin:2px 0 2px 15px;padding:0;color:#606266;border:none;outline:none;box-sizing:border-box}.el-cascader__search-input::-webkit-input-placeholder{color:#c0c4cc}.el-cascader__search-input::-ms-input-placeholder{color:#c0c4cc}.el-cascader__search-input::placeholder{color:#c0c4cc}.el-color-predefine{display:-ms-flexbox;display:flex;font-size:12px;margin-top:8px;width:280px}.el-color-predefine__colors{display:-ms-flexbox;display:flex;-ms-flex:1;flex:1;-ms-flex-wrap:wrap;flex-wrap:wrap}.el-color-predefine__color-selector{margin:0 0 8px 8px;width:20px;height:20px;border-radius:4px;cursor:pointer}.el-color-predefine__color-selector:nth-child(10n+1){margin-left:0}.el-color-predefine__color-selector.selected{box-shadow:0 0 3px 2px #42d885}.el-color-predefine__color-selector>div{display:-ms-flexbox;display:flex;height:100%;border-radius:3px}.el-color-predefine__color-selector.is-alpha{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.el-color-hue-slider{position:relative;box-sizing:border-box;width:280px;height:12px;background-color:red;padding:0 2px}.el-color-hue-slider__bar{position:relative;background:linear-gradient(90deg,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red);height:100%}.el-color-hue-slider__thumb{position:absolute;cursor:pointer;box-sizing:border-box;left:0;top:0;width:4px;height:100%;border-radius:1px;background:#fff;border:1px solid #f0f0f0;box-shadow:0 0 2px rgba(0,0,0,.6);z-index:1}.el-color-hue-slider.is-vertical{width:12px;height:180px;padding:2px 0}.el-color-hue-slider.is-vertical .el-color-hue-slider__bar{background:linear-gradient(180deg,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red)}.el-color-hue-slider.is-vertical .el-color-hue-slider__thumb{left:0;top:0;width:100%;height:4px}.el-color-svpanel{position:relative;width:280px;height:180px}.el-color-svpanel__black,.el-color-svpanel__white{position:absolute;top:0;left:0;right:0;bottom:0}.el-color-svpanel__white{background:linear-gradient(90deg,#fff,hsla(0,0%,100%,0))}.el-color-svpanel__black{background:linear-gradient(0deg,#000,transparent)}.el-color-svpanel__cursor{position:absolute}.el-color-svpanel__cursor>div{cursor:head;width:4px;height:4px;box-shadow:0 0 0 1.5px #fff,inset 0 0 1px 1px rgba(0,0,0,.3),0 0 1px 2px rgba(0,0,0,.4);border-radius:50%;transform:translate(-2px,-2px)}.el-color-alpha-slider{position:relative;box-sizing:border-box;width:280px;height:12px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.el-color-alpha-slider__bar{position:relative;background:linear-gradient(90deg,hsla(0,0%,100%,0) 0,#fff);height:100%}.el-color-alpha-slider__thumb{position:absolute;cursor:pointer;box-sizing:border-box;left:0;top:0;width:4px;height:100%;border-radius:1px;background:#fff;border:1px solid #f0f0f0;box-shadow:0 0 2px rgba(0,0,0,.6);z-index:1}.el-color-alpha-slider.is-vertical{width:20px;height:180px}.el-color-alpha-slider.is-vertical .el-color-alpha-slider__bar{background:linear-gradient(180deg,hsla(0,0%,100%,0) 0,#fff)}.el-color-alpha-slider.is-vertical .el-color-alpha-slider__thumb{left:0;top:0;width:100%;height:4px}.el-color-dropdown{width:300px}.el-color-dropdown__main-wrapper{margin-bottom:6px}.el-color-dropdown__main-wrapper:after{content:"";display:table;clear:both}.el-color-dropdown__btns{margin-top:6px;text-align:right}.el-color-dropdown__value{float:left;line-height:26px;font-size:12px;color:#000;width:160px}.el-color-dropdown__btn{border:1px solid #dcdcdc;color:#333;line-height:24px;border-radius:2px;padding:0 20px;cursor:pointer;background-color:transparent;outline:none;font-size:12px}.el-color-dropdown__btn[disabled]{color:#ccc;cursor:not-allowed}.el-color-dropdown__btn:hover{color:#42d885;border-color:#42d885}.el-color-dropdown__link-btn{cursor:pointer;color:#42d885;text-decoration:none;padding:15px;font-size:12px}.el-color-dropdown__link-btn:hover{color:tint(#42d885,20%)}.el-color-picker{display:inline-block;position:relative;line-height:normal;height:40px}.el-color-picker.is-disabled .el-color-picker__trigger{cursor:not-allowed}.el-color-picker--medium{height:36px}.el-color-picker--medium .el-color-picker__trigger{height:36px;width:36px}.el-color-picker--medium .el-color-picker__mask{height:34px;width:34px}.el-color-picker--small{height:32px}.el-color-picker--small .el-color-picker__trigger{height:32px;width:32px}.el-color-picker--small .el-color-picker__mask{height:30px;width:30px}.el-color-picker--small .el-color-picker__empty,.el-color-picker--small .el-color-picker__icon{transform:translate3d(-50%,-50%,0) scale(.8)}.el-color-picker--mini{height:28px}.el-color-picker--mini .el-color-picker__trigger{height:28px;width:28px}.el-color-picker--mini .el-color-picker__mask{height:26px;width:26px}.el-color-picker--mini .el-color-picker__empty,.el-color-picker--mini .el-color-picker__icon{transform:translate3d(-50%,-50%,0) scale(.8)}.el-color-picker__mask{height:38px;width:38px;border-radius:4px;position:absolute;top:1px;left:1px;z-index:1;cursor:not-allowed;background-color:hsla(0,0%,100%,.7)}.el-color-picker__trigger{display:inline-block;box-sizing:border-box;height:40px;width:40px;padding:4px;border:1px solid #e6e6e6;border-radius:4px;font-size:0;position:relative;cursor:pointer}.el-color-picker__color{position:relative;display:block;box-sizing:border-box;border:1px solid #999;border-radius:2px;width:100%;height:100%;text-align:center}.el-color-picker__color.is-alpha{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.el-color-picker__color-inner{position:absolute;left:0;top:0;right:0;bottom:0}.el-color-picker__empty{color:#999}.el-color-picker__empty,.el-color-picker__icon{font-size:12px;position:absolute;top:50%;left:50%;transform:translate3d(-50%,-50%,0)}.el-color-picker__icon{display:inline-block;width:100%;color:#fff;text-align:center}.el-color-picker__panel{position:absolute;z-index:10;padding:6px;box-sizing:content-box;background-color:#fff;border:1px solid #ebeef5;border-radius:4px;box-shadow:0 2px 12px 0 rgba(0,0,0,.1)}.el-textarea{position:relative;display:inline-block;width:100%;vertical-align:bottom;font-size:14px}.el-textarea__inner{display:block;resize:vertical;padding:5px 15px;line-height:1.5;box-sizing:border-box;width:100%;font-size:inherit;color:#606266;background-color:#fff;background-image:none;border:1px solid #dcdfe6;border-radius:4px;transition:border-color .2s cubic-bezier(.645,.045,.355,1)}.el-textarea__inner::-webkit-input-placeholder{color:#c0c4cc}.el-textarea__inner::-ms-input-placeholder{color:#c0c4cc}.el-textarea__inner::placeholder{color:#c0c4cc}.el-textarea__inner:hover{border-color:#c0c4cc}.el-textarea__inner:focus{outline:none;border-color:#42d885}.el-textarea .el-input__count{color:#909399;background:#fff;position:absolute;font-size:12px;bottom:5px;right:10px}.el-textarea.is-disabled .el-textarea__inner{background-color:#f5f7fa;border-color:#e4e7ed;color:#c0c4cc;cursor:not-allowed}.el-textarea.is-disabled .el-textarea__inner::-webkit-input-placeholder{color:#c0c4cc}.el-textarea.is-disabled .el-textarea__inner::-ms-input-placeholder{color:#c0c4cc}.el-textarea.is-disabled .el-textarea__inner::placeholder{color:#c0c4cc}.el-textarea.is-exceed .el-textarea__inner{border-color:#ff6d6d}.el-textarea.is-exceed .el-input__count{color:#ff6d6d}.el-input{position:relative;font-size:14px;display:inline-block;width:100%}.el-input::-webkit-scrollbar{z-index:11;width:6px}.el-input::-webkit-scrollbar:horizontal{height:6px}.el-input::-webkit-scrollbar-thumb{border-radius:5px;width:6px;background:#b4bccc}.el-input::-webkit-scrollbar-corner,.el-input::-webkit-scrollbar-track{background:#fff}.el-input::-webkit-scrollbar-track-piece{background:#fff;width:6px}.el-input .el-input__clear{color:#c0c4cc;font-size:14px;cursor:pointer;transition:color .2s cubic-bezier(.645,.045,.355,1)}.el-input .el-input__clear:hover{color:#909399}.el-input .el-input__count{height:100%;display:-ms-inline-flexbox;display:inline-flex;-ms-flex-align:center;align-items:center;color:#909399;font-size:12px}.el-input .el-input__count .el-input__count-inner{background:#fff;line-height:normal;display:inline-block;padding:0 5px}.el-input__inner{-webkit-appearance:none;background-color:#fff;background-image:none;border-radius:4px;border:1px solid #dcdfe6;box-sizing:border-box;color:#606266;display:inline-block;font-size:inherit;height:40px;line-height:40px;outline:none;padding:0 15px;transition:border-color .2s cubic-bezier(.645,.045,.355,1);width:100%}.el-input__inner::-webkit-input-placeholder{color:#c0c4cc}.el-input__inner::-ms-input-placeholder{color:#c0c4cc}.el-input__inner::placeholder{color:#c0c4cc}.el-input__inner:hover{border-color:#c0c4cc}.el-input__inner:focus{outline:none;border-color:#42d885}.el-input__suffix{position:absolute;height:100%;right:5px;top:0;text-align:center;color:#c0c4cc;transition:all .3s;pointer-events:none}.el-input__suffix-inner{pointer-events:all}.el-input__prefix{position:absolute;left:5px;top:0;color:#c0c4cc}.el-input__icon,.el-input__prefix{height:100%;text-align:center;transition:all .3s}.el-input__icon{width:25px;line-height:40px}.el-input__icon:after{content:"";height:100%;width:0;display:inline-block;vertical-align:middle}.el-input__validateIcon{pointer-events:none}.el-input.is-active .el-input__inner{outline:none;border-color:#42d885}.el-input.is-disabled .el-input__inner{background-color:#f5f7fa;border-color:#e4e7ed;color:#c0c4cc;cursor:not-allowed}.el-input.is-disabled .el-input__inner::-webkit-input-placeholder{color:#c0c4cc}.el-input.is-disabled .el-input__inner::-ms-input-placeholder{color:#c0c4cc}.el-input.is-disabled .el-input__inner::placeholder{color:#c0c4cc}.el-input.is-disabled .el-input__icon{cursor:not-allowed}.el-input.is-exceed .el-input__inner{border-color:#ff6d6d}.el-input.is-exceed .el-input__suffix .el-input__count{color:#ff6d6d}.el-input--suffix .el-input__inner{padding-right:30px}.el-input--prefix .el-input__inner{padding-left:30px}.el-input--medium{font-size:14px}.el-input--medium .el-input__inner{height:36px;line-height:36px}.el-input--medium .el-input__icon{line-height:36px}.el-input--small{font-size:13px}.el-input--small .el-input__inner{height:32px;line-height:32px}.el-input--small .el-input__icon{line-height:32px}.el-input--mini{font-size:12px}.el-input--mini .el-input__inner{height:28px;line-height:28px}.el-input--mini .el-input__icon{line-height:28px}.el-input-group{line-height:normal;display:inline-table;width:100%;border-collapse:separate;border-spacing:0}.el-input-group>.el-input__inner{vertical-align:middle;display:table-cell}.el-input-group__append,.el-input-group__prepend{background-color:#f5f7fa;color:#909399;vertical-align:middle;display:table-cell;position:relative;border:1px solid #dcdfe6;border-radius:4px;padding:0 20px;width:1px;white-space:nowrap}.el-input-group__append:focus,.el-input-group__prepend:focus{outline:none}.el-input-group__append .el-button,.el-input-group__append .el-select,.el-input-group__prepend .el-button,.el-input-group__prepend .el-select{display:inline-block;margin:-10px -20px}.el-input-group__append button.el-button,.el-input-group__append div.el-select .el-input__inner,.el-input-group__append div.el-select:hover .el-input__inner,.el-input-group__prepend button.el-button,.el-input-group__prepend div.el-select .el-input__inner,.el-input-group__prepend div.el-select:hover .el-input__inner{border-color:transparent;background-color:transparent;color:inherit;border-top:0;border-bottom:0}.el-input-group__append .el-button,.el-input-group__append .el-input,.el-input-group__prepend .el-button,.el-input-group__prepend .el-input{font-size:inherit}.el-input-group__prepend{border-right:0;border-top-right-radius:0;border-bottom-right-radius:0}.el-input-group__append{border-left:0}.el-input-group--prepend .el-input__inner,.el-input-group__append{border-top-left-radius:0;border-bottom-left-radius:0}.el-input-group--prepend .el-select .el-input.is-focus .el-input__inner{border-color:transparent}.el-input-group--append .el-input__inner{border-top-right-radius:0;border-bottom-right-radius:0}.el-input-group--append .el-select .el-input.is-focus .el-input__inner{border-color:transparent}.el-input__inner::-ms-clear{display:none;width:0;height:0}.el-button{display:inline-block;line-height:1;white-space:nowrap;cursor:pointer;background:#fff;border:1px solid #dcdfe6;border-color:#dcdfe6;color:#606266;-webkit-appearance:none;text-align:center;box-sizing:border-box;outline:none;margin:0;transition:.1s;font-weight:500;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;padding:12px 20px;font-size:14px;border-radius:4px}.el-button+.el-button{margin-left:10px}.el-button.is-round{padding:12px 20px}.el-button:focus,.el-button:hover{color:#42d885;border-color:#c6f3da;background-color:#ecfbf3}.el-button:active{color:#3bc278;border-color:#3bc278;outline:none}.el-button::-moz-focus-inner{border:0}.el-button [class*=el-icon-]+span{margin-left:5px}.el-button.is-plain:focus,.el-button.is-plain:hover{background:#fff;border-color:#42d885;color:#42d885}.el-button.is-plain:active{background:#fff;outline:none}.el-button.is-active,.el-button.is-plain:active{border-color:#3bc278;color:#3bc278}.el-button.is-disabled,.el-button.is-disabled:focus,.el-button.is-disabled:hover{color:#c0c4cc;cursor:not-allowed;background-image:none;background-color:#fff;border-color:#ebeef5}.el-button.is-disabled.el-button--text{background-color:transparent}.el-button.is-disabled.is-plain,.el-button.is-disabled.is-plain:focus,.el-button.is-disabled.is-plain:hover{background-color:#fff;border-color:#ebeef5;color:#c0c4cc}.el-button.is-loading{position:relative;pointer-events:none}.el-button.is-loading:before{pointer-events:none;content:"";position:absolute;left:-1px;top:-1px;right:-1px;bottom:-1px;border-radius:inherit;background-color:hsla(0,0%,100%,.35)}.el-button.is-round{border-radius:20px;padding:12px 23px}.el-button.is-circle{border-radius:50%;padding:12px}.el-button--primary{color:#fff;background-color:#42d885;border-color:#42d885}.el-button--primary:focus,.el-button--primary:hover{background:#68e09d;border-color:#68e09d;color:#fff}.el-button--primary:active{outline:none}.el-button--primary.is-active,.el-button--primary:active{background:#3bc278;border-color:#3bc278;color:#fff}.el-button--primary.is-disabled,.el-button--primary.is-disabled:active,.el-button--primary.is-disabled:focus,.el-button--primary.is-disabled:hover{color:#fff;background-color:#a1ecc2;border-color:#a1ecc2}.el-button--primary.is-plain{color:#42d885;background:#ecfbf3;border-color:#b3efce}.el-button--primary.is-plain:focus,.el-button--primary.is-plain:hover{background:#42d885;border-color:#42d885;color:#fff}.el-button--primary.is-plain:active{background:#3bc278;border-color:#3bc278;color:#fff;outline:none}.el-button--primary.is-plain.is-disabled,.el-button--primary.is-plain.is-disabled:active,.el-button--primary.is-plain.is-disabled:focus,.el-button--primary.is-plain.is-disabled:hover{color:#8ee8b6;background-color:#ecfbf3;border-color:#d9f7e7}.el-button--success{color:#fff;background-color:#42d885;border-color:#42d885}.el-button--success:focus,.el-button--success:hover{background:#68e09d;border-color:#68e09d;color:#fff}.el-button--success:active{outline:none}.el-button--success.is-active,.el-button--success:active{background:#3bc278;border-color:#3bc278;color:#fff}.el-button--success.is-disabled,.el-button--success.is-disabled:active,.el-button--success.is-disabled:focus,.el-button--success.is-disabled:hover{color:#fff;background-color:#a1ecc2;border-color:#a1ecc2}.el-button--success.is-plain{color:#42d885;background:#ecfbf3;border-color:#b3efce}.el-button--success.is-plain:focus,.el-button--success.is-plain:hover{background:#42d885;border-color:#42d885;color:#fff}.el-button--success.is-plain:active{background:#3bc278;border-color:#3bc278;color:#fff;outline:none}.el-button--success.is-plain.is-disabled,.el-button--success.is-plain.is-disabled:active,.el-button--success.is-plain.is-disabled:focus,.el-button--success.is-plain.is-disabled:hover{color:#8ee8b6;background-color:#ecfbf3;border-color:#d9f7e7}.el-button--warning{color:#fff;background-color:#f9c855;border-color:#f9c855}.el-button--warning:focus,.el-button--warning:hover{background:#fad377;border-color:#fad377;color:#fff}.el-button--warning:active{outline:none}.el-button--warning.is-active,.el-button--warning:active{background:#e0b44d;border-color:#e0b44d;color:#fff}.el-button--warning.is-disabled,.el-button--warning.is-disabled:active,.el-button--warning.is-disabled:focus,.el-button--warning.is-disabled:hover{color:#fff;background-color:#fce4aa;border-color:#fce4aa}.el-button--warning.is-plain{color:#f9c855;background:#fefaee;border-color:#fde9bb}.el-button--warning.is-plain:focus,.el-button--warning.is-plain:hover{background:#f9c855;border-color:#f9c855;color:#fff}.el-button--warning.is-plain:active{background:#e0b44d;border-color:#e0b44d;color:#fff;outline:none}.el-button--warning.is-plain.is-disabled,.el-button--warning.is-plain.is-disabled:active,.el-button--warning.is-plain.is-disabled:focus,.el-button--warning.is-plain.is-disabled:hover{color:#fbde99;background-color:#fefaee;border-color:#fef4dd}.el-button--danger{color:#fff;background-color:#ff6d6d;border-color:#ff6d6d}.el-button--danger:focus,.el-button--danger:hover{background:#ff8a8a;border-color:#ff8a8a;color:#fff}.el-button--danger:active{outline:none}.el-button--danger.is-active,.el-button--danger:active{background:#e66262;border-color:#e66262;color:#fff}.el-button--danger.is-disabled,.el-button--danger.is-disabled:active,.el-button--danger.is-disabled:focus,.el-button--danger.is-disabled:hover{color:#fff;background-color:#ffb6b6;border-color:#ffb6b6}.el-button--danger.is-plain{color:#ff6d6d;background:#fff0f0;border-color:#ffc5c5}.el-button--danger.is-plain:focus,.el-button--danger.is-plain:hover{background:#ff6d6d;border-color:#ff6d6d;color:#fff}.el-button--danger.is-plain:active{background:#e66262;border-color:#e66262;color:#fff;outline:none}.el-button--danger.is-plain.is-disabled,.el-button--danger.is-plain.is-disabled:active,.el-button--danger.is-plain.is-disabled:focus,.el-button--danger.is-plain.is-disabled:hover{color:#ffa7a7;background-color:#fff0f0;border-color:#ffe2e2}.el-button--info{color:#fff;background-color:#909399;border-color:#909399}.el-button--info:focus,.el-button--info:hover{background:#a6a9ad;border-color:#a6a9ad;color:#fff}.el-button--info:active{outline:none}.el-button--info.is-active,.el-button--info:active{background:#82848a;border-color:#82848a;color:#fff}.el-button--info.is-disabled,.el-button--info.is-disabled:active,.el-button--info.is-disabled:focus,.el-button--info.is-disabled:hover{color:#fff;background-color:#c8c9cc;border-color:#c8c9cc}.el-button--info.is-plain{color:#909399;background:#f4f4f5;border-color:#d3d4d6}.el-button--info.is-plain:focus,.el-button--info.is-plain:hover{background:#909399;border-color:#909399;color:#fff}.el-button--info.is-plain:active{background:#82848a;border-color:#82848a;color:#fff;outline:none}.el-button--info.is-plain.is-disabled,.el-button--info.is-plain.is-disabled:active,.el-button--info.is-plain.is-disabled:focus,.el-button--info.is-plain.is-disabled:hover{color:#bcbec2;background-color:#f4f4f5;border-color:#e9e9eb}.el-button--medium{padding:10px 20px;font-size:14px;border-radius:4px}.el-button--medium.is-round{padding:10px 20px}.el-button--medium.is-circle{padding:10px}.el-button--small{padding:9px 15px;font-size:12px;border-radius:3px}.el-button--small.is-round{padding:9px 15px}.el-button--small.is-circle{padding:9px}.el-button--mini{padding:7px 15px;font-size:12px;border-radius:3px}.el-button--mini.is-round{padding:7px 15px}.el-button--mini.is-circle{padding:7px}.el-button--text{border-color:transparent;color:#42d885;background:transparent;padding-left:0;padding-right:0}.el-button--text:focus,.el-button--text:hover{color:#68e09d;border-color:transparent;background-color:transparent}.el-button--text:active{color:#3bc278;background-color:transparent}.el-button--text.is-disabled,.el-button--text.is-disabled:focus,.el-button--text.is-disabled:hover,.el-button--text:active{border-color:transparent}.el-button-group{display:inline-block;vertical-align:middle}.el-button-group:after,.el-button-group:before{display:table;content:""}.el-button-group:after{clear:both}.el-button-group>.el-button{float:left;position:relative}.el-button-group>.el-button+.el-button{margin-left:0}.el-button-group>.el-button.is-disabled{z-index:1}.el-button-group>.el-button:first-child{border-top-right-radius:0;border-bottom-right-radius:0}.el-button-group>.el-button:last-child{border-top-left-radius:0;border-bottom-left-radius:0}.el-button-group>.el-button:first-child:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px;border-top-left-radius:4px;border-bottom-left-radius:4px}.el-button-group>.el-button:first-child:last-child.is-round{border-radius:20px}.el-button-group>.el-button:first-child:last-child.is-circle{border-radius:50%}.el-button-group>.el-button:not(:first-child):not(:last-child){border-radius:0}.el-button-group>.el-button:not(:last-child){margin-right:-1px}.el-button-group>.el-button.is-active,.el-button-group>.el-button:active,.el-button-group>.el-button:focus,.el-button-group>.el-button:hover{z-index:1}.el-button-group>.el-dropdown>.el-button{border-top-left-radius:0;border-bottom-left-radius:0;border-left-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--primary:first-child{border-right-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--primary:last-child{border-left-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--primary:not(:first-child):not(:last-child){border-left-color:hsla(0,0%,100%,.5);border-right-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--success:first-child{border-right-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--success:last-child{border-left-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--success:not(:first-child):not(:last-child){border-left-color:hsla(0,0%,100%,.5);border-right-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--warning:first-child{border-right-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--warning:last-child{border-left-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--warning:not(:first-child):not(:last-child){border-left-color:hsla(0,0%,100%,.5);border-right-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--danger:first-child{border-right-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--danger:last-child{border-left-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--danger:not(:first-child):not(:last-child){border-left-color:hsla(0,0%,100%,.5);border-right-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--info:first-child{border-right-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--info:last-child{border-left-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--info:not(:first-child):not(:last-child){border-left-color:hsla(0,0%,100%,.5);border-right-color:hsla(0,0%,100%,.5)}.el-transfer{font-size:14px}.el-transfer__buttons{display:inline-block;vertical-align:middle;padding:0 30px}.el-transfer__button{display:block;margin:0 auto;padding:10px;border-radius:50%;color:#fff;background-color:#42d885;font-size:0}.el-transfer__button.is-with-texts{border-radius:4px}.el-transfer__button.is-disabled,.el-transfer__button.is-disabled:hover{border:1px solid #dcdfe6;background-color:#f5f7fa;color:#c0c4cc}.el-transfer__button:first-child{margin-bottom:10px}.el-transfer__button:nth-child(2){margin:0}.el-transfer__button i,.el-transfer__button span{font-size:14px}.el-transfer__button [class*=el-icon-]+span{margin-left:0}.el-transfer-panel{border:1px solid #ebeef5;border-radius:4px;overflow:hidden;background:#fff;display:inline-block;vertical-align:middle;width:200px;max-height:100%;box-sizing:border-box;position:relative}.el-transfer-panel__body{height:246px}.el-transfer-panel__body.is-with-footer{padding-bottom:40px}.el-transfer-panel__list{margin:0;padding:6px 0;list-style:none;height:246px;overflow:auto;box-sizing:border-box}.el-transfer-panel__list.is-filterable{height:194px;padding-top:0}.el-transfer-panel__item{height:30px;line-height:30px;padding-left:15px;display:block}.el-transfer-panel__item+.el-transfer-panel__item{margin-left:0}.el-transfer-panel__item.el-checkbox{color:#606266}.el-transfer-panel__item:hover{color:#42d885}.el-transfer-panel__item.el-checkbox .el-checkbox__label{width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block;box-sizing:border-box;padding-left:24px;line-height:30px}.el-transfer-panel__item .el-checkbox__input{position:absolute;top:8px}.el-transfer-panel__filter{text-align:center;margin:15px;box-sizing:border-box;display:block;width:auto}.el-transfer-panel__filter .el-input__inner{height:32px;width:100%;font-size:12px;display:inline-block;box-sizing:border-box;border-radius:16px;padding-right:10px;padding-left:30px}.el-transfer-panel__filter .el-input__icon{margin-left:5px}.el-transfer-panel__filter .el-icon-circle-close{cursor:pointer}.el-transfer-panel .el-transfer-panel__header{height:40px;line-height:40px;background:#f5f7fa;margin:0;padding-left:15px;border-bottom:1px solid #ebeef5;box-sizing:border-box;color:#000}.el-transfer-panel .el-transfer-panel__header .el-checkbox{display:block;line-height:40px}.el-transfer-panel .el-transfer-panel__header .el-checkbox .el-checkbox__label{font-size:16px;color:#303133;font-weight:400}.el-transfer-panel .el-transfer-panel__header .el-checkbox .el-checkbox__label span{position:absolute;right:15px;color:#909399;font-size:12px;font-weight:400}.el-transfer-panel .el-transfer-panel__footer{height:40px;background:#fff;margin:0;padding:0;border-top:1px solid #ebeef5;position:absolute;bottom:0;left:0;width:100%;z-index:1}.el-transfer-panel .el-transfer-panel__footer:after{display:inline-block;content:"";height:100%;vertical-align:middle}.el-transfer-panel .el-transfer-panel__footer .el-checkbox{padding-left:20px;color:#606266}.el-transfer-panel .el-transfer-panel__empty{margin:0;height:30px;line-height:30px;padding:6px 15px 0;color:#909399;text-align:center}.el-transfer-panel .el-checkbox__label{padding-left:8px}.el-transfer-panel .el-checkbox__inner{height:14px;width:14px;border-radius:3px}.el-transfer-panel .el-checkbox__inner:after{height:6px;width:3px;left:4px}.el-container{display:-ms-flexbox;display:flex;-ms-flex-direction:row;flex-direction:row;-ms-flex:1;flex:1;-ms-flex-preferred-size:auto;flex-basis:auto;box-sizing:border-box;min-width:0}.el-container.is-vertical{-ms-flex-direction:column;flex-direction:column}.el-header{padding:0 20px}.el-aside,.el-header{box-sizing:border-box;-ms-flex-negative:0;flex-shrink:0}.el-aside,.el-main{overflow:auto}.el-main{display:block;-ms-flex:1;flex:1;-ms-flex-preferred-size:auto;flex-basis:auto;padding:20px}.el-footer,.el-main{box-sizing:border-box}.el-footer{padding:0 20px;-ms-flex-negative:0;flex-shrink:0}.el-timeline{margin:0;font-size:14px;list-style:none}.el-timeline .el-timeline-item:last-child .el-timeline-item__tail{display:none}.el-timeline-item{position:relative;padding-bottom:20px}.el-timeline-item__wrapper{position:relative;padding-left:28px;top:-3px}.el-timeline-item__tail{position:absolute;left:4px;height:100%;border-left:2px solid #e4e7ed}.el-timeline-item__icon{color:#fff;font-size:13px}.el-timeline-item__node{position:absolute;background-color:#e4e7ed;border-radius:50%;display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center;-ms-flex-align:center;align-items:center}.el-timeline-item__node--normal{left:-1px;width:12px;height:12px}.el-timeline-item__node--large{left:-2px;width:14px;height:14px}.el-timeline-item__node--primary,.el-timeline-item__node--success{background-color:#42d885}.el-timeline-item__node--warning{background-color:#f9c855}.el-timeline-item__node--danger{background-color:#ff6d6d}.el-timeline-item__node--info{background-color:#909399}.el-timeline-item__dot{position:absolute;display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center;-ms-flex-align:center;align-items:center}.el-timeline-item__content{color:#303133}.el-timeline-item__timestamp{color:#909399;line-height:1;font-size:13px}.el-timeline-item__timestamp.is-top{margin-bottom:8px;padding-top:4px}.el-timeline-item__timestamp.is-bottom{margin-top:8px}.el-link{display:-ms-inline-flexbox;display:inline-flex;-ms-flex-direction:row;flex-direction:row;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;vertical-align:middle;position:relative;text-decoration:none;outline:none;cursor:pointer;padding:0;font-size:14px;font-weight:500}.el-link.is-underline:hover:after{content:"";position:absolute;left:0;right:0;height:0;bottom:0;border-bottom:1px solid #42d885}.el-link.is-disabled{cursor:not-allowed}.el-link [class*=el-icon-]+span{margin-left:5px}.el-link.el-link--default{color:#606266}.el-link.el-link--default:hover{color:#42d885}.el-link.el-link--default:after{border-color:#42d885}.el-link.el-link--default.is-disabled{color:#c0c4cc}.el-link.el-link--primary{color:#42d885}.el-link.el-link--primary:hover{color:#68e09d}.el-link.el-link--primary:after{border-color:#42d885}.el-link.el-link--primary.is-disabled{color:#a1ecc2}.el-link.el-link--primary.is-underline:hover:after{border-color:#42d885}.el-link.el-link--danger{color:#ff6d6d}.el-link.el-link--danger:hover{color:#ff8a8a}.el-link.el-link--danger:after{border-color:#ff6d6d}.el-link.el-link--danger.is-disabled{color:#ffb6b6}.el-link.el-link--danger.is-underline:hover:after{border-color:#ff6d6d}.el-link.el-link--success{color:#42d885}.el-link.el-link--success:hover{color:#68e09d}.el-link.el-link--success:after{border-color:#42d885}.el-link.el-link--success.is-disabled{color:#a1ecc2}.el-link.el-link--success.is-underline:hover:after{border-color:#42d885}.el-link.el-link--warning{color:#f9c855}.el-link.el-link--warning:hover{color:#fad377}.el-link.el-link--warning:after{border-color:#f9c855}.el-link.el-link--warning.is-disabled{color:#fce4aa}.el-link.el-link--warning.is-underline:hover:after{border-color:#f9c855}.el-link.el-link--info{color:#909399}.el-link.el-link--info:hover{color:#a6a9ad}.el-link.el-link--info:after{border-color:#909399}.el-link.el-link--info.is-disabled{color:#c8c9cc}.el-link.el-link--info.is-underline:hover:after{border-color:#909399}.el-divider{background-color:#dcdfe6;position:relative}.el-divider--horizontal{display:block;height:1px;width:100%;margin:24px 0}.el-divider--vertical{display:inline-block;width:1px;height:1em;margin:0 8px;vertical-align:middle;position:relative}.el-divider__text{position:absolute;background-color:#fff;padding:0 20px;font-weight:500;color:#303133;font-size:14px}.el-divider__text.is-left{left:20px;transform:translateY(-50%)}.el-divider__text.is-center{left:50%;transform:translateX(-50%) translateY(-50%)}.el-divider__text.is-right{right:20px;transform:translateY(-50%)}.el-image__error,.el-image__inner,.el-image__placeholder{width:100%;height:100%}.el-image{position:relative;display:inline-block;overflow:hidden}.el-image__inner{vertical-align:top}.el-image__inner--center{position:relative;top:50%;left:50%;transform:translate(-50%,-50%);display:block}.el-image__error,.el-image__placeholder{background:#f5f7fa}.el-image__error{display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center;-ms-flex-align:center;align-items:center;font-size:14px;color:#c0c4cc;vertical-align:middle}.el-image__preview{cursor:pointer}.el-image-viewer__wrapper{position:fixed;top:0;right:0;bottom:0;left:0}.el-image-viewer__btn{position:absolute;z-index:1;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;border-radius:50%;opacity:.8;cursor:pointer;box-sizing:border-box;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.el-image-viewer__close{top:40px;right:40px;width:40px;height:40px;font-size:40px}.el-image-viewer__canvas{width:100%;height:100%;display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center;-ms-flex-align:center;align-items:center}.el-image-viewer__actions{left:50%;bottom:30px;transform:translateX(-50%);width:282px;height:44px;padding:0 23px;background-color:#606266;border-color:#fff;border-radius:22px}.el-image-viewer__actions__inner{width:100%;height:100%;text-align:justify;cursor:default;font-size:23px;color:#fff;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:distribute;justify-content:space-around}.el-image-viewer__prev{left:40px}.el-image-viewer__next,.el-image-viewer__prev{top:50%;transform:translateY(-50%);width:44px;height:44px;font-size:24px;color:#fff;background-color:#606266;border-color:#fff}.el-image-viewer__next{right:40px;text-indent:2px}.el-image-viewer__mask{position:absolute;width:100%;height:100%;top:0;left:0;opacity:.5;background:#000}.viewer-fade-enter-active{animation:viewer-fade-in .3s}.viewer-fade-leave-active{animation:viewer-fade-out .3s}@keyframes viewer-fade-in{0%{transform:translate3d(0,-20px,0);opacity:0}to{transform:translateZ(0);opacity:1}}@keyframes viewer-fade-out{0%{transform:translateZ(0);opacity:1}to{transform:translate3d(0,-20px,0);opacity:0}}.el-calendar{background-color:#fff}.el-calendar__header{display:-ms-flexbox;display:flex;-ms-flex-pack:justify;justify-content:space-between;padding:12px 20px;border-bottom:1px solid #ebeef5}.el-calendar__title{color:#000;-ms-flex-item-align:center;align-self:center}.el-calendar__body{padding:12px 20px 35px}.el-calendar-table{table-layout:fixed;width:100%}.el-calendar-table thead th{padding:12px 0;color:#606266;font-weight:400}.el-calendar-table:not(.is-range) td.next,.el-calendar-table:not(.is-range) td.prev{color:#c0c4cc}.el-calendar-table td{border-bottom:1px solid #ebeef5;border-right:1px solid #ebeef5;vertical-align:top;transition:background-color .2s ease}.el-calendar-table td.is-selected{background-color:#f2f8fe}.el-calendar-table td.is-today{color:#42d885}.el-calendar-table tr:first-child td{border-top:1px solid #ebeef5}.el-calendar-table tr td:first-child{border-left:1px solid #ebeef5}.el-calendar-table tr.el-calendar-table__row--hide-border td{border-top:none}.el-calendar-table .el-calendar-day{box-sizing:border-box;padding:8px;height:85px}.el-calendar-table .el-calendar-day:hover{cursor:pointer;background-color:#f2f8fe}.el-backtop{position:fixed;background-color:#fff;width:40px;height:40px;border-radius:50%;color:#42d885;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;font-size:20px;box-shadow:0 0 6px rgba(0,0,0,.12);cursor:pointer;z-index:5}.el-backtop:hover{background-color:#f2f6fc}.el-page-header{display:-ms-flexbox;display:flex;line-height:24px}.el-page-header__left{display:-ms-flexbox;display:flex;cursor:pointer;margin-right:40px;position:relative}.el-page-header__left:after{content:"";position:absolute;width:1px;height:16px;right:-20px;top:50%;transform:translateY(-50%);background-color:#dcdfe6}.el-page-header__left .el-icon-back{font-size:18px;margin-right:6px;-ms-flex-item-align:center;align-self:center}.el-page-header__title{font-size:14px;font-weight:500}.el-page-header__content{font-size:18px;color:#303133}.el-checkbox{color:#606266;font-weight:500;font-size:14px;position:relative;cursor:pointer;display:inline-block;white-space:nowrap;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;margin-right:30px}.el-checkbox.is-bordered{padding:9px 20px 9px 10px;border-radius:4px;border:1px solid #dcdfe6;box-sizing:border-box;line-height:normal;height:40px}.el-checkbox.is-bordered.is-checked{border-color:#42d885}.el-checkbox.is-bordered.is-disabled{border-color:#ebeef5;cursor:not-allowed}.el-checkbox.is-bordered+.el-checkbox.is-bordered{margin-left:10px}.el-checkbox.is-bordered.el-checkbox--medium{padding:7px 20px 7px 10px;border-radius:4px;height:36px}.el-checkbox.is-bordered.el-checkbox--medium .el-checkbox__label{line-height:17px;font-size:14px}.el-checkbox.is-bordered.el-checkbox--medium .el-checkbox__inner{height:14px;width:14px}.el-checkbox.is-bordered.el-checkbox--small{padding:5px 15px 5px 10px;border-radius:3px;height:32px}.el-checkbox.is-bordered.el-checkbox--small .el-checkbox__label{line-height:15px;font-size:12px}.el-checkbox.is-bordered.el-checkbox--small .el-checkbox__inner{height:12px;width:12px}.el-checkbox.is-bordered.el-checkbox--small .el-checkbox__inner:after{height:6px;width:2px}.el-checkbox.is-bordered.el-checkbox--mini{padding:3px 15px 3px 10px;border-radius:3px;height:28px}.el-checkbox.is-bordered.el-checkbox--mini .el-checkbox__label{line-height:12px;font-size:12px}.el-checkbox.is-bordered.el-checkbox--mini .el-checkbox__inner{height:12px;width:12px}.el-checkbox.is-bordered.el-checkbox--mini .el-checkbox__inner:after{height:6px;width:2px}.el-checkbox__input{white-space:nowrap;cursor:pointer;outline:none;display:inline-block;line-height:1;position:relative;vertical-align:middle}.el-checkbox__input.is-disabled .el-checkbox__inner{background-color:#edf2fc;border-color:#dcdfe6;cursor:not-allowed}.el-checkbox__input.is-disabled .el-checkbox__inner:after{cursor:not-allowed;border-color:#c0c4cc}.el-checkbox__input.is-disabled .el-checkbox__inner+.el-checkbox__label{cursor:not-allowed}.el-checkbox__input.is-disabled.is-checked .el-checkbox__inner{background-color:#f2f6fc;border-color:#dcdfe6}.el-checkbox__input.is-disabled.is-checked .el-checkbox__inner:after{border-color:#c0c4cc}.el-checkbox__input.is-disabled.is-indeterminate .el-checkbox__inner{background-color:#f2f6fc;border-color:#dcdfe6}.el-checkbox__input.is-disabled.is-indeterminate .el-checkbox__inner:before{background-color:#c0c4cc;border-color:#c0c4cc}.el-checkbox__input.is-disabled+span.el-checkbox__label{color:#c0c4cc;cursor:not-allowed}.el-checkbox__input.is-checked .el-checkbox__inner{background-color:#42d885;border-color:#42d885}.el-checkbox__input.is-checked .el-checkbox__inner:after{transform:rotate(45deg) scaleY(1)}.el-checkbox__input.is-checked+.el-checkbox__label{color:#42d885}.el-checkbox__input.is-focus .el-checkbox__inner{border-color:#42d885}.el-checkbox__input.is-indeterminate .el-checkbox__inner{background-color:#42d885;border-color:#42d885}.el-checkbox__input.is-indeterminate .el-checkbox__inner:before{content:"";position:absolute;display:block;background-color:#fff;height:2px;transform:scale(.5);left:0;right:0;top:5px}.el-checkbox__input.is-indeterminate .el-checkbox__inner:after{display:none}.el-checkbox__inner{display:inline-block;position:relative;border:1px solid #dcdfe6;border-radius:2px;box-sizing:border-box;width:14px;height:14px;background-color:#fff;z-index:1;transition:border-color .25s cubic-bezier(.71,-.46,.29,1.46),background-color .25s cubic-bezier(.71,-.46,.29,1.46)}.el-checkbox__inner:hover{border-color:#42d885}.el-checkbox__inner:after{box-sizing:content-box;content:"";border:1px solid #fff;border-left:0;border-top:0;height:7px;left:4px;position:absolute;top:1px;transform:rotate(45deg) scaleY(0);width:3px;transition:transform .15s ease-in .05s;transform-origin:center}.el-checkbox__original{opacity:0;outline:none;position:absolute;margin:0;width:0;height:0;z-index:-1}.el-checkbox__label{display:inline-block;padding-left:10px;line-height:19px;font-size:14px}.el-checkbox:last-of-type{margin-right:0}.el-checkbox-button,.el-checkbox-button__inner{position:relative;display:inline-block}.el-checkbox-button__inner{line-height:1;font-weight:500;white-space:nowrap;vertical-align:middle;cursor:pointer;background:#fff;border:1px solid #dcdfe6;border-left:0;color:#606266;-webkit-appearance:none;text-align:center;box-sizing:border-box;outline:none;margin:0;transition:all .3s cubic-bezier(.645,.045,.355,1);-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;padding:12px 20px;font-size:14px;border-radius:0}.el-checkbox-button__inner.is-round{padding:12px 20px}.el-checkbox-button__inner:hover{color:#42d885}.el-checkbox-button__inner [class*=el-icon-]{line-height:.9}.el-checkbox-button__inner [class*=el-icon-]+span{margin-left:5px}.el-checkbox-button__original{opacity:0;outline:none;position:absolute;margin:0;z-index:-1}.el-checkbox-button.is-checked .el-checkbox-button__inner{color:#fff;background-color:#42d885;border-color:#42d885;box-shadow:-1px 0 0 0 #8ee8b6}.el-checkbox-button.is-checked:first-child .el-checkbox-button__inner{border-left-color:#42d885}.el-checkbox-button.is-disabled .el-checkbox-button__inner{color:#c0c4cc;cursor:not-allowed;background-image:none;background-color:#fff;border-color:#ebeef5;box-shadow:none}.el-checkbox-button.is-disabled:first-child .el-checkbox-button__inner{border-left-color:#ebeef5}.el-checkbox-button:first-child .el-checkbox-button__inner{border-left:1px solid #dcdfe6;border-radius:4px 0 0 4px;box-shadow:none!important}.el-checkbox-button.is-focus .el-checkbox-button__inner{border-color:#42d885}.el-checkbox-button:last-child .el-checkbox-button__inner{border-radius:0 4px 4px 0}.el-checkbox-button--medium .el-checkbox-button__inner{padding:10px 20px;font-size:14px;border-radius:0}.el-checkbox-button--medium .el-checkbox-button__inner.is-round{padding:10px 20px}.el-checkbox-button--small .el-checkbox-button__inner{padding:9px 15px;font-size:12px;border-radius:0}.el-checkbox-button--small .el-checkbox-button__inner.is-round{padding:9px 15px}.el-checkbox-button--mini .el-checkbox-button__inner{padding:7px 15px;font-size:12px;border-radius:0}.el-checkbox-button--mini .el-checkbox-button__inner.is-round{padding:7px 15px}.el-checkbox-group{font-size:0}.el-radio{color:#606266;font-weight:500;line-height:1;position:relative;cursor:pointer;display:inline-block;white-space:nowrap;outline:none;font-size:14px;margin-right:30px;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.el-radio.is-bordered{padding:12px 20px 0 10px;border-radius:4px;border:1px solid #dcdfe6;box-sizing:border-box;height:40px}.el-radio.is-bordered.is-checked{border-color:#42d885}.el-radio.is-bordered.is-disabled{cursor:not-allowed;border-color:#ebeef5}.el-radio.is-bordered+.el-radio.is-bordered{margin-left:10px}.el-radio--medium.is-bordered{padding:10px 20px 0 10px;border-radius:4px;height:36px}.el-radio--medium.is-bordered .el-radio__label{font-size:14px}.el-radio--medium.is-bordered .el-radio__inner{height:14px;width:14px}.el-radio--small.is-bordered{padding:8px 15px 0 10px;border-radius:3px;height:32px}.el-radio--small.is-bordered .el-radio__label{font-size:12px}.el-radio--small.is-bordered .el-radio__inner{height:12px;width:12px}.el-radio--mini.is-bordered{padding:6px 15px 0 10px;border-radius:3px;height:28px}.el-radio--mini.is-bordered .el-radio__label{font-size:12px}.el-radio--mini.is-bordered .el-radio__inner{height:12px;width:12px}.el-radio:last-child{margin-right:0}.el-radio__input{white-space:nowrap;cursor:pointer;outline:none;display:inline-block;line-height:1;position:relative;vertical-align:middle}.el-radio__input.is-disabled .el-radio__inner{background-color:#f5f7fa;border-color:#e4e7ed;cursor:not-allowed}.el-radio__input.is-disabled .el-radio__inner:after{cursor:not-allowed;background-color:#f5f7fa}.el-radio__input.is-disabled .el-radio__inner+.el-radio__label{cursor:not-allowed}.el-radio__input.is-disabled.is-checked .el-radio__inner{background-color:#f5f7fa;border-color:#e4e7ed}.el-radio__input.is-disabled.is-checked .el-radio__inner:after{background-color:#c0c4cc}.el-radio__input.is-disabled+span.el-radio__label{color:#c0c4cc;cursor:not-allowed}.el-radio__input.is-checked .el-radio__inner{border-color:#42d885;background:#42d885}.el-radio__input.is-checked .el-radio__inner:after{transform:translate(-50%,-50%) scale(1)}.el-radio__input.is-checked+.el-radio__label{color:#42d885}.el-radio__input.is-focus .el-radio__inner{border-color:#42d885}.el-radio__inner{border:1px solid #dcdfe6;border-radius:100%;width:14px;height:14px;background-color:#fff;position:relative;cursor:pointer;display:inline-block;box-sizing:border-box}.el-radio__inner:hover{border-color:#42d885}.el-radio__inner:after{width:4px;height:4px;border-radius:100%;background-color:#fff;content:"";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%) scale(0);transition:transform .15s ease-in}.el-radio__original{opacity:0;outline:none;position:absolute;z-index:-1;top:0;left:0;right:0;bottom:0;margin:0}.el-radio:focus:not(.is-focus):not(:active):not(.is-disabled) .el-radio__inner{box-shadow:0 0 2px 2px #42d885}.el-radio__label{font-size:14px;padding-left:10px}.el-scrollbar{overflow:hidden;position:relative}.el-scrollbar:active>.el-scrollbar__bar,.el-scrollbar:focus>.el-scrollbar__bar,.el-scrollbar:hover>.el-scrollbar__bar{opacity:1;transition:opacity .34s ease-out}.el-scrollbar__wrap{overflow:scroll;height:100%}.el-scrollbar__wrap--hidden-default::-webkit-scrollbar{width:0;height:0}.el-scrollbar__thumb{position:relative;display:block;width:0;height:0;cursor:pointer;border-radius:inherit;background-color:hsla(220,4%,58%,.3);transition:background-color .3s}.el-scrollbar__thumb:hover{background-color:hsla(220,4%,58%,.5)}.el-scrollbar__bar{position:absolute;right:2px;bottom:2px;z-index:1;border-radius:4px;opacity:0;transition:opacity .12s ease-out}.el-scrollbar__bar.is-vertical{width:6px;top:2px}.el-scrollbar__bar.is-vertical>div{width:100%}.el-scrollbar__bar.is-horizontal{height:6px;left:2px}.el-scrollbar__bar.is-horizontal>div{height:100%}.el-cascader-panel{display:-ms-flexbox;display:flex;border-radius:4px;font-size:14px}.el-cascader-panel.is-bordered{border:1px solid #e4e7ed;border-radius:4px}.el-cascader-menu{min-width:180px;box-sizing:border-box;color:#606266;border-right:1px solid #e4e7ed}.el-cascader-menu:last-child{border-right:none}.el-cascader-menu:last-child .el-cascader-node{padding-right:20px}.el-cascader-menu__wrap{height:204px}.el-cascader-menu__list{position:relative;min-height:100%;margin:0;padding:6px 0;list-style:none;box-sizing:border-box}.el-cascader-menu__hover-zone{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none}.el-cascader-menu__empty-text{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);text-align:center;color:#c0c4cc}.el-cascader-node{position:relative;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:0 30px 0 20px;height:34px;line-height:34px;outline:none}.el-cascader-node.is-selectable.in-active-path{color:#606266}.el-cascader-node.in-active-path,.el-cascader-node.is-active,.el-cascader-node.is-selectable.in-checked-path{color:#42d885;font-weight:700}.el-cascader-node:not(.is-disabled){cursor:pointer}.el-cascader-node:not(.is-disabled):focus,.el-cascader-node:not(.is-disabled):hover{background:#f5f7fa}.el-cascader-node.is-disabled{color:#c0c4cc;cursor:not-allowed}.el-cascader-node__prefix{position:absolute;left:10px}.el-cascader-node__postfix{position:absolute;right:10px}.el-cascader-node__label{-ms-flex:1;flex:1;padding:0 10px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.el-cascader-node>.el-checkbox,.el-cascader-node>.el-radio{margin-right:0}.el-cascader-node>.el-radio .el-radio__label{padding-left:0}.el-avatar{display:inline-block;box-sizing:border-box;text-align:center;overflow:hidden;color:#fff;background:#c0c4cc;width:40px;height:40px;line-height:40px;font-size:14px}.el-avatar>img{display:block;height:100%;vertical-align:middle}.el-avatar--circle{border-radius:50%}.el-avatar--square{border-radius:4px}.el-avatar--icon{font-size:18px}.el-avatar--large{width:40px;height:40px;line-height:40px}.el-avatar--medium{width:36px;height:36px;line-height:36px}.el-avatar--small{width:28px;height:28px;line-height:28px}@keyframes el-drawer-fade-in{0%{opacity:0}to{opacity:1}}@keyframes rtl-drawer-in{0%{transform:translate(100%)}to{transform:translate(0)}}@keyframes rtl-drawer-out{0%{transform:translate(0)}to{transform:translate(100%)}}@keyframes ltr-drawer-in{0%{transform:translate(-100%)}to{transform:translate(0)}}@keyframes ltr-drawer-out{0%{transform:translate(0)}to{transform:translate(-100%)}}@keyframes ttb-drawer-in{0%{transform:translateY(-100%)}to{transform:translate(0)}}@keyframes ttb-drawer-out{0%{transform:translate(0)}to{transform:translateY(-100%)}}@keyframes btt-drawer-in{0%{transform:translateY(100%)}to{transform:translate(0)}}@keyframes btt-drawer-out{0%{transform:translate(0)}to{transform:translateY(100%)}}.el-drawer{position:absolute;box-sizing:border-box;background-color:#fff;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;box-shadow:0 8px 10px -5px rgba(0,0,0,.2),0 16px 24px 2px rgba(0,0,0,.14),0 6px 30px 5px rgba(0,0,0,.12);overflow:hidden}.el-drawer.rtl{animation:rtl-drawer-out 225ms cubic-bezier(0,0,.2,1) 0ms}.el-drawer__open .el-drawer.rtl{animation:rtl-drawer-in 225ms cubic-bezier(0,0,.2,1) 0ms}.el-drawer.ltr{animation:ltr-drawer-out 225ms cubic-bezier(0,0,.2,1) 0ms}.el-drawer__open .el-drawer.ltr{animation:ltr-drawer-in 225ms cubic-bezier(0,0,.2,1) 0ms}.el-drawer.ttb{animation:ttb-drawer-out 225ms cubic-bezier(0,0,.2,1) 0ms}.el-drawer__open .el-drawer.ttb{animation:ttb-drawer-in 225ms cubic-bezier(0,0,.2,1) 0ms}.el-drawer.btt{animation:btt-drawer-out 225ms cubic-bezier(0,0,.2,1) 0ms}.el-drawer__open .el-drawer.btt{animation:btt-drawer-in 225ms cubic-bezier(0,0,.2,1) 0ms}.el-drawer__header{-ms-flex-align:center;align-items:center;color:#72767b;display:-ms-flexbox;display:flex;margin-bottom:32px;padding:20px;padding-bottom:0}.el-drawer__header>:first-child{-ms-flex:1;flex:1}.el-drawer__title{margin:0;-ms-flex:1;flex:1;line-height:inherit;font-size:1rem}.el-drawer__close-btn{border:none;cursor:pointer;font-size:20px;color:inherit;background-color:transparent}.el-drawer__body{-ms-flex:1;flex:1}.el-drawer__body>*{box-sizing:border-box}.el-drawer.ltr,.el-drawer.rtl{height:100%;top:0;bottom:0}.el-drawer.btt,.el-drawer.ttb{width:100%;left:0;right:0}.el-drawer.ltr{left:0}.el-drawer.rtl{right:0}.el-drawer.ttb{top:0}.el-drawer.btt{bottom:0}.el-drawer__container{position:relative;left:0;right:0;top:0;bottom:0;height:100%;width:100%}.el-drawer-fade-enter-active{animation:el-drawer-fade-in 225ms cubic-bezier(0,0,.2,1) 0ms}.el-drawer-fade-leave-active{animation:el-drawer-fade-in 225ms cubic-bezier(0,0,.2,1) 0ms reverse}.dark-themes #app,.dark-themes body,.dark-themeshtml{background-color:#161616;color:#a7a7a7}.dark-themes .h1,.dark-themes .h2,.dark-themes .h3,.dark-themes .h4,.dark-themes .h5,.dark-themes .h6,.dark-themes h1,.dark-themes h2,.dark-themes h3,.dark-themes h4,.dark-themes h5,.dark-themes h6,.dark-themes p{color:#a7a7a7;font-weight:400}.dark-themes .el-table:not(.el-table--public){color:#a7a7a7!important;border:1px solid #292929;background-color:transparent!important}.dark-themes .el-table:not(.el-table--public) .el-table__empty-block,.dark-themes .el-table:not(.el-table--public) th,.dark-themes .el-table:not(.el-table--public) tr{background-color:#1f1d1d!important}.dark-themes .el-table:not(.el-table--public) .el-table__header-wrapper,.dark-themes .el-table:not(.el-table--public) td,.dark-themes .el-table:not(.el-table--public) th.is-leaf{border-bottom:1px solid #161616}.dark-themes .el-table:not(.el-table--public) .el-table__header-wrapper .cell{color:#ddd!important}.dark-themes .el-table:not(.el-table--public) .el-table__expanded-cell{background-color:#242327}.dark-themes .el-table:not(.el-table--public) .el-table__body-wrapper .el-table__body tr.current-row>td{background-color:transparent}.dark-themes .el-table:not(.el-table--public) .el-table__body-wrapper .el-table__body tr:hover td{background-color:#393a3e!important;color:#ddd!important}.dark-themes .el-table:not(.el-table--public) .el-table__body-wrapper .el-table__body tr:last-child td{border-bottom:none}.dark-themes .el-table__body tr.hover-row.current-row>td,.dark-themes .el-table__body tr.hover-row.el-table__row--striped.current-row>td,.dark-themes .el-table__body tr.hover-row.el-table__row--striped>td,.dark-themes .el-table__body tr.hover-row>td,.dark-themes .el-table__body tr:hover>td{background-color:#393a3e!important}.dark-themes .el-table__fixed,.dark-themes .el-table__fixed-right{box-shadow:0 0 10px rgba(0,0,0,.48)}.dark-themes .el-checkbox .el-checkbox__input.is-checked+.el-checkbox__label{color:#606266}.dark-themes .el-select:not(.el-select--public) .el-input__inner{background-color:transparent!important;color:#a7a7a7}.dark-themes .el-select:not(.el-select--public) .el-input__inner:focus,.dark-themes .el-select:not(.el-select--public) .el-input__inner:hover{border-color:#737373}.dark-themes .el-select:not(.el-select--public).select-radius .el-input__inner{border-color:#37363d!important}.dark-themes .el-select:not(.el-select--public):hover .el-input__inner{border-color:#737373!important}.dark-themes .el-dialog:not(.el-dialog--private) .el-dialog__body{padding:10px 20px}.dark-themes .el-select-dropdown:not(.el-select--public){border-color:#373737;background-color:#373737;border-left:none;border-right:none}.dark-themes .el-select-dropdown:not(.el-select--public) .el-select-dropdown__item{color:#a7a7a7!important}.dark-themes .el-select-dropdown:not(.el-select--public) .el-select-dropdown__item.hover,.dark-themes .el-select-dropdown:not(.el-select--public) .el-select-dropdown__item.selected,.dark-themes .el-select-dropdown:not(.el-select--public) .el-select-dropdown__item:hover{background-color:#282828}.dark-themes .el-select-dropdown:not(.el-select--public) .popper__arrow,.dark-themes .el-select-dropdown:not(.el-select--public) .popper__arrow:after{border-bottom-color:#373737}.dark-themes .el-date-picker .el-popper[x-placement^=bottom] .popper__arrow,.dark-themes .el-date-picker .el-popper[x-placement^=bottom] .popper__arrow:after{border-bottom-color:#fff!important}.dark-themes .el-form:not(.el-form--public) .el-form-item .el-checkbox__label,.dark-themes .el-form:not(.el-form--public) .el-form-item .el-form-item__label,.dark-themes .page-title .el-form-item .el-checkbox__label,.dark-themes .page-title .el-form-item .el-form-item__label{color:#a7a7a7!important}.dark-themes .el-form:not(.el-form--public) .el-input .el-input__inner,.dark-themes .el-form:not(.el-form--public) .el-input .el-textarea__inner,.dark-themes .el-form:not(.el-form--public) .el-textarea .el-input__inner,.dark-themes .el-form:not(.el-form--public) .el-textarea .el-textarea__inner,.dark-themes .page-title .el-input .el-input__inner,.dark-themes .page-title .el-input .el-textarea__inner,.dark-themes .page-title .el-textarea .el-input__inner,.dark-themes .page-title .el-textarea .el-textarea__inner{background-color:transparent!important;color:#a7a7a7!important;border-color:#37363d!important}.dark-themes .el-form:not(.el-form--public) .el-input.is-disabled .el-input__inner,.dark-themes .el-form:not(.el-form--public) .el-input.is-disabled .el-textarea__inner,.dark-themes .el-form:not(.el-form--public) .el-textarea.is-disabled .el-input__inner,.dark-themes .el-form:not(.el-form--public) .el-textarea.is-disabled .el-textarea__inner,.dark-themes .page-title .el-input.is-disabled .el-input__inner,.dark-themes .page-title .el-input.is-disabled .el-textarea__inner,.dark-themes .page-title .el-textarea.is-disabled .el-input__inner,.dark-themes .page-title .el-textarea.is-disabled .el-textarea__inner{background-color:#242325!important;border-color:#242325!important}.dark-themes .el-form:not(.el-form--public) .el-input.is-disabled:hover .el-input__inner,.dark-themes .el-form:not(.el-form--public) .el-input.is-disabled:hover .el-textarea__inner,.dark-themes .el-form:not(.el-form--public) .el-textarea.is-disabled:hover .el-input__inner,.dark-themes .el-form:not(.el-form--public) .el-textarea.is-disabled:hover .el-textarea__inner,.dark-themes .page-title .el-input.is-disabled:hover .el-input__inner,.dark-themes .page-title .el-input.is-disabled:hover .el-textarea__inner,.dark-themes .page-title .el-textarea.is-disabled:hover .el-input__inner,.dark-themes .page-title .el-textarea.is-disabled:hover .el-textarea__inner{border-color:#242325!important}.dark-themes .el-form:not(.el-form--public) .el-input.input-radius .el-input__inner,.dark-themes .el-form:not(.el-form--public) .el-textarea.input-radius .el-input__inner,.dark-themes .page-title .el-input.input-radius .el-input__inner,.dark-themes .page-title .el-textarea.input-radius .el-input__inner{border-color:#37363d!important;border-radius:40px}.dark-themes .el-form:not(.el-form--public) .el-input:hover .el-input__inner,.dark-themes .el-form:not(.el-form--public) .el-input:hover .el-textarea__inner,.dark-themes .el-form:not(.el-form--public) .el-textarea:hover .el-input__inner,.dark-themes .el-form:not(.el-form--public) .el-textarea:hover .el-textarea__inner,.dark-themes .page-title .el-input:hover .el-input__inner,.dark-themes .page-title .el-input:hover .el-textarea__inner,.dark-themes .page-title .el-textarea:hover .el-input__inner,.dark-themes .page-title .el-textarea:hover .el-textarea__inner{border-color:#737373!important}.dark-themes .el-form:not(.el-form--public) input::-webkit-input-placeholder,.dark-themes .el-form:not(.el-form--public) textarea::-webkit-input-placeholder,.dark-themes .page-title input::-webkit-input-placeholder,.dark-themes .page-title textarea::-webkit-input-placeholder{color:hsla(0,0%,65%,.5)!important}.dark-themes .el-form:not(.el-form--public) input:-moz-placeholder,.dark-themes .el-form:not(.el-form--public) input::-moz-placeholder,.dark-themes .el-form:not(.el-form--public) textarea:-moz-placeholder,.dark-themes .el-form:not(.el-form--public) textarea::-moz-placeholder,.dark-themes .page-title input:-moz-placeholder,.dark-themes .page-title input::-moz-placeholder,.dark-themes .page-title textarea:-moz-placeholder,.dark-themes .page-title textarea::-moz-placeholder{color:hsla(0,0%,65%,.5)!important}.dark-themes .el-form:not(.el-form--public) input:-ms-input-placeholder,.dark-themes .el-form:not(.el-form--public) textarea:-ms-input-placeholder,.dark-themes .page-title input:-ms-input-placeholder,.dark-themes .page-title textarea:-ms-input-placeholder{color:hsla(0,0%,65%,.5)!important}.dark-themes .el-form.el-form--public .el-input.is-disabled .el-input__inner,.dark-themes .el-form.el-form--public .el-input.is-disabled .el-textarea__inner,.dark-themes .el-form.el-form--public .el-input.is-disabled:hover .el-input__inner,.dark-themes .el-form.el-form--public .el-input.is-disabled:hover .el-textarea__inner{border-color:#f5f7fa!important}.dark-themes .el-loading-mask{background-color:#232429!important}.dark-themes .el-button.is-plain{color:#a7a7a7!important;background-color:transparent!important;border-color:#44444c!important}.dark-themes .el-button.is-plain.el-button--success:hover{border-color:#42d885!important;background-color:#42d885!important;color:#fff!important}.dark-themes .el-button.is-plain.el-button--warning:hover{border-color:#f9c855!important;background-color:#f9c855!important;color:#fff!important}.dark-themes .el-button.is-plain.el-button--danger:hover{border-color:#ff6d6d!important;background-color:#ff6d6d!important;color:#fff!important}.dark-themes .el-card.el-card--self{color:#a7a7a7!important;background-color:#1f1d1d!important}.dark-themes .el-card.el-card--self .el-card__header{color:#fff!important}.dark-themes .cache-btn{color:#a7a7a7!important}.dark-themes .cache-btn:hover{color:#42d885!important}.dark-themes .refresh-btn{color:#fff!important}.dark-themes .page-title,.dark-themes .refresh-btn:hover{color:#fff}.dark-themes .page-title .el-breadcrumb .el-breadcrumb__inner{color:#e8e8e8!important}.dark-themes .page-title .el-breadcrumb .el-breadcrumb__inner:hover{color:#fff!important}.dark-themes .page-title .el-breadcrumb .el-breadcrumb__item.breadcrumb-name .el-breadcrumb__inner,.dark-themes .page-title .el-breadcrumb .el-breadcrumb__item.breadcrumb-name:hover .el-breadcrumb__inner{color:#929299!important}.dark-themes .overview-view .card-box .card-title{color:#fff}.dark-themes .overview-view .card-item{background-color:#1f1d1d;border:1px solid #292929}.dark-themes .overview-view .card-item .icon{color:#227d51;border-color:#227d51;background-color:#232d2e}.dark-themes .overview-view .card-item .desc h3{color:#fff}.dark-themes .overview-view .card-item .desc p{color:#929299}.dark-themes .status:before{background-color:#a7a7a7!important}.dark-themes .status.running{color:#227d51!important}.dark-themes .status.stopped.danger:before{background-color:#f56c6c!important}.dark-themes .status.running:before{background-color:#227d51!important}.dark-themes .el-pagination .el-select .el-input .el-input__inner{border-color:#37363d}.dark-themes .el-pagination.is-background{color:#a7a7a7!important}.dark-themes .el-pagination.is-background button{background-color:transparent!important}.dark-themes .el-pagination.is-background button:hover{color:#42d885}.dark-themes .el-pagination.is-background .el-pager .number{color:#a7a7a7!important;background-color:transparent!important}.dark-themes .el-pagination.is-background .el-pager .number:hover{color:#42d885!important}.dark-themes .el-pagination.is-background .el-pager .number.active{background-color:#42d885!important;color:#fff!important}.dark-themes .rule-create .form-block--wrapper{border-bottom:1px solid #37363d}.dark-themes .rule-create .sql-tips{border:4px dashed #37363d;color:#c0c4cc}.dark-themes .rule-create .sql-tips .title{color:#fff}.dark-themes .rule-create .sql-tips p{color:#c0c4cc}.dark-themes .rule-create .code{background-color:rgba(55,54,61,.5)}.dark-themes .rule-create .code-sql__editor{border:1px solid #37363d;background-color:#2b292d}.dark-themes .rule-create .code-sql__editor .CodeMirror-gutters{background-color:#2b292d!important;border-right-color:#37363d!important}.dark-themes .rule-create .code-sql__editor .CodeMirror-scroll{background-color:#1e1c1c}.dark-themes .rule-create .code-sql__editor .CodeMirror-line{color:#606266}.dark-themes .rule-create .code-sql__editor .cm-keyword,.dark-themes .rule-create .code-sql__editor .cm-operator{color:#f92371}.dark-themes .rule-create .payload-type{background-color:#37363d80;border:1px solid #37363d;border-top:none}.dark-themes .rule-actions .action-card{background:#37363d80}.dark-themes .rule-actions .action-card .action-footer{border-top:1px solid #37363d}.dark-themes .rule-actions .action-card .filed-item .title{color:#ddd}.dark-themes .monaco-container{height:100%;border:1px solid #37363d}.dark-themes .jwt-payload-desc{background:rgba(55,54,61,.5)}.dark-themes .clients-view .card-subtitle{color:#f8f8f8}.dark-themes .custom-pagination a{border:1px solid #292929}.dark-themes .topic-qos-radio .el-radio-button__inner{background:#1b1c20;color:#9e9e9f;border:1px solid #35363b}.dark-themes .topic-qos-radio .el-radio-button__orig-radio:checked+.el-radio-button__inner{background-color:#42d885;color:#fff;box-shadow:none}.dark-themes .topic-metrics .message-card.in{background:linear-gradient(90deg,#1d1e27,#272644)}.dark-themes .topic-metrics .message-card.out{background:linear-gradient(90deg,#1c2023,#1e322d)}.dark-themes .topic-metrics .message-card.drop{background:linear-gradient(90deg,#1a1f27,#212d44)}.dark-themes .alarms-view .table-title{color:#fff}.light-themes #app,.light-themes body,.light-themeshtml{background-color:#f6f7fb;color:#71737d}.light-themes .h1,.light-themes .h2,.light-themes .h3,.light-themes .h4,.light-themes .h5,.light-themes .h6,.light-themes h1,.light-themes h2,.light-themes h3,.light-themes h4,.light-themes h5,.light-themes h6,.light-themes p{color:#71737d;font-weight:400}.light-themes .el-table:not(.el-table--public){color:#71737d;border:1px solid #f1f1f1;background-color:transparent!important}.light-themes .el-table:not(.el-table--public) .el-table__empty-block,.light-themes .el-table:not(.el-table--public) th,.light-themes .el-table:not(.el-table--public) tr{background-color:#fff!important}.light-themes .el-table:not(.el-table--public) .el-table__header-wrapper,.light-themes .el-table:not(.el-table--public) td,.light-themes .el-table:not(.el-table--public) th.is-leaf{border-bottom:1px solid #f1f1f1}.light-themes .el-table:not(.el-table--public) .el-table__header-wrapper .cell{color:#606266!important}.light-themes .el-table:not(.el-table--public) .el-table__body-wrapper .el-table__body tr.current-row>td{background-color:transparent}.light-themes .el-table:not(.el-table--public) .el-table__body-wrapper .el-table__body tr:hover td{background-color:#f5f5f5!important;color:#71737d!important}.light-themes .el-table:not(.el-table--public) .el-table__body-wrapper .el-table__body tr:last-child td{border-bottom:none}.light-themes .el-table__body tr.hover-row.current-row>td,.light-themes .el-table__body tr.hover-row.el-table__row--striped.current-row>td,.light-themes .el-table__body tr.hover-row.el-table__row--striped>td,.light-themes .el-table__body tr.hover-row>td,.light-themes .el-table__body tr:hover>td{background-color:#f5f5f5!important}.light-themes .el-checkbox .el-checkbox__input.is-checked+.el-checkbox__label{color:#606266}.light-themes .el-select:not(.el-select--public) .el-input__inner{background-color:transparent!important;color:#71737d}.light-themes .el-select:not(.el-select--public) .el-input__inner:focus,.light-themes .el-select:not(.el-select--public) .el-input__inner:hover{border-color:#c0c4cc}.light-themes .el-dialog:not(.el-dialog--private) .el-dialog__body{padding:10px 20px}.light-themes .el-select-dropdown:not(.el-select--public){background-color:#fff}.light-themes .el-select-dropdown:not(.el-select--public) .el-select-dropdown__item{color:#71737d!important}.light-themes .el-select-dropdown:not(.el-select--public) .el-select-dropdown__item.hover,.light-themes .el-select-dropdown:not(.el-select--public) .el-select-dropdown__item.selected,.light-themes .el-select-dropdown:not(.el-select--public) .el-select-dropdown__item:hover{background-color:#f5f5f5}.light-themes .el-form:not(.el-form--public) .el-form-item .el-checkbox__label,.light-themes .el-form:not(.el-form--public) .el-form-item .el-form-item__label,.light-themes .page-title .el-form-item .el-checkbox__label,.light-themes .page-title .el-form-item .el-form-item__label{color:#71737d!important}.light-themes .el-form:not(.el-form--public) .el-input .el-input__inner,.light-themes .el-form:not(.el-form--public) .el-input .el-textarea__inner,.light-themes .el-form:not(.el-form--public) .el-textarea .el-input__inner,.light-themes .el-form:not(.el-form--public) .el-textarea .el-textarea__inner,.light-themes .page-title .el-input .el-input__inner,.light-themes .page-title .el-input .el-textarea__inner,.light-themes .page-title .el-textarea .el-input__inner,.light-themes .page-title .el-textarea .el-textarea__inner{background-color:transparent!important}.light-themes .el-form:not(.el-form--public) .el-input.is-disabled .el-input__inner,.light-themes .el-form:not(.el-form--public) .el-input.is-disabled .el-textarea__inner,.light-themes .el-form:not(.el-form--public) .el-textarea.is-disabled .el-input__inner,.light-themes .el-form:not(.el-form--public) .el-textarea.is-disabled .el-textarea__inner,.light-themes .page-title .el-input.is-disabled .el-input__inner,.light-themes .page-title .el-input.is-disabled .el-textarea__inner,.light-themes .page-title .el-textarea.is-disabled .el-input__inner,.light-themes .page-title .el-textarea.is-disabled .el-textarea__inner{background-color:#f5f5f5!important;border-color:#f5f5f5!important}.light-themes .el-form:not(.el-form--public) .el-input.is-disabled:hover .el-input__inner,.light-themes .el-form:not(.el-form--public) .el-input.is-disabled:hover .el-textarea__inner,.light-themes .el-form:not(.el-form--public) .el-textarea.is-disabled:hover .el-input__inner,.light-themes .el-form:not(.el-form--public) .el-textarea.is-disabled:hover .el-textarea__inner,.light-themes .page-title .el-input.is-disabled:hover .el-input__inner,.light-themes .page-title .el-input.is-disabled:hover .el-textarea__inner,.light-themes .page-title .el-textarea.is-disabled:hover .el-input__inner,.light-themes .page-title .el-textarea.is-disabled:hover .el-textarea__inner{border-color:#f5f5f5!important}.light-themes .el-form:not(.el-form--public) .el-input.input-radius .el-input__inner,.light-themes .el-form:not(.el-form--public) .el-textarea.input-radius .el-input__inner,.light-themes .page-title .el-input.input-radius .el-input__inner,.light-themes .page-title .el-textarea.input-radius .el-input__inner{border-radius:40px}.light-themes .el-form:not(.el-form--public) .el-input.input-radius .el-input__inner:focus,.light-themes .el-form:not(.el-form--public) .el-input.input-radius .el-input__inner:hover,.light-themes .el-form:not(.el-form--public) .el-textarea.input-radius .el-input__inner:focus,.light-themes .el-form:not(.el-form--public) .el-textarea.input-radius .el-input__inner:hover,.light-themes .page-title .el-input.input-radius .el-input__inner:focus,.light-themes .page-title .el-input.input-radius .el-input__inner:hover,.light-themes .page-title .el-textarea.input-radius .el-input__inner:focus,.light-themes .page-title .el-textarea.input-radius .el-input__inner:hover{border-color:#c0c4cc}.light-themes .el-form.el-form--public .el-input.is-disabled .el-input__inner,.light-themes .el-form.el-form--public .el-input.is-disabled .el-textarea__inner,.light-themes .el-form.el-form--public .el-input.is-disabled:hover .el-input__inner,.light-themes .el-form.el-form--public .el-input.is-disabled:hover .el-textarea__inner{border-color:#f5f7fa!important}.light-themes .el-loading-mask{background-color:#f5f5f5!important}.light-themes .el-button.is-plain{color:#71737d!important;background-color:transparent!important;border-color:#d6d9e2!important}.light-themes .el-button.is-plain.el-button--success:hover{border-color:#42d885!important;background-color:#42d885!important;color:#fff!important}.light-themes .el-button.is-plain.el-button--warning:hover{border-color:#f9c855!important;background-color:#f9c855!important;color:#fff!important}.light-themes .el-button.is-plain.el-button--danger:hover{border-color:#ff6d6d!important;background-color:#ff6d6d!important;color:#fff!important}.light-themes .el-card.el-card--self{color:#71737d!important;background-color:#fff!important}.light-themes .cache-btn,.light-themes .el-card.el-card--self .el-card__header{color:#71737d!important}.light-themes .cache-btn:hover{color:#42d885!important}.light-themes .refresh-btn{color:#71737d!important}.light-themes .refresh-btn:hover{color:#444!important}.light-themes .page-title{color:#444}.light-themes .page-title .el-breadcrumb .el-breadcrumb__inner{color:#6e6e75!important}.light-themes .page-title .el-breadcrumb .el-breadcrumb__inner:hover{color:#444!important}.light-themes .page-title .el-breadcrumb .el-breadcrumb__item.breadcrumb-name .el-breadcrumb__inner,.light-themes .page-title .el-breadcrumb .el-breadcrumb__item.breadcrumb-name:hover .el-breadcrumb__inner{color:#929299!important}.light-themes .overview-view .card-box .card-title{color:#606266}.light-themes .overview-view .card-item{background-color:#fff!important;border:1px solid #f1f1f1}.light-themes .overview-view .card-item .icon{color:#34c388;border-color:#34c388;background-color:#eaf9f3}.light-themes .overview-view .card-item .desc h3{color:#444}.light-themes .overview-view .card-item .desc p{color:#71737d}.light-themes .status:before{background-color:#a7a7a7!important}.light-themes .status.running{color:#34c388!important}.light-themes .status.stopped.danger:before{background-color:#f56c6c!important}.light-themes .status.running:before{background-color:#34c388!important}.light-themes .el-pagination .el-select .el-input .el-input__inner{border-color:#c0c4cc}.light-themes .el-pagination.is-background{color:#71737d!important}.light-themes .el-pagination.is-background button{background-color:transparent!important}.light-themes .el-pagination.is-background button:hover{color:#42d885}.light-themes .el-pagination.is-background .el-pager .number{color:#71737d!important;background-color:transparent!important}.light-themes .el-pagination.is-background .el-pager .number:hover{color:#42d885!important}.light-themes .el-pagination.is-background .el-pager .number.active{background-color:#42d885!important;color:#fff!important}.light-themes .rule-create .form-block--wrapper{border-bottom:1px solid #dcdfe6}.light-themes .rule-create .sql-tips{border:4px dashed #d8d8d8;color:#71737d}.light-themes .rule-create .sql-tips .title{color:#666}.light-themes .rule-create .sql-tips p{color:#71737d}.light-themes .rule-create .code{background-color:hsla(0,0%,87%,.8)}.light-themes .rule-create .code-sql__editor{border:1px solid #dcdfe6;background-color:hsla(0,0%,87%,.8)}.light-themes .rule-create .code-sql__editor .CodeMirror-gutters{background-color:hsla(0,0%,87%,.8)!important;border-right-color:hsla(0,0%,87%,.8)!important}.light-themes .rule-create .code-sql__editor .CodeMirror-scroll{background-color:#fff}.light-themes .rule-create .code-sql__editor .CodeMirror-line{color:#71737d}.light-themes .rule-create .code-sql__editor .cm-keyword,.light-themes .rule-create .code-sql__editor .cm-operator{color:#a11}.light-themes .rule-create .payload-type{background-color:#dfdfdfcc;border:1px solid #dcdfe6;border-top:none}.light-themes .rule-actions .action-card{background:#dfdfdfcc}.light-themes .rule-actions .action-card .action-footer{border-top:1px solid #dcdfe6}.light-themes .rule-actions .action-card .filed-item .title{color:#6e6e75}.light-themes .left-bar{box-shadow:none}.light-themes .help-view{width:80%}.light-themes .help-view .help-item h3{color:#444}.light-themes .help-view .help-item p{color:#606266}.light-themes .help-view .help-item .follow-link{background:#ececec;color:#606266}.light-themes .help-view .el-divider{background-color:#dcdfe6}.light-themes .el-tabs.normal-tabs>.el-tabs__header .el-tabs__item{background:#fff;border-bottom:1px solid #fff}.light-themes .el-tabs.normal-tabs>.el-tabs__header .el-tabs__item.is-active{background:#fff;border:1px solid #fff;border-left:2px solid;color:#34c388}.light-themes .clients-basic .clients-basic-form .form-subtitle{color:#343434;font-size:14px;margin:24px 0}.light-themes .clients-basic .clients-basic-form .el-form-item__content{color:#343434}.light-themes .custom-pagination a{border:1px solid #e6e6e6}.light-themes .monaco-container{height:100%;border:1px solid #dcdfe6}.light-themes .jwt-payload-desc{background:hsla(0,0%,87%,.8)}.light-themes .clients-view .card-subtitle{color:#6e6e75}.light-themes .topic-metrics .message-card{color:#fff}.light-themes .topic-metrics .message-card.in{background:linear-gradient(90deg,#3e3ab4,#4c5ae0)}.light-themes .topic-metrics .message-card.out{background:linear-gradient(90deg,#0c7cd1,#19bcc2)}.light-themes .topic-metrics .message-card.drop{background:linear-gradient(90deg,#00ac70,#34c388)}.light-themes .alarms-view .table-title{color:#444}.el-form--label-top .el-form-item__label{padding:0}.el-table:not(.el-table--public){border-radius:4px}.el-table:not(.el-table--public).el-table--small{font-size:14px}.el-table:not(.el-table--public):before{height:0}.el-table:not(.el-table--public).el-table--border:after,.el-table:not(.el-table--public).el-table--group:after{width:0}.el-table:not(.el-table--public) td,.el-table:not(.el-table--public) th{border-right:none}.el-table:not(.el-table--public) th{border-bottom:none}.el-table__fixed-right:before,.el-table__fixed:before{display:none}.el-checkbox .el-checkbox__inner{width:18px;height:18px;border-radius:4px}.el-checkbox .el-checkbox__inner:after{border-left:0;border-top:0;height:8px;left:5px;position:absolute;top:2px;width:4px}.el-select.el-select--small .el-input__inner{height:40px!important}.el-select.select-radius{width:240px}.el-select.select-radius .el-input__inner{border-radius:40px}.el-select-dropdown{min-height:40px}.el-input.input-radius,.el-textarea.input-radius{width:240px}.el-input.input-radius .el-input__inner,.el-textarea.input-radius .el-input__inner{border-radius:40px}.el-input .el-input__suffix,.el-textarea .el-input__suffix{width:30px;font-size:16px;cursor:pointer}.el-input .el-input__suffix .el-input__suffix-inner,.el-textarea .el-input__suffix .el-input__suffix-inner{font-weight:bolder}.el-button.el-button--mini{padding:4px}.el-button.is-plain{font-weight:400!important}.el-card{border:none!important;font-size:16px;font-weight:600}.el-card .el-card__header{border-bottom:1px solid #f1f1f1}.el-card.el-card--self{font-weight:400}.el-card.el-card--self .el-card__header{border-bottom:none!important}.cache-btn{cursor:pointer;font-weight:500}.el-switch__input:focus~.el-switch__core{outline:none!important}.el-dialog .el-dialog__header{border-bottom:1px solid #f1f1f1!important}.el-loading-mask{opacity:.8}.el-tabs.normal-tabs{margin-top:24px}.el-tabs.normal-tabs>.el-tabs__header{border-bottom:0;margin-bottom:0}.el-tabs.normal-tabs>.el-tabs__header .el-tabs__nav{border:none}.el-tabs.normal-tabs>.el-tabs__header .el-tabs__item{min-width:120px;text-align:center;background:#1d1e24;border-radius:4px 4px 0 0;margin-right:8px;border:1px solid transparent;border-bottom:1px solid #1f1d1d;line-height:38px;color:#adafb4;transition:all .5s;font-size:16px}.el-tabs.normal-tabs>.el-tabs__header .el-tabs__item.is-active{background:#1f1d1d;border:1px solid #1f1d1d;border-left:2px solid;color:#34c388}.el-dropdown{cursor:pointer}.el-pagination{float:none!important}#app,body,html{height:100%;margin:0}@font-face{font-family:Roboto;font-style:normal;font-weight:300;src:local("Roboto Light"),local("Roboto-Light"),url(/static/fonts/Roboto-Light.woff) format("woff"),url(/static/fonts/Roboto-Light.ttf) format("truetype")}body{font-family:Roboto,Helvetica Neue,Helvetica,Work sans,Arial,sans-serif;-webkit-font-smoothing:subpixel-antialiased;font-size:14px;font-weight:400}body #nprogress .bar{background:#42d885}body #nprogress .peg{box-shadow:0 0 10px #42d885,0 0 5px #42d885}*{box-sizing:border-box}a{color:#42d885;text-decoration:none!important}.clear-fix{clear:both}::-ms-clear,::-ms-reveal{display:none}.page-title{font-size:24px;text-transform:capitalize;padding:30px 0 10px!important}.page-title .el-select{float:right}.page-title .el-select input{height:40px!important}.page-title .el-breadcrumb{margin-top:2px;font-size:24px}.page-title .el-breadcrumb .uppercase{text-transform:Capitalize}.operation-area{margin-top:20px}.operation-area .el-button.el-button--text{padding-right:20px}.cache-btn,.confirm-btn{min-width:80px}input{line-height:normal!important}.empty-content{width:100%;height:200px;line-height:200px;margin-top:-20px;text-align:center}.desc--text{font-size:14px;font-weight:400;line-height:1.4}.el-pagination{margin:20px 0;float:right}.el-card.thin__body .el-card__body{padding:0 20px;font-size:16px}.el-card .card-header--like{padding:18px 0;color:#6e6e75}.status:before{content:"";display:inline-block;height:8px;width:8px;margin-right:3px;border-radius:4px}.btn{cursor:pointer;color:#34c388}.a-line:hover{text-decoration:underline}.blank{max-width:500px;width:100%;margin:100px auto;text-align:center;height:200px}.blank .icon{width:80px;height:80px;margin:4px auto;border:2px solid #42d885;border-radius:50%;font-size:36px;color:#42d885;line-height:80px}.guide-doc{text-align:left}.emq-link{cursor:pointer;color:#42d885}.dialog-preview .option-item{margin:0 auto;padding:6px;min-height:32px;line-height:32px;clear:both}.dialog-preview .option-item .option-title{width:48%;float:left;color:#888}.dialog-preview .option-item .option-value{width:48%;float:left;color:#000}.dialog-preview .option-item .option-all{clear:both;width:100%}.dialog-preview .option-item .option-all .option-item{padding:6px 0}.status-circle{width:8px;height:8px;display:inline-block;border-radius:50%;margin-right:5px}.connected{color:#34c388}.connected.status-circle{background:#34c388}.disconnected{color:#ff6d6d}.disconnected.status-circle{background:#ff6d6d}.center-align{text-align:center}.data-table .cell .el-input__inner{border-color:transparent}.data-table .cell .el-input__inner:focus{border-color:#dcdfe6}.data-table .data-input{position:relative}.data-table .data-input .el-input-group__append{background-color:#fff;border:none;font-size:12px;color:#ff6d6d}.data-table .oper-icon{width:40px;height:26px;line-height:28px;visibility:hidden;cursor:pointer;text-align:center}.data-table td{padding:2px 0!important}.data-table .cell{padding:0 4px}.data-table .el-table__row.hover-row .el-icon-close{visibility:visible}.data-table .el-input__inner{border-radius:0}.data-table .el-input.is-error .el-input__inner{border-width:2px;border-color:#ff6d6d}.data-table .data-value,.data-table.disable .el-input{display:none}.data-table.disable .data-value{display:inline-block}.data-table .value-column .cell{display:-ms-flexbox;display:flex}.data-table .value-column .cell .data-input{-ms-flex:1;flex:1}.data-table th.is-leaf{font-weight:400} \ No newline at end of file diff --git a/apps/emqx_dashboard/priv/www/static/css/font-awesome.min.css b/apps/emqx_dashboard/priv/www/static/css/font-awesome.min.css new file mode 100644 index 000000000..540440ce8 --- /dev/null +++ b/apps/emqx_dashboard/priv/www/static/css/font-awesome.min.css @@ -0,0 +1,4 @@ +/*! + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.7.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.fa-handshake-o:before{content:"\f2b5"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-o:before{content:"\f2b7"}.fa-linode:before{content:"\f2b8"}.fa-address-book:before{content:"\f2b9"}.fa-address-book-o:before{content:"\f2ba"}.fa-vcard:before,.fa-address-card:before{content:"\f2bb"}.fa-vcard-o:before,.fa-address-card-o:before{content:"\f2bc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-circle-o:before{content:"\f2be"}.fa-user-o:before{content:"\f2c0"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"}.fa-quora:before{content:"\f2c4"}.fa-free-code-camp:before{content:"\f2c5"}.fa-telegram:before{content:"\f2c6"}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-shower:before{content:"\f2cc"}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:"\f2cd"}.fa-podcast:before{content:"\f2ce"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"}.fa-bandcamp:before{content:"\f2d5"}.fa-grav:before{content:"\f2d6"}.fa-etsy:before{content:"\f2d7"}.fa-imdb:before{content:"\f2d8"}.fa-ravelry:before{content:"\f2d9"}.fa-eercast:before{content:"\f2da"}.fa-microchip:before{content:"\f2db"}.fa-snowflake-o:before{content:"\f2dc"}.fa-superpowers:before{content:"\f2dd"}.fa-wpexplorer:before{content:"\f2de"}.fa-meetup:before{content:"\f2e0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto} diff --git a/apps/emqx_dashboard/priv/www/static/css/iconfont.css b/apps/emqx_dashboard/priv/www/static/css/iconfont.css new file mode 100644 index 000000000..3b6afc896 --- /dev/null +++ b/apps/emqx_dashboard/priv/www/static/css/iconfont.css @@ -0,0 +1,1237 @@ +@font-face {font-family: "iconfont"; + src: url('iconfont.eot?t=1567498326614'); /* IE9 */ + src: url('iconfont.eot?t=1567498326614#iefix') format('embedded-opentype'), /* IE6-IE8 */ + url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAIAcAAsAAAABIDAAAH/IAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgClaAqD4lyC+0UBNgIkA4lIC4RmAAQgBYRtB6B1G2jpN8TbR6K4HcA7n5UfNypqUuBlZmWd5Kyg7P//Py+pjKFpgLSATHHK7j4jwcNNrbaF6ejGN2/NMUbDC/sIaZg4YmqaHd43nD0Q7+0K5u6Qz6hUCU6r6J3juhOjwEWFjxOHmFTSgZklynmL7sp+cmX4FP+HB2ISVerX/sv87JVnJL+U/xRbImP64hXbum/byvtSqdtjIQp8nJxJP/ZAhSxwnAehIycP/O/vv33uuQ/fIycySX0SmZhArP5nSpkIJRlneN5tvQ+oiPBZTlABx8ycgw+uhWOXkGNWrpWClgPLXJWoKWhD256zMpNsLCtrX0vu6uquuytbEzAIDit7Il8it5i0T1wAQIXLzV5PvhpQCiX5yc2XrF+tJBc34IvJvbuIfxFhgRW6LN06dhdRIAPb7R0J+kcP6vVP45ss+pKf4gFR7VPnNx6vFD1lZT/JkDjosD8eAJbHRcNFfb6lmu+xTgxJ0aH6RedAV7+PqWhuQBLafaQESOJiGAjylrOUhFhppjDlbTcTRAjbQFlh5w7o7Xj/OELlYdvO3mYVUg/ds537SSIhJZAAvOtomwez/ILoO/jES1hITT2VRcCxOfq8kghlGr+JJ7GMHAzxmzCoxmIxW+IH1VAvrOyAeKKO4P/qrP6X7OS9L8mKF6jbotu96q4p586yAkOevJkMwbIaq7Xa4QWCY2oD872b/WeAbs+ZSQI9p8AVt3avya6PUFjBWq46P+Q3/I4AQVbAa+t+TZLwTKZyq5IveV1VBFgx8FX1+p+Sb1L7Q3wN6XSDzzhkVIGWe9pPuflNrpNdfzMT2fWQIOtyuHnAq4FS9bkk1+RaAyoGRGry6bqczOr308T+6FZ4IMns7t4rgQQUJrrodG0rVGd29woY6vybqtViBMnxArUhVfLbpw3RoWhkX0xF43dNNT8MgD9//oAzA4AcDEAhkLIAkFoAQ8oIpD0AufaAov1AivaC3iRvlDZSm+KAIG2ClLwgKXlFhzvKUb4c8utTaK9srr13RdVcUfaHDDmVA1jWMqwVYSQRShK0KXoOmf+NjZQiRYKUDvkZc/8f2Bp3WxnlQkU9AuIRsXrvz6EyNEMQ2v9tGdmQcft/mcvn7Y7JtehtBwpIkBky/k82tD8yZ9+AtvtaD+MTAQEnYypCAoEkAlr/ODUBldpZBRr1C4sFZbm4o4Aw7y97HShPmvzm4KAsKC5OmIewt4Jytm2LYc/43g9vmhOGTCGKTsbM9c8Aw56D1hJ67QOaHEdK/D8dRzMiugPyJu1cdsfN0Jt0H7Ry9TetPE6MAZgwWj0HtWn1rf41pB4Px4aG7dZUmE0R2e+E66puCk//fbTSzlPHtGV1q5oy8VxtUl1/49btbDFz94pmWK5v/vd1tQ4teuXGCD0YkJ+fl1hu+84zXunsNZhwES7DXXgKn0s/67PJZpf/Z3GjTzD9rUyuUKrUGq2hUXEYm2SHD1o3fLP8FZQ2lu1wutweLwQjKIfL4wuEIgmGEyRFMzIQHq/PHwiGwpFoLJ5IcrzQ29c/MDg0PDIKgBCMoBhOkBTNsBwviJKiarphWrbjer4AyrgAqVZtrPMhplwqbvtxNsRO58v1dgdACEZQDCdIimZYjhdESVZUTTdMy3Zczw/CKE7SLC/Kqm7arh/GaV7WbT8ez9f78/39IRhBMZwgKZphOV4QJVlRNd0wbcf1/CCM4iTN8qKs6qbt+mGc5mXd9uO87uf9QKcmBZlcoVSpNVraOnTq0q1HLwQjPL5AKBJLpBhOkBRdB4rruQCK7u8GekyuV/pUcMKIqknpULXgY1BdKR2rG6VTdad0rh6ULtWT0rV6UbpVb0r36kPpUdmUnhWh9KocGFa5lN7VN0+fP2ijhrQ8e8dRmjQ4QjsNDZRmjW5QNBXCelkH7SUNOkg6dJQM6CSZ0FmyoItkQ1fJgW6SC90lD3pIPvSU9dArG6B3NkKfFEDfFEK/FEH/FMOAlMDAlMKglMHglMOQVMDQVMLwVMHIVMOo1MDobIIxEcHYtMC4iGF8WmFCtsLEbINJaYPJ2Q5T0g5T0wHT0gnT0wUz0g0zswNmZSfMzi6Ykx6YGwnMl16YP32wQPphweyGhTIAC2cQFokUFo0MFssQLJ5hWCJ7YMnshaWyD5bOflgmM7BsjsNyOQHL5zqskCVYMTdhpTyAlfM7rJKHsGqWYbUoYPX8CWvkGayZ57BW/oK18wLWyUtYN29g/azABnkLG+YdbJT3sHG+wyb5AZvmJ2yWX7B5lLCFALYUgq1EwdaqwjaqwbZiYTvVYXtxsIMasKN42EkC7CwMu0iEXSXBblJhdzVhD7VgT7VhL3Vgb3VhH/VgX2mwn3TYX304QAM4UEM4SAYcLBMOkQWHagSHaQyHawJHaApHagZHaQ5HawHHaAnHagXHuRqO1xZO0A5O1AFO0hFO1glO0RlO1QVO0xVO1w3O0B3O1APO0hPO1gvO0RvO1QfOkw3ni8AFcuBCuXCRvnCxfnCJ/nCpAXCZgXC5QXCFwXClIXCVoXC1YXCN4XCtEXCdkXC9PLjBKLjRaLjJGLjZWLjFOLjVeLjNBLjdRLjDJLjTZLjLFLjbNXCPa+FeU+E++XC/AnjAdfCgafCQ6fCwGfCImfCoWfCY2fC4OfCEufCkefAUMB+eBq6HZ4Ab4FngRngOWADPAwvhBWARvAgshpeAJfAysBReAZbBq8ByeA1YAa8DK+ENYBW8CayGt4A18DZwE7wDrIV3gXXwHlAI7wNF8AGwHj4ENsBHwM3wCXALfApshM+ATfA5sBm+ALbAl0AxfAVsha+BW+Eb4Db4FtgG3wG3w/fAdqjADmgAdkIjsAuagN3QDNwBAe4EgbugBdgDrUAJ/ADshR/tg5/sh5/dDb84AL86CL8phd+VwR8OwZ8Ow1/ugb/dC/+4D/51P/znCPzvKMzzAAUeJNQE2BYZbIcI2yOHHVCAHVGEnVCCnVGGXVABu6ISdkMV7I5q2AM1sCdqYS/Uwd5oEOyDhsG+aBTsh8bBDdA8uCFaBDfCuSuGEiiFGMQhAUlIQRoy0ND4f+BkcG96UPoGdWbzuuRbxu9uPOG9NXVIv0imO2hOKTf8IEUvwd/fsMKNK0oR2TROFrvRNFt0wAXNAdMeH2pM82FhcMt0IulTsVTCaPDBHHRDwiBILgynBEiwYNoRpF7pnCCh60eoeFgeyAnfsQDaCww1E8IlGlIWkrLgZfI9MFgDgJXRFbjLbXQkwDIZZcDgSLzDMkIB1LQEkzGhR4U0A1wBPcFjs3ggYV0xB0dXBC09YOn9AZTFq9/FMdMrFSzDLM9vQj3y0eBmisKA/Z7s0Qg9wYhJ1IHymA6SfMhyb8S9dtDn05aNqNasp4k8+pI1DP0Fm+ms6PPLlPw928vvjSPr8ThlfEOGTNZleYv8vmXYhpLtVSe3+8MmBC4LPR6oL7kZP/SGTFgDN8sH5h3/GwNzsZ0NI5bFJd+4oo/V9mQk9yobcqYkuWH0cK/AadfDgUxRdEpcXGKoG1dj0i4w6Vwx0bYo+/UmjMPOKchwEMapXdNQFCSBtLlJYSA1X9U7uX9ARNc+NbVt5MAPT+efKGdA/AGSbPaclLYwUFVdxwekfoiTXgGJ5btPk8NzXALIZDNkRTt2LQxgCgvmBODIsP44c8VCwT4B3eWkKKNWMZNX6UHZlMykJRuI1VJ8IekkgawxtPtQ7xtr+nQxcnLy+5btCYyy9BexB23LaxG2iwe+6faBIDZxr73X8YzT3vtrVQY23Gei3rP08kw2T1jG6HWpF4t2ax6G25R7zEqpGTG1y1oC1bhkKIGhiZQUOEnP4mnUNCZnVk3JsdiStie7jDnctdm8y6GxbjZ5HptM5ot5y0IUOK9/FH1SvBgVtxpCiGeU361qtNd4ORdPjXkkYkDoDihCoWQa7kkjawn96XB48lqcROC2NHWqAEGBau9uSG+d+4y/DUUAW/AkVPm2v8X6rNeWL+S2iMoXiRMPJHX95j5rXwO9y96EpzzpaJv8452EAP6UCStieQlHSq3BGRROiCgpY8nzrzRIZTRUjC8m37I1UlhXeDSzMxDa6lYPH4IZY0B/Ovho7eIxBcvErz7SWqZ1QpUJ0ISEzsXw0mc9T5I1V/ao9kKHvE7eMXHhcokSucM0OMODNy1AsC1ZYgZG9V2M23tznTcDVUccQ22jHi9pCvzImtlw1SYpQ1rkSTU1lX3v3a2Gi8+ztlAt4HfUSBYM+cfV2JZkLyShgFItacFqUFpgCeBsIZGwztl3VRy5FsSRqyZaCK5RUnJjjx07+/xYljWhDjnXZhh9juigst+g0HqBzDavkrUo8kVcYI8wDgpd5OAyu6bR4owgocDrL0ME9KAhaSiDTH3dQZPNthjSZnK607S/dL92vsnB20NvCmmRfwSdyAtsP72XzaA/aQOXa3HDdHOzEj42Hy8227xfU/7BxadcSATKSHl/6v+0yLbjkOlZsPgs6KHrI/YhrpgLlAwvEvjX4cktxcfT7ui4puxuMnUlHE2KbVidGon1aLmwh05fhLVBuOlQnpz4xNcMd2sneglEr04MNAlUs/Fgs50qASwrKHCPRBUMZPUK2MFZqLDvVjt3++qQE44kFYnZrqal24VtcTGW6ehGrlcu7KMq5SpimstZaQ86Sk5JGWFL6zbHV+qy7MoB08QuvAvLVxSrCaW9JIDJPFARVcsK8KIgVzjgTpT1RkmzwCTX8qgcZSpOKa3lAFOZ6ZfC7SghmMcuRapZxojIn1WmEpkXMA8C3iA1WEdlmNKXlEpfZCrC2Hqhs41EhAh5ngcKMpSWyJro3aF/CBegQWst4VWeumZ/hmmovA0Q5FKWIiyKgtaKwfFSCp9oRrysVKY3aDySWFDIBgTADtSrKgEO7oBu3zKRGoz15rkY8wKCUpZcVRbQ53hnjgMRUBCGWJYP9UUAdlG7sNf55bWqzJsHtgE6aHrfqBakwSZ4mGBpWp/WjjEx04iHVOEBCUi2SVDRYkWbQHFRKnNqblZIVIxbNeXAq0p5IphJ1AxD4oI5TaEruVDhzXAx1IZKfCd/OEFV7a9rogx4xCHWCdDIH7ChH3R3HKXl6v2w2PuqF/Zr/Q7LmstATT5Owy0xDD5RcyvFUOsSUsdaB8DFVdzLrZqIkc4u9S9G7zjBEr266vxIDgVN+9/kRjW2RPpcWLFSeozQMhOUEm8nUGfYvRb61LZMtDpC+FDLbOEJJ8RJ72xeGuKWVtEU4Ojj9hx2VZDWngVia6NQlpESluR5UhnPhQ2Z491bkGp4UyBzkL/ptcIAe/M4Utow/GClMCK+ArQiUMfAsaXk4n1caW0XpKoXNAjNtVb0ymrNx5Eq76r2/xLkmXrbcblo/0FgkzqXfQ095NDWb24De00Y/1O/dZcP6yjsojAE4X6e8jADD04Qy3eSRSFba3rtRrsjjIAHPcPdEA1+hJVBMWih3uYaiO12JrolDsYM9UmwNtDB0GCHejoQCtJ6d3stOGrwRjtIB6B7b3TyoOfwzrb1+F4u+kpeBBB/4iSB3nQ2KPU7ZZgpMtcpK3Q5bfQIVL2DQeUBpaisXO1VHR90SWDdIFz1rHtGx8fQ4xSaCiiXQ06IjrhBN7ang5o+J1kdxX32+PsdXY66vjiB6N+KYg88H0O9NSpOfWka5lG54WyMuDQXXUtfXqzR8kRB14SPdE5EmEuAkwpyrBkAzLLTOvRGO2NELoeH/H22IJcyZuofRB8TWpRGXEL6nraStXJQlOAqwcoFWEWvcKxQDWMsYVpvH/4DtsG9dNv6h6AUIppjxU0HNQgKWCO77tMe1Xn3kMjdS06UTTPCAVw2jyBksAvfs0c9sK9KYnVlRi3volkTbnfUlpljFt5gnLzQYoqT6/52ksw4+mbdrqOt4Pr2VPDyEuzyZ0SvytRdF4SVJ2yRFBYVmxCwYC5Sn22pzGuwHdGUJnCZnLgpzaRPSrem3Z/7RMUv2DrdACLcR0CiYCSQVnCa2mCxu4u+ZUei09FlTjyZdgGB05VIpOJKiccsOVQZ/uDbnU3bIma4OSrCbZ3bzWBvL3iMyW2Ki1xQbboudg2+pIKHEUVxU2TiKWGgBHBDkyVpMNCa1Pw7AhDD6x4r9FmevHQMwF1co1R2wSrRjpJT+odn1A9wX0vS2w5yNEObB3rq3pGa3HIkqZi9igwCxYWhNvgdSG4dxwJdCD+0ADlOINOsoHQyL7gyeLhyF1kfA72ycOsNYRRnMKk2dBtSerwIPxL51+1qZYOd+X7NbUcm/vP1+reONHwa7G+10n9e03/92/z/xz08ifET7TCc8P9Ae+iI3dojs49xcBQOa7T/5qKOkQ+83Ctv3z08JkoG4a2X7LGQca/PPzrM3CUQ8OC9ChDRfXSLzGlQeB0j9JGBEKevbx86pcEMKLBtpeOySA/wQxH77G2Ai/ffBTAFuxpwcXp1aG9fvkAGM7UY5gJnVLO/ExzWr/Jdsem3VhAxPis9gUctbVWxPlNQ1RmQX2g1dT7/NKMW5p9xlM+YKXJeHFIvpkYAY2JuguC+FVd6VYHBen5GBhO92ehn8n0q5QKJMlOQza1ctknKNF1W1hb5S/IcF6nNW0swOMHDglWKkAgXM5YlV/Gbm2WkzK0VnK8ndzip+o625HmR9doL89XU0b2blgMnO2pB5b0mt9Azgw7cUMyDmm/WAPNMq84yPWNTwzxXbzDSSfk6lfFGm8yJ6GGLUvn1luD0FLNigsli2TbcMZjK1jZgg0gqKRPtJmJfdfKKGqM904qxHOwr3kRuyoSS+7FHKu79dFY6BwJwfvZpQBCdgphzKlRfTpolGQABSxfRHSpFLOqQRzpJzZRHRXXXUS/E7OMgBQqJkAiye0ich5gUTvgtIt+BlJ/mNqpGsrVr7tOs/GoUe4a0jWeeUf2NnfnAyQr3FPamZIMNyKxohny3pnMXR6OjptJtjM3A/zakyv7+cE8E4C8H3ubfbu/+9UzGBfQK/hqtFFV+suWS8qencLFtayakfaRPcFBGQSwuHO0QXWVVT7xGiadCiI+1iUUo+InGj99u/kyV2GxQfaxe0VbxYDEy8cga1nXSqd6QOlkzF6e0yMXIxNQyz0eC3PpctwAF0V9/HN92ceA2+hy5anHtVVgjV+/edDWeYbcfO3U7QfbOK8N3krX02pUN1zKQX7Nn8zVsFt9x/PQdFDNkDu1jBC+tIhqubySYHt2JYX54P6ZseTUFtrWFMnLiUft4e23+3URcGFpklXOD1mcEZJODxoEGQYPOAKqPD07tQzG7E+gLwF/N0TAFI2kbfHlanfS+T0qZZnE+09E9FCDmkZ4gg0Ccf9/2UB0Z1uMMcVoMpOmY05I7tGccUF9MLrDTQz0JgJw5psslGBoQwnGCVJLhNAIy0hTBQb92lR5UAYqmTn7w2J0wJGvSQuZQBQFasAqiahf7WVdDGNpYgjHEbBRFNBAKekJp/DEQYAphSQp1k1RHM5GlRG0LukjBUlpMMhcJTuEMlogL4WPwimYaUE3fKHyQ25qKthjTg+3tVZMjFiyPDJgfUWAcfDRY7Y4UX96gM8kR4jwCU5ySCVuxpCxzsImS59g4KCdXz0qAWtVnKJKNBn1Pjd02tsf5/FEea7bZhVsJE4lJNpmya5OsxxjkoyIXXsejQZNtVImckimYIDJJQ6kBlD3g04KYSzB6s6V2UBxrOXsJB6RKKWliif4mgqWlscbDTRnhEPnAGA1+aNhfvY4wjzcd/HrI+Xqc+JNpemFWYWdd1CFkrzyMR8AdiX7EbX/c5mugJZrohDCVD2qQ4HVHU8x/MZVREmUBA0ssUEpcZQXKFtvklAGJSheleW7JiQBahGxOpdeLAHyld5VkmDUk/Rs1pvJUdgwe1QmS+tVsfBcypYx4EZRgTGbCW73fax6GWoIgGmxEUxzXJtCzfYFiSrbBrGSaFgAdATpL15dJG7TaEU7ITbZdP2iXY+9b2Qt1KGq2+cYjyN7Lt/U7IraxshxeJDZkqfZBpeVnOinAc4JWIQkr3SdCxExJhEqF0e5bk6MIb1Gew+2bOsKQrijoBFidlEsmK5I3dN2hbkN6hBnGtD3vtUhUsfkQZPACf++msZvMXAn7HnpiocgLArTfcL8ey8fO9bOpZJ7t5Yk+lcyqZkJJEHAv0oAE8eFNhaFkvoxpt5IgavS7DgvG7KiUteoECwS4SKpRgGZos9K2AhGMO3XIOaY6DkapV10ENMZJDU56ai4qz37gkfLxw/eoaOhqLmpv2KO8wBUMrBwYOCkt9rVfSGx+96AZ6zgbC9X3KHYCvNVm1bygRqoo6p8AKmVqUlfhEsw+K/M/gH3h3wB94nO55o05lY4HXyTn1lhjzHNXptBoIZGa7wJaVH6bIDvtx8ivlEYLj2PoFMHLhx3+lulyiFMrK7+7azG7sXv+2+fXP5U/s4edEYdkbA0eEwMIJGf+QSwZuCgeZSVYwdbUclCxWSFS50w6QXRDuSieWeLJFPKdjATqy02o3o+dN0COQxRFYizBiU4bNukMGYjI1EDS7HvU0eERNoEZBXomaESI4Q7XgQWL1UAkp60Ib8VbuAKbCIgL+PlUuTvYQpvjwgMza1YRKBhGN6W4TyujopsQEooMIZmEXGYOsUN6GNuzmqvgRtnPaApVNjnE/lctNXQt79teUhEx/5D+kdCgcVi+lT3LL4Zr3hXSUZv87gAxsmefPikjDDb9Dabt+lwN64x5SI08QljiSKv0wAaM1BFqZxTAlmVcCx3G9JaZEIqlh/m68lhVGEaKPjCmt94LoVszbTRxFsu/aCK18lILJs6fw1Q8PASlqPC889PzFan4BX0EB63sErygqTPMMESZgTyVnnCU/ppVUOpMlmXYwqZ5llw3h7M4Q0wkpjlBroOqmLR7QbjymDTQLojNT+hwW5arBfA01EDgDch7sSgzWE1ld9Xlscpx+ZnTN3j5pU6mtfdkxzENGb92m9BztMPkxiAgc5jp8MqyeeI2NFn2dhFd3bkmrYMAr23RP3V1fuG73nfv3WvvuXf2rnueu/uu/L2/qE7ciQZBIeEoTpSdYl/bEHd0ljqgKWQCxSgq6GNLArKb/gxZCpFAMgWUEcQEV1y2EdA00Aan12evBVF0NTNnRaq34QRqImsY1P4UtYyzSUa3hntXavA2N1piRbT83jsLeR4jYZWgC1I7bREEwp4BsgWrZb8mQe05yRrbpTDznQbZhaDhWih4xRECg/155LWmiatlpqx2xDB4qr5ZuVtMzn2kayqTrKFoqtOU11Qayw3L8sBZkAESgXCB8Y/XmfakJJzDQeYW63dKV5JpGZcmYwWFC50fPnpBR2WUkyvFtqLzxh4JAosotwrV4BEzPYOBFYjqugYAsqfM/RpuBzrG+A+wwZ3/i2lA5eO6FwVTl8WMwT5I6fyHevqm+Bc8q5HTSYDOk9HaqrUG5Xi2qkXoBiGODDFZUs52RV+Riplzo4lT0jAH5BthTPk8VG/hjKaZEPAOdkhvgkuErqKiDwRiRethFqbnBySDszTlhTJYpmgZood8Cj43coVBhOj6ba5b0HvqP28mM4eTw8VkzS7dPX1Mrvbe+8GMcIJ0i+/v+Trupv8fGdlrZvJ4G7UYPUemjxMZKABlvUSyp4nVvnI9igK8WZ/GJfqnGq6UmV/rSD1ylmnGvtn9L25GGdrCcK96ADkaPOMNLvuX2bCQq+uDqlGNQGBCPv0e3k+7vLlOOvJm0vsPn3Qwx8mtcx6yh7/BD2uwlsI2lT1uxr3mjnDa1iXgCA8LoubBvchQDQUmHHqR6WzQwKfhNjIwxTJCyfXAQs2IlhXN2UH1OhrGpP/c1F4OI7meS4iJFmF9XBM/3GVkwtBgoPNNwFl8bIsXdE8J0N50lnbIQR9FcRZW4lmjTUt6kdvf5NgDDo4PvCGIE5No0LO0bgbw8AME8Zjfvfk3Z4/H3Rex1XXCCmDdQ5xg4RvVIBNw1r4Y+BILPozJ7DS0fffgioUqO7DcqOydGVf2FFS2aSUHtGXJ4w83tdJevhNsvd4mwZVWrfrMqXgp1J3S3raFfCI9RbwONlU5VxH7m1/UVXFxFFyFFSVUgWrFFlWHl3n0R068VfZ1blWRVwxsUzbyV/RWebi62h1tA3YSem2pzLVsmnBApiHIS831yfpq8g3yXNGrOnve4Lxuz22tgfZwgC2Rg23LlX5nj18NWQoqv2oK6LhNHgLvIvPm/tSUnm6ogc5x3wl4SVfiFkv4qFYi4ZAvalat8T8Br/9Bm0J4MMbGwcP4j8bq6AD3E10VL7Xq3/ziuv3a0VKYRly7/eOIVuz1/tXoGAcvxRwHlVEjHHFg2Xt9Vv4Ofz1U30bAKfiTIOuwGB1957XjUAlcfTs7FfgTluwMT34vcoRNe8PnY08JUD1aa34WLo30JC24PHATb7TECZ6hN803OAgx3cX6wcZjfISEXumN5utbSXild3pPjfPNRyf2lLCQQlw05W+OXM5EhhmlPJiB9ptjpsyVQSjbUQMfaHALzanPgdQ5x/CAgq2NcEMQ5EsW3iUoW9Ks3cPrgJTbPS58YO8yJ1V2md2yS5bkFl8NKMmhaaSJUfYOiDdR6RtwIIpzwBEYzeg3ZkSwhyL1TDAdIi1PJTSOugL+TbgwEzcRjBEOMevfdyexZFZxIdZRGQVY9n7ybmD+7Mf4WOyR9+BZFkxMeZM2AE28o9j5cMQQeNvfH2ZAAYZ+YfBxHA0ISvH8WoNwJ/FkJ4LtwDiTBNbokRVFV4Bz4xs7BrSY1v00TU5ZJ6AFYpwveqUrDP14bXoDKatBTqXe4lSX1rsqmpeyvgdtT696BuIu8NjObloFtvh3KVMZg7eC+LVMGZBFEOawhRAqmbALtofgqoX0UA6bpg7Q1x05foBId2vRHjQeg7XZDy++f/XT90eouqAu/QGWibvkb5njEjoRM4Rh+5AIIrtZ+inbTriBnU4z2LpUutsrd26HiUXRqql40azWQW28t6vRDiyjvb3xbO8dFRmHvEEjAeIk3BQjtgd+rqlaRq2dPikFbVMq8FqELK1A58F5SUsvgIgXQme5gKtBPdv15PuBxPxATxVG9vxCITOXZHGUY3coGAfeVWIv2gv/pVmLvCidklAr2LdWqaULq/DJsvtOkWX9J2BeAteCkV/wnMgZRxPsJPuoij77lil9UJci9rJjDTfZZ4Bkn2K9ewg0CGcoAH2zZ2dFapHKN6gHuU7td2X6me1SIto63tKjjr8ktYEl4th4oaf2rB/1pzdN/KpmJa/dUhvsSDe9UsP6sc+Yl918vvl6iPKyySOQZg1DKpENRYDkqZDD9mYJdVlzdLesQkZ1nRnNOdMpPEpIqHlcVlXOaEEVNnf/raPK660SXFZaij2CXepHODiBQNbGJnRoV0jRPhrVkJCUZ7W86k9AAviWh9mfkwMiZipM5faM7UXfxG22hw3jT3R0+egq0At6sMewIgs0gXoV0VFNbLLTQZk6P7XNdK23WC9b/DpbyGvsK2XaTD9WipFt4UoBZkTdlSShTTBkUn6e9IjJ1A8VNnSu+lT0Nuiy+qqKtw6hjyWS2ahn4fSBp+QvU5mdNjdnPLBEJBz0/Gj+TczkgOyTAgMngXkswAvizp8WSqU7CA5wk2LvyrmqiVi/ZiulHo4u56S+gF6gjcttZXn3NFXwYN/Di9fM8Z9hKhka2IhIDu/sPxxnop3ceoq2coTRqac27fHqkIJZPVhPo1vnOTRLo7rA4C+eC/TQrAC87cvapbPHEaRCziwQ635Lj4YhGZ8UTHNRu+RphYkv48NIMKNFP91zm1sQKwlE4//Pwaa7978UHGXP0zLnbxAyEILfElhTYAE7DturHoSp5DwLFduiA5jmKtwc0tJWq1/A8Vhy0eR6Ti+VS9wNogFoijRh2gVbsdDXfhUv056GYVN6YLCvPpEpjHky+Cwqr2Fv3C6l4sWQBihViHJXdK+3oyWjFlRxbf1i6FhqJZ0OZ92245lno0eWOlkUYlHLN8RezEGeuTwpP7WhRXevhXr7q6rFGPm9sqc8vW5oqa7i6MVUvVUbBunwWmX13oS+zWPTw0pRCF3cQyK4fQfu9+FKjlnPadduRcQgkaUU8GDL9HytLPnrbjbKrxKR7OvYSiJHJqvZpRwv9xMaB9EWdJC1qEAwIbCB9itOE4K84aMc8LnrNXN68hHzhWSp2gzaCYlO5hPMSWq5RjhXRw7GG+z8Qv7+KjDxUnF+QK6MGnULZQsN4b+Eoi3SIDlwU9zwJrqWD3upA7fGfvvy5snIRw9ZDNME03lUSgjBTSocJYln8pyo7b+smE2HiicR6C7QXJzQdMhpyJIygZlMUA5WGx5k8aIpAq7Sntd4u+4jSEtTkybTX46gwt7KkdGScMtBbA7sK86t4ajl5QYpvxW5Ww8v7h6n/E2HFv6+Nb9Ws++/u3iwP5+8uef+cXyFoVcrt62GdowqQpuWI1eo1c0D8BR0A+bItIJEf6fl/P9q8kcXBK9eYyJ7fJO6STgj/lhF/Nqm35PpXGhMlsgT4fvvqR+NArUSxCiW6BmMegH/CPbYztIaMx62x7Ixp6dvBeWG+vVgpWmvlSx4zUpS9P6qrUo0rWv8F9/Fo6urXpuNQo3DzMCu8zbykBqotUYpzoprVYLOm/rwELe6BFE8Dhg4K2gIQ58W5SUBNeKSyKEs0CTIapTTJntVpRZszxtw+/NJHceHl9l+jJk6hTQyCERLD86z8PBij+N/oy8hoz32WjWucGntxuBKIsvUVQ4wLAINFBcokQqolE8ccUJ6WzPKo0jquhUCrSWI8OZNgncd2C8tIvogPXpa6K4Z6xYF9jPJmE4PRCwFkEi5gVdnzG2sxKAoVSIPWwUeG+e91F+73xrug0q7ZDEPYOYklsgQv887TYnFNnQlNK8Cve/7Q8fBeQH3xOSgv3lRYbNq0o8JIQxvHSP4C4YXts5/yrYMtXgf+3JBNiDh5tqZN6979aHHr3vjxscffaLwxq1/fDc+uJ4Y2FleQrKI3YrY0WnZuFTqR9DOmTKPubhp9DD76FKNCvy0Z07hyaaFkzUnoZFotf9TZlCNs2917Z+j5iLfcEtSyXQKo72Is0YhD9qrzwgNiatM0sahJmJufR1D9i4udeLkWOO+MSU3Iz9GVHBwFbM+6kVbLHGAIV97nkFtOzwcGxva24cGf9Sr04lhbcujyqjWO3FfPblEBm/6Mx67P5rjsPx9VWJcorspDG2ojaYgespXaUcN0dWcodJ0N2jWuqSEkhlCYubBkiQn5WcuLB/R//1rRja8lfa6E7Myg4yId1QjfWGs8afPgnCjn9pajy8vEb02HDiyFJgReUpluKhD4YhaejwupkLtCpdwr/FEZT9+nYrohhELsAlGIl1PqbSI2jVox62eHlQBKYG2LRul1q9hEzOnV0z9L2KEO65lasd5EOtAzMuiAwOnlOgpMuX+DP8dI64SlxMYl3k7G+C11Gj4hM1NfpCZd6qRwPDExIN2Hw1+da/y9/Jghh7lE1rT8nUxv1dtbUqcqvKkaFLXVsM8GYMeNUXwHIvMWfJI8cB4ec6NnIp8QraowKqFlF4X1m33CJI5rbUtlWu4GnqDx/DbgMn7u7cvt3d57+4Jof9xtGf/8ZuXB44G3ha3vm87Zqs8iLeIk2hHYJBNRzwnVhZwlaMxFJETdNy5nhMvKIFKJuayt1tCM/pmbBGlzTVpGiFWZ2IRW0dSf46MCPuZ4IM6AojJFwYrRaNkbNbgcgwBNdOK+QVTqYSoVLIK63kq5m6EsohRk4GcQn0SJNn3ACCwkTAj/SlB6OEo0DBnhBAhulWRNATJdzFSHnTu3Ht2p88pJR3XUq6tXyANb+B6Z1COQUq02ErEXL88Af8fFs7Juv7nT30NS3nI+wT7mSpbETFUerh4kk1cZK5vgaXFcsFvTwX+8+DAA8PNcQ70LXVlOHD0bFGaH/2SfKZs6BvS5R4b7BNopNCNW9jl0CDLeuUn7/fomqoRaWZY+z0CF21D6mBKXi6x1m0pn3/q6My0D7zCPZYD5ZK3eju0C+TcQq7TGvpQD80vSSJG4uqrIns4PIOM9Ly2aLxh841nEHQVNowjODBqKevWoxxS/dYMSH1U8aqUHq4aogCkz8SHircKiWonS4h59hwERYx9mB90IL2MzAa7jihHJWxJwsu7wZGocmEhX1xr90ma+kf8+8OLyvlftcFPpks2PLQoF8c2fWzgFNkHen7S5zQPbce563O/HoRBsrU+r6KK5DHeZpTButxAjK7Yedwp7QRkCBHBnjhmsKfi2Z7HE9lxtafZk72XJkQBhBS14C+w9j7XL1mnZB4BKxs8pk/Veuh8O4KIvGamRSdCD3JBHRpkQMKcZRLRIc3NYcM2y0njJ3owVgPvFWxqAaXQ8+TFpxUWSxmzyb4MLGtSzVo17+JEGu0wvefgPZlF4pUOeBFONGR6BXn6AbxEilytbvokUK7Q5wGr0wzxaaDh02F9KbokKmcqiyY4kjnUzA0xRJgDj+xVZjCuS3cq7wrBZMbGXutZZjSnzvgA2ayGtHP6Kz8ovugFS15fQUl2gC14O5XvYBRIWt8z1lvh/XSeNZN8p0VX8awsBjaOwMBRkwMYyugE5eitAS0AAbQkg+TMOih/sKgProz0iS32EGDhQQWETtwOvwZN6NUc7NWQ9naTSg9q0K/Y5wkR9d26GDIjQUcYh4KAI/bL2501+I2uHcL58eMBkZqiSwvrxXXnIim/3mZ/vuIGUw47w2QGCVac58bcn9dal4nIK/sWXAtcg2tyQ2GzVEKDkbAQB7z6kWUsGEIGkpflllk21dWYHUrCxhISuiWmuSw1sZedA6Vdae98VI7uFB+gOZpyydd4f1Wjmuj6eFI3lwkAS7qPa7blfhQi4KyW+NREY4Ez1Au681vuuAFygWf2HpOjO8Lj0b01+MWKnOYx+4rC3TBgwpQaqo/UBwESY/ESzT/afgaowHu1iteIAvv+aK4whthy0xFNIekYVRG6bjD2UKSkQcKqWiWjZUEwEuiHqr3scDifoBYsdhFdHHZ2B2j4huTykx/9ce71f/UXh46wxArzBMy4cHncJA2sAAQGC1KcpjpRDrQOMkgu6RhM1lmR+qeYSen7RiS1jFWnBZvoo/I9OnkQM9DHUKcDDFQRtQ5TknLSJ3ezQV/Dkio8k+AAJwbfcnB/T2/EXLrJF30vyH1hvJmNCR7Wq5xhVWPPFfGDsi14rhlYmVKb81uKlikJzfSC6TUcS9ujl43He6XcxnGQ/KR1Fq7h34hs1KDvFqyso4XNTLd/NtHNeMt74X9RjBL/ZIGHym9g83CMdDIRlsAmGuId1DTS/TsREmw6yrT1AQuIiSDJRqSpM1QtonApP88oy2HCKRX4mH+HAH/fRuo96MErnk/g6yF1Zb1FiV5T4caf2XqNBh1LgfiihWYXb0IUA0q/RTpcnOroVfoRKkxAMcHIfR2HdhauJVKolcHG5EnMKKS9I78+mzytqW6SlhAMVDZ4DeNUE/wIpd4tMxIkFroF1jy0slnwtjAOi44QtG2I4bGp0dQqscS+haX1zaTmmmAHJ27RzkJ9HPIe7qxQ7N76/44zvrslUv0S0KrtHsl1kyX7EPPVFf+ph7cMIWVuxrA/WZiLwLHVxZoXtOAkj83mb/cV/Xx9YSaPi9muI82jp3QQI5mOO6cSAvfxXpojWRLB54lTVDCO2e3CH6B6o7lnPCjXl6F8WwhY9+f0PR69PIZTjQRkiDVBDOjLCgJZR5aS/k0ETM1Oy9kHWqQLvQgcamXIWiSaikEDPvCR4qjdoYJMRM0gThRIKmVvPSGaKk3R50gRU9Xg6YnrtvmjKStxbt+fPi7TSSR9XJdw40EB27giU/HkzbbjsVlx5EnrXNnwn4Srp/9i5pq27CMvD7sWS6AVCjY+9qi0E0RFlnScj1965Eo86S6GU7z50RqTuRudi0iox4azvG8pMAfkrBhW4YH4FJy0BiZOGKY/5xm6EKU6lfmlhRAKdKfGFtfX/oxvnZbwYr5P/Qun6eblsedm155eD4G4f2R1zZw50wV/jnY9d2pdF9052DV78uRUzPKyqqGttGK+n5cVTNCr+qNDBxSdbiP3axj2rNrofQ+clzZdJ8TsSh+l/dmqhUlLmuq+0l1y+ONVaRBFesxUOEqsxdwDCDNbQMM189kgoUcm+fb3F9E1rMPd2cFwHki111VJaT4Vq1p5UJJx1al9b5srit4c/vHG6hJv/Rhdp/uZx6Xnx3DspVlCmzrV2wxQqwTu3dAuH3Qa7EMjtiGQ1OMfaDEim34RsB1Nvsiy5ntmk/iFtiMgwBsQcYSGEZxijZvg1KtxSczOY91JeBGTzZw3fshUvyuur4/SBSB0AyCFR8zk7QJDLO8UYUoM0dBe0CQSIPXuk9WQCWaPnPoluInbPbS2IkW7aeYIXeYMxjo2kikbcsWB56oFre3KERFZp0mm1DU8k5ThFUik7eBqMGgqtMpe6OfeLq0yOqQB1Sta1prjuIFCyD+EKSoVAJNG5bX8p0QrOaFtbGXuqxCAISxnpXTWqpbLfUeLSeD1ZPOvE8muaiww0TsB7f2LWC6bLgbsekM0hEVIlu+eGSX1eJqD2XKR6NU/Q94zCf3/EhZ1Tz9oAyWOGIqdD8GgCThva5vwZd2PX/ZngAn+px7eCpjyb2yH1wRuNfrD4zD56wdud/FT8fL1SQn/c7r+W6kk0F/pTvkLPNsh1wuj85OgadvYsEv991uPoBEBNFjHCrXALlSZUoX+oQD+nI/gsRAeQfFAsmUItjNwYVMLB9nDCTzEAvfGHeesoB/qpUrc1D/YL5gigOYmdvRCZBPFWxjdStjmePjJvp3YrzYPNGyTKssteLog7qbKoe1ckAu/oyJjeYpJ4WyLHpI8ZeSjJGymVJxHvVfoIRkHyIDs45ZKx441fQVbKJN3L0vkdK/WIZLPFxj5bB4v5Glhgc0XCBB17K2hutMimDuJDSusVvUhtp8t/JgbX8KDJ7UP8BJXriRnWN8xEl3F8z/IUQzlAfdDtob78B7xRlR7f1vlUzTwg9Nt55UVM5xrV2s5hsN0ZK7zFMEQR/NeAg9bzoSvvheT5s+1Vqx0QIOjfMkQ9Gd817rtcG31FQeD2bp1cZkA0bfLGfUxKmf58SafTvpTl1g5a4dnO86wnJoTvMnLKl/Ih2baT+JbIIGkOtRtcrIwSKTkEoYKREVUQEXIfhhfeTF+GQd5lPmvWP447vAeaoetFY48S9/CsQINg5wha704FDSYfm6erKyA5i4yMXUhHCefay0xYRPQSM/NP+2+kydRVo9iygiXwrS4RtevmLFe3hNqOZcxMUFfJk1odLqo19L444lYi4HEEFSLt7K5TCSTy2qHF5J0FhaE5T7OgY3PoLt/NNMd7SjLUzgkmRzcql1MhBBWqDSl3wE9XhCI15it3PewydEBrWt3Jcvrr4A0IBhogIG77geume69ZHH8jj7AASIk/W/icfC62cgN69n7iRG4x/XHrA9dNd932fLAEbTosMXoJZP9V6wOHoUgQkF8Qt+0ZvdtBVyKBuiZdb17VzNtx95WNifVP3NiINFphmx4zFn8yefFyR/Hxazs88h55zeZre79vmvDeretfXwiyzKZb6K8E+aySsAc5vsPjHxznQdQO8nyTogCHmgRIorDItg4kUwuslwE4q1fz4P0RWSOOETOEMrkzG1tgUqMtSheeTd+/qDM0cXRVXPeYxmPUSKyofhYUrMJXRWtdURagUE8a15QkMohio1/1ZmVBO/fhbdTYviNt3QbWUaT/FTNnM8foqVRNylIdZqsOkMK7GYpLlZXoOpMR9Nb1/kbDAPGN1OYrE+GTfucuMm1qM8EpuhTYBNLWYoTJ88RQgk2LSBAH3Li4lWCgnhB+/BnafAx8hLBiLBEjmv989Ou9YfQu6t1lG1wFgeRtrKEirKMwDAv9hdMhmWawl/Gfn0r1DPYuL8NmVOkHs5eurUQuKIk7JPrHdfIccNW2nZa/wb25BqHNUXZ0G/Zv9XsNvTPV/eXL0P/B9r+zp10nczmo6Og/HxIvqgOkMUQvdPgSQuAJgDNz4DJMFAATF0DJK6RZ4JEQADbBvTJncIk3BlTsbycQmDpswgpx7jZV8HuwZ7eOwvY/bHBPZpNBpbfp5NI6XY/fjd9X3P//SeblJ5OQt8YcF/+/fKWiP5AfOcTPXzgiTLNshP5gdF70hmI70/QTHBb07b9JzGfP2NOJvsN/3xs2bCY6dEa3mLqvi2VD915tAl1aTRZ7HJbnGMPxGNO7rXMEkyG89tSo3lMpioveqGkFsMylKopilUld4hFM4+U8synt9yho2QwGQx9G0yabrqYvV+aPFV2PyebOJ1zr3zqa1v5CXmq6ULO/p/tTpS3f0DOqEjGKbujWPHOhK8c0hgp6MtyJeCxxLBsvnOoTeOMCCbDGkNgM6IzbRp3Dlk1N46krzVGOb41LpnorsSp3den4IpjNo6if1+tEnfPP9NQup8Znd/2NIWnDGAFBhqTg5JCcFmEkCKKwwJsnEiOnMC4+67har4wUTNR2a0NfIu8qPV8W/MsVlvtb2h1apFr1eHGZtiPWtnjfFzsEpngJ7gIigeITqRPJCeiB9BNIRdvwlV2eHRU4j6h+zRh9+fovLSco4tGlxLIbcMRG1K8YDLwgAQCpJLBVG7g+Xqv+MDsyIDCMzyePsorjO7nnvEmQot+s2+69jlQnzpMbqjY4JSD/20FbwZ+z2GH+YTsWGe4o2a1hKBSXC7MAhmgpFq1kHFpVc5mNbupUGNO3NbfgRlecQZyPhMR/Hwhpp0d78vfkrR+wR6/edfOalAHJH24FtRQvmR81Rqv8DVF5PpoNdU0Sfh1nRKwOgZFtjPTuenKGsCPJpGmNSXHxomYANdwqUY5nCN07mK7sTWN/s9uVIFDy9LkAVT89DSBTCfjQd3R2UJAoNDJhAR//qSGuiUdRuq9E4evupcs+sxI9MRA3NlzdMOz7j/ObseEPpoqKe8oVgNBkYa5umWTJV9DVY4ApVBe7pHxy10bFUUPDstt2e8l9Gfx699j8fZ2qeOFhWAY/eABenh9cw7/JaRovsPiHGUiWOrVAt3d5lJqXmA+OGiLmfvRCFjeHQYAEy24ioFhjHZehWGvUYA/WzOGfvUKDd9YB8iiDtBhMkxIy2AyocAOfdBi1gYstyrwcNAqbeskWEPx4ZoaIVIgkuOISW9xVHyRKa1EQf7rDtm0mLECKPzwA2kR/Fma4aMVtBPnJedP0BRW8CXKvTFp4OPwGgsY+gZcjVnbok1IrScITVsMPDm5mmtzGquTPRmr++5v/rijySNaEHzgtCp/dUDZtIC6i+ATE2Nyn38uZ7RpKr/6IAaucarG8yHoT1kde/f+epKO8o2N8UwuNY0dPJmBKfncJPujxszgY7T28XCKxvXbJG4WyZe6lipiTevba20d+Ckm+pGmSX7EyimKQRGupaOyowU3jURxBY0CBjsZKJ41y6aLpQDhmaM8KtiBKyTUvKAcyiklU9uQV962DgY/Fl3Z1+fmByP371SJiIvrAokJGF5Tud1c0B+3B3UD1ZKs8OMt4/hUaQdJ/HYBhMhTC8F59GgPnCMlBybDI0RfRTpMplPgdE2fxWeaIzALuEDIt3gdnHuqZ7qLMtmsERKR6ZJmyUqXdE93vrpu3LcWxXD1c/JX8nPqFuM/hSl9Etc1tpoMwTQrpdlWbczS3UG7pZyMUld1I5AJGstdKEIx9RW1mHBpyrAEE5G6IFuqM2b5FEorLBaoLEbD+HD+QdzH+A2uqADVK3/7dlTacl2tm0iQb1KSr3xQ5ZGiWm0O5HrEMSUETkM17aG3CjYuOg5r7bDrh9M/fx+ICWOiLy/g7fDHqrUL+82oXXP+C4czUns7xA/+dIzk6hxL3iDQ1LCQX0lb21PY8/tC31ULZNU+bSfaEpnwKwXwaErNFkbNM0i6j/5FIBucYiuGgC6aKU+gAEGs4dEe7RYx+Fs/adLZCPk05yDg+bZEVZXuBAL12YUyb2rL3HQrwcfU5dNKeDy1xXskG7tj4XIX7NoGwfSeqxxtPh9nyp/D/GBDC/EoDH76y5vjaPLxpYufxqxfXy4LhuOLVUKxobn8UEjO5yReKoVQKBUMBgVRUH4sFonJ5CEY5q/xM9HpJ898BE7Qv4olMv2U8qgnDJq25oSfVl39mOoOm81b0P4hIbVhYejAsnSfHp1rm9Zq3gszVa/l1apn9AgEsluAIHawKWUIcga7lntpxnriggIJzWjr1Pu2Ond1VU6siPryk2B23ToxTfyrhd6yzv2sdkEdVRSTU2XLUe/svFJ65XDp4VWyZk7zwYPoEzGaXA9mpFfvbOTV14cjD7VMRDI9fKkx/XYHDlRy8g/n510Nv6q8N/c9Y6z9ixwqCDD0pom4Y90fi2bz8iV6EtVM0Jh3OaYRltJ77O6Vq6cK9h5ctbnZxrqhxaa2nqOl7VelISPv4Wv7tqwyYnQwHDnbcbUa1End/AyXAI6W5WbOF3DqznSGo7a2b5zpQHq6tl+LzdifYXokujSdOFr+0f+4uHC1rDejKyDm4Q9h7K9gjOYOVBQmeIdmFMpoATwA0whdgcHknd7HMFK4qd7fUx3aECQgnYl0f74QQQhZRcZWOGapgDS16gg6q6d0qmIme9/6VlgjwTZAVYiheqge0tOWMTnZBp+pGGGA6rOHVAPeXTNVOdM8teW4Eb06Ik0NZKlUOGLJAdYhhFt3PMJvriVlBwJ1f8/6TaJ6RwIlZBvy2NporBese3sD+4C8TjAvFTAFbD5jDZoJ3JGZixdNPVFtp05tR/m/cgNMlj/Bb3a2sHBmBmSS4ozQG4/6b3Gca0N5Rl+66ORkAAyU1V8cX5gF7FxkvfjL1dmtGJL0oooZG0ZHZ2bGxuLggJGRe4xiVK8EKnaLKfnrRQUCTJojeb16RjRJ5NQjJXqXCkCpyFMNlouTL5vIRcuuRXBPcmbmeuS1lUfh4NWpiRPnjZwdxGIqRJ08c3DYd71+jV1HDxZTbpRFGpUuPmQhGzYtiElKcuScPrA2latx5YB+L+jTP/iDQlm7ZmQCL1GKaaE9TMpKDV4CBLWKATRzrq351lYAQfrV2iamjgmJLOSpI4A2NRXF7te5v1bV9uaL9yAIeLU77ZB7mAdo52kHmHvIL2/vEaWJEngVuDQYopmN1ELwt4bqzXy36oJ+8aITHQvMTInKtMfZ/Mr9566cVymZwbRfkJzbX5l/drV2tRt/c3Vh3+CS41ztz6P3T06JU87+vr1KyYgmksBxxKBOZNN1I522sekGEUK2F3s9qr0dJd/6DpDFmIIXP2WsuxZ5vL+gLVN3g1igGmG20jQE5s2Q3pqTiSBah9R9MBFqmfzwka/+wx1lxHvrqinSPkOwXMAaKUG/sYXLUfBsAplA5gZBZA5CAuMpZAKLXoAKy8wIhcKg+D6ACgO+0TkcvGU7SzaLqx6TBwvsO31H+BXz9itO9s1Uxwlao3LBqEPJ/v8B4eBI4ovS6Redm3ruPMMm5AdGHfjAlrDRek09CVDyg6iLqGmlNMIMhqkAKKWpUF0dJF9qB8hiSN71a0Vdi5SCMzSwHBaoGSjmAlk0nzfgEpOiQrkHID/ptxUCj3R5E5LgGP7XOqiotO0iA1dcVfXvpm5B7Sb1Esaltlpdq0YPE25S22VSDGHlt1SNCvuDxZIMglB1u/PZKyk+eOfkEVhMbuXRSHfMi2s3iXactWKy+bDv2vhVFD/Rx3RS4+CuOlAL+rpJm9OwRa3nw/y4ySLghkYAeSKAgRYg236MDeRAKd7qhfPMWmXLrYHAQC6Y37cAQ0cSKdk35bF1kMsph9Cha5P+yXh2Mslp6tq4S9DVUAfa49BYfDJ7+wVhMb92N5lSMg8Tsvpj49wrK72j/U9mUg5nEU74u8dVVkZ7x/ZTt9wq7QYChffocYuJxxvR3qf6tN7T5t/ZyewKpB2yjgK+HMhFiKKRHFIgAJEbb5vcEY8H88ssxUzzbKbjFln82vpZ+ttHQWk3vbBR9knk0bt3cxM0sXzrOhR5uOtK5MmjT0UCBpvowIhVNblFSzazejo0dXt7tzTjFUw3qQbqtIE4URVW3Q3W7mx/5U7SwYaaDDrCYnLmO4cieHisDgqBfOOSOFCTbOfKbr/dKzuPLY8d9nVu1G5U4fND+16jmd/TI7jcdyb6tYgZwDPF3lfxOYpYOaiWwmT4u+C714wuewFg+F1bu254C7yQtMY5s82WI0Ke6ZkoGBwRRxUX8MMJ+MtyRI5rl8llyJh87MPylGzqg/Sq7OqVyEJ5YcfU2NTHsatjwAsNRIEISmsbKSJAGBeWyIReea9f7AQrtJ4TBPLyb2J6b3XtqS6LxfTMjEwxS/SjANwgGYrETFqDQsFkmFisBSa3CXegL1xA70BtGz8jhlNhsnb3xWfGaQdC9Qo20EMFzjU8VtKW+iTDs3lV+6PDIRQXduYVQIBfGqUMt4ew9I1EJLmn8eY/+o/FEqvH61KeTDnEWyh8YXIi1ee/xAj5BTGNpS4GSiWreQphtq2P5pzODBZZVCLo4QcPhtFd5dYci/Lianf2cNUj262hHeLQQ5jMA7w+pd9XouYr7siOF0EjaKa4U6IuwWKetlj9tg0azVZSURRHsi/THsVUZaJ2kFnGFBSVrURHCGPGjeCaYfgMAtBn1HKkPgAeKAWSx+chJiAAkmX3kJBaT5g3mczYMBnmvgHFEThCCPMnauOuzkIUefC7/tOKJDQxSGNF2WMUiX4D9bcxlwKdn1B08cY4iHy0hKJ/7vrIF6i1wC1qT/uAiAkXd1UAFr8D7FLifqc5lF860qPTfEjy/GNvhxG29Su+pVNypH+ivxkI5NWw9whbZFsDwrwILXevS2ji8qbwwCfnjeadl2Jg7XlqxH9RYdVbxYQDr0eGZmctHZI0clyshaGELgbzUlEVangYJV9V51FhmvZDVGdY0ainAzxo/XqIJ5q2vlenWNXTFG1rh0UAEJuugSUy4ablaTcJZHu6Or+Agtzdb11vG4EM4cyUMoLA+UElxAERyL/2XtwlOTu0MPGIVrx470KLzi657B0j3tRFhnsGk2ulK6+JxNcrap/toJ0spNEFNcbhmzYchsnw1jegvixAyRCtSN/LC0++gbnX2FowBAGEZCiUzg+aDO4+Gc8q+mrPRJayBeDXSDQzWE06e+bJpBFsXvlZaibFftjcaPLJvYONeqQ1CcKmvxXSOT3t85B0lmGmuJj74sXgpwNjdki6zERtTL9alY2oqB6k2HeQ6yjP2iE51/HgPl6X2r1LdlxxKChVdH6az+VjiN3FAAKJ8MMpDJ/m70UyacA77O9e2r50D0VMvCP3kE5soe9QpJupq1colRvALUHIhCWjJQJZxBnyee7jNcAByIRLr5E+maA01f9UNrRTI6AoSyhn2QQIYp+eYiYT1TO5wmRurcEC83zxwsbHY10XiiDJ3ocwCrVQ2D2/PU8uHAaBQsmrn/98nDnHpUHr322CJLb876ZVa3beWcVmLN6X75sknRis5PHZBsndfKVmDbt3SlNwS+Be9KBXT+LwYSXhxdr9e/FdPy0jn7moPPbPj83iYNX3mt9E1RZIvXgcjWnZfD/ojJc/e14/dhDwV7lm9oWqflBROXCyV48xkpdhBIFGBFG09VQFIiOhCYY9ocJAQN3CMweuZzV+LYIy93L3qwDxcSLJGKk2qr4tltnYiVbE5yp45VTitojisNkc1KLb4SuN4vU94QEWCd3tvbxKW3FgYJxzovF2THQMertRXGFASaJa5v/dmI6M+iZoE5pB+FJj+JBqjksxuSTXeS3yqw/VbhT3JnRIS7L8K4uEK8KacGzjwqM69IfO82jBwaYvBlYFGMWh2iv30I8e59MF7ykeEILsg0VMZk3k0ahoaXWJOSjkwPD/kyDqBARKvz4ZZgpu0l5Ajoy8B5Nk1YGJQJcl+eCZRrjtnDfk02zYjNg/X6SZWbCBjSgQIUNkIb5wbgLUZQnkGzKfZpyjbFzAf0/hTpHwYXlV+I5neBf38uHCgY6vSYHS8nEBqYyJiI0+1z+C+nMaA6TG1eD5/EaS94Xo4z7H06/5kAKaNSpSCZSzMpvKABzHwsZOl+9eyMhvhcnwmKYfY4+dFjJ2aQjwcgHpm83nJm/Si3/uzbnjXsfPvjnbMiWuE5+rba1rBfZJt84nrV04EU3z8IPjvkat8RckUyuj+aWmZmcWXm4+fGGUp3uMHH08aqsbj6ZXHJ1UaOzkK9Gj1o925bUlaAZxD/cLRIbondsvzjuLaPu9BpcZa6paaBKspmi0Iad1a6n72rPncsPO/Gv/3CqlwoQg7rTXE0uVixwwLn3zpqWA+VpAY/LnEDHW12ixy3Jx0w3bnfqqudNXIrLHtnpEtdT3nBl+lK7/74HtwM6RmBn4ghG+rmZvtSV/s7hmH6/AtgYWBNkWwxVRv6L3icgtyWRhjjK6IxzHccCFF9032NolsKzZ86jagre5Nb+qYWLsBv2ff3hoRDWjVrtVisj7f0W5ROiOh3qGu07oeIb8ivbRLyCVuqcB14VqSUfL6PnHxx+tinn0frFJr3fuURUNXDHPHWUG5Y16RzgAG9/VsOk1ovyFbtmppmhiRFNU5ITdCg+5gfBWIqQdkR1JDglm+0sBjo8zdh3kdbKuHZiv1K3U6/aay/g1zz5J4FWoohGkMv+s3PXeJWT35n/pGY8me0YKxSGCuS5Xrs81AX4m5KjuCvVh7GgXWk8y2dMjmnbghUIS0UJ+eBGzKDwdMUTxB93wQdKtA0K0sHIVO0HhP6xS7y45DxnQHsRIu3PAUAI5YM8jIuTYm6srPTB19fEdoQc0apXKxb/10WFftwNukKLFWwS1DF6sY7UJfOwWtC2+Zc+1oJonJ5vlQ3WAvMboNRVIw1vm2/k5fj0tlyMiUad9OYM9IlFcdJxIBPjL17qEHHVNJBchAEFMILoA9QqFiGWx50VlwWxqTmylB5HbOgGe8gXXibej4hMvvaOCIX8jYaH7/FenTT/tR8X/vWcN10eQOVbAe8x+fn7QaFBO7USmiEl0kTEa0+m08xN+X9KwjCYbTqrxRE1LqdcXKOQ6ECrDTUm3IrGylPXLUGhRciuSjoxJZ9OJURa4dla3xt55/iGPg/2yg8423W0Olsv2c8OtJh4mBm1Dmrj7gU66azplpnbuzpa3tjBpTEEQ4thUEtYs3EBBCvL5LNO4i4kVv4Z2qaJncnHgBSkUQUHs1IWcYsAD4T6/DrdCT3Y4CzOG9m22zp2pKQG70TeX0APkYy270Rlgf6p9TGoqcL9FhyAj2lOvXQpFpoCTPqW1v5QXyucL5B3y9nbeGEc4NMZT8DqM8o4ICAIuaOBe3zD3Ro7JQegJqMKAZRzHW6s/O/o+L4eeegq2d/5As26zHrPH6VbA+WbU0cle+xcN1qtiLW+U51jv3js6IxABH87UP1sGXMZOtvaIBLKjAwfX292uvHfx+ybwfxSR/ygcHXtpDnq9BvqmphI9B5qk8NFK8/LaBsh2ObjAhcWmpgYGclrF0Ul0UODpleVQ9GptyWG0eHkd7t1WBuwa3ILgCp/Z10yzCbH8IgPsXlOco5LTeaBrwfiw0ePTfRG1HXbMNyQ5FY/ebIi3k4/h5Si6LdyBU0nZhJdjLO3k1XgLToe6Fz/ZpfnCkIe2tjlGy6HX7VEHzlbOOWBdhLz83WZythVaPmiumnTHyrz8lbP3X1dGEV4PHZh2659he7w/8zHROD9Oyy/NGR0clJD4YL82VJVcohNspfcqxjpVfUE11KJ1I+uw0QUSZWJnzWp99tB7gubRz8tjqAvAEX34/keEuyR6TVnDXufE/Esl1yeJ0lpg6vL3eQNfvQ0+7nGd2lbeWO+wtWrP7RsCQXJob9CpHt2eDen5wxxUZlNTpnyozsPHuXXe3B0CpaVBIbZBdbkZ5Nt1bKGQtLSQI7xe/e9p4F6Ia21N8OoCMd2bH0F0kHBV0LZtLXQjPQfyJJeDDeP/SaOCQY3kGTeuR1px4XSSwoVU7LGO5jGLOGEWdQFijhN8pqmGN9qxtKgXdJFOghGhFWZ1iYv6PLRWgj1DZx127nyFbhfQWTrM6kYAoIOaVzTaxgCF85+Il8RI7j7AIFDonn7c4eALYTL4CHaJQ6b6a9DXwxdFxhGU9gb7p78JFxBk29rKlmTIknUTl9F0iSFVyBTLkYWgsGP9eMwlxRJQKvvwTXKOo0rrU4vD022FG+MOHnTEOcrJGGcvPBI3mTOdPZ29n/ld9H2e+6crZiomqxPWhvqZGqmzvmdycig6kaYyG6AUwmR4nRcAO/RnY/n+Bw864ByUiSvAbsM6vsKw/Ue8W8IdNfbcfm37TcpNcgTTzQlOd4xz00+IS2P+EoC19ivQHPAA5yHIiUeCvFJTBb65d8vjdOtH2cmV0zGDBDKB6dc/xzNB3qlTem1HZdIJFXi3vl1mwLZxbSzxqEv2qP/+9UBHLaqGhMUgrSYBf2qqEk5F74Fs+BRvLVXi6ZIXGuh/gaGlJdPYgeitHmfFtLqjgbJZiVsiOxkQ09XhQhZTwaTHgdC/pvA9HvswKKWj8tjLa9ULMYTALFBQSlQllk4RXdXx2x4HBKA4iBq8eZqYgMXtdiamX5uHVSz2Teq7EUsnNTx5/pYp3njt29DNnz8SQXHJWum7HIM38UwhG+rTN2P+VPPnB5BAtvHEFAV4QCBS9i/fZ8g4PKGuSnlFtCE1qWv8HktyNchQYWt+riDiV1dPGOuCUY8ODE35JBXV6hF1/K/vFFUTF3eNsrrC4wwpUZ3UuEBKwJEmxBrBxzaLIfmwDDCoQiyxcZOvJsbgiNkpB2fk9FzIBf8YK6gezP1e0aRBWh6eoYn7OZwq5TvRltSD03gVQ3Y3zMBwtXR7iHj73ZOmuuD4mg4YLoUkFbWt+9Xh13SKqplriEZ52PlR6uZ1tZoshmE3Bq1GbrpMrvQ3f3n/i0W93btBXSy5CQdbTg5qFxqqoERYkt/zjCHMTPqBHZjhsbCrnOyoTxR+yd1NSHeNEwO9jcanyFhjqxSygT5tC/qZKnFSc7wIPLtGdU52Gk0rVjoOu123qiY7m6+rr6pKjHDbg1UlPSRYwaXquEu+REdaNNqTMpVN0LBOqGfql6AUy9KgfwiHVVSrdmHxj1+RVFlUN5wK6xg5o/8qdJK91QgpWBcO2cda3isMofcYBmGh6IKNMSgkCOLHQwiKHZH7iFMUEqJjUHKBf5Y75PPMrCMy3Iq+J3MFqCz4mnpWJNpP3ez9le94ngSyBmvHPJURRuhQ+ddesCxsLA67kbVyAA4NYrOUgdw0QD74fVg0NV0IYhsiLO2QUhohZ8CN4iM4hyh6RP2aUeezLMoBwUXxAbdWYhBBwrVXOYhNF67gcuMOO7Q/nBf/UD/m0WB9k3bTQP2r2FXh/bureiqtWzEYqcfojQyE0mqwvpwbg9Nqyks4ssuRR4CSKEP8aQNuINVvypIALZKWulL8UoblpEWIYDllX7VrKX1wMiwo4R5B0JQjyGnCrYAztKSbu3P1zlxdIbHVeI2BCxqR5IjItRf0SsBz6H++9GFpAJzfAVEmVoTNFJ0GKhVjzEKw7BR8ymb72Gl1GkNqAajhNFl0/SV6hA/rEDcANt+5KXzmCwDaUUvf7UOgKGd/Mdr3j2pY+83dWooi/2b3bv6bQ59h33eHY+/sVNNDrxLdFgEhCFAiOoiO+xBQshGcmGcprRiVVQI99U/qegJYIdpnFe49mS6gk98bpyNGV7+gv55fEE+jTQgxuCL0faM0Nz0dWrybYkHv83XOhMIJZDqLQOawAWmkyBA3iHxUezaeQqcQjDj46BzgC4VnZtLv1FG1Y8v/XJPgnU/+2Ce3MEFkWI6ISmBgFL7txMlmFLPxjW+rRgUGqiAa9sgmn3Xs3RVttMKwAS3HoQRie7pN+JrViDpiYvF4TW5QHB4jT1andjIhmZngGvMqkkskpzxk6Ef6S5O91egQUoBv2a57IqKbUSH7rsdtluaa3h1fapFJ5YCqVMa2p4Bwprwl9yJkuKXVpbVWjpVRK8stLzHsGcYRJN9LicbCkBHcf+tWP8yYdvfDl4+F+yfkGjpS2/kZIhw9ShApFxBEsxIRlDhwBoWV1tSLtH9tlHe4Bby+xq/tSO8J9a1W6rSt6ieGH3P9uI+Hra0MoMWoFTlEg+RyFFrmX4V4yaEHCdYsojXpYCOYZ5fRoJAtF4C4R2JXtHvsqKt6nz3SmXqGkNDJv6JZV5Iq2Rc8xUY9Wzp1vCFEmGjRwUMiVD0qrocSMREmlNncNYkCucFwEDQsBO3uHTICQDSwzYY8P1LkE3HKhZeR4FW44GPaYkF/oca/ibbzwm5o0Dlnsk46gC06Wl75q0ltg+xF6fcyaln2uyfAc/yb2eu0ZJNbsePjVEeKSOTgaLRnxdm8OyEUoTjJ1DT5IePtazh/Wih+EeFfqwe0DlrO5gDljVC1DYWdVLqIi5xlhF693kWx4SxZ7KVZSe0E6J3nz++UD1151AnsxhWyOoIWAIIeOTx5GQWMebm47kO24ZQTly6nporn9d7SMsvbuLwspl3+MezSE8CR8J9ChO7hU2tPpZUoCUPACS0QjWAXYKSFj0ggYszXFgQgBRHkJCdCQnZTx+svXyorxK7K9u3J7SYS1ZmDHnDnNYf9B1W3TRcyPdfBLvA6z8VfzhVU/drjOBEhUOBTm36tc3L3THf903kephAQeGiQeSL+r/gTSKGc/B4P0op2ptJTKyhaWpSK1J3/PT9Iw30E88vEv54wr96aRew4e5pfTnC0T82T6r13XOTsJd+v84f3ZD6DiYj8e5oyOyj78kATZ7CP8K9PisBILTmgmcQzMQIstKAffeM6ut+dmfvTxElj3ezKdRzfiQpfe93R/U+d+l8XBQeraQUHCgSjW0vtXAaozmRksJxYz58bOxqnmy8jfUY1buTokDFVjJxRjOJIzbBYOsWZgiJ7R3sgji4uPuG8yKfEsPCijeBs2NxgrmG+JgYQg+NLXdEGAz67DTIMdvsMGKAEB9ZocU2IAXDNWyGLshpZaqFQRgYkX2gHyKt2CN5EfWnQfUGx1bp89tqksbZ5zY8Osw7wq9d48tp92laL8kJ3vHx1v5CxLGAbKx/JXdiF1bFQYSEUSz54Xaq7sHsL6tgxlG8LeMQAX4nYA6MEifMRuBIREACQamQ95XYmQ/29Q8PnpNL4mVvCeuCg9vANpQZwhqi/rlzR5613Edg1GPlyYbmSXV5XczPsN1ciqzftKOdAP0C6wjkaqRUYphUUeZS7MghKd8QMcpVSZelKXhB/S3WkVlCYVqC7bV5QwZYaqnF5bWlPrd6RGpT32CA93yDjiurHddJDfI8O/uem0h/nJaSWVBsbl7NjQXf9wnWxxuijmR926IjDhyr61wqa+OaNW4oqLEuv99B0Lp5Mlzz6W6wnuaXXVt6266Rpe9seYfWWjUHV1FqqVOlwNEo7lKcddsBObcuA/cr2X4z8Ykae0vPSANNabhJQ8gVDneGssxDoSbnd5jL7xxWrBoH90RdGfqnmed6Bn9GL6i2pQcmrHm19K4mMXIx7UfhcRvI2L2jjlryrfgEBU6GL4KH6zYZZIanEJDHKA2DpiHNsGLWMYEEJZWUJ8kE9ACUYeaznXRs3Svr+8vb/rc/jnblpRIDp3nsJjKsjSScvCcbYoRIlBCOAU7UPUAA+AzCZIr8O0JlHBIiUP//StZpvLtsvtYg+8O6ZVAe4cBV/6K5PZUYcrBpmyrNnTp1IPH+3aBA8mWOfAse8t7F3A2n9gLp0fUnCNfr9L31EP4VVYid9Q7Pz76p1efWt596CSH4sIUS9npDaC8aRX7cjjPA0Att0pfk9A3/OKHtU2R0QKe6w1xUH8Ew8XSp35Jnb1Z8e6pXod0ALkNYak8F3K9kHYSJsBqJAlhkdrwCWb/k7GzqZICCQgTtl5/4deXXz+Y5qz03UGtl743Pb7uYHRR84l31k4lDq/ePJU2dP+WnFzKiMsRs5h8cpFCctn9ml9C8mzz4/zpsKdT1wOGXr95Ts9U15/brJuVbpw/yCP0WFamuAB0Dx4CsZFPi5pjhFABq0TYwxKq6M9ET7Grkuvd+Ex/n8/+U+M1xVMOKrPBVlikDsUn1EGNDQ6DxjasMhpgiUPJWr4t1bvLRduZfY5WRovWfyLGgTE+0GYO7fRj5DvRZUKEQkmY9J8CbXrTmY5hTB7HRLPA7AaYmcMgKKRIZYxumJMMAtqlOUyQKFwgES/GS9ThZcnWqJ26V9euLIIo/i+8fTaCLAxbVMzQa8rjOBidV40s9bNihAJj60AB6QXCSLizQijS9BmQzCNUiNPonsnDhUAxlTdpLNRJgCyv5lIWKGGKnXWuohwIN34IpJ7NfDQWeqLM08vWpvimax6QoFmaTyQ6bpA5mGeLvQIYmkeTysyDDyQYfLpjpuOxpGOfN5BJL6u4K/mbxEoS+sQB6fTapmhsVxuIj8V+fvdGZr66cPd7RTw19rJbFs24Qek3Nrr7N3/enH5W3H7c/aCcyYyNR21WdEveD2B3fpZKEnyOcsxr1Qm+d/zsRkfq4Ai+k4MC8ssvPpIgmdryVwuts8I7YL50/pIm/9vXU0ZGJj/9H2Sd72iUq6mM0E211AMmRQBMyKPCgwl5sLKjZjQr47Y1mkEClJc+f6T1axxG9d5x5EWiGIVWTbo0CfDxJGyaO2cyEEibR6MOfybuMQcam7vjVyS4XPVhrhd7/CO5e5O7PNJ1dykEAoUCCYHwkJBJBRNmokX8TjF+X4dl3paHSjUqCGwp789mkWQ77yexIlKddK2kjt7Rrn5kht38+N7zp/vguv/fxabaS5cxrb7ztRfOoUcAKyJT/X3ey4as01R4HmyiU0kvqFUpAgcAq7KQ/OdOoOCq6o39N3bA2j3/mQLiL2Y2zYG/g2WM+cHahjzDLraYjM3/5dfk7rjEDb8q05pTyrcIr03xn6G/F7jd9K6GSwfVxz1nyWfYg6RIojXRyUiTvb/Oz5c30zYhYjk2jWSMpkxJEaS4g9L4tYoi+R7PCtLGuuSNkVI1+fGPsnrB4wGDVUshvrhwok+X6tNnHIDqLw/9HjVzrtah1UD0KFXH8DwLKTiQYJQfnaOe2hmnV1LrRKtMcqnTfdFSKafuh2fW4IVfTnKvZGoHN3LR7oAfzaQg9v98JtAypclYFxm+Nk/zvkXf/2lbgQXd2xmRF1bEZUfFScSCddDukSPAr/Pz9K4yHOt8yNtmRW3h1/rM+NrGhnlfaq0IOA873dqMtj+ykOHcm4DVxQJ81u/0iaXbFl3OUTZ9heMUPlCiZBP0ufcCqtEyUpSlwu4TTOT05gWuzwvoFTG+9Euit98rphwqlNhJMq6GQ0UergDLwa1rc9LfSeAHJwO5d/abB/A0FA+PVThIjmDwj9R/17B2S5HVENMQoI9qtAYUjnI6nuF7vejvVw7ysnm1f164gBi3f/XEPLc3biIT4t6sZ6kspiKm+YEVgrj6muufPA98Uk0agH68wlp1YX1K4unBXTKTSxkUmS1CYB2f14rsHikX9AyOTFkImE9exXyZYnyO5X9bYbcmwnK0YrzkeZmiZYCbSybdbsuKuvswEd+ijHsi2lqSYnxYgTZHDTQX9y4VywDxAOdW4LX9t/ZCBy5Wfmr5e/Pd7WeOJK+JXDIPSI+iXEFD5jfiFDuPyl0HNKs/vrH2d/Plk1N4hZULTY0ye3nmyjXoNlhsWr51bc8jUFfj6kS9x6D/f8s09Zdie5Tt+XOJ20YxHqj/B3MRp9WH4g13q81LR54IV89LtqlTa2YayE7j+vghpAZ4UWfiz0yEKjdtgVXbZ5v7d07341u7FZF+xHbCAkovatj5O90Xkti5O91nmTAWD0MfAYN6aOweq5BKxu0T704wvoneaNrrVr//3zrti8Fucos0dm0Y4wGd5CYMEoCNNkMXs3PuOuLiMoxKrLBFV1fE8riq1n9qCrCIZx3qXG2TjV+ngLVSFmCpLO4quidz6+gK0IiEM/9aMylCuTWuC/f6c6YKKROqDpohFc43zW1wFT9tNWP4MLOqOVrwU7uietZZAU2ow9/AHkL3V/1tLuKWupd3+v5e3bo6cf0q/9RQZNWdd37vTQbN88tQow0gUS1NUZVKtxsUPR2n/flToZF+D8aFoyR5w7TIaTBqyeiZ5KUGCUVoHDas5p8yR3KyETtXFfdx2qFrW/u6JbG1qgW6/OfN0Nk+GcvQH+av2eMixo2BLutUucm8KIQvWbRqdUtjav+bNidblzOdj6Uy2WDeK8QwMNnJ+FVoslobYBgWvNM8D7B/pBXk8KAV+udqJwA65wa27Eeng8q3lVTb0Fl7Y67rbAab1gv58FqeZODrdsjvLre9bTiRU6xy2XxBc/xoCfX+GNqeaZyqkLDjEOApEVHBxiLuzPmsmevOFXCPxkIeAU3IxMudXpn9H+RkbFokjf/h69zLwMvOWhqEyNtI+aWo02uwQ7lsoImh/TMjVQXnw/qKsXhu1voqq9ZB2Kjn8GFWISaoebAA8oUzQeF9WrRwR6k+OfermERqVJ4qLGRQ3mRkSmINIU2VSx2GB5taLINGWVaZ3fvXXOyUd2RZFERNUVfwDDlVVTUZM7jWBFdIZpIcABhRg/TFpzoUWNZ4krMzSCG40lTfv947apbtOk6g7fpT1vI03jreJWLiYumlC00LN1BCp0WlvvUUyzE+O3C4aAHEiVNf804cUxDnD8hOU+c5GpN981r9Ez0X+kX9LZ8hU/BKfDU399PCRp1um5dKTcIe0bEE5CQRweb8QgjvAAb7Xl4A7DOQULnzdYrI4sSvJE+y8n+QWEuWZ8DwvRtt0/oEPL1zOyrC3yDF3vgQBZ8tZ1ki++Wgs7SHjVvr6AU7XOtdqiDUfonfpHass49nnGzPeKAXaP107zCUO0VjepjKun0onBBZzSs2xZOEw3Gud53Ds9X5Pp8vvZ01zTTS4bPE9t2E3vph8Bb5aJN8PeNiX4PSZocgIvBBQaC9T6HUIq5QI+LMfDxg/D1IA76janiXDpvDIQehUfovrGTUK4wBvm7j8EjEuciutvofnN014uh9W9iwG2VGAXKBVBtnIZ3C5ss0BcM2j6NITlPechFZuAFOBl0HjmOYrGKJtVO7b1au2QpiM0Fu2IRCvI3GZW04nQlBsTqGeQIIfTNpBrRliNi4Co24Oluh9iFjUzC1Ajv7+oFGQJFwFlidFli8t+mvMfVcB65AINHfNX7hREvt43dAztwsgqotqbNJgMq5c9QagY/FK6e0gkKQqCup/nMArFI7q7py/h0V2jAwAmw8VvTkc1g+MOAjKLScLdako+ab8yax/SdAtHYrLIguMOzXW90EK4rW0L9UL6/zLOb8btSNWbrDHTDyNEQ8w41E59HhRB0I8g81DL7NQdOJtzwEeWFZwNLiNMm5r6ha1LU0aOnM0JNKOFm2TD2ED+g0ENvAOHsZ4S5tCXYXezWKW5xkYXcQqZncztKZ9aF0H3synLT7TwXcKhuDjf0CTT4ksmm9i7/1JT0dDnYRzTgz0RwavGykXqDvOqmc3nLCpCp7jMh97pmpjTX7QWXbtP9dVsJBn+hmUO5H/MJx/f8OFwN3AnH9HO9Jaz6CwCz7jySCnpAKnsOqs8IGNXdczEyxxxdEdj6I+3FOMJ41vevlSMrek4R4cztNwQzU9FQrTKWRW0sPijZnLugWTWhqlsTRXzJrdC+MDSRleXk7nLrBCHF6lzfqtzhNN0IicIkI62ZpZoq6kIw0Z51MKHvbwNlUF7r4b0/QLML0dfSFnK7bKAtVnIxCf1YBTDaOeWSBXtkpYsuZFUc36Mfm1qxr2tbN/8W+9l1K31MRF7PmlKjgtmyPSPN/l1HhgAMgQI+HwAzyqa5yMyxN4qDf5hWT+Z7GmpOivcObVLkjtR+lNqbhea6pXiOw7tsvd6IVupYTp+wKTIvSv3kF0hoyXr/304Xr6HaPCohgEmGhHQPgGIDqlNCABfSQqZnCQCtffhL7kZ81UyzozKugw3cOkN9NXIQ8voZIKIQD6u1pp0DGzJL6+pTLHfOdWcfGal5NQ0pQTl1Cu9Ht4IXegzrrbvJ+mnauI1ciXtzKi/PNym4oPfqfO6ia2B16T6fLyz7I2rL/Q1Gsgm9lrUMdn2AQ80E8kDAcY6jyvliJwvFeWYgI7X5wNEQLp819+GPVbuxkSBuBjAY/SyxfDWesrISVRjHnWzVp2TA0YOP6e36uKcbOc8VOvEXItGq3p4+FDnSKs7k1xjtjk/cs+zyUOV7d5dhi5HBxKTCwIFAb4v9fmImkUnqkRVbHZ/xgRuo/np2BY62zubuoqM++a2/PN8s6TSNoA2Tmik4SyE8wMaZ9PsFXT6sQ2PpeQyTJKsHqQnS39Fv4liFaDfOQhVJhER3JQqcbPXUT7/1dmqnp7FdZNVKdyICJOpHknl2Vd8/lGv5j3Du3xBuZKmdj0PISLNs1lclXL69b9TTVXSNLRg+e/r08csoYcgQxOVkp4Sd9sFnrQLO8+G7qE+1V+PPOJRjzpLLyD01KlTBWn5LkM3qbOcyxI9I3WJf7ZPtr9E3UhP8poRkeiaa1m/TSzLMqMQrbMWuy0WiQ41rY415s27xiq9OodBK79Gczj+B2YDRqH1R9le+zW42OCeHvw5mfI9mBHyriGcfLd6ttcmCiFvS9yYZ5IWIQG0SIIc8lG1FjWmxgQoWHDjsRTQjnS4R43ZTTd7So22QXlRcstT2G7R645CTV5f3P4O/ct/dycZ/8eZX056k6UmVW9f0Ow4/qowO1hFGPBvIxo63rUkIjr5S56tiJ5NLwn+DtW3XpmIcssC+6Gxx8ADtSLn9bIEeHIOsjD8pFMEb5gX4bTQlde1hNsidkjHezqRMEwg0sMmNj3JUOm9USq3uweTh00dArv6z32Hr+43mz2Nzwlt2AU5yf0aKh4KROW+BKe0nYidGHh1dbQ9zfPYgDOS5cqMcNfaAaar2QBYbvjdH7LB5adjW57HS/2pVHws3iepkiur5AjX3/pWMZnI/dKZWpgM9/gLcB2BQZBaOdffIZAJe86Rxj9ka+IZs+fvN/SYlHt2mkBe+rJEJpyEyX+RIdSx0fF3M6hz0xfCp7x98ORG84k+QIuOvp9Ji/Y+J8C739X9UXFZl42rHHzVfmWdVRRjknfn5dSW5wXV8tCy+DKyi8pbn/DOwNW+N4qP1wa1gTE0/qBcfhCvcUguP9RhDTKNZrOuehnoCL4SkSMCLQyE7LwFKDgvXIKN3hpIVDpsk38TZByTF8qBc5e5OoXjZBATH3vP2tfRUz04uqmcXq7fiI/TbzOtzQje4nLodsMbuBGNDt8aDpF/DQVtsUFgsD2MmFoMwj2xWrwx4EaPiaCRnSj5wO3PgzFp7/SyIjKibNKjwtzHKd5BHqGU8SCf/HgDb/LJLRdfxSoZcwh1fbxPkHvvxiQDmNNi9N5FZMUe9+jkxK52EdnEG6wCbhBBvfRQzlRL2Fo/gtOP775jfrMH/NTUAX+5rIXke4f3HwMcwM0QT34qLTe0iDvtLKotqIbiBo5u9SFRaGy+WyHl3bEBXtH+RdtNzN3G+zyJ4fBtm9ocG8BYFglES1qPsD38w/qErOBJoYIZOB94GQfC/XE/ve26G93voK8K0viul1NcTYzYCDvZVeSKCyqCKVauVpRgHHlZtOwSpsXL85Uxa6mGDZ8SyL79fyCGDXzc2ho29UJP2vfI95ymrabJ+qrbuQN2ZA4KIaEYL89tAvyyklIQrbdh7f//giyfi9vPcsDrFYHyD+5ZO6c/udCNNze4wNtvHXC92QpKgk6Wgwu2+Ipz4QqzcKyQ+dexEFAn1Mh71DZ5HjYrl64hd6sNvS2IRm1lsVP7MvP3piGPZHsmT9recVRs5hKAeJfqZaXCjSySH1lbHaxGM0VykcBA4R4UCIAytkcy0lvY20eJ+yuBGSrTnodT0aQd2oqpJAV/zScvKbNEJlNfzCds7Mi+g5YFaTpaJWtSrbK4I63p/ME2WjJfRibLebNO/om5+wxzDETKrn8F7pOt/SGBc8/k+D5xxGju5squWytHoCNKClU/+ET09v4CLzST2b784UVeHD7dOv1agl/mjBen+T1QFJgM3xq9RY8OuLIf/R0AsGVLzweHaCkChrtNCXBTMx7vd//e4p074VTglSY+9kdS0rEn03fhq/DdC8fuBQePe3HhLnyJcO/uraHIgnMD0dmzW/wKz3cEmEpCDtCnH6p4f9RO4en5073CxREwz+9xP7mD/GrxM3+aToo2La7omTb2Bzu4FT+w44+KluupKgmqmtFq66MNDfKjorBchtAPJDpTNROd/CDy0a1Jvcn6WwRzo7DvVjIwXB8draapmqBCrXd8C4ie4QaSgxkbgj5ox7Q7iFZAi/2IFciLB/HQYA+zJuQv2qowxLoO9b21W6t0qmq39Yr6IRfIKz9VIcY6dIrrHBaq23bKZXgurxywdxPCL563hje93L5jowZE4Trp8xJjZ3T9yJ60iKgmHI5EJDPAeZz5Xf2eQezQN04ti0WIbrXJlXVAje49cJZ9Oxuo5byr9+yavPMLff5xC9bP8qjMgPob9yEZMIYvRD4fyCow/1hDbr9yBGbJyDBqsqWuZRP5Poe5OvNH5D61BUjwzczFl/sthjAcLn67F5M7/E40ITiEZUfefP1ll2Hm73pOMXBWjlDtjLMu7gQ2BDTBZk6QC4DH+L6bRFfUM28R9UQbP0qn/+sJAzPxDSCAwel2dDKodPc6Yr/TtS6Lq1d4nwcYsuIMGC9B/JpWGbKHde3a6JYh56ZBvK9HaYIn5rwvmHaEXzpsAMtDlTdfL742aOYi3GYD/cKblePZZ8OQjmeYSvVtP3OwaOQxUwDWlS4tm5JaR8+8+yTVW9OCSpH/kLvWCqF54fz3COCQL2D8MFxabfHexbqUVpeYUEcrWZXe3R1duGqTdlI0o8q4NKUqRZcze7c2GUQwfowTblj3GZNp7Q0UHicJZF1DOx+G/DazhSJEJF9+QIBSChRAudyNOs97VA4iEAm00fIbZsFrwdKyelRbfhZEPvhdMnzMjtt7pP425hKZMHBj7BsaIJDJYG28WP85CPuL5JwVUccjZ8W7ORo/K0VBmeTkJxyUr2fKXZZ6oomqrR9W1ZeTgGL5+BduMRXM30jV/XbhCl6xlDYU1GqqDXB4dX3g+FXDh5fUVi6J4rBD2DgRtAB5LyV61E6JUjoZasv1PVR1TK++w5wS132dcaQhtxomw9eR6wccVcW+gKw7mIoej6nAQ8/k0tf3InCT/0Stvtqx/1zI9rG9IMx4kR2VE6Fpi3v+tUOnoe3+vTkihRkzzSdvdMj/VfifGbHKgh48Nzfses3MhO/kbpVZML7o1jDX57Vrn0d3rlidRROzfX0PzAccBsKHl3Ye2/b0QEuBZ2eibL4zoFF641l2FPrhHo3A+Xe6eMD7lcbya67IrcMDrVmMms3DPVHoGJZLeQRQHnt5qOxDvnai7n9jGcRerDFI1DT/cF5720pjoN5vEPPfWKKuzu4/YmMmEGzy6azokP8v7tyD5XqcZlA/gJCXsgF155Mxs+ADYD5GUaFvb74fhPwv+l3PNP7bmfZkvRgfyfbMsoHhrd31h4nGvM5YNmBbBiifFR2frBjJnhbO37073p7p7JGKyaLKr0G6v7qZulVYJgiIa/9sCLigchJv3okmIlhdIHWWRxMjIJVIs17TFMTXM8KqHsr3DoaUp8bNrzUISotoIAn4KGSiRb9jmEzM7+QDzL1GAWHPpbMYNBqDnWfRaC9qsvYisojpwywiTtCqOjkaM/oQe5B0EIujuPVYHaLlGLdDwoJBRQ5vrqVljrfkfH6T4M3ljCzgJI7YMjUMBNV7HyymFjWsTRCyaQG/cbTfX5K2t48sBNLO0AO1kIKEtQX1JZqPJbGaFJ8UvSxDt+13Q7eiJL4ZKmijaDVej9NpLOAvxRvmdUKCVz7NBXTSlRMcpzVoe+ISiS7gNr0CqdkdsQySGvGJqCFgkHZHEIVoMr+xTm4inzlmqvYW4tfV8QVZmHdd/ls1M1u+6X3GrR9wtHna5gz/Q5Wtf1z9JdtpEI8KtmZkVuccpELuKuInFrOzG9b7nP/7ZUOzQz9gHt8zvDiMdi0CoRLM6ADuYX6TBl7Fs+I3rOH+q+dxz/+K/+tl3MuX8UDFEUk+WVbtB9wCpUael+kbcGwkMiCGqfwUv4DIwxx8A/IygS1fXRrmoaj/E3wrUhmTCUV/Wo4yBEUqmIbQ4c+fnbazp+hodGJjEZNqQNpYfGQfyK0hEjMziUR8AYVyEYUSA+x5kSlK5fy/HeAB3etAOsC2n60baRstuGvQZZ6CPPtCyszIBl/jdA29LB391xq5O/fk7d2bn2Bv8X6lOSQH/rlMz6rvTDPj+tmtnQbOpORw1x0gGiRxZbV1g5wECKUOJUID3E2buAMgQVUFJHCldbUy7uQQ91eL+E/NU1AaNfrxqX8ENmWxMa9OPabyoHWzKI5N6efpjAmoUf8935qCVaXLnIHd4dBWSkRv7vEZ1/DFYyGFU8cDII+OR2HmtPu7+6HkkrM1/EK/NGyHexopyZsZNQ971OFeMDkTCLl3XA13pd+XDkBrqJFbK2Q+d1Yu+Db7mBod0vnAJc+A/ykixSXT/9Nqnuf6IC7FWbTjgVmeQarLszpn+n3ST829l/5rnIFCMLEwoShrKAtMgpPhpKSgZkLyZDKh+YwCyhRA6TOH+f79EfTk+9xrFGg8s+hDX7+Ohq+vA+RVH5gdg3Zf7S3cc6L+fU1V81ZjhHon/KFJfzrGfHHGyNvTz9fJj5xlPNtfDvibQ+0K0VH79u/7r2zxQtOE4vgEelZoWGh0tKNWEq379tdi4MHE+q34vel/5GyT7pXYlZ7oR7GParUv/yK32NpY45iY2hjgjkgsmizuOTU9b+primpilvQU7F5r6Xelqi1npP9LIi30SiBQN2bXPa5TMbZxe+xGzP876u/qJwewuTcicWfj1vKt4temPPWm0b6+wGiP8bWAAJ2/T2zLv8bEnFx989baW38rZw248t6+/aT0G5XZatLOaH93ac2lrIV1tSP+h9Ydunfibi1SgvTeJdSbRrtqE7QvASaanXFrYLPKMVLz90WiAzS+A7pz7mL7v68L/ru8nXu5ZI43XoK1bx7j/ntssw6lkjTWg758Gd1DPk7eg3ZONzj11Swi7VvGJhPuHJpJ7fA7eMpvbEq6kpTUSDDhsaNEP3+2R7N3ndCY5PCUpsbVptmcjv//7+Cwsb7Ezo1uG2mpXLvrP35cZ3I37qdt5DJfHnA7biqtwA38M1ACwEUrDSZtKPhmNnDMMhvYj3Axbr7o0rb1dQYlAs9HGjX/mNr3ttl9XkPf0ZnXXHsHmJb+H+9HOqLCTb+Ex0KSk0OS7jrEGkjKfBPkdsmSMXZXl5ERXH3QcanRQQqobZggT1RunmCWyejTVzwF2KIoWh9lHHOTHqsgxxTB7tIryZLEh8SQuZbXkDlDLjljHvuSXxqQMlfNcOGNbpzMp+2UHRN9ZYUH4gGFs/zZy7yfPGQP50p1yHj1MTfxogq/6WzHkFt06RWKrQQU4YXuqVL6zg4Qj/v0WFVDN4hw87jl7rWDC4RURQgyza3fz7ziuqq8NKOM76YU9d7PsQXSrLO69pjSAtktP/acU0J0TqdDsuiMPTQJxgry36+U0oULxYambz2nVmKIW7aF1tYkeTyLV4VwsloB2SFi8jzslOyTPUs6tEgkN2/nYB1StlqnbvfH/57H4yfvws4JO3P0jLc8oEbnDYnCvjFmCRMC8Zry6FNkWIQsJVVgxSPDBD2EcRNx0VmyGUMhSgQyhYls0VkxLbtlKlrPM64u3WG1hSbnNSqEm3LuvGGZLKbxK2yngiUKWg5I+zy3RvZts4CwV6I9LqNWxvr3uhy3nI2YylhwmrJ7GJ17DMfWjr1gnhs2kekBccsyr8l5Y44OuYTv/rBe/iG+AHSBeY/dTSQXa9sEprTVMJGIuXI52Bt7FvJAeaCNcr6iKjALozIP7dtHHfmP25zgyhA2oKiRnKRpv0cZhzD98tMAaTsZBHKOUC4vG8VeFRfGyakdxvxyTFtlnJd4eHKIZIcIlg/BvmRCSx56xl+qz3sBIV7K60ma7Bk2Di2zXR5VQOOxG7wTsEluzB7teVx7Rm6Eqw6pwoUJvgK1AddoZVs9PGNJd5zlYBOND5ibDtrIdj+Paxby0MWyQVprFdV4dTKImf+wYvOwQRMZD62jFJExfIWoqmR6hXmPPfYv9Sii6Psqoif8Aclfr/NUZFKrx8p1Zue4akEWhImREGnpqt5TjCc7Ro05+wTtpSngMe7/FOXRbQ1isgHi2XvN3LNYbMOxXfeV9IhSP4wt9YeskBWys9gC3gXpcZAJLWcCqfNCcSn78ubxcflsHnMT4hE8VJX5ZIirbMviCoz6c9+WGg8IfjY4+l8LtETsfmEIrfxL6Q87MXgv3GhDxOPrS3piD2MgzdwAmT15jQWZsgwtG8L6jxHdPb+ap09yT69vo5GDWwcT+CdUWi8J6UaiLIMb/6eHlFyU4PrduxNeIqFvvrG8T7aW/ftFAIQbmP/fsRLOjUL+UYL0TxryX//0S4f/WRdgX8XoNQmEvsYbAshQ+VrHf5pqbyNPXZ/UlBt9kjKD57szJW13R2XtuXxH990FVfrvLioburtSN4Enr9JYsSjkFeiqcbI7aODY7kyto7ujBq5x+Y4nuwua+X93UYPguyuNDdQvQpWOYXrSPRSgCIKwRjSPQcaA3fHgL1Cbo+Xg8Xf9Qal6H5mH6frACwQoItrUXS2IksgSPXmenB44F0kq0QDHYUVMt+MoozYx8OhvuocCFEEQ1j6vqHkM8raxu/me/wK1OVoSqm6v+Ael6redzMPEwb3QwFUVSnHd1YJUl+R9bImePFMd3GsmkhTdygDHYc2RSrcjnUzy0qF65sde2vnGe7nlv6bp/5rqTW5r7/i/Ux3W9f/ygnMg/AFPJDle6O3rHxgcGh4ZBUAIRlAMJ8i/62INDMvxgijJyr9+4H92umFatuN6fhBGcZJmeVFWddN2/TBO87Ju+3Fe9/N+PwjBCIrhBEnRDMvxgijJiqrphmnZjuv5QRjFSZrlRVnVTdv1wzjNy7rtx+P5en++vz8EIyiGEyRFMyzHC6IkK6r2V5B+1TQt23E9PwijOEmzvCirumm7fhineVm3/Tiv+3k/oCgh9KI+1n7LSk03TMt2XM+HYATlcHl8gVAklkgxnCApmpHJFUqVWqM1NDI2MTULJqXcOrWQyGm5UR1ONt5+/ORW3ZVf3VPtPsYt8aGwhmOEdPTY8ZK4HuKckVwRMUh6VMxwktFzwzPfRcw1JFyya8UJL9pB3ILc0HrjXktqGL1dbLL3PqupN10M3rAYx3aVPGDlyPKAuNLAHeBoGkMoIS1TMFGx7aUjzUukRw9Sb1W+nEXFTRw5SlyVJZnrmJI7slaoqhbSk+FshbzWehtIGpKqgZVVUj1tLO5Y7yTv15I4TyoMxypF+1r9YYvJxNjWB7VDYeDDqnpOteJ6iwYbJBfaWDw7oR4kQa2oysUX0BiJ16tSGnqkTk+WyXpI65mUXWdsUDucWy+YWAYVN0PSdfRCTRFQukgP4n+uxa4kpUcKmjNIhxJvn2f0vHqMbEhbk1MFFQrBt1WUjAlpTtHVGxE/qg0c1dUki38aa7V+A0bizqGQmckx59Nn6ErhEl2ANF+IuGCnEnoK7L1b+MK1t71YlSn+gO7b2g8c4oqvEehY3H7z1LU8Z4IdZpqQR+I+9V7UnG7CkCxqz0Vdbxg4IzkuJUtbZacGa2Hfk+NOkRXv4yO6mPCKMDq246RaE3iGZPhWiZWLnogNNMnO/nrqrNeZ6l1TlgJwp2ElizMV55erxwx6o0XAM5EMhGxT9DBZbSvmSowzJCeWpBBw1Leez7HxCYknLTG5SGdwavkqQEdYouuVqvqldvikP35erjrlySxoLLUGeBIPuZGyDSMpQd7dhCfGSq62dJlqST9QJEhOz2oTxj2Oa+nBrcfxagOSAHGtvyoicVnvvE3jd0KeokVQW00X7PqS1I4qAEQ5fdorGrauJq6rBy/SbaBlDAG2K5FzYDBCesz5FNcaeVJkR+JLv2RJA3vqbKbVe1cCPhKrJ4mgxysU691h3KR70EqViU0pl3KyDg9YvjqDNCr3Uh2VqyQLEQ94qSzJfX/Id32uaZ3e3X4bvbXeklNJD35adqQU+P6AbR6vP2zuz/9uXo6fN++3XzYfl1/yI1g9HI8esYq4zrT7SJ1THFgJBwaBL2q9kbwIPrZ57pR2KBXsYwwhl5HVBv+MlTC2E1Qp+K2A6YFwoRqtFtCDO3qxudj+KTgqCQs0pFVdG03zDM4gLS6xNrRYoDSD5PDWg1KxGu1XteXQKpaZTj4jqLjVI2pr3pCkU+rytqUncReSwVAqdMTlYZx/bKwkcY3GEVIkBFRpCvbpQe7TzinRJBhoS1lM5E66eu5gB3Fpv5fk5J9vueXUCl72hpEHI5S1JK03Rsywhc+g7LWKJ926kYW2/3z6mYiXZpNpPkkD0qjez0pSiUFDR2tPikuZMwmTOByBrRHL9BXUONJlQU5Gq4svbcEIfdfJqk7WGRIDScuPUXphpA7rMRpJtBZlWOYwRThqdOTsWFxWXW7Y9RjFAwH5y1K/o7eGYnmjbaLeODnGQZEkgyjigUQXWBuODsP8FeaQzZH48qP3JC52LmoPbJhuoxI2H8f/6VAPxFBrlWFvzSe96K5pjh0cohcZRug6LV8ELbb+Pz6u2yg5haDUiWcWN3oUOMQhZZpk6yOt2q+/mpZl5AH1COMFjMkNatHJMhXLD4RnLMvgyGQN9sofKA5nkBjvJLqVrh5bFIFjDEjFgxk2P60GJYZ2HaOlvj/pxg8EUjmUCAw7NBTqW8VrRnYYMS03RZGMXEnSL+q0psTig65ojNLTTErzC1xwuMyWKkSeIDuc7U64ggujazUMjxGELBd787axJFmjmDtKLwI6wo2SYtB1Xg9qbUcFqcEmJCWLHLSYUXgMB1QLYwYhQsjdP4ND0e9pIRk5udTK0IMSy3PA/CSP88DRYnQuIU4R318njRFIyoc05IxYoRqkuBXiq/BGEqPqbIpGPzpbVFmDuqDMeJ4CX/SMkaNm8FXNLlc2C1MYAdvUctVtcYjpvBbCtotcHkgwSHaCLCnkg61FgtrNlY64NvbcAyVQfszGRM4vHQbCrlatpSKAlpONnKXom2x31np8tdivNWkYV/SyRpJCYU71TmxrN5bwyek/2ytvFOG7vzfggpYCVK4Yg2sWOqznEaNkYvGkBTeIcO0dh/31aeZvx+eJ6XX1kKLUxTw441ZO0rJqDBD2Uj5DhjXnXG09BSTzpNfeJ+ZZBC+yk/mOAZvEhBd9+j6MFAO91fEzsxSNO1J0D0QDqTSwa8TK37b0/dQpq/8x8E3oxvEzk2mESvZ9uCAgHG2vr/Rb/XwDAAAA') format('woff2'), + url('iconfont.woff?t=1567498326614') format('woff'), + url('iconfont.ttf?t=1567498326614') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ + url('iconfont.svg?t=1567498326614#iconfont') format('svg'); /* iOS 4.1- */ +} + +.iconfont { + font-family: "iconfont" !important; + font-size: 16px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.icon-logout:before { + content: "\e838"; +} + +.icon-facebook:before { + content: "\e645"; +} + +.icon-icons-google_groups:before { + content: "\ee07"; +} + +.icon-youtube:before { + content: "\e733"; +} + +.icon-tiaoshi:before { + content: "\eb61"; +} + +.icon-changjingguanli:before { + content: "\eb62"; +} + +.icon-bianji:before { + content: "\eb63"; +} + +.icon-guanlianshebei:before { + content: "\eb64"; +} + +.icon-guanfangbanben:before { + content: "\eb65"; +} + +.icon-gongnengdingyi:before { + content: "\eb66"; +} + +.icon-jichuguanli:before { + content: "\eb67"; +} + +.icon-jishufuwu:before { + content: "\eb68"; +} + +.icon-hezuohuobanmiyueguanli:before { + content: "\eb69"; +} + +.icon-ceshishenqing:before { + content: "\eb6a"; +} + +.icon-jiedianguanli:before { + content: "\eb6b"; +} + +.icon-jinggao:before { + content: "\eb6c"; +} + +.icon-peiwangyindao:before { + content: "\eb6d"; +} + +.icon-renjijiaohu:before { + content: "\eb6e"; +} + +.icon-shiyongwendang:before { + content: "\eb6f"; +} + +.icon-quanxianshenpi:before { + content: "\eb70"; +} + +.icon-yishouquan:before { + content: "\eb71"; +} + +.icon-tianshenpi:before { + content: "\eb72"; +} + +.icon-shujukanban:before { + content: "\eb73"; +} + +.icon-yingyongguanli:before { + content: "\eb74"; +} + +.icon-yibiaopan:before { + content: "\eb75"; +} + +.icon-zhanghaoquanxianguanli:before { + content: "\eb76"; +} + +.icon-yuanquyunwei:before { + content: "\eb77"; +} + +.icon-slack:before { + content: "\e641"; +} + +.icon-jizhanguanli:before { + content: "\eb78"; +} + +.icon-gongju:before { + content: "\e600"; +} + +.icon-guanbi:before { + content: "\eb79"; +} + +.icon-zidingyi:before { + content: "\eb7a"; +} + +.icon-xiajiantou:before { + content: "\eb7b"; +} + +.icon-shangjiantou:before { + content: "\eb7c"; +} + +.icon-icon_loading:before { + content: "\eb80"; +} + +.icon-icon_renwujincheng:before { + content: "\eb88"; +} + +.icon-icon_rukou:before { + content: "\eb89"; +} + +.icon-icon_yiwenkongxin:before { + content: "\eb8a"; +} + +.icon-icon_fabu:before { + content: "\eb8b"; +} + +.icon-icon_tianjia:before { + content: "\eb8c"; +} + +.icon-icon_yulan:before { + content: "\eb8d"; +} + +.icon-icon_zhanghao:before { + content: "\eb8e"; +} + +.icon-icon_wangye:before { + content: "\eb8f"; +} + +.icon-icon_shezhi:before { + content: "\eb90"; +} + +.icon-icon_baocun:before { + content: "\eb91"; +} + +.icon-icon_yingyongguanli:before { + content: "\eb92"; +} + +.icon-icon_shiyongwendang:before { + content: "\eb93"; +} + +.icon-icon_bangzhuwendang:before { + content: "\eb94"; +} + +.icon-biaodanzujian-shurukuang:before { + content: "\eb95"; +} + +.icon-biaodanzujian-biaoge:before { + content: "\eb96"; +} + +.icon-biaodanzujian-xialakuang:before { + content: "\eb97"; +} + +.icon-tubiao-bingtu:before { + content: "\eb98"; +} + +.icon-biaodanzujian-anniu:before { + content: "\eb99"; +} + +.icon-gongyezujian-yibiaopan:before { + content: "\eb9a"; +} + +.icon-tubiao-qiapian:before { + content: "\eb9b"; +} + +.icon-gongyezujian-zhishideng:before { + content: "\eb9c"; +} + +.icon-tubiao-zhexiantu:before { + content: "\eb9d"; +} + +.icon-xingzhuang-juxing:before { + content: "\eb9e"; +} + +.icon-xingzhuang-jianxing:before { + content: "\eb9f"; +} + +.icon-gongyezujian-kaiguan:before { + content: "\eba0"; +} + +.icon-tubiao-zhuzhuangtu:before { + content: "\eba1"; +} + +.icon-xingzhuang-tupian:before { + content: "\eba2"; +} + +.icon-xingzhuang-wenzi:before { + content: "\eba3"; +} + +.icon-xingzhuang-tuoyuanxing:before { + content: "\eba4"; +} + +.icon-xingzhuang-sanjiaoxing:before { + content: "\eba5"; +} + +.icon-xingzhuang-xingxing:before { + content: "\eba6"; +} + +.icon-guize:before { + content: "\ebb7"; +} + +.icon-shebeiguanli:before { + content: "\ebb8"; +} + +.icon-gongnengdingyi1:before { + content: "\ebb9"; +} + +.icon-jishufuwu1:before { + content: "\ebce"; +} + +.icon-yunyingzhongxin:before { + content: "\ebd0"; +} + +.icon-yunyingguanli:before { + content: "\ebd1"; +} + +.icon-zuzhixiaxia:before { + content: "\ebd8"; +} + +.icon-zuzhizhankai:before { + content: "\ebd9"; +} + +.icon-zuzhiqunzu:before { + content: "\ebda"; +} + +.icon-dakai:before { + content: "\ebdf"; +} + +.icon-yingwen:before { + content: "\ebe0"; +} + +.icon-zhongwen:before { + content: "\ebe2"; +} + +.icon-miwen:before { + content: "\ebe3"; +} + +.icon-xianhao:before { + content: "\ebe4"; +} + +.icon-kongxinduigou:before { + content: "\ebe5"; +} + +.icon-huixingzhen:before { + content: "\ebe6"; +} + +.icon-duigou:before { + content: "\ebe7"; +} + +.icon-stack-overflow:before { + content: "\e970"; +} + +.icon-xiayibu:before { + content: "\ebef"; +} + +.icon-shangyibu:before { + content: "\ebf0"; +} + +.icon-kongjianxuanzhong:before { + content: "\ebf1"; +} + +.icon-kongjianweixuan:before { + content: "\ebf2"; +} + +.icon-kongjianyixuan:before { + content: "\ebf3"; +} + +.icon--diangan:before { + content: "\ebfb"; +} + +.icon-rongxuejirongjiechi:before { + content: "\ebfc"; +} + +.icon-lubiantingchechang:before { + content: "\ebfd"; +} + +.icon--lumingpai:before { + content: "\ebfe"; +} + +.icon-jietouzuoyi:before { + content: "\ebff"; +} + +.icon--zhongdaweixian:before { + content: "\ec00"; +} + +.icon--jiaotongbiaozhipai:before { + content: "\ec01"; +} + +.icon-gongcezhishipai:before { + content: "\ec02"; +} + +.icon-fangkuai:before { + content: "\ec06"; +} + +.icon-fangkuai-:before { + content: "\ec07"; +} + +.icon-shuaxin:before { + content: "\ec08"; +} + +.icon-baocun:before { + content: "\ec09"; +} + +.icon-fabu:before { + content: "\ec0a"; +} + +.icon-xiayibu1:before { + content: "\ec0b"; +} + +.icon-shangyibu1:before { + content: "\ec0c"; +} + +.icon-xiangxiazhanhang:before { + content: "\ec0d"; +} + +.icon-xiangshangzhanhang:before { + content: "\ec0e"; +} + +.icon-tupianjiazaishibai:before { + content: "\ec0f"; +} + +.icon-fuwudiqiu:before { + content: "\ec10"; +} + +.icon-suoxiao:before { + content: "\ec13"; +} + +.icon-fangda:before { + content: "\ec14"; +} + +.icon-huanyuanhuabu:before { + content: "\ec15"; +} + +.icon-quanping:before { + content: "\ec16"; +} + +.icon-biaodanzujian-biaoge1:before { + content: "\ec17"; +} + +.icon-APIshuchu:before { + content: "\ec18"; +} + +.icon-APIjieru:before { + content: "\ec19"; +} + +.icon-wenjianjia:before { + content: "\ec1a"; +} + +.icon-DOC:before { + content: "\ec1b"; +} + +.icon-BMP:before { + content: "\ec1c"; +} + +.icon-GIF:before { + content: "\ec1d"; +} + +.icon-JPG:before { + content: "\ec1e"; +} + +.icon-PNG:before { + content: "\ec1f"; +} + +.icon-weizhigeshi:before { + content: "\ec20"; +} + +.icon-gengduo:before { + content: "\ec21"; +} + +.icon-yunduanxiazai:before { + content: "\ec22"; +} + +.icon-yunduanshangchuan:before { + content: "\ec23"; +} + +.icon-dian:before { + content: "\ec24"; +} + +.icon-mian:before { + content: "\ec25"; +} + +.icon-xian:before { + content: "\ec26"; +} + +.icon-shebeizhuangtai:before { + content: "\ec27"; +} + +.icon-fenzuguanli:before { + content: "\ec28"; +} + +.icon-kuaisubianpai:before { + content: "\ec29"; +} + +.icon-APPkaifa:before { + content: "\ec2a"; +} + +.icon-wentijieda:before { + content: "\ec2e"; +} + +.icon-kefu:before { + content: "\ec2f"; +} + +.icon-ruanjiankaifabao:before { + content: "\ec30"; +} + +.icon-sousuobianxiao:before { + content: "\ec32"; +} + +.icon-sousuofangda:before { + content: "\ec33"; +} + +.icon-dingwei:before { + content: "\ec34"; +} + +.icon-wumoxing:before { + content: "\ec35"; +} + +.icon-gaojing:before { + content: "\ec36"; +} + +.icon-renwujincheng:before { + content: "\ec37"; +} + +.icon-xiaoxitongzhi:before { + content: "\ec38"; +} + +.icon-youhui:before { + content: "\ec39"; +} + +.icon-gaojing1:before { + content: "\ec3a"; +} + +.icon-zhihangfankui:before { + content: "\ec3b"; +} + +.icon-gongdanqueren:before { + content: "\ec3c"; +} + +.icon-guangbo:before { + content: "\ec3d"; +} + +.icon-gongdan:before { + content: "\ec3e"; +} + +.icon-xiaoxi:before { + content: "\ec3f"; +} + +.icon-ditu-qi:before { + content: "\ec40"; +} + +.icon-ditu-dibiao:before { + content: "\ec41"; +} + +.icon-ditu-cha:before { + content: "\ec42"; +} + +.icon-ditu-qipao:before { + content: "\ec43"; +} + +.icon-ditu-tuding:before { + content: "\ec44"; +} + +.icon-ditu-huan:before { + content: "\ec45"; +} + +.icon-ditu-xing:before { + content: "\ec46"; +} + +.icon-ditu-yuan:before { + content: "\ec47"; +} + +.icon-chehuisekuai:before { + content: "\ec48"; +} + +.icon-shanchusekuai:before { + content: "\ec49"; +} + +.icon-fabusekuai:before { + content: "\ec4a"; +} + +.icon-xinhao:before { + content: "\ec4b"; +} + +.icon-lanya:before { + content: "\ec4c"; +} + +.icon-Wi-Fi:before { + content: "\ec4d"; +} + +.icon-chaxun:before { + content: "\ec4e"; +} + +.icon-dianbiao:before { + content: "\ec4f"; +} + +.icon-anquan:before { + content: "\ec50"; +} + +.icon-daibanshixiang:before { + content: "\ec51"; +} + +.icon-bingxiang:before { + content: "\ec52"; +} + +.icon-fanshe:before { + content: "\ec53"; +} + +.icon-fengche:before { + content: "\ec54"; +} + +.icon-guandao:before { + content: "\ec55"; +} + +.icon-guize1:before { + content: "\ec56"; +} + +.icon-guizeyinqing:before { + content: "\ec57"; +} + +.icon-huowudui:before { + content: "\ec58"; +} + +.icon-jianceqi:before { + content: "\ec59"; +} + +.icon-jinggai:before { + content: "\ec5a"; +} + +.icon-liujisuan:before { + content: "\ec5b"; +} + +.icon-hanshu:before { + content: "\ec5c"; +} + +.icon-lianjieliu:before { + content: "\ec5d"; +} + +.icon-ludeng:before { + content: "\ec5e"; +} + +.icon-shexiangji:before { + content: "\ec5f"; +} + +.icon-rentijiance:before { + content: "\ec60"; +} + +.icon-moshubang:before { + content: "\ec61"; +} + +.icon-shujuwajue:before { + content: "\ec62"; +} + +.icon-wangguan:before { + content: "\ec63"; +} + +.icon-shenjing:before { + content: "\ec64"; +} + +.icon-chucun:before { + content: "\ec65"; +} + +.icon-wuguan:before { + content: "\ec66"; +} + +.icon-yunduanshuaxin:before { + content: "\ec67"; +} + +.icon-yunhang:before { + content: "\ec68"; +} + +.icon-luyouqi:before { + content: "\ec69"; +} + +.icon-bug:before { + content: "\ec6a"; +} + +.icon-get:before { + content: "\ec6b"; +} + +.icon-PIR:before { + content: "\ec6c"; +} + +.icon-zhexiantu:before { + content: "\ec6d"; +} + +.icon-shuibiao:before { + content: "\ec6e"; +} + +.icon-js:before { + content: "\ec6f"; +} + +.icon-zihangche:before { + content: "\ec70"; +} + +.icon-liebiao:before { + content: "\ec71"; +} + +.icon-qichedingwei:before { + content: "\ec72"; +} + +.icon-dici:before { + content: "\ec73"; +} + +.icon-mysql:before { + content: "\ec74"; +} + +.icon-qiche:before { + content: "\ec75"; +} + +.icon-shenjing1:before { + content: "\ec76"; +} + +.icon-chengshi:before { + content: "\ec77"; +} + +.icon-tixingshixin:before { + content: "\ec78"; +} + +.icon-menci:before { + content: "\ec79"; +} + +.icon-chazuo:before { + content: "\ec7a"; +} + +.icon-ranqijianceqi:before { + content: "\ec7b"; +} + +.icon-kaiguan:before { + content: "\ec7c"; +} + +.icon-chatou:before { + content: "\ec7d"; +} + +.icon-xiyiji:before { + content: "\ec7e"; +} + +.icon-yijiankaiguan:before { + content: "\ec7f"; +} + +.icon-yanwubaojingqi:before { + content: "\ec80"; +} + +.icon-wuxiandianbo:before { + content: "\ec81"; +} + +.icon-fuzhi:before { + content: "\ec82"; +} + +.icon-tuite:before { + content: "\e615"; +} + +.icon-shanchu:before { + content: "\ec83"; +} + +.icon-bianjisekuai:before { + content: "\ec84"; +} + +.icon-ishipinshixiao:before { + content: "\ec85"; +} + +.icon-iframetianjia:before { + content: "\ec86"; +} + +.icon-tupiantianjia:before { + content: "\ec87"; +} + +.icon-liebiaomoshi_kuai:before { + content: "\ec88"; +} + +.icon-qiapianmoshi_kuai:before { + content: "\ec89"; +} + +.icon-fenlan:before { + content: "\ec8a"; +} + +.icon-fengexian:before { + content: "\ec8b"; +} + +.icon-dianzan:before { + content: "\ec8c"; +} + +.icon-charulianjie:before { + content: "\ec8d"; +} + +.icon-charutupian:before { + content: "\ec8e"; +} + +.icon-quxiaolianjie:before { + content: "\ec8f"; +} + +.icon-wuxupailie:before { + content: "\ec90"; +} + +.icon-juzhongduiqi:before { + content: "\ec91"; +} + +.icon-yinyong:before { + content: "\ec92"; +} + +.icon-youxupailie:before { + content: "\ec93"; +} + +.icon-youduiqi:before { + content: "\ec94"; +} + +.icon-zitidaima:before { + content: "\ec95"; +} + +.icon-xiaolian:before { + content: "\ec96"; +} + +.icon-zitijiacu:before { + content: "\ec97"; +} + +.icon-zitishanchuxian:before { + content: "\ec98"; +} + +.icon-zitishangbiao:before { + content: "\ec99"; +} + +.icon-zitibiaoti:before { + content: "\ec9a"; +} + +.icon-zitixiahuaxian:before { + content: "\ec9b"; +} + +.icon-zitixieti:before { + content: "\ec9c"; +} + +.icon-zitiyanse:before { + content: "\ec9d"; +} + +.icon-zuoduiqi:before { + content: "\ec9e"; +} + +.icon-zitiyulan:before { + content: "\ec9f"; +} + +.icon-zitixiabiao:before { + content: "\eca0"; +} + +.icon-zuoyouduiqi:before { + content: "\eca1"; +} + +.icon-tianxie:before { + content: "\eca2"; +} + +.icon-huowudui1:before { + content: "\eca3"; +} + +.icon-yingjian:before { + content: "\eca4"; +} + +.icon-shebeikaifa:before { + content: "\eca5"; +} + +.icon-dianzan_kuai:before { + content: "\eca6"; +} + +.icon-zhihuan:before { + content: "\eca7"; +} + +.icon-tuoguan:before { + content: "\eca8"; +} + +.icon-duigoux:before { + content: "\eca9"; +} + +.icon-guanbi1:before { + content: "\ecaa"; +} + +.icon-aixin_shixin:before { + content: "\ecab"; +} + +.icon-ranqixieloubaojingqi:before { + content: "\ecac"; +} + +.icon-dianbiao_shiti:before { + content: "\ecad"; +} + +.icon-aixin:before { + content: "\ecae"; +} + +.icon-shuibiao_shiti:before { + content: "\ecaf"; +} + +.icon-zhinengxiaofangshuan:before { + content: "\ecb0"; +} + +.icon-ranqibiao_shiti:before { + content: "\ecb1"; +} + +.icon-shexiangtou_shiti:before { + content: "\ecb2"; +} + +.icon-shexiangtou_guanbi:before { + content: "\ecb3"; +} + +.icon-shexiangtou:before { + content: "\ecb4"; +} + +.icon-shengyin_shiti:before { + content: "\ecb5"; +} + +.icon-shengyinkai:before { + content: "\ecb6"; +} + +.icon-shoucang_shixin:before { + content: "\ecb7"; +} + +.icon-shoucang:before { + content: "\ecb8"; +} + +.icon-shengyinwu:before { + content: "\ecb9"; +} + +.icon-shengyinjingyin:before { + content: "\ecba"; +} + +.icon-zhunbeiliangchan:before { + content: "\ecbb"; +} + +.icon-shebeikaifa1:before { + content: "\ecbc"; +} + +.icon-document-circle:before { + content: "\e6b8"; +} + +.icon-git:before { + content: "\e64a"; +} + +.icon-Notificationlisttongzhiliebiao:before { + content: "\e782"; +} + +.icon-kongxinwenhao:before { + content: "\ed19"; +} + +.icon-cuowukongxin:before { + content: "\ed1a"; +} + +.icon-fangkuai1:before { + content: "\ed1b"; +} + +.icon-fangkuai2:before { + content: "\ed1c"; +} + +.icon-kongjianxuanzhong1:before { + content: "\ed1d"; +} + +.icon-kongxinduigou1:before { + content: "\ed1e"; +} + +.icon-xinxikongxin:before { + content: "\ed1f"; +} + +.icon-kongjian:before { + content: "\ed20"; +} + +.icon-gaojingkongxin:before { + content: "\ed21"; +} + +.icon-duigou_kuai:before { + content: "\ed22"; +} + +.icon-cuocha_kuai:before { + content: "\ed23"; +} + +.icon-jia_sekuai:before { + content: "\ed24"; +} + +.icon-jian_sekuai:before { + content: "\ed25"; +} + +.icon-fenxiangfangshi:before { + content: "\ed2e"; +} + +.icon-i18n:before { + content: "\e614"; +} + +.icon-gongju1:before { + content: "\e637"; +} + +.icon-bangzhu:before { + content: "\e638"; +} + +.icon-xitong:before { + content: "\e639"; +} + +.icon-guanli:before { + content: "\e63a"; +} + +.icon-jiankong:before { + content: "\e63b"; +} + +.icon-guize2:before { + content: "\e63c"; +} + +.icon-arrow:before { + content: "\e63d"; +} + +.icon-systemname:before { + content: "\e63e"; +} + +.icon-version:before { + content: "\e63f"; +} + +.icon-Systemtime:before { + content: "\e640"; +} + +.icon-uptime:before { + content: "\e642"; +} + +.icon-in:before { + content: "\e643"; +} + diff --git a/apps/emqx_dashboard/priv/www/static/css/iconfont.eot b/apps/emqx_dashboard/priv/www/static/css/iconfont.eot new file mode 100644 index 000000000..0ddb250fc Binary files /dev/null and b/apps/emqx_dashboard/priv/www/static/css/iconfont.eot differ diff --git a/apps/emqx_dashboard/priv/www/static/css/iconfont.js b/apps/emqx_dashboard/priv/www/static/css/iconfont.js new file mode 100644 index 000000000..801ac4009 --- /dev/null +++ b/apps/emqx_dashboard/priv/www/static/css/iconfont.js @@ -0,0 +1 @@ +!function(v){var a,l='',h=(a=document.getElementsByTagName("script"))[a.length-1].getAttribute("data-injectcss");if(h&&!v.__iconfont__svg__cssinject__){v.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(a){console&&console.log(a)}}!function(a){if(document.addEventListener)if(~["complete","loaded","interactive"].indexOf(document.readyState))setTimeout(a,0);else{var h=function(){document.removeEventListener("DOMContentLoaded",h,!1),a()};document.addEventListener("DOMContentLoaded",h,!1)}else document.attachEvent&&(c=a,i=v.document,o=!1,(z=function(){try{i.documentElement.doScroll("left")}catch(a){return void setTimeout(z,50)}l()})(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,l())});function l(){o||(o=!0,c())}var c,i,o,z}(function(){var a,h;(a=document.createElement("div")).innerHTML=l,l=null,(h=a.getElementsByTagName("svg")[0])&&(h.setAttribute("aria-hidden","true"),h.style.position="absolute",h.style.width=0,h.style.height=0,h.style.overflow="hidden",function(a,h){h.firstChild?function(a,h){h.parentNode.insertBefore(a,h)}(a,h.firstChild):h.appendChild(a)}(h,document.body))})}(window); \ No newline at end of file diff --git a/apps/emqx_dashboard/priv/www/static/css/iconfont.svg b/apps/emqx_dashboard/priv/www/static/css/iconfont.svg new file mode 100644 index 000000000..bb47f2b06 --- /dev/null +++ b/apps/emqx_dashboard/priv/www/static/css/iconfont.svg @@ -0,0 +1,941 @@ + + + + + +Created by iconfont + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/emqx_dashboard/priv/www/static/css/iconfont.ttf b/apps/emqx_dashboard/priv/www/static/css/iconfont.ttf new file mode 100644 index 000000000..e0772f2bc Binary files /dev/null and b/apps/emqx_dashboard/priv/www/static/css/iconfont.ttf differ diff --git a/apps/emqx_dashboard/priv/www/static/css/iconfont.woff b/apps/emqx_dashboard/priv/www/static/css/iconfont.woff new file mode 100644 index 000000000..b0bae09a5 Binary files /dev/null and b/apps/emqx_dashboard/priv/www/static/css/iconfont.woff differ diff --git a/apps/emqx_dashboard/priv/www/static/css/iconfont.woff2 b/apps/emqx_dashboard/priv/www/static/css/iconfont.woff2 new file mode 100644 index 000000000..538f1da1c Binary files /dev/null and b/apps/emqx_dashboard/priv/www/static/css/iconfont.woff2 differ diff --git a/apps/emqx_dashboard/priv/www/static/editor.worker.js b/apps/emqx_dashboard/priv/www/static/editor.worker.js new file mode 100644 index 000000000..b596dd49a --- /dev/null +++ b/apps/emqx_dashboard/priv/www/static/editor.worker.js @@ -0,0 +1 @@ +!function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:r})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s="/p8O")}({"/p8O":function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=new(function(){function e(){this.listeners=[],this.unexpectedErrorHandler=function(e){setTimeout(function(){if(e.stack)throw new Error(e.message+"\n\n"+e.stack);throw e},0)}}return e.prototype.emit=function(e){this.listeners.forEach(function(t){t(e)})},e.prototype.onUnexpectedError=function(e){this.unexpectedErrorHandler(e),this.emit(e)},e.prototype.onUnexpectedExternalError=function(e){this.unexpectedErrorHandler(e)},e}());function i(e){u(e)||r.onUnexpectedError(e)}function o(e){return e instanceof Error?{$isError:!0,name:e.name,message:e.message,stack:e.stacktrace||e.stack}:e}var s="Canceled";function u(e){return e instanceof Error&&e.name===s&&e.message===s}var a=!1,l="__is_disposable_tracked__";function h(e){if(a&&e&&e!==m.None)try{e[l]=!0}catch(e){}}function c(e){if(!a)return e;var t=new Error("Potentially leaked disposable").stack;return setTimeout(function(){e[l]||console.log(t)},3e3),e}function f(){for(var e=[],t=0;tr?e[a]=o[u++]:u>i?e[a]=o[s++]:t(o[u],o[s])<0?e[a]=o[u++]:e[a]=o[s++]}(t,n,r,s,i,o)}(e,t,0,e.length-1,[]),e}var E=function(){function e(e,t,n,r){this.originalStart=e,this.originalLength=t,this.modifiedStart=n,this.modifiedLength=r}return e.prototype.getOriginalEnd=function(){return this.originalStart+this.originalLength},e.prototype.getModifiedEnd=function(){return this.modifiedStart+this.modifiedLength},e}();function S(e){return{getLength:function(){return e.length},getElementAtIndex:function(t){return e.charCodeAt(t)}}}function w(e,t,n){return new T(S(e),S(t)).ComputeDiff(n)}var A,P=function(){function e(){}return e.Assert=function(e,t){if(!e)throw new Error(t)},e}(),M=function(){function e(){}return e.Copy=function(e,t,n,r,i){for(var o=0;o0||this.m_modifiedCount>0)&&this.m_changes.push(new E(this.m_originalStart,this.m_originalCount,this.m_modifiedStart,this.m_modifiedCount)),this.m_originalCount=0,this.m_modifiedCount=0,this.m_originalStart=Number.MAX_VALUE,this.m_modifiedStart=Number.MAX_VALUE},e.prototype.AddOriginalElement=function(e,t){this.m_originalStart=Math.min(this.m_originalStart,e),this.m_modifiedStart=Math.min(this.m_modifiedStart,t),this.m_originalCount++},e.prototype.AddModifiedElement=function(e,t){this.m_originalStart=Math.min(this.m_originalStart,e),this.m_modifiedStart=Math.min(this.m_modifiedStart,t),this.m_modifiedCount++},e.prototype.getChanges=function(){return(this.m_originalCount>0||this.m_modifiedCount>0)&&this.MarkNextChange(),this.m_changes},e.prototype.getReverseChanges=function(){return(this.m_originalCount>0||this.m_modifiedCount>0)&&this.MarkNextChange(),this.m_changes.reverse(),this.m_changes},e}(),T=function(){function e(e,t,n){void 0===n&&(n=null),this.OriginalSequence=e,this.ModifiedSequence=t,this.ContinueProcessingPredicate=n,this.m_forwardHistory=[],this.m_reverseHistory=[]}return e.prototype.ElementsAreEqual=function(e,t){return this.OriginalSequence.getElementAtIndex(e)===this.ModifiedSequence.getElementAtIndex(t)},e.prototype.OriginalElementsAreEqual=function(e,t){return this.OriginalSequence.getElementAtIndex(e)===this.OriginalSequence.getElementAtIndex(t)},e.prototype.ModifiedElementsAreEqual=function(e,t){return this.ModifiedSequence.getElementAtIndex(e)===this.ModifiedSequence.getElementAtIndex(t)},e.prototype.ComputeDiff=function(e){return this._ComputeDiff(0,this.OriginalSequence.getLength()-1,0,this.ModifiedSequence.getLength()-1,e)},e.prototype._ComputeDiff=function(e,t,n,r,i){var o=this.ComputeDiffRecursive(e,t,n,r,[!1]);return i?this.PrettifyChanges(o):o},e.prototype.ComputeDiffRecursive=function(e,t,n,r,i){for(i[0]=!1;e<=t&&n<=r&&this.ElementsAreEqual(e,n);)e++,n++;for(;t>=e&&r>=n&&this.ElementsAreEqual(t,r);)t--,r--;if(e>t||n>r){var o=void 0;return n<=r?(P.Assert(e===t+1,"originalStart should only be one more than originalEnd"),o=[new E(e,0,n,r-n+1)]):e<=t?(P.Assert(n===r+1,"modifiedStart should only be one more than modifiedEnd"),o=[new E(e,t-e+1,n,0)]):(P.Assert(e===t+1,"originalStart should only be one more than originalEnd"),P.Assert(n===r+1,"modifiedStart should only be one more than modifiedEnd"),o=[]),o}var s=[0],u=[0],a=this.ComputeRecursionPoint(e,t,n,r,s,u,i),l=s[0],h=u[0];if(null!==a)return a;if(!i[0]){var c=this.ComputeDiffRecursive(e,l,n,h,i),f=[];return f=i[0]?[new E(l+1,t-(l+1)+1,h+1,r-(h+1)+1)]:this.ComputeDiffRecursive(l+1,t,h+1,r,i),this.ConcatenateChanges(c,f)}return[new E(e,t-e+1,n,r-n+1)]},e.prototype.WALKTRACE=function(e,t,n,r,i,o,s,u,a,l,h,c,f,d,m,p,g,_){var v,y,C=null,b=new O,L=t,N=n,S=f[0]-p[0]-r,w=Number.MIN_VALUE,A=this.m_forwardHistory.length-1;do{(y=S+e)===L||y=0&&(e=(a=this.m_forwardHistory[A])[0],L=1,N=a.length-1)}while(--A>=-1);if(v=b.getReverseChanges(),_[0]){var P=f[0]+1,M=p[0]+1;if(null!==v&&v.length>0){var T=v[v.length-1];P=Math.max(P,T.getOriginalEnd()),M=Math.max(M,T.getModifiedEnd())}C=[new E(P,c-P+1,M,m-M+1)]}else{b=new O,L=o,N=s,S=f[0]-p[0]-u,w=Number.MAX_VALUE,A=g?this.m_reverseHistory.length-1:this.m_reverseHistory.length-2;do{(y=S+i)===L||y=l[y+1]?(d=(h=l[y+1]-1)-S-u,h>w&&b.MarkNextChange(),w=h+1,b.AddOriginalElement(h+1,d+1),S=y+1-i):(d=(h=l[y-1])-S-u,h>w&&b.MarkNextChange(),w=h,b.AddModifiedElement(h+1,d+1),S=y-1-i),A>=0&&(i=(l=this.m_reverseHistory[A])[0],L=1,N=l.length-1)}while(--A>=-1);C=b.getChanges()}return this.ConcatenateChanges(v,C)},e.prototype.ComputeRecursionPoint=function(e,t,n,r,i,o,s){var u,a=0,l=0,h=0,c=0,f=0,d=0;e--,n--,i[0]=0,o[0]=0,this.m_forwardHistory=[],this.m_reverseHistory=[];var m,p,g=t-e+(r-n),_=g+1,v=new Array(_),y=new Array(_),C=r-n,b=t-e,L=e-n,N=t-r,S=(b-C)%2==0;for(v[C]=e,y[b]=t,s[0]=!1,u=1;u<=g/2+1;u++){var w=0,A=0;for(h=this.ClipDiagonalBound(C-u,u,C,_),c=this.ClipDiagonalBound(C+u,u,C,_),m=h;m<=c;m+=2){for(l=(a=m===h||mw+A&&(w=a,A=l),!S&&Math.abs(m-b)<=u-1&&a>=y[m])return i[0]=a,o[0]=l,p<=y[m]&&u<=1448?this.WALKTRACE(C,h,c,L,b,f,d,N,v,y,a,t,i,l,r,o,S,s):null}var P=(w-e+(A-n)-u)/2;if(null!==this.ContinueProcessingPredicate&&!this.ContinueProcessingPredicate(w,this.OriginalSequence,P))return s[0]=!0,i[0]=w,o[0]=A,P>0&&u<=1448?this.WALKTRACE(C,h,c,L,b,f,d,N,v,y,a,t,i,l,r,o,S,s):[new E(++e,t-e+1,++n,r-n+1)];for(f=this.ClipDiagonalBound(b-u,u,b,_),d=this.ClipDiagonalBound(b+u,u,b,_),m=f;m<=d;m+=2){for(l=(a=m===f||m=y[m+1]?y[m+1]-1:y[m-1])-(m-b)-N,p=a;a>e&&l>n&&this.ElementsAreEqual(a,l);)a--,l--;if(y[m]=a,S&&Math.abs(m-C)<=u&&a<=v[m])return i[0]=a,o[0]=l,p>=v[m]&&u<=1448?this.WALKTRACE(C,h,c,L,b,f,d,N,v,y,a,t,i,l,r,o,S,s):null}if(u<=1447){var O=new Array(c-h+2);O[0]=C-h+1,M.Copy(v,h,O,1,c-h+1),this.m_forwardHistory.push(O),(O=new Array(d-f+2))[0]=b-f+1,M.Copy(y,f,O,1,d-f+1),this.m_reverseHistory.push(O)}}return this.WALKTRACE(C,h,c,L,b,f,d,N,v,y,a,t,i,l,r,o,S,s)},e.prototype.PrettifyChanges=function(e){for(var t=0;t0,s=n.modifiedLength>0;n.originalStart+n.originalLength=0;t--){n=e[t],r=0,i=0;if(t>0){var a=e[t-1];a.originalLength>0&&(r=a.originalStart+a.originalLength),a.modifiedLength>0&&(i=a.modifiedStart+a.modifiedLength)}o=n.originalLength>0,s=n.modifiedLength>0;for(var l=0,h=this._boundaryScore(n.originalStart,n.originalLength,n.modifiedStart,n.modifiedLength),c=1;;c++){var f=n.originalStart-c,d=n.modifiedStart-c;if(fh&&(h=m,l=c)}n.originalStart-=l,n.modifiedStart-=l}return e},e.prototype._OriginalIsBoundary=function(e){if(e<=0||e>=this.OriginalSequence.getLength()-1)return!0;var t=this.OriginalSequence.getElementAtIndex(e);return"string"==typeof t&&/^\s*$/.test(t)},e.prototype._OriginalRegionIsBoundary=function(e,t){if(this._OriginalIsBoundary(e)||this._OriginalIsBoundary(e-1))return!0;if(t>0){var n=e+t;if(this._OriginalIsBoundary(n-1)||this._OriginalIsBoundary(n))return!0}return!1},e.prototype._ModifiedIsBoundary=function(e){if(e<=0||e>=this.ModifiedSequence.getLength()-1)return!0;var t=this.ModifiedSequence.getElementAtIndex(e);return"string"==typeof t&&/^\s*$/.test(t)},e.prototype._ModifiedRegionIsBoundary=function(e,t){if(this._ModifiedIsBoundary(e)||this._ModifiedIsBoundary(e-1))return!0;if(t>0){var n=e+t;if(this._ModifiedIsBoundary(n-1)||this._ModifiedIsBoundary(n))return!0}return!1},e.prototype._boundaryScore=function(e,t,n,r){return(this._OriginalRegionIsBoundary(e,t)?1:0)+(this._ModifiedRegionIsBoundary(n,r)?1:0)},e.prototype.ConcatenateChanges=function(e,t){var n=[];if(0===e.length||0===t.length)return t.length>0?t:e;if(this.ChangesOverlap(e[e.length-1],t[0],n)){var r=new Array(e.length+t.length-1);return M.Copy(e,0,r,0,e.length-1),r[e.length-1]=n[0],M.Copy(t,1,r,e.length,t.length-1),r}r=new Array(e.length+t.length);return M.Copy(e,0,r,0,e.length),M.Copy(t,0,r,e.length,t.length),r},e.prototype.ChangesOverlap=function(e,t,n){if(P.Assert(e.originalStart<=t.originalStart,"Left change is not less than or equal to right change"),P.Assert(e.modifiedStart<=t.modifiedStart,"Left change is not less than or equal to right change"),e.originalStart+e.originalLength>=t.originalStart||e.modifiedStart+e.modifiedLength>=t.modifiedStart){var r=e.originalStart,i=e.originalLength,o=e.modifiedStart,s=e.modifiedLength;return e.originalStart+e.originalLength>=t.originalStart&&(i=t.originalStart+t.originalLength-e.originalStart),e.modifiedStart+e.modifiedLength>=t.modifiedStart&&(s=t.modifiedStart+t.modifiedLength-e.modifiedStart),n[0]=new E(r,i,o,s),!0}return n[0]=null,!1},e.prototype.ClipDiagonalBound=function(e,t,n,r){if(e>=0&&e=n?I:{done:!1,value:e[t++]}}}},e.from=function(t){return t?Array.isArray(t)?e.fromArray(t):t:e.empty()},e.map=function(e,t){return{next:function(){var n=e.next();return n.done?I:{done:!1,value:t(n.value)}}}},e.filter=function(e,t){return{next:function(){for(;;){var n=e.next();if(n.done)return I;if(t(n.value))return{done:!1,value:n.value}}}}},e.forEach=function(e,t){for(var n=e.next();!n.done;n=e.next())t(n.value)},e.collect=function(e,t){void 0===t&&(t=Number.POSITIVE_INFINITY);var n=[];if(0===t)return n;for(var r=0,i=e.next();!(i.done||(n.push(i.value),++r>=t));i=e.next());return n},e.concat=function(){for(var e=[],t=0;t=e.length)return I;var t=e[n].next();return t.done?(n++,this.next()):t}}}}(A||(A={}));(function(e){function t(t,n,r,i){return void 0===n&&(n=0),void 0===r&&(r=t.length),void 0===i&&(i=n-1),e.call(this,t,n,r,i)||this}x(t,e),t.prototype.current=function(){return e.prototype.current.call(this)},t.prototype.previous=function(){return this.index=Math.max(this.index-1,this.start-1),this.current()},t.prototype.first=function(){return this.index=this.start,this.current()},t.prototype.last=function(){return this.index=this.end-1,this.current()},t.prototype.parent=function(){return null}})(function(){function e(e,t,n,r){void 0===t&&(t=0),void 0===n&&(n=e.length),void 0===r&&(r=t-1),this.items=e,this.start=t,this.end=n,this.index=r}return e.prototype.first=function(){return this.index=this.start,this.current()},e.prototype.next=function(){return this.index=Math.min(this.index+1,this.end),this.current()},e.prototype.current=function(){return this.index===this.start-1||this.index===this.end?null:this.items[this.index]},e}()),function(){function e(e,t){this.iterator=e,this.fn=t}e.prototype.next=function(){return this.fn(this.iterator.next())}}();var R,U=this&&this.__extends||function(){var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(t,n)};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}(),k=/^\w[\w\d+.-]*$/,D=/^\//,F=/^\/\//,K=!0;var q="",V="/",B=/^(([^:/?#]+?):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/,Y=function(){function e(e,t,n,r,i,o){void 0===o&&(o=!1),"object"==typeof e?(this.scheme=e.scheme||q,this.authority=e.authority||q,this.path=e.path||q,this.query=e.query||q,this.fragment=e.fragment||q):(this.scheme=function(e,t){return t||K?e||q:(e||(console.trace("BAD uri lacks scheme, falling back to file-scheme."),e="file"),e)}(e,o),this.authority=t||q,this.path=function(e,t){switch(e){case"https":case"http":case"file":t?t[0]!==V&&(t=V+t):t=V}return t}(this.scheme,n||q),this.query=r||q,this.fragment=i||q,function(e,t){if(!e.scheme){if(t||K)throw new Error('[UriError]: Scheme is missing: {scheme: "", authority: "'+e.authority+'", path: "'+e.path+'", query: "'+e.query+'", fragment: "'+e.fragment+'"}');console.warn('[UriError]: Scheme is missing: {scheme: "", authority: "'+e.authority+'", path: "'+e.path+'", query: "'+e.query+'", fragment: "'+e.fragment+'"}')}if(e.scheme&&!k.test(e.scheme))throw new Error("[UriError]: Scheme contains illegal characters.");if(e.path)if(e.authority){if(!D.test(e.path))throw new Error('[UriError]: If a URI contains an authority component, then the path component must either be empty or begin with a slash ("/") character')}else if(F.test(e.path))throw new Error('[UriError]: If a URI does not contain an authority component, then the path cannot begin with two slash characters ("//")')}(this,o))}return e.isUri=function(t){return t instanceof e||!!t&&("string"==typeof t.authority&&"string"==typeof t.fragment&&"string"==typeof t.path&&"string"==typeof t.query&&"string"==typeof t.scheme&&"function"==typeof t.fsPath&&"function"==typeof t.with&&"function"==typeof t.toString)},Object.defineProperty(e.prototype,"fsPath",{get:function(){return z(this)},enumerable:!0,configurable:!0}),e.prototype.with=function(e){if(!e)return this;var t=e.scheme,n=e.authority,r=e.path,i=e.query,o=e.fragment;return void 0===t?t=this.scheme:null===t&&(t=q),void 0===n?n=this.authority:null===n&&(n=q),void 0===r?r=this.path:null===r&&(r=q),void 0===i?i=this.query:null===i&&(i=q),void 0===o?o=this.fragment:null===o&&(o=q),t===this.scheme&&n===this.authority&&r===this.path&&i===this.query&&o===this.fragment?this:new W(t,n,r,i,o)},e.parse=function(e,t){void 0===t&&(t=!1);var n=B.exec(e);return n?new W(n[2]||q,decodeURIComponent(n[4]||q),decodeURIComponent(n[5]||q),decodeURIComponent(n[7]||q),decodeURIComponent(n[9]||q),t):new W(q,q,q,q,q)},e.file=function(e){var t=q;if(p.c&&(e=e.replace(/\\/g,V)),e[0]===V&&e[1]===V){var n=e.indexOf(V,2);-1===n?(t=e.substring(2),e=V):(t=e.substring(2,n),e=e.substring(n)||V)}return new W("file",t,e,q,q)},e.from=function(e){return new W(e.scheme,e.authority,e.path,e.query,e.fragment)},e.prototype.toString=function(e){return void 0===e&&(e=!1),X(this,e)},e.prototype.toJSON=function(){return this},e.revive=function(t){if(t){if(t instanceof e)return t;var n=new W(t);return n._formatted=t.external,n._fsPath=t._sep===j?t.fsPath:null,n}return t},e}(),j=p.c?1:void 0,W=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t._formatted=null,t._fsPath=null,t}return U(t,e),Object.defineProperty(t.prototype,"fsPath",{get:function(){return this._fsPath||(this._fsPath=z(this)),this._fsPath},enumerable:!0,configurable:!0}),t.prototype.toString=function(e){return void 0===e&&(e=!1),e?X(this,!0):(this._formatted||(this._formatted=X(this,!1)),this._formatted)},t.prototype.toJSON=function(){var e={$mid:1};return this._fsPath&&(e.fsPath=this._fsPath,e._sep=j),this._formatted&&(e.external=this._formatted),this.path&&(e.path=this.path),this.scheme&&(e.scheme=this.scheme),this.authority&&(e.authority=this.authority),this.query&&(e.query=this.query),this.fragment&&(e.fragment=this.fragment),e},t}(Y),H=((R={})[58]="%3A",R[47]="%2F",R[63]="%3F",R[35]="%23",R[91]="%5B",R[93]="%5D",R[64]="%40",R[33]="%21",R[36]="%24",R[38]="%26",R[39]="%27",R[40]="%28",R[41]="%29",R[42]="%2A",R[43]="%2B",R[44]="%2C",R[59]="%3B",R[61]="%3D",R[32]="%20",R);function G(e,t){for(var n=void 0,r=-1,i=0;i=97&&o<=122||o>=65&&o<=90||o>=48&&o<=57||45===o||46===o||95===o||126===o||t&&47===o)-1!==r&&(n+=encodeURIComponent(e.substring(r,i)),r=-1),void 0!==n&&(n+=e.charAt(i));else{void 0===n&&(n=e.substr(0,i));var s=H[o];void 0!==s?(-1!==r&&(n+=encodeURIComponent(e.substring(r,i)),r=-1),n+=s):-1===r&&(r=i)}}return-1!==r&&(n+=encodeURIComponent(e.substring(r))),void 0!==n?n:e}function Q(e){for(var t=void 0,n=0;n1&&"file"===e.scheme?"//"+e.authority+e.path:47===e.path.charCodeAt(0)&&(e.path.charCodeAt(1)>=65&&e.path.charCodeAt(1)<=90||e.path.charCodeAt(1)>=97&&e.path.charCodeAt(1)<=122)&&58===e.path.charCodeAt(2)?e.path[1].toLowerCase()+e.path.substr(2):e.path,p.c&&(t=t.replace(/\//g,"\\")),t}function X(e,t){var n=t?Q:G,r="",i=e.scheme,o=e.authority,s=e.path,u=e.query,a=e.fragment;if(i&&(r+=i,r+=":"),(o||"file"===i)&&(r+=V,r+=V),o){var l=o.indexOf("@");if(-1!==l){var h=o.substr(0,l);o=o.substr(l+1),-1===(l=h.indexOf(":"))?r+=n(h,!1):(r+=n(h.substr(0,l),!1),r+=":",r+=n(h.substr(l+1),!1)),r+="@"}-1===(l=(o=o.toLowerCase()).indexOf(":"))?r+=n(o,!1):(r+=n(o.substr(0,l),!1),r+=o.substr(l))}if(s){if(s.length>=3&&47===s.charCodeAt(0)&&58===s.charCodeAt(2))(c=s.charCodeAt(1))>=65&&c<=90&&(s="/"+String.fromCharCode(c+32)+":"+s.substr(3));else if(s.length>=2&&58===s.charCodeAt(1)){var c;(c=s.charCodeAt(0))>=65&&c<=90&&(s=String.fromCharCode(c+32)+":"+s.substr(2))}r+=n(s,!0)}return u&&(r+="?",r+=n(u,!1)),a&&(r+="#",r+=t?a:G(a,!1)),r}var Z=function(){function e(e,t){this.lineNumber=e,this.column=t}return e.prototype.with=function(t,n){return void 0===t&&(t=this.lineNumber),void 0===n&&(n=this.column),t===this.lineNumber&&n===this.column?this:new e(t,n)},e.prototype.delta=function(e,t){return void 0===e&&(e=0),void 0===t&&(t=0),this.with(this.lineNumber+e,this.column+t)},e.prototype.equals=function(t){return e.equals(this,t)},e.equals=function(e,t){return!e&&!t||!!e&&!!t&&e.lineNumber===t.lineNumber&&e.column===t.column},e.prototype.isBefore=function(t){return e.isBefore(this,t)},e.isBefore=function(e,t){return e.lineNumbern||e===n&&t>r?(this.startLineNumber=n,this.startColumn=r,this.endLineNumber=e,this.endColumn=t):(this.startLineNumber=e,this.startColumn=t,this.endLineNumber=n,this.endColumn=r)}return e.prototype.isEmpty=function(){return e.isEmpty(this)},e.isEmpty=function(e){return e.startLineNumber===e.endLineNumber&&e.startColumn===e.endColumn},e.prototype.containsPosition=function(t){return e.containsPosition(this,t)},e.containsPosition=function(e,t){return!(t.lineNumbere.endLineNumber)&&(!(t.lineNumber===e.startLineNumber&&t.columne.endColumn))},e.prototype.containsRange=function(t){return e.containsRange(this,t)},e.containsRange=function(e,t){return!(t.startLineNumbere.endLineNumber||t.endLineNumber>e.endLineNumber)&&(!(t.startLineNumber===e.startLineNumber&&t.startColumne.endColumn)))},e.prototype.strictContainsRange=function(t){return e.strictContainsRange(this,t)},e.strictContainsRange=function(e,t){return!(t.startLineNumbere.endLineNumber||t.endLineNumber>e.endLineNumber)&&(!(t.startLineNumber===e.startLineNumber&&t.startColumn<=e.startColumn)&&!(t.endLineNumber===e.endLineNumber&&t.endColumn>=e.endColumn)))},e.prototype.plusRange=function(t){return e.plusRange(this,t)},e.plusRange=function(t,n){var r,i,o,s;return n.startLineNumbert.endLineNumber?(o=n.endLineNumber,s=n.endColumn):n.endLineNumber===t.endLineNumber?(o=n.endLineNumber,s=Math.max(n.endColumn,t.endColumn)):(o=t.endLineNumber,s=t.endColumn),new e(r,i,o,s)},e.prototype.intersectRanges=function(t){return e.intersectRanges(this,t)},e.intersectRanges=function(t,n){var r=t.startLineNumber,i=t.startColumn,o=t.endLineNumber,s=t.endColumn,u=n.startLineNumber,a=n.startColumn,l=n.endLineNumber,h=n.endColumn;return rl?(o=l,s=h):o===l&&(s=Math.min(s,h)),r>o?null:r===o&&i>s?null:new e(r,i,o,s)},e.prototype.equalsRange=function(t){return e.equalsRange(this,t)},e.equalsRange=function(e,t){return!!e&&!!t&&e.startLineNumber===t.startLineNumber&&e.startColumn===t.startColumn&&e.endLineNumber===t.endLineNumber&&e.endColumn===t.endColumn},e.prototype.getEndPosition=function(){return new Z(this.endLineNumber,this.endColumn)},e.prototype.getStartPosition=function(){return new Z(this.startLineNumber,this.startColumn)},e.prototype.toString=function(){return"["+this.startLineNumber+","+this.startColumn+" -> "+this.endLineNumber+","+this.endColumn+"]"},e.prototype.setEndPosition=function(t,n){return new e(this.startLineNumber,this.startColumn,t,n)},e.prototype.setStartPosition=function(t,n){return new e(t,n,this.endLineNumber,this.endColumn)},e.prototype.collapseToStart=function(){return e.collapseToStart(this)},e.collapseToStart=function(t){return new e(t.startLineNumber,t.startColumn,t.startLineNumber,t.startColumn)},e.fromPositions=function(t,n){return void 0===n&&(n=t),new e(t.lineNumber,t.column,n.lineNumber,n.column)},e.lift=function(t){return t?new e(t.startLineNumber,t.startColumn,t.endLineNumber,t.endColumn):null},e.isIRange=function(e){return e&&"number"==typeof e.startLineNumber&&"number"==typeof e.startColumn&&"number"==typeof e.endLineNumber&&"number"==typeof e.endColumn},e.areIntersectingOrTouching=function(e,t){return!(e.endLineNumbere.startLineNumber},e}();String.fromCharCode(65279);var $=5e3,ee=3;function te(e,t,n,r){return new T(e,t,n).ComputeDiff(r)}var ne=function(){function e(t){for(var n=[],r=[],i=0,o=t.length;i=0;n--){var r=e.charCodeAt(n);if(32!==r&&9!==r)return n}return-1}(e);return-1===n?t:n+2},e.prototype.getCharSequence=function(e,t,n){for(var r=[],i=[],o=[],s=0,u=t;u<=n;u++)for(var a=this._lines[u],l=e?this._startColumns[u]:1,h=e?this._endColumns[u]:a.length+1,c=l;c1&&m>1;){if(c.charCodeAt(d-2)!==f.charCodeAt(m-2))break;d--,m--}(d>1||m>1)&&this._pushTrimWhitespaceCharChange(i,o+1,1,d,s+1,1,m);for(var p=ne._getLastNonBlankColumn(c,1),g=ne._getLastNonBlankColumn(f,1),_=c.length+1,v=f.length+1;p<_&&g255?255:0|e}function le(e){return e<0?0:e>4294967295?4294967295:0|e}var he=function(){return function(e,t){this.index=e,this.remainder=t}}(),ce=function(){function e(e){this.values=e,this.prefixSum=new Uint32Array(e.length),this.prefixSumValidIndex=new Int32Array(1),this.prefixSumValidIndex[0]=-1}return e.prototype.getCount=function(){return this.values.length},e.prototype.insertValues=function(e,t){e=le(e);var n=this.values,r=this.prefixSum,i=t.length;return 0!==i&&(this.values=new Uint32Array(n.length+i),this.values.set(n.subarray(0,e),0),this.values.set(n.subarray(e),e+i),this.values.set(t,e),e-1=0&&this.prefixSum.set(r.subarray(0,this.prefixSumValidIndex[0]+1)),!0)},e.prototype.changeValue=function(e,t){return e=le(e),t=le(t),this.values[e]!==t&&(this.values[e]=t,e-1=n.length)return!1;var i=n.length-e;return t>=i&&(t=i),0!==t&&(this.values=new Uint32Array(n.length-t),this.values.set(n.subarray(0,e),0),this.values.set(n.subarray(e+t),e),this.prefixSum=new Uint32Array(this.values.length),e-1=0&&this.prefixSum.set(r.subarray(0,this.prefixSumValidIndex[0]+1)),!0)},e.prototype.getTotalValue=function(){return 0===this.values.length?0:this._getAccumulatedValue(this.values.length-1)},e.prototype.getAccumulatedValue=function(e){return e<0?0:(e=le(e),this._getAccumulatedValue(e))},e.prototype._getAccumulatedValue=function(e){if(e<=this.prefixSumValidIndex[0])return this.prefixSum[e];var t=this.prefixSumValidIndex[0]+1;0===t&&(this.prefixSum[0]=this.values[0],t++),e>=this.values.length&&(e=this.values.length-1);for(var n=t;n<=e;n++)this.prefixSum[n]=this.prefixSum[n-1]+this.values[n];return this.prefixSumValidIndex[0]=Math.max(this.prefixSumValidIndex[0],e),this.prefixSum[e]},e.prototype.getIndexOf=function(e){e=Math.floor(e),this.getTotalValue();for(var t=0,n=this.values.length-1,r=0,i=0,o=0;t<=n;)if(r=t+(n-t)/2|0,e<(o=(i=this.prefixSum[r])-this.values[r]))n=r-1;else{if(!(e>=i))break;t=r+1}return new he(r,e-o)},e}(),fe=(function(){function e(e){this._cacheAccumulatedValueStart=0,this._cache=null,this._actual=new ce(e),this._bustCache()}e.prototype._bustCache=function(){this._cacheAccumulatedValueStart=0,this._cache=null},e.prototype.insertValues=function(e,t){this._actual.insertValues(e,t)&&this._bustCache()},e.prototype.changeValue=function(e,t){this._actual.changeValue(e,t)&&this._bustCache()},e.prototype.removeValues=function(e,t){this._actual.removeValues(e,t)&&this._bustCache()},e.prototype.getTotalValue=function(){return this._actual.getTotalValue()},e.prototype.getAccumulatedValue=function(e){return this._actual.getAccumulatedValue(e)},e.prototype.getIndexOf=function(e){if(e=Math.floor(e),null!==this._cache){var t=e-this._cacheAccumulatedValueStart;if(t>=0&&t/?";var me=function(e){void 0===e&&(e="");for(var t="(-?\\d*\\.\\d\\w*)|([^",n=0,r=de;n=0||(t+="\\"+i)}return t+="\\s]+)",new RegExp(t,"g")}();var pe=function(){function e(t){var n=ae(t);this._defaultValue=n,this._asciiMap=e._createAsciiMap(n),this._map=new Map}return e._createAsciiMap=function(e){for(var t=new Uint8Array(256),n=0;n<256;n++)t[n]=e;return t},e.prototype.set=function(e,t){var n=ae(t);e>=0&&e<256?this._asciiMap[e]=n:this._map.set(e,n)},e.prototype.get=function(e){return e>=0&&e<256?this._asciiMap[e]:this._map.get(e)||this._defaultValue},e}(),ge=(function(){function e(){this._actual=new pe(0)}e.prototype.add=function(e){this._actual.set(e,1)},e.prototype.has=function(e){return 1===this._actual.get(e)}}(),function(){function e(e){for(var t=0,n=0,r=0,i=e.length;rt&&(t=u),s>n&&(n=s),a>n&&(n=a)}var l=new ue(++n,++t,0);for(r=0,i=e.length;r=this._maxCharCode?0:this._states.get(e,t)},e}()),_e=null;var ve=null;var ye=function(){function e(){}return e._createLink=function(e,t,n,r,i){var o=i-1;do{var s=t.charCodeAt(o);if(2!==e.get(s))break;o--}while(o>r);if(r>0){var u=t.charCodeAt(r-1),a=t.charCodeAt(o);(40===u&&41===a||91===u&&93===a||123===u&&125===a)&&o--}return{range:{startLineNumber:n,startColumn:r+1,endLineNumber:n,endColumn:o+2},url:t.substring(r,o+1)}},e.computeLinks=function(t,n){void 0===n&&(null===_e&&(_e=new ge([[1,104,2],[1,72,2],[1,102,6],[1,70,6],[2,116,3],[2,84,3],[3,116,4],[3,84,4],[4,112,5],[4,80,5],[5,115,9],[5,83,9],[5,58,10],[6,105,7],[6,73,7],[7,108,8],[7,76,8],[8,101,9],[8,69,9],[9,58,10],[10,47,11],[11,47,12]])),n=_e);for(var r=function(){if(null===ve){ve=new pe(0);for(var e=0;e<" \t<>'\"、。。、,.:;?!@#$%&*‘“〈《「『【〔([{「」}])〕】』」》〉”’`~…".length;e++)ve.set(" \t<>'\"、。。、,.:;?!@#$%&*‘“〈《「『【〔([{「」}])〕】』」》〉”’`~…".charCodeAt(e),1);for(e=0;e<".,;".length;e++)ve.set(".,;".charCodeAt(e),2)}return ve}(),i=[],o=1,s=t.getLineCount();o<=s;o++){for(var u=t.getLineContent(o),a=u.length,l=0,h=0,c=0,f=1,d=!1,m=!1,p=!1;l=0?((r+=n?1:-1)<0?r=e.length-1:r%=e.length,e[r]):null},e.INSTANCE=new e,e}();n("tZcU");var be,Le=function(){function e(t){this.element=t,this.next=e.Undefined,this.prev=e.Undefined}return e.Undefined=new e(void 0),e}(),Ne=function(){function e(){this._first=Le.Undefined,this._last=Le.Undefined,this._size=0}return Object.defineProperty(e.prototype,"size",{get:function(){return this._size},enumerable:!0,configurable:!0}),e.prototype.isEmpty=function(){return this._first===Le.Undefined},e.prototype.clear=function(){this._first=Le.Undefined,this._last=Le.Undefined,this._size=0},e.prototype.unshift=function(e){return this._insert(e,!1)},e.prototype.push=function(e){return this._insert(e,!0)},e.prototype._insert=function(e,t){var n=this,r=new Le(e);if(this._first===Le.Undefined)this._first=r,this._last=r;else if(t){var i=this._last;this._last=r,r.prev=i,i.next=r}else{var o=this._first;this._first=r,r.next=o,o.prev=r}this._size+=1;var s=!1;return function(){s||(s=!0,n._remove(r))}},e.prototype.shift=function(){if(this._first!==Le.Undefined){var e=this._first.element;return this._remove(this._first),e}},e.prototype.pop=function(){if(this._last!==Le.Undefined){var e=this._last.element;return this._remove(this._last),e}},e.prototype._remove=function(e){if(e.prev!==Le.Undefined&&e.next!==Le.Undefined){var t=e.prev;t.next=e.next,e.next.prev=t}else e.prev===Le.Undefined&&e.next===Le.Undefined?(this._first=Le.Undefined,this._last=Le.Undefined):e.next===Le.Undefined?(this._last=this._last.prev,this._last.next=Le.Undefined):e.prev===Le.Undefined&&(this._first=this._first.next,this._first.prev=Le.Undefined);this._size-=1},e.prototype.iterator=function(){var e,t=this._first;return{next:function(){return t===Le.Undefined?I:(e?e.value=t.element:e={done:!1,value:t.element},t=t.next,e)}}},e.prototype.toArray=function(){for(var e=[],t=this._first;t!==Le.Undefined;t=t.next)e.push(t.element);return e},e}(),Ee=this&&this.__extends||function(){var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(t,n)};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}();!function(e){function t(e){return function(t,n,r){void 0===n&&(n=null);var i,o=!1;return i=e(function(e){if(!o)return i?i.dispose():o=!0,t.call(n,e)},null,r),o&&i.dispose(),i}}function n(e,t){return s(function(n,r,i){return void 0===r&&(r=null),e(function(e){return n.call(r,t(e))},null,i)})}function r(e,t){return s(function(n,r,i){return void 0===r&&(r=null),e(function(e){t(e),n.call(r,e)},null,i)})}function i(e,t){return s(function(n,r,i){return void 0===r&&(r=null),e(function(e){return t(e)&&n.call(r,e)},null,i)})}function o(e,t,r){var i=r;return n(e,function(e){return i=t(i,e)})}function s(e){var t,n=new Pe({onFirstListenerAdd:function(){t=e(n.fire,n)},onLastListenerRemove:function(){t.dispose()}});return n.event}function u(e){var t,n=!0;return i(e,function(e){var r=n||e!==t;return n=!1,t=e,r})}e.None=function(){return m.None},e.once=t,e.map=n,e.forEach=r,e.filter=i,e.signal=function(e){return e},e.any=function(){for(var e=[],t=0;t1)&&l.fire(e),a=0},n)})},onLastListenerRemove:function(){o.dispose()}});return l.event},e.stopwatch=function(e){var r=(new Date).getTime();return n(t(e),function(e){return(new Date).getTime()-r})},e.latch=u,e.buffer=function(e,t,n){void 0===t&&(t=!1),void 0===n&&(n=[]);var r=n.slice(),i=e(function(e){r?r.push(e):s.fire(e)}),o=function(){r&&r.forEach(function(e){return s.fire(e)}),r=null},s=new Pe({onFirstListenerAdd:function(){i||(i=e(function(e){return s.fire(e)}))},onFirstListenerDidAdd:function(){r&&(t?setTimeout(o):o())},onLastListenerRemove:function(){i&&i.dispose(),i=null}});return s.event};var a=function(){function e(e){this.event=e}return e.prototype.map=function(t){return new e(n(this.event,t))},e.prototype.forEach=function(t){return new e(r(this.event,t))},e.prototype.filter=function(t){return new e(i(this.event,t))},e.prototype.reduce=function(t,n){return new e(o(this.event,t,n))},e.prototype.latch=function(){return new e(u(this.event))},e.prototype.on=function(e,t,n){return this.event(e,t,n)},e.prototype.once=function(e,n,r){return t(this.event)(e,n,r)},e}();e.chain=function(e){return new a(e)},e.fromNodeEventEmitter=function(e,t,n){void 0===n&&(n=function(e){return e});var r=function(){for(var e=[],t=0;t0?new Ae(this._options&&this._options.leakWarningThreshold):void 0}return Object.defineProperty(e.prototype,"event",{get:function(){var t=this;return this._event||(this._event=function(n,r,i){t._listeners||(t._listeners=new Ne);var o=t._listeners.isEmpty();o&&t._options&&t._options.onFirstListenerAdd&&t._options.onFirstListenerAdd(t);var s,u,a=t._listeners.push(r?[n,r]:n);return o&&t._options&&t._options.onFirstListenerDidAdd&&t._options.onFirstListenerDidAdd(t),t._options&&t._options.onListenerDidAdd&&t._options.onListenerDidAdd(t,n,r),t._leakageMon&&(s=t._leakageMon.check(t._listeners.size)),u={dispose:function(){(s&&s(),u.dispose=e._noop,t._disposed)||(a(),t._options&&t._options.onLastListenerRemove&&(t._listeners&&!t._listeners.isEmpty()||t._options.onLastListenerRemove(t)))}},i instanceof d?i.add(u):Array.isArray(i)&&i.push(u),u}),this._event},enumerable:!0,configurable:!0}),e.prototype.fire=function(e){if(this._listeners){this._deliveryQueue||(this._deliveryQueue=new Ne);for(var t=this._listeners.iterator(),n=t.next();!n.done;n=t.next())this._deliveryQueue.push([n.value,e]);for(;this._deliveryQueue.size>0;){var r=this._deliveryQueue.shift(),o=r[0],s=r[1];try{"function"==typeof o?o.call(void 0,s):o[0].call(o[1],s)}catch(n){i(n)}}}},e.prototype.dispose=function(){this._listeners&&this._listeners.clear(),this._deliveryQueue&&this._deliveryQueue.clear(),this._leakageMon&&this._leakageMon.dispose(),this._disposed=!0},e._noop=function(){},e}(),Me=(function(e){function t(t){var n=e.call(this,t)||this;return n._isPaused=0,n._eventQueue=new Ne,n._mergeFn=t&&t.merge,n}Ee(t,e),t.prototype.pause=function(){this._isPaused++},t.prototype.resume=function(){if(0!==this._isPaused&&0==--this._isPaused)if(this._mergeFn){var t=this._eventQueue.toArray();this._eventQueue.clear(),e.prototype.fire.call(this,this._mergeFn(t))}else for(;!this._isPaused&&0!==this._eventQueue.size;)e.prototype.fire.call(this,this._eventQueue.shift())},t.prototype.fire=function(t){this._listeners&&(0!==this._isPaused?this._eventQueue.push(t):e.prototype.fire.call(this,t))}}(Pe),function(){function e(){var e=this;this.hasListeners=!1,this.events=[],this.emitter=new Pe({onFirstListenerAdd:function(){return e.onFirstListenerAdd()},onLastListenerRemove:function(){return e.onLastListenerRemove()}})}Object.defineProperty(e.prototype,"event",{get:function(){return this.emitter.event},enumerable:!0,configurable:!0}),e.prototype.add=function(e){var t=this,n={event:e,listener:null};this.events.push(n),this.hasListeners&&this.hook(n);var r,i;return r=function(e){var t,n=this,r=!1;return function(){return r?t:(r=!0,t=e.apply(n,arguments))}}(function(){t.hasListeners&&t.unhook(n);var e=t.events.indexOf(n);t.events.splice(e,1)}),i=c({dispose:function(){h(i),r()}})},e.prototype.onFirstListenerAdd=function(){var e=this;this.hasListeners=!0,this.events.forEach(function(t){return e.hook(t)})},e.prototype.onLastListenerRemove=function(){var e=this;this.hasListeners=!1,this.events.forEach(function(t){return e.unhook(t)})},e.prototype.hook=function(e){var t=this;e.listener=e.event(function(e){return t.emitter.fire(e)})},e.prototype.unhook=function(e){e.listener&&e.listener.dispose(),e.listener=null},e.prototype.dispose=function(){this.emitter.dispose()}}(),function(){function e(){this.buffers=[]}e.prototype.wrapEvent=function(e){var t=this;return function(n,r,i){return e(function(e){var i=t.buffers[t.buffers.length-1];i?i.push(function(){return n.call(r,e)}):n.call(r,e)},void 0,i)}},e.prototype.bufferEvents=function(e){var t=[];this.buffers.push(t);var n=e();return this.buffers.pop(),t.forEach(function(e){return e()}),n}}(),function(){function e(){var e=this;this.listening=!1,this.inputEvent=be.None,this.inputEventListener=m.None,this.emitter=new Pe({onFirstListenerDidAdd:function(){e.listening=!0,e.inputEventListener=e.inputEvent(e.emitter.fire,e.emitter)},onLastListenerRemove:function(){e.listening=!1,e.inputEventListener.dispose()}}),this.event=this.emitter.event}Object.defineProperty(e.prototype,"input",{set:function(e){this.inputEvent=e,this.listening&&(this.inputEventListener.dispose(),this.inputEventListener=e(this.emitter.fire,this.emitter))},enumerable:!0,configurable:!0}),e.prototype.dispose=function(){this.inputEventListener.dispose(),this.emitter.dispose()}}(),Object.freeze(function(e,t){var n=setTimeout(e.bind(t),0);return{dispose:function(){clearTimeout(n)}}}));!function(e){e.isCancellationToken=function(t){return t===e.None||t===e.Cancelled||t instanceof Te||!(!t||"object"!=typeof t)&&"boolean"==typeof t.isCancellationRequested&&"function"==typeof t.onCancellationRequested},e.None=Object.freeze({isCancellationRequested:!1,onCancellationRequested:be.None}),e.Cancelled=Object.freeze({isCancellationRequested:!0,onCancellationRequested:Me})}(Se||(Se={}));var Oe,Te=function(){function e(){this._isCancelled=!1,this._emitter=null}return e.prototype.cancel=function(){this._isCancelled||(this._isCancelled=!0,this._emitter&&(this._emitter.fire(void 0),this.dispose()))},Object.defineProperty(e.prototype,"isCancellationRequested",{get:function(){return this._isCancelled},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"onCancellationRequested",{get:function(){return this._isCancelled?Me:(this._emitter||(this._emitter=new Pe),this._emitter.event)},enumerable:!0,configurable:!0}),e.prototype.dispose=function(){this._emitter&&(this._emitter.dispose(),this._emitter=null)},e}(),xe=function(){function e(e){this._token=void 0,this._parentListener=void 0,this._parentListener=e&&e.onCancellationRequested(this.cancel,this)}return Object.defineProperty(e.prototype,"token",{get:function(){return this._token||(this._token=new Te),this._token},enumerable:!0,configurable:!0}),e.prototype.cancel=function(){this._token?this._token instanceof Te&&this._token.cancel():this._token=Se.Cancelled},e.prototype.dispose=function(){this._parentListener&&this._parentListener.dispose(),this._token?this._token instanceof Te&&this._token.dispose():this._token=Se.None},e}(),Ie=function(){function e(){this._keyCodeToStr=[],this._strToKeyCode=Object.create(null)}return e.prototype.define=function(e,t){this._keyCodeToStr[e]=t,this._strToKeyCode[t.toLowerCase()]=e},e.prototype.keyCodeToStr=function(e){return this._keyCodeToStr[e]},e.prototype.strToKeyCode=function(e){return this._strToKeyCode[e.toLowerCase()]||0},e}(),Re=new Ie,Ue=new Ie,ke=new Ie;!function(){function e(e,t,n,r){void 0===n&&(n=t),void 0===r&&(r=n),Re.define(e,t),Ue.define(e,n),ke.define(e,r)}e(0,"unknown"),e(1,"Backspace"),e(2,"Tab"),e(3,"Enter"),e(4,"Shift"),e(5,"Ctrl"),e(6,"Alt"),e(7,"PauseBreak"),e(8,"CapsLock"),e(9,"Escape"),e(10,"Space"),e(11,"PageUp"),e(12,"PageDown"),e(13,"End"),e(14,"Home"),e(15,"LeftArrow","Left"),e(16,"UpArrow","Up"),e(17,"RightArrow","Right"),e(18,"DownArrow","Down"),e(19,"Insert"),e(20,"Delete"),e(21,"0"),e(22,"1"),e(23,"2"),e(24,"3"),e(25,"4"),e(26,"5"),e(27,"6"),e(28,"7"),e(29,"8"),e(30,"9"),e(31,"A"),e(32,"B"),e(33,"C"),e(34,"D"),e(35,"E"),e(36,"F"),e(37,"G"),e(38,"H"),e(39,"I"),e(40,"J"),e(41,"K"),e(42,"L"),e(43,"M"),e(44,"N"),e(45,"O"),e(46,"P"),e(47,"Q"),e(48,"R"),e(49,"S"),e(50,"T"),e(51,"U"),e(52,"V"),e(53,"W"),e(54,"X"),e(55,"Y"),e(56,"Z"),e(57,"Meta"),e(58,"ContextMenu"),e(59,"F1"),e(60,"F2"),e(61,"F3"),e(62,"F4"),e(63,"F5"),e(64,"F6"),e(65,"F7"),e(66,"F8"),e(67,"F9"),e(68,"F10"),e(69,"F11"),e(70,"F12"),e(71,"F13"),e(72,"F14"),e(73,"F15"),e(74,"F16"),e(75,"F17"),e(76,"F18"),e(77,"F19"),e(78,"NumLock"),e(79,"ScrollLock"),e(80,";",";","OEM_1"),e(81,"=","=","OEM_PLUS"),e(82,",",",","OEM_COMMA"),e(83,"-","-","OEM_MINUS"),e(84,".",".","OEM_PERIOD"),e(85,"/","/","OEM_2"),e(86,"`","`","OEM_3"),e(110,"ABNT_C1"),e(111,"ABNT_C2"),e(87,"[","[","OEM_4"),e(88,"\\","\\","OEM_5"),e(89,"]","]","OEM_6"),e(90,"'","'","OEM_7"),e(91,"OEM_8"),e(92,"OEM_102"),e(93,"NumPad0"),e(94,"NumPad1"),e(95,"NumPad2"),e(96,"NumPad3"),e(97,"NumPad4"),e(98,"NumPad5"),e(99,"NumPad6"),e(100,"NumPad7"),e(101,"NumPad8"),e(102,"NumPad9"),e(103,"NumPad_Multiply"),e(104,"NumPad_Add"),e(105,"NumPad_Separator"),e(106,"NumPad_Subtract"),e(107,"NumPad_Decimal"),e(108,"NumPad_Divide")}(),function(e){e.toString=function(e){return Re.keyCodeToStr(e)},e.fromString=function(e){return Re.strToKeyCode(e)},e.toUserSettingsUS=function(e){return Ue.keyCodeToStr(e)},e.toUserSettingsGeneral=function(e){return ke.keyCodeToStr(e)},e.fromUserSettings=function(e){return Ue.strToKeyCode(e)||ke.strToKeyCode(e)}}(Oe||(Oe={}));!function(){function e(e,t,n,r,i){this.ctrlKey=e,this.shiftKey=t,this.altKey=n,this.metaKey=r,this.keyCode=i}e.prototype.equals=function(e){return this.ctrlKey===e.ctrlKey&&this.shiftKey===e.shiftKey&&this.altKey===e.altKey&&this.metaKey===e.metaKey&&this.keyCode===e.keyCode},e.prototype.isModifierKey=function(){return 0===this.keyCode||5===this.keyCode||57===this.keyCode||6===this.keyCode||4===this.keyCode},e.prototype.toChord=function(){return new dt([this])},e.prototype.isDuplicateModifierCase=function(){return this.ctrlKey&&5===this.keyCode||this.shiftKey&&4===this.keyCode||this.altKey&&6===this.keyCode||this.metaKey&&57===this.keyCode}}();var De,Fe,Ke,qe,Ve,Be,Ye,je,We,He,Ge,Qe,ze,Xe,Ze,Je,$e,et,tt,nt,rt,it,ot,st,ut,at,lt,ht,ct,ft,dt=function(){function e(e){if(0===e.length)throw(t="parts")?new Error("Illegal argument: "+t):new Error("Illegal argument");var t;this.parts=e}return e.prototype.equals=function(e){if(null===e)return!1;if(this.parts.length!==e.parts.length)return!1;for(var t=0;t "+this.positionLineNumber+","+this.positionColumn+"]"},t.prototype.equalsSelection=function(e){return t.selectionsEqual(this,e)},t.selectionsEqual=function(e,t){return e.selectionStartLineNumber===t.selectionStartLineNumber&&e.selectionStartColumn===t.selectionStartColumn&&e.positionLineNumber===t.positionLineNumber&&e.positionColumn===t.positionColumn},t.prototype.getDirection=function(){return this.selectionStartLineNumber===this.startLineNumber&&this.selectionStartColumn===this.startColumn?0:1},t.prototype.setEndPosition=function(e,n){return 0===this.getDirection()?new t(this.startLineNumber,this.startColumn,e,n):new t(e,n,this.startLineNumber,this.startColumn)},t.prototype.getPosition=function(){return new Z(this.positionLineNumber,this.positionColumn)},t.prototype.setStartPosition=function(e,n){return 0===this.getDirection()?new t(e,n,this.endLineNumber,this.endColumn):new t(this.endLineNumber,this.endColumn,e,n)},t.fromPositions=function(e,n){return void 0===n&&(n=e),new t(e.lineNumber,e.column,n.lineNumber,n.column)},t.liftSelection=function(e){return new t(e.selectionStartLineNumber,e.selectionStartColumn,e.positionLineNumber,e.positionColumn)},t.selectionsArrEqual=function(e,t){if(e&&!t||!e&&t)return!1;if(!e&&!t)return!0;if(e.length!==t.length)return!1;for(var n=0,r=e.length;n>>0)>>>0}(e,t)},e.CtrlCmd=2048,e.Shift=1024,e.Alt=512,e.WinCtrl=256,e}();var vt=this&&this.__extends||function(){var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(t,n)};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}(),yt=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return vt(t,e),Object.defineProperty(t.prototype,"uri",{get:function(){return this._uri},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"version",{get:function(){return this._versionId},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"eol",{get:function(){return this._eol},enumerable:!0,configurable:!0}),t.prototype.getValue=function(){return this.getText()},t.prototype.getLinesContent=function(){return this._lines.slice(0)},t.prototype.getLineCount=function(){return this._lines.length},t.prototype.getLineContent=function(e){return this._lines[e-1]},t.prototype.getWordAtPosition=function(e,t){var n=function(e,t,n,r){t.lastIndex=0;var i=t.exec(n);if(!i)return null;var o=i[0].indexOf(" ")>=0?function(e,t,n,r){var i,o=e-1-r;for(t.lastIndex=0;i=t.exec(n);){var s=i.index||0;if(s>o)return null;if(t.lastIndex>=o)return{word:i[0],startColumn:r+1+s,endColumn:r+1+t.lastIndex}}return null}(e,t,n,r):function(e,t,n,r){var i,o=e-1-r,s=n.lastIndexOf(" ",o-1)+1;for(t.lastIndex=s;i=t.exec(n);){var u=i.index||0;if(u<=o&&t.lastIndex>=o)return{word:i[0],startColumn:r+1+u,endColumn:r+1+t.lastIndex}}return null}(e,t,n,r);return t.lastIndex=0,o}(e.column,function(e){var t=me;if(e&&e instanceof RegExp)if(e.global)t=e;else{var n="g";e.ignoreCase&&(n+="i"),e.multiline&&(n+="m"),e.unicode&&(n+="u"),t=new RegExp(e.source,n)}return t.lastIndex=0,t}(t),this._lines[e.lineNumber-1],0);return n?new J(e.lineNumber,n.startColumn,e.lineNumber,n.endColumn):null},t.prototype.getWordUntilPosition=function(e,t){var n=this.getWordAtPosition(e,t);return n?{word:this._lines[e.lineNumber-1].substring(n.startColumn-1,e.column-1),startColumn:n.startColumn,endColumn:e.column}:{word:"",startColumn:e.column,endColumn:e.column}},t.prototype.createWordIterator=function(e){var t,n,r=this,i=0,o=0,s=[],u=function(){if(o=r._lines.length?I:(n=r._lines[i],s=r._wordenize(n,e),o=0,i+=1,u())};return{next:u}},t.prototype.getLineWords=function(e,t){for(var n=this._lines[e-1],r=[],i=0,o=this._wordenize(n,t);ithis._lines.length)t=this._lines.length,n=this._lines[t-1].length+1,r=!0;else{var i=this._lines[t-1].length+1;n<1?(n=1,r=!0):n>i&&(n=i,r=!0)}return r?{lineNumber:t,column:n}:e},t}(fe),Ct=function(){function e(e,t){this._host=e,this._models=Object.create(null),this._foreignModuleFactory=t,this._foreignModule=null}return e.prototype.dispose=function(){this._models=Object.create(null)},e.prototype._getModel=function(e){return this._models[e]},e.prototype._getModels=function(){var e=this,t=[];return Object.keys(this._models).forEach(function(n){return t.push(e._models[n])}),t},e.prototype.acceptNewModel=function(e){this._models[e.url]=new yt(Y.parse(e.url),e.lines,e.EOL,e.versionId)},e.prototype.acceptModelChanged=function(e,t){this._models[e]&&this._models[e].onEvents(t)},e.prototype.acceptRemovedModel=function(e){this._models[e]&&delete this._models[e]},e.prototype.computeDiff=function(e,t,n){var r=this._getModel(e),i=this._getModel(t);if(!r||!i)return Promise.resolve(null);var o=r.getLinesContent(),s=i.getLinesContent(),u=new se(o,s,{shouldComputeCharChanges:!0,shouldPostProcessCharChanges:!0,shouldIgnoreTrimWhitespace:n,shouldMakePrettyDiff:!0}).computeDiff(),a=!(u.length>0)&&this._modelsAreIdentical(r,i);return Promise.resolve({identical:a,changes:u})},e.prototype._modelsAreIdentical=function(e,t){var n=e.getLineCount();if(n!==t.getLineCount())return!1;for(var r=1;r<=n;r++){if(e.getLineContent(r)!==t.getLineContent(r))return!1}return!0},e.prototype.computeMoreMinimalEdits=function(t,n){var r=this._getModel(t);if(!r)return Promise.resolve(n);for(var i=[],o=void 0,s=0,u=n=N(n,function(e,t){return e.range&&t.range?J.compareRangesUsingStarts(e.range,t.range):(e.range?0:1)-(t.range?0:1)});se._diffLimit)i.push({range:l,text:h});else for(var d=w(f,h,!1),m=r.offsetAt(J.lift(l).getStartPosition()),p=0,g=d;p1)for(var n=1;n=0,o=a.indexOf("Macintosh")>=0,s=a.indexOf("Linux")>=0,u=!0,navigator.language;var d=i,m=u,p="object"==typeof self?self:"object"==typeof r?r:{}}).call(t,n("W2nU"),n("DuR2"))},tZcU:function(e,t,n){(function(e){(function(){"use strict";function t(e){var t=this.constructor;return this.then(function(n){return t.resolve(e()).then(function(){return n})},function(n){return t.resolve(e()).then(function(){return t.reject(n)})})}var n=setTimeout;function r(){}function i(e){if(!(this instanceof i))throw new TypeError("Promises must be constructed via new");if("function"!=typeof e)throw new TypeError("not a function");this._state=0,this._handled=!1,this._value=void 0,this._deferreds=[],l(e,this)}function o(e,t){for(;3===e._state;)e=e._value;0!==e._state?(e._handled=!0,i._immediateFn(function(){var n=1===e._state?t.onFulfilled:t.onRejected;if(null!==n){var r;try{r=n(e._value)}catch(e){return void u(t.promise,e)}s(t.promise,r)}else(1===e._state?s:u)(t.promise,e._value)})):e._deferreds.push(t)}function s(e,t){try{if(t===e)throw new TypeError("A promise cannot be resolved with itself.");if(t&&("object"==typeof t||"function"==typeof t)){var n=t.then;if(t instanceof i)return e._state=3,e._value=t,void a(e);if("function"==typeof n)return void l((r=n,o=t,function(){r.apply(o,arguments)}),e)}e._state=1,e._value=t,a(e)}catch(t){u(e,t)}var r,o}function u(e,t){e._state=2,e._value=t,a(e)}function a(e){2===e._state&&0===e._deferreds.length&&i._immediateFn(function(){e._handled||i._unhandledRejectionFn(e._value)});for(var t=0,n=e._deferreds.length;t + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/emqx_dashboard/priv/www/static/fonts/Roboto.ttf b/apps/emqx_dashboard/priv/www/static/fonts/Roboto.ttf new file mode 100644 index 000000000..7b25f3ce9 Binary files /dev/null and b/apps/emqx_dashboard/priv/www/static/fonts/Roboto.ttf differ diff --git a/apps/emqx_dashboard/priv/www/static/fonts/Roboto.woff b/apps/emqx_dashboard/priv/www/static/fonts/Roboto.woff new file mode 100644 index 000000000..941dfa4ba Binary files /dev/null and b/apps/emqx_dashboard/priv/www/static/fonts/Roboto.woff differ diff --git a/apps/emqx_dashboard/priv/www/static/fonts/Roboto.woff2 b/apps/emqx_dashboard/priv/www/static/fonts/Roboto.woff2 new file mode 100644 index 000000000..120796bb7 Binary files /dev/null and b/apps/emqx_dashboard/priv/www/static/fonts/Roboto.woff2 differ diff --git a/apps/emqx_dashboard/priv/www/static/fonts/element-icons.535877f.woff b/apps/emqx_dashboard/priv/www/static/fonts/element-icons.535877f.woff new file mode 100644 index 000000000..02b9a2539 Binary files /dev/null and b/apps/emqx_dashboard/priv/www/static/fonts/element-icons.535877f.woff differ diff --git a/apps/emqx_dashboard/priv/www/static/fonts/element-icons.732389d.ttf b/apps/emqx_dashboard/priv/www/static/fonts/element-icons.732389d.ttf new file mode 100644 index 000000000..91b74de36 Binary files /dev/null and b/apps/emqx_dashboard/priv/www/static/fonts/element-icons.732389d.ttf differ diff --git a/apps/emqx_dashboard/priv/www/static/fonts/fontawesome-webfont.eot b/apps/emqx_dashboard/priv/www/static/fonts/fontawesome-webfont.eot new file mode 100644 index 000000000..e9f60ca95 Binary files /dev/null and b/apps/emqx_dashboard/priv/www/static/fonts/fontawesome-webfont.eot differ diff --git a/apps/emqx_dashboard/priv/www/static/fonts/fontawesome-webfont.svg b/apps/emqx_dashboard/priv/www/static/fonts/fontawesome-webfont.svg new file mode 100644 index 000000000..855c845e5 --- /dev/null +++ b/apps/emqx_dashboard/priv/www/static/fonts/fontawesome-webfont.svg @@ -0,0 +1,2671 @@ + + + + +Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016 + By ,,, +Copyright Dave Gandy 2016. All rights reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/emqx_dashboard/priv/www/static/fonts/fontawesome-webfont.ttf b/apps/emqx_dashboard/priv/www/static/fonts/fontawesome-webfont.ttf new file mode 100644 index 000000000..35acda2fa Binary files /dev/null and b/apps/emqx_dashboard/priv/www/static/fonts/fontawesome-webfont.ttf differ diff --git a/apps/emqx_dashboard/priv/www/static/fonts/fontawesome-webfont.woff b/apps/emqx_dashboard/priv/www/static/fonts/fontawesome-webfont.woff new file mode 100644 index 000000000..400014a4b Binary files /dev/null and b/apps/emqx_dashboard/priv/www/static/fonts/fontawesome-webfont.woff differ diff --git a/apps/emqx_dashboard/priv/www/static/fonts/fontawesome-webfont.woff2 b/apps/emqx_dashboard/priv/www/static/fonts/fontawesome-webfont.woff2 new file mode 100644 index 000000000..4d13fc604 Binary files /dev/null and b/apps/emqx_dashboard/priv/www/static/fonts/fontawesome-webfont.woff2 differ diff --git a/apps/emqx_dashboard/priv/www/static/js/0.7a09d1383e1319441399.js b/apps/emqx_dashboard/priv/www/static/js/0.7a09d1383e1319441399.js new file mode 100644 index 000000000..c0f306b1a --- /dev/null +++ b/apps/emqx_dashboard/priv/www/static/js/0.7a09d1383e1319441399.js @@ -0,0 +1,8 @@ +webpackJsonp([0],{"1H6C":function(e,t,r){var n=function(){return this}()||Function("return this")(),i=n.regeneratorRuntime&&Object.getOwnPropertyNames(n).indexOf("regeneratorRuntime")>=0,a=i&&n.regeneratorRuntime;if(n.regeneratorRuntime=void 0,e.exports=r("HhN8"),i)n.regeneratorRuntime=a;else try{delete n.regeneratorRuntime}catch(e){n.regeneratorRuntime=void 0}},"3IRH":function(e,t){e.exports=function(e){return e.webpackPolyfill||(e.deprecate=function(){},e.paths=[],e.children||(e.children=[]),Object.defineProperty(e,"loaded",{enumerable:!0,get:function(){return e.l}}),Object.defineProperty(e,"id",{enumerable:!0,get:function(){return e.i}}),e.webpackPolyfill=1),e}},FcGO:function(e,t,r){"use strict";var n=r("Xxa5"),i=r.n(n),a=r("exGp"),s=r.n(a),o={name:"emq-select",components:{},props:{value:{},field:{type:Object,required:!0},fieldName:{type:Object,default:function(){return{label:"label",value:"value"}}},disabledItem:{type:Array,default:function(){return[]}},refresh:{type:Boolean}},data:function(){return{options:[],parserField:{}}},computed:{rawValue:{get:function(){return"boolean"==typeof this.value?this.value.toString():this.value},set:function(e){var t=this.fieldName.value;this.options.find(function(r){return r[t]===e})&&this.parserField[t]&&(e="true"===e),this.$emit("update:value",e)}}},watch:{refresh:function(e){e&&this.loadData()},field:{handler:function(){this.loadData()},deep:!0}},created:function(){this.loadData()},methods:{loadData:function(){var e=this;return s()(i.a.mark(function t(){var r,n,a;return i.a.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,e.getOptions();case 2:r=t.sent,e.parserField={},n=e.fieldName.value,a=e.fieldName.label,e.options=r.map(function(t){var r=t[n],i=t[a];return"boolean"==typeof r&&(e.parserField[n]="boolean",t[n]=r.toString(),"boolean"==typeof i&&(t[a]=i.toString())),t}),e.$emit("update:refresh",!1);case 8:case"end":return t.stop()}},t,e)}))()},isDisabled:function(e){return this.disabledItem.includes(e[this.fieldName.value])},getOptions:function(){var e=this;return s()(i.a.mark(function t(){var r,n,a,s,o;return i.a.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:if(r=e.field,n=r.api,r.url,a=r.options,s=r.list,o=[],!a){t.next=6;break}o=a,t.next=14;break;case 6:if(!s){t.next=10;break}o=s.map(function(e){return{label:e,value:e}}),t.next=14;break;case 10:if(!n){t.next=14;break}return t.next=13,n();case 13:o=t.sent;case 14:return t.abrupt("return",o);case 15:case"end":return t.stop()}},t,e)}))()}}},c={render:function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("el-select",e._g(e._b({staticClass:"emq-select",attrs:{value:e.rawValue}},"el-select",e.$attrs,!1),e.$listeners),[e._t("default",e._l(e.options,function(t,n){return r("el-option",{key:n,attrs:{value:t[e.fieldName.value],label:t[e.fieldName.label],disabled:e.isDisabled(t)}},[e._t("option",null,{item:t})],2)}))],2)},staticRenderFns:[]},l=r("VU/8")(o,c,!1,null,null,null);t.a=l.exports},"G5A+":function(e,t){},HhN8:function(e,t){!function(t){"use strict";var r,n=Object.prototype,i=n.hasOwnProperty,a="function"==typeof Symbol?Symbol:{},s=a.iterator||"@@iterator",o=a.asyncIterator||"@@asyncIterator",c=a.toStringTag||"@@toStringTag",l="object"==typeof e,u=t.regeneratorRuntime;if(u)l&&(e.exports=u);else{(u=t.regeneratorRuntime=l?e.exports:{}).wrap=_;var p="suspendedStart",h="suspendedYield",d="executing",f="completed",y={},v={};v[s]=function(){return this};var m=Object.getPrototypeOf,b=m&&m(m(C([])));b&&b!==n&&i.call(b,s)&&(v=b);var g=w.prototype=E.prototype=Object.create(v);x.prototype=g.constructor=w,w.constructor=x,w[c]=x.displayName="GeneratorFunction",u.isGeneratorFunction=function(e){var t="function"==typeof e&&e.constructor;return!!t&&(t===x||"GeneratorFunction"===(t.displayName||t.name))},u.mark=function(e){return Object.setPrototypeOf?Object.setPrototypeOf(e,w):(e.__proto__=w,c in e||(e[c]="GeneratorFunction")),e.prototype=Object.create(g),e},u.awrap=function(e){return{__await:e}},O($.prototype),$.prototype[o]=function(){return this},u.AsyncIterator=$,u.async=function(e,t,r,n){var i=new $(_(e,t,r,n));return u.isGeneratorFunction(t)?i:i.next().then(function(e){return e.done?e.value:i.next()})},O(g),g[c]="Generator",g[s]=function(){return this},g.toString=function(){return"[object Generator]"},u.keys=function(e){var t=[];for(var r in e)t.push(r);return t.reverse(),function r(){for(;t.length;){var n=t.pop();if(n in e)return r.value=n,r.done=!1,r}return r.done=!0,r}},u.values=C,I.prototype={constructor:I,reset:function(e){if(this.prev=0,this.next=0,this.sent=this._sent=r,this.done=!1,this.delegate=null,this.method="next",this.arg=r,this.tryEntries.forEach(R),!e)for(var t in this)"t"===t.charAt(0)&&i.call(this,t)&&!isNaN(+t.slice(1))&&(this[t]=r)},stop:function(){this.done=!0;var e=this.tryEntries[0].completion;if("throw"===e.type)throw e.arg;return this.rval},dispatchException:function(e){if(this.done)throw e;var t=this;function n(n,i){return o.type="throw",o.arg=e,t.next=n,i&&(t.method="next",t.arg=r),!!i}for(var a=this.tryEntries.length-1;a>=0;--a){var s=this.tryEntries[a],o=s.completion;if("root"===s.tryLoc)return n("end");if(s.tryLoc<=this.prev){var c=i.call(s,"catchLoc"),l=i.call(s,"finallyLoc");if(c&&l){if(this.prev=0;--r){var n=this.tryEntries[r];if(n.tryLoc<=this.prev&&i.call(n,"finallyLoc")&&this.prev=0;--t){var r=this.tryEntries[t];if(r.finallyLoc===e)return this.complete(r.completion,r.afterLoc),R(r),y}},catch:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var r=this.tryEntries[t];if(r.tryLoc===e){var n=r.completion;if("throw"===n.type){var i=n.arg;R(r)}return i}}throw new Error("illegal catch attempt")},delegateYield:function(e,t,n){return this.delegate={iterator:C(e),resultName:t,nextLoc:n},"next"===this.method&&(this.arg=r),y}}}function _(e,t,r,n){var i=t&&t.prototype instanceof E?t:E,a=Object.create(i.prototype),s=new I(n||[]);return a._invoke=function(e,t,r){var n=p;return function(i,a){if(n===d)throw new Error("Generator is already running");if(n===f){if("throw"===i)throw a;return A()}for(r.method=i,r.arg=a;;){var s=r.delegate;if(s){var o=S(s,r);if(o){if(o===y)continue;return o}}if("next"===r.method)r.sent=r._sent=r.arg;else if("throw"===r.method){if(n===p)throw n=f,r.arg;r.dispatchException(r.arg)}else"return"===r.method&&r.abrupt("return",r.arg);n=d;var c=k(e,t,r);if("normal"===c.type){if(n=r.done?f:h,c.arg===y)continue;return{value:c.arg,done:r.done}}"throw"===c.type&&(n=f,r.method="throw",r.arg=c.arg)}}}(e,r,s),a}function k(e,t,r){try{return{type:"normal",arg:e.call(t,r)}}catch(e){return{type:"throw",arg:e}}}function E(){}function x(){}function w(){}function O(e){["next","throw","return"].forEach(function(t){e[t]=function(e){return this._invoke(t,e)}})}function $(e){var t;this._invoke=function(r,n){function a(){return new Promise(function(t,a){!function t(r,n,a,s){var o=k(e[r],e,n);if("throw"!==o.type){var c=o.arg,l=c.value;return l&&"object"==typeof l&&i.call(l,"__await")?Promise.resolve(l.__await).then(function(e){t("next",e,a,s)},function(e){t("throw",e,a,s)}):Promise.resolve(l).then(function(e){c.value=e,a(c)},s)}s(o.arg)}(r,n,t,a)})}return t=t?t.then(a,a):a()}}function S(e,t){var n=e.iterator[t.method];if(n===r){if(t.delegate=null,"throw"===t.method){if(e.iterator.return&&(t.method="return",t.arg=r,S(e,t),"throw"===t.method))return y;t.method="throw",t.arg=new TypeError("The iterator does not provide a 'throw' method")}return y}var i=k(n,e.iterator,t.arg);if("throw"===i.type)return t.method="throw",t.arg=i.arg,t.delegate=null,y;var a=i.arg;return a?a.done?(t[e.resultName]=a.value,t.next=e.nextLoc,"return"!==t.method&&(t.method="next",t.arg=r),t.delegate=null,y):a:(t.method="throw",t.arg=new TypeError("iterator result is not an object"),t.delegate=null,y)}function T(e){var t={tryLoc:e[0]};1 in e&&(t.catchLoc=e[1]),2 in e&&(t.finallyLoc=e[2],t.afterLoc=e[3]),this.tryEntries.push(t)}function R(e){var t=e.completion||{};t.type="normal",delete t.arg,e.completion=t}function I(e){this.tryEntries=[{tryLoc:"root"}],e.forEach(T,this),this.reset(!0)}function C(e){if(e){var t=e[s];if(t)return t.call(e);if("function"==typeof e.next)return e;if(!isNaN(e.length)){var n=-1,a=function t(){for(;++n0&&void 0!==arguments[0]?arguments[0]:{};var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";var n=[];var i="";var a=c()({},r,{});var o={};s()(t).forEach(function(t){var s=h()(t,2),c=s[0],l=s[1];if("$resource"!==c){var p=l.format,d=l.enum,f=l.input,y=l.order,v=l.items,m=l.title,b=l.type,g=l.description,_=l.default;"object"===(void 0===m?"undefined":u()(m))&&(m=m[E]),"object"===(void 0===g?"undefined":u()(g))&&(g=g[E]);var k=_||"";w.includes(p)&&(k={url:"http://"}[p]);var x={placeholder:k=k.toString()};if((d||"boolean"===b)&&(b="emq-select",x.field=d?{options:d.map(function(e){return{value:e,label:e}})}:{options:[{label:!0,value:!0},{label:!1,value:!1}]}),"object"!==b||_||(_={}),"array"===b&&"object"===v.type){var $=v.schema;o=e($,"config"),_.length||(_=[])}"textarea"===f&&(x.type="textarea",x.rows=5),n.push({key:c,type:b,label:m||c,prop:c,defaultValue:_,$attrs:x,description:(g||"").replace(/\n/g,"
"),order:y,oneObjOfArray:o}),r?a[r][c]=O(t):a[c]=O(t)}else i="string"});n=n.sort(function(e,t){return e.order-t.order});return{model:n,rules:a,resource:i}},t.b=function(e){if("zh"===E)return _[e];return k[e]},t.d=function(e,t,r){return new i.a(function(n,i){try{var a=e.filter(function(e){if(e[t]){var n=e[t].toLowerCase().replace(/\s+/g,""),i=r.toLocaleLowerCase().replace(/\s+/g,"");return n.match(i)}return null});return n(a)}catch(e){return i(e)}})},t.g=function(e){var t=e.replace(/\"/g,""),r=null;return["message.publish","message.deliver","message.acked","message.dropped","client.connected","client.disconnected","client.subscribe","client.unsubscribe"].forEach(function(e){var n=e.split("."),i=h()(n,2),a=i[0],s=i[1],o=new RegExp(a+"\\."+s,"gim");t.match(o)&&(r=t.match(o))}),r},t.f=function(e,t){var r={"message.publish":"","message.deliver":"$events/message_delivered","message.acked":"$events/message_acked","message.dropped":"$events/message_dropped","client.connected":"$events/client_connected","client.disconnected":"$events/client_disconnected","client.subscribe":"$events/session_subscribed","client.unsubscribe":"$events/session_unsubscribed"}[t],n=e.replace(/\"/g,""),i=m.a.parse(n);""===r&&(i.value.where=null,r="#");return i.value.from.value[0].value.value.value='"'+r+'"',m.a.stringify(i)},t.a=function(e,t){var r=(t-e)%864e5,n=Math.floor(r/36e5),i=r%36e5,a=Math.floor(i/6e4),s=i%6e4,o=Math.round(s/1e3);return n+":"+a+":"+o},r.d(t,"h",function(){return S});var E=window.localStorage.language||window.EMQX_DASHBOARD_CONFIG.lang||"en",x={is_required:{en:"is required",zh:"必填"}},w=["string","number","boolean","method","regexp","integer","float","array","object","enum","date","url","hex","email"];function O(e){var t=h()(e,2),r=t[0],n=t[1],i=(n.type,n.format,n.required),a=(n.enum,n.title);"object"===(void 0===a?"undefined":u()(a))&&(a=a[E]);var s={};i&&(s.required=!0,s.message=(a||r)+" "+x.is_required[E])}function $(e,t){var r=new y.a(t.target,{text:function(){return e}});r.on("success",function(){d.default.prototype.$message({message:d.default.prototype.$t("oper.copySuccess"),type:"success",duration:1500}),r.destroy()}),r.on("error",function(){d.default.prototype.$message({message:d.default.prototype.$t("oper.copyFailed"),type:"error"}),r.destroy()}),r.onClick(t)}var S=function(e,t,r){t?t.length>64?r(new Error(d.default.prototype.$t("rule.id_len_tip"))):/^[0-9a-zA-Z_:]{1,64}$/.test(t)?r():r(new Error(d.default.prototype.$t("rule.id_char_tip"))):r(new Error("ID "+d.default.prototype.$t("rule.is_required")))}},SHGx:function(e,t,r){"use strict";var n=r("pFYg"),i=r.n(n),a=r("fZjL"),s=r.n(a),o=r("Dd8w"),c=r.n(o),l=r("FcGO"),u=r("d7EF"),p=r.n(u),h=r("W3Iv"),d=r.n(h),f=r("woOf"),y=r.n(f),v={name:"ArrayEditor",components:{EmqSelect:l.a},model:{prop:"value",event:"update"},props:{value:{type:Array,required:!0},notNull:{type:Boolean,default:!1},data:{type:Object,required:!0}},data:function(){return{tableData:[],headers:[],oneRow:{},defaultConfig:{}}},created:function(){this.initData()},methods:{assignValue:function(){var e=this;if(this.value.length){for(var t=0;t0&&void 0!==arguments[0])||arguments[0];this.$refs.record.validate(function(r){if(r){var n=e.record.config;s()(n).forEach(function(t){var r=n[t];"true"===r&&(e.record.config[t]=!0),"false"===r&&(e.record.config[t]=!1)});var i=t?"/resources":"/resources?test=true";e.$httpPost(i,e.record).then(function(r){t?(e.$message.success(e.$t("rule.create_success")),e.dialogVisible=!1,e.$emit("confirm",r.data)):e.$message.success(e.$t("rule.conf_test_success"))}).catch(function(){})}})},handleTypeChange:function(e){this.paramsList=[],this.resourceRules={};var t=this.resourceTypes.find(function(t){return t.name===e});if(t){var r=Object(g.e)(t.params,"config"),n=r.model,i=r.rules;this.resourceRules=i,this.paramsList=n,this.initRecord(),setTimeout(this.clearTabIndex,500)}},initRecord:function(){var e=this;0===this.paramsList.length?this.$set(this.record,"config",void 0):this.record.config||this.$set(this.record,"config",{}),this.$set(this.record,"config",{}),this.paramsList.forEach(function(t){e.$set(e.record.config,t.key,t.defaultValue)}),setTimeout(function(){e.$refs.record.clearValidate()},30)},loadResourceTypes:function(){var e=this;this.$httpGet("/resource_types").then(function(t){e.record={type:"",config:{},description:"",id:"resource:"+Math.random().toString().slice(3,9)},e.resourceType&&(e.record.type=e.resourceType),e.resourceTypes=t.data.map(function(e){return e.titleLabel="object"===i()(e.title)?e.title[_]:e.title,e}),e.handleTypeChange(e.record.type),setTimeout(function(){e.$refs.record.clearValidate()},30)})}}},E={render:function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("el-dialog",e._b({staticClass:"resource-dialog",attrs:{width:"700px",visible:e.dialogVisible,title:e.$t("rule.resource_mgmt")},on:{"update:visible":function(t){e.dialogVisible=t},close:e.close,open:e.loadResourceTypes}},"el-dialog",e.$attrs,!1),[r("el-form",{ref:"record",staticClass:"el-form--public",attrs:{model:e.record,rules:e.rules}},[r("el-row",{attrs:{gutter:20}},[r("el-col",{attrs:{span:12}},[r("el-form-item",{attrs:{prop:"type",label:e.$t("rule.resource_type")}},[r("el-select",{staticClass:"el-select--public",staticStyle:{width:"100%"},attrs:{"popper-class":"el-select--public",disabled:!!e.resourceType},on:{change:e.handleTypeChange},model:{value:e.record.type,callback:function(t){e.$set(e.record,"type",t)},expression:"record.type"}},e._l(e.resourceTypes,function(t,n){return r("div",{key:n},[0===e.enableItem.length||e.enableItem.includes(t.name)?r("el-option",{attrs:{label:t.titleLabel,value:t.name}}):e._e()],1)}),0)],1)],1),e._v(" "),r("el-col",{attrs:{span:12}},[r("el-form-item",[r("template",{slot:"label"},[e._v(" ")]),e._v(" "),r("el-button",{attrs:{type:"primary"},on:{click:function(t){return e.handleCreate(!1)}}},[e._v("\n "+e._s(e.$t("rule.conf_test"))+"\n ")])],2)],1),e._v(" "),e.record.type?[r("el-col",{attrs:{span:12}},[r("el-form-item",{attrs:{prop:"id",label:e.$t("rule.resource_id")}},[r("el-input",{model:{value:e.record.id,callback:function(t){e.$set(e.record,"id",t)},expression:"record.id"}})],1)],1),e._v(" "),r("el-col",{attrs:{span:12}},[r("el-form-item",{attrs:{prop:"description",label:e.$t("rule.resource_des")}},[r("el-input",{attrs:{type:"textarea"},model:{value:e.record.description,callback:function(t){e.$set(e.record,"description",t)},expression:"record.description"}})],1)],1),e._v(" "),e._l(e.paramsList,function(t,n){return r("el-col",{key:n,attrs:{span:"object"===t.type||"array"===t.type||"textarea"===t.$attrs.type?24:12}},[r("el-form-item",{attrs:{prop:"config."+t.prop}},[r("template",{slot:"label"},[e._v("\n "+e._s(t.label)+"\n\n "),t.description?r("el-popover",{attrs:{placement:"right",width:"200",trigger:"hover"}},[r("div",{domProps:{innerHTML:e._s(t.description)}}),e._v(" "),r("span",{staticClass:"el-icon-question",attrs:{slot:"reference",tabindex:"-1"},slot:"reference"})]):e._e()],1),e._v(" "),"object"===t.type?r("data-table",{model:{value:e.record.config[t.key],callback:function(r){e.$set(e.record.config,t.key,r)},expression:"record.config[item.key]"}}):"array"===t.type?[r("array-editor",{attrs:{data:t.oneObjOfArray},model:{value:e.record.config[t.key],callback:function(r){e.$set(e.record.config,t.key,r)},expression:"record.config[item.key]"}})]:"emq-select"===t.type?r("emq-select",e._b({staticClass:"el-select--public",attrs:{"popper-class":"el-select--public"},model:{value:e.record.config[t.key],callback:function(r){e.$set(e.record.config,t.key,r)},expression:"record.config[item.key]"}},"emq-select",t.$attrs,!1)):"number"===t.type?r("el-input",e._b({attrs:{type:"number"},model:{value:e.record.config[t.key],callback:function(r){e.$set(e.record.config,t.key,e._n(r))},expression:"record.config[item.key]"}},"el-input",t.$attrs,!1)):r("el-input",e._b({model:{value:e.record.config[t.key],callback:function(r){e.$set(e.record.config,t.key,r)},expression:"record.config[item.key]"}},"el-input",t.$attrs,!1))],2)],1)})]:e._e()],2)],1),e._v(" "),r("div",{attrs:{slot:"footer"},slot:"footer"},[r("el-button",{staticClass:"cache-btn",attrs:{type:"text"},on:{click:function(t){e.dialogVisible=!1}}},[e._v("\n "+e._s(e.$t("rule.cancel"))+"\n ")]),e._v(" "),r("el-button",{staticClass:"confirm-btn",attrs:{type:"success"},on:{click:e.handleCreate}},[e._v("\n "+e._s(e.$t("rule.create"))+"\n ")])],1)],1)},staticRenderFns:[]};var x=r("VU/8")(k,E,!1,function(e){r("G5A+")},null,null);t.a=x.exports},TQvf:function(e,t,r){ +/*! + * clipboard.js v2.0.6 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */ +var n;n=function(){return function(e){var t={};function r(n){if(t[n])return t[n].exports;var i=t[n]={i:n,l:!1,exports:{}};return e[n].call(i.exports,i,i.exports,r),i.l=!0,i.exports}return r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)r.d(n,i,function(t){return e[t]}.bind(null,i));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=6)}([function(e,t){e.exports=function(e){var t;if("SELECT"===e.nodeName)e.focus(),t=e.value;else if("INPUT"===e.nodeName||"TEXTAREA"===e.nodeName){var r=e.hasAttribute("readonly");r||e.setAttribute("readonly",""),e.select(),e.setSelectionRange(0,e.value.length),r||e.removeAttribute("readonly"),t=e.value}else{e.hasAttribute("contenteditable")&&e.focus();var n=window.getSelection(),i=document.createRange();i.selectNodeContents(e),n.removeAllRanges(),n.addRange(i),t=n.toString()}return t}},function(e,t){function r(){}r.prototype={on:function(e,t,r){var n=this.e||(this.e={});return(n[e]||(n[e]=[])).push({fn:t,ctx:r}),this},once:function(e,t,r){var n=this;function i(){n.off(e,i),t.apply(r,arguments)}return i._=t,this.on(e,i,r)},emit:function(e){for(var t=[].slice.call(arguments,1),r=((this.e||(this.e={}))[e]||[]).slice(),n=0,i=r.length;n0&&void 0!==arguments[0]?arguments[0]:{};this.action=e.action,this.container=e.container,this.emitter=e.emitter,this.target=e.target,this.text=e.text,this.trigger=e.trigger,this.selectedText=""}},{key:"initSelection",value:function(){this.text?this.selectFake():this.target&&this.selectTarget()}},{key:"selectFake",value:function(){var e=this,t="rtl"==document.documentElement.getAttribute("dir");this.removeFake(),this.fakeHandlerCallback=function(){return e.removeFake()},this.fakeHandler=this.container.addEventListener("click",this.fakeHandlerCallback)||!0,this.fakeElem=document.createElement("textarea"),this.fakeElem.style.fontSize="12pt",this.fakeElem.style.border="0",this.fakeElem.style.padding="0",this.fakeElem.style.margin="0",this.fakeElem.style.position="absolute",this.fakeElem.style[t?"right":"left"]="-9999px";var r=window.pageYOffset||document.documentElement.scrollTop;this.fakeElem.style.top=r+"px",this.fakeElem.setAttribute("readonly",""),this.fakeElem.value=this.text,this.container.appendChild(this.fakeElem),this.selectedText=i()(this.fakeElem),this.copyText()}},{key:"removeFake",value:function(){this.fakeHandler&&(this.container.removeEventListener("click",this.fakeHandlerCallback),this.fakeHandler=null,this.fakeHandlerCallback=null),this.fakeElem&&(this.container.removeChild(this.fakeElem),this.fakeElem=null)}},{key:"selectTarget",value:function(){this.selectedText=i()(this.target),this.copyText()}},{key:"copyText",value:function(){var e=void 0;try{e=document.execCommand(this.action)}catch(t){e=!1}this.handleResult(e)}},{key:"handleResult",value:function(e){this.emitter.emit(e?"success":"error",{action:this.action,text:this.selectedText,trigger:this.trigger,clearSelection:this.clearSelection.bind(this)})}},{key:"clearSelection",value:function(){this.trigger&&this.trigger.focus(),document.activeElement.blur(),window.getSelection().removeAllRanges()}},{key:"destroy",value:function(){this.removeFake()}},{key:"action",set:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"copy";if(this._action=e,"copy"!==this._action&&"cut"!==this._action)throw new Error('Invalid "action" value, use either "copy" or "cut"')},get:function(){return this._action}},{key:"target",set:function(e){if(void 0!==e){if(!e||"object"!==(void 0===e?"undefined":a(e))||1!==e.nodeType)throw new Error('Invalid "target" value, use a valid Element');if("copy"===this.action&&e.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if("cut"===this.action&&(e.hasAttribute("readonly")||e.hasAttribute("disabled")))throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes');this._target=e}},get:function(){return this._target}}]),e}(),c=r(1),l=r.n(c),u=r(2),p=r.n(u),h="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},d=function(){function e(e,t){for(var r=0;r0&&void 0!==arguments[0]?arguments[0]:{};this.action="function"==typeof e.action?e.action:this.defaultAction,this.target="function"==typeof e.target?e.target:this.defaultTarget,this.text="function"==typeof e.text?e.text:this.defaultText,this.container="object"===h(e.container)?e.container:document.body}},{key:"listenClick",value:function(e){var t=this;this.listener=p()(e,"click",function(e){return t.onClick(e)})}},{key:"onClick",value:function(e){var t=e.delegateTarget||e.currentTarget;this.clipboardAction&&(this.clipboardAction=null),this.clipboardAction=new o({action:this.action(t),target:this.target(t),text:this.text(t),container:this.container,trigger:t,emitter:this})}},{key:"defaultAction",value:function(e){return y("action",e)}},{key:"defaultTarget",value:function(e){var t=y("target",e);if(t)return document.querySelector(t)}},{key:"defaultText",value:function(e){return y("text",e)}},{key:"destroy",value:function(){this.listener.destroy(),this.clipboardAction&&(this.clipboardAction.destroy(),this.clipboardAction=null)}}],[{key:"isSupported",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:["copy","cut"],t="string"==typeof e?[e]:e,r=!!document.queryCommandSupported;return t.forEach(function(e){r=r&&!!document.queryCommandSupported(e)}),r}}]),t}();function y(e,t){var r="data-clipboard-"+e;if(t.hasAttribute(r))return t.getAttribute(r)}t.default=f}]).default},e.exports=n()},Xxa5:function(e,t,r){e.exports=r("1H6C")},cMrt:function(e,t){e.exports={en:{emqx_auth_clientid:"https://docs.emqx.io/broker/v4.1/en/advanced/auth-clientid.html",emqx_auth_username:"https://docs.emqx.io/broker/v4.1/en/advanced/auth-username.html",emqx_auth_http:"https://docs.emqx.io/broker/v4.1/en/advanced/auth-http.html",emqx_auth_jwt:"https://docs.emqx.io/broker/v4.1/en/advanced/auth-jwt.html",emqx_auth_ldap:"https://docs.emqx.io/broker/v4.1/en/advanced/auth-ldap.html",emqx_auth_mnesia:"https://docs.emqx.io/broker/v4.1/en/advanced/auth-mnesia.html",emqx_auth_mongo:"https://docs.emqx.io/broker/v4.1/en/advanced/auth-mongodb.html",emqx_auth_mysql:"https://docs.emqx.io/broker/v4.1/en/advanced/auth-mysql.html",emqx_auth_pgsql:"https://docs.emqx.io/broker/v4.1/en/advanced/auth-postgresql.html",emqx_auth_redis:"https://docs.emqx.io/broker/v4.1/en/advanced/auth-redis.html",emqx_dashboard:"https://docs.emqx.io/broker/v4.1/en/getting-started/dashboard.html",emqx_extension_hook:"https://docs.emqx.io/broker/v4.1/en/advanced/multiple-language-support.html",emqx_rule_engine:"https://docs.emqx.io/broker/v4.1/en/rule/rule-engine.html"},zh:{emqx_auth_clientid:"https://docs.emqx.io/broker/v4.1/cn/advanced/auth-clientid.html",emqx_auth_username:"https://docs.emqx.io/broker/v4.1/cn/advanced/auth-username.html",emqx_auth_http:"https://docs.emqx.io/broker/v4.1/cn/advanced/auth-http.html",emqx_auth_jwt:"https://docs.emqx.io/broker/v4.1/cn/advanced/auth-jwt.html",emqx_auth_ldap:"https://docs.emqx.io/broker/v4.1/cn/advanced/auth-ldap.html",emqx_auth_mnesia:"https://docs.emqx.io/broker/v4.1/cn/advanced/auth-mnesia.html",emqx_auth_mongo:"https://docs.emqx.io/broker/v4.1/cn/advanced/auth-mongodb.html",emqx_auth_mysql:"https://docs.emqx.io/broker/v4.1/cn/advanced/auth-mysql.html",emqx_auth_pgsql:"https://docs.emqx.io/broker/v4.1/cn/advanced/auth-postgresql.html",emqx_auth_redis:"https://docs.emqx.io/broker/v4.1/cn/advanced/auth-redis.html",emqx_dashboard:"https://docs.emqx.io/broker/v4.1/cn/getting-started/dashboard.html",emqx_extension_hook:"https://docs.emqx.io/broker/v4.1/cn/advanced/multiple-language-support.html",emqx_rule_engine:"https://docs.emqx.io/broker/v4.1/cn/rule/rule-engine.html"}}},dmxg:function(e,t,r){var n,i=function(){var e=function(e,t,r,n){for(r=r||{},n=e.length;n--;r[e[n]]=t);return r},t=[1,8],r=[1,4],n=[2,4],i=[1,11],a=[1,10],s=[2,16],o=[1,14],c=[1,15],l=[1,16],u=[6,8],p=[2,144],h=[1,19],d=[1,20],f=[16,33,35,36,37,38,39,40,41,42,45,46,50,52,53,55,56,58,59,61,76,79,81,82,83,84,86,87,88,101],y=[16,18,32,33,35,36,37,38,39,40,41,42,45,46,50,52,53,55,56,58,59,61,76,79,81,82,83,84,86,87,88,101],v=[2,158],m=[1,29],b=[6,8,14,17,146,150,152,154],g=[1,42],_=[1,60],k=[1,51],E=[1,58],x=[1,59],w=[1,61],O=[1,62],$=[1,63],S=[1,64],T=[1,65],R=[1,57],I=[1,52],C=[1,53],A=[1,54],L=[1,55],N=[1,56],q=[1,43],F=[1,44],K=[1,45],P=[1,34],D=[16,35,36,37,38,39,40,41,42,45,46,50,52,53,55,56,58,59,61,76,79,81,82,83,84,86,87,88,101],j=[6,8,14,17,150,152,154],B=[2,141],U=[1,74],H=[1,75],M=[6,8,14,17,43,133,138,144,146,150,152,154],G=[1,80],V=[1,77],Q=[1,78],W=[1,79],X=[1,81],J=[6,8,14,17,36,43,49,50,71,72,74,77,89,107,124,125,126,127,129,133,135,138,141,142,144,146,150,152,154,157,164,165,167,168,173,177,179,180,182],z=[6,8,14,17,34,36,43,49,50,71,72,74,77,89,107,112,113,114,115,116,117,121,124,125,126,127,129,133,135,138,141,142,144,146,150,152,154,157,164,165,167,168,173,177,179,180,182],Y=[1,102],Z=[1,100],ee=[1,101],te=[1,96],re=[1,97],ne=[1,98],ie=[1,99],ae=[1,103],se=[1,104],oe=[1,105],ce=[1,106],le=[1,107],ue=[1,108],pe=[2,101],he=[6,8,14,17,34,36,43,45,49,50,71,72,74,77,79,81,89,91,92,93,94,95,96,97,98,99,101,105,106,107,108,109,110,112,113,114,115,116,117,121,124,125,126,127,129,133,135,138,141,142,144,146,150,152,154,157,164,165,167,168,173,177,179,180,182],de=[6,8,14,17,34,36,43,45,49,50,71,72,74,77,79,81,89,91,92,93,94,95,96,97,98,99,101,103,105,106,107,108,109,110,112,113,114,115,116,117,121,124,125,126,127,129,133,135,138,141,142,144,146,150,152,154,157,164,165,167,168,173,177,179,180,182],fe=[1,109],ye=[1,116],ve=[2,62],me=[1,117],be=[16,35,37,38,39,40,41,42,45,46,50,52,53,55,56,58,59,61,76,79,81,82,83,84,86,87,88,101],ge=[16,29,35,50,52,53,55,56,58,59,61,76,79,81,82,83,84,86,87,88,119],_e=[1,163],ke=[17,43],Ee=[2,57],xe=[1,172],we=[1,170],Oe=[1,171],$e=[6,8,138,146],Se=[16,35,38,39,40,41,42,45,46,50,52,53,55,56,58,59,61,76,79,81,82,83,84,86,87,88,101],Te=[6,8,14,17,138,144,146,150,152,154],Re=[6,8,14,17,36,43,49,50,71,72,74,77,89,125,126,127,129,133,135,138,141,142,144,146,150,152,154,157,164,165,167,168,173,177,179,180,182],Ie=[6,8,14,17,34,36,43,49,50,71,72,74,77,89,91,92,93,94,99,101,105,106,107,108,109,110,112,113,114,115,116,117,121,124,125,126,127,129,133,135,138,141,142,144,146,150,152,154,157,164,165,167,168,173,177,179,180,182],Ce=[6,8,14,17,34,36,43,49,50,71,72,74,77,79,81,89,91,92,93,94,99,101,105,106,107,108,109,110,112,113,114,115,116,117,121,124,125,126,127,129,133,135,138,141,142,144,146,150,152,154,157,164,165,167,168,173,177,179,180,182],Ae=[16,35,39,40,41,42,45,46,50,52,53,55,56,58,59,61,76,79,81,82,83,84,86,87,88,101],Le=[16,35,40,41,42,45,46,50,52,53,55,56,58,59,61,76,79,81,82,83,84,86,87,88,101],Ne=[16,35,42,45,46,50,52,53,55,56,58,59,61,76,79,81,82,83,84,86,87,88,101],qe=[71,74,77],Fe=[16,35,45,46,50,52,53,55,56,58,59,61,76,79,81,82,83,84,86,87,88,101],Ke=[1,232],Pe=[1,233],De=[6,8,14,17],je=[6,8,14,17,43,157],Be=[1,249],Ue=[1,245],He=[2,195],Me=[1,252],Ge=[1,253],Ve=[6,8,14,17,43,129,135,138,144,146,150,152,154,182],Qe=[1,255],We=[1,258],Xe=[1,259],Je=[1,260],ze=[1,261],Ye=[2,172],Ze=[1,257],et=[6,8,14,17,36,43,89,129,135,138,144,146,150,152,154,164,165,167,168,173,177,179,180,182],tt=[6,8,14,17,135,138,144,146,150,152,154],rt=[1,273],nt=[2,177],it=[170,173],at=[6,8,14,17,36,43,89,129,135,138,144,146,150,152,154,164,165,167,168,173,177,179,180,182,192,193,194],st=[2,197],ot=[1,278],ct=[1,290],lt=[1,298],ut=[1,299],pt=[1,300],ht=[6,8,14,17,138,146,150,152,154],dt=[1,310],ft=[1,316],yt=[1,317],vt=[2,202],mt=[1,328],bt=[16,152],gt=[6,8,14,17,152,154],_t=[1,344],kt={trace:function(){},yy:{},symbols_:{error:2,main:3,selectClause:4,semicolonOpt:5,EOF:6,unionClause:7,";":8,unionClauseNotParenthesized:9,unionClauseParenthesized:10,order_by_opt:11,limit_opt:12,selectClauseParenthesized:13,UNION:14,distinctOpt:15,"(":16,")":17,SELECT:18,highPriorityOpt:19,maxStateMentTimeOpt:20,straightJoinOpt:21,sqlSmallResultOpt:22,sqlBigResultOpt:23,sqlBufferResultOpt:24,sqlCacheOpt:25,sqlCalcFoundRowsOpt:26,selectExprList:27,selectDataSetOpt:28,ALL:29,DISTINCT:30,DISTINCTROW:31,HIGH_PRIORITY:32,MAX_STATEMENT_TIME:33,"=":34,NUMERIC:35,STRAIGHT_JOIN:36,SQL_SMALL_RESULT:37,SQL_BIG_RESULT:38,SQL_BUFFER_RESULT:39,SQL_CACHE:40,SQL_NO_CACHE:41,SQL_CALC_FOUND_ROWS:42,",":43,selectExpr:44,"*":45,SELECT_EXPR_STAR:46,expr:47,selectExprAliasOpt:48,AS:49,IDENTIFIER:50,string:51,QUOTED_IDENTIFIER:52,STRING:53,number:54,EXPONENT_NUMERIC:55,HEX_NUMERIC:56,boolean:57,TRUE:58,FALSE:59,null:60,NULL:61,literal:62,function_call:63,function_call_param_list:64,function_call_param:65,identifier:66,DOT:67,identifier_list:68,case_expr_opt:69,when_then_list:70,WHEN:71,THEN:72,case_when_else:73,ELSE:74,case_when:75,CASE:76,END:77,simple_expr_prefix:78,"+":79,simple_expr:80,"-":81,"~":82,"!":83,BINARY:84,expr_list:85,ROW:86,EXISTS:87,"{":88,"}":89,bit_expr:90,"|":91,"&":92,"<<":93,">>":94,"/":95,DIV:96,MOD:97,"%":98,"^":99,not_opt:100,NOT:101,escape_opt:102,ESCAPE:103,predicate:104,IN:105,BETWEEN:106,AND:107,SOUNDS:108,LIKE:109,REGEXP:110,comparison_operator:111,">=":112,">":113,"<=":114,"<":115,"<>":116,"!=":117,sub_query_data_set_opt:118,ANY:119,boolean_primary:120,IS:121,boolean_extra:122,UNKNOWN:123,"&&":124,"||":125,OR:126,XOR:127,where_opt:128,WHERE:129,group_by_opt:130,group_by:131,roll_up_opt:132,WITH:133,ROLLUP:134,GROUP_BY:135,group_by_order_by_item_list:136,order_by:137,ORDER_BY:138,group_by_order_by_item:139,sort_opt:140,ASC:141,DESC:142,having_opt:143,HAVING:144,limit:145,LIMIT:146,OFFSET:147,procedure_opt:148,procedure:149,PROCEDURE:150,for_update_lock_in_share_mode_opt:151,FOR:152,UPDATE:153,LOCK:154,SHARE:155,MODE:156,FROM:157,table_references:158,partitionOpt:159,escaped_table_reference:160,table_reference:161,OJ:162,join_inner_cross:163,INNER:164,CROSS:165,left_right:166,LEFT:167,RIGHT:168,out_opt:169,OUTER:170,left_right_out_opt:171,join_table:172,JOIN:173,table_factor:174,join_condition:175,on_join_condition:176,NATURAL:177,join_condition_opt:178,ON:179,USING:180,partition_names:181,PARTITION:182,aliasOpt:183,index_or_key:184,INDEX:185,KEY:186,for_opt:187,identifier_list_opt:188,index_hint_list_opt:189,index_hint_list:190,index_hint:191,USE:192,IGNORE:193,FORCE:194,$accept:0,$end:1},terminals_:{2:"error",6:"EOF",8:";",14:"UNION",16:"(",17:")",18:"SELECT",29:"ALL",30:"DISTINCT",31:"DISTINCTROW",32:"HIGH_PRIORITY",33:"MAX_STATEMENT_TIME",34:"=",35:"NUMERIC",36:"STRAIGHT_JOIN",37:"SQL_SMALL_RESULT",38:"SQL_BIG_RESULT",39:"SQL_BUFFER_RESULT",40:"SQL_CACHE",41:"SQL_NO_CACHE",42:"SQL_CALC_FOUND_ROWS",43:",",45:"*",46:"SELECT_EXPR_STAR",49:"AS",50:"IDENTIFIER",52:"QUOTED_IDENTIFIER",53:"STRING",55:"EXPONENT_NUMERIC",56:"HEX_NUMERIC",58:"TRUE",59:"FALSE",61:"NULL",67:"DOT",71:"WHEN",72:"THEN",74:"ELSE",76:"CASE",77:"END",79:"+",81:"-",82:"~",83:"!",84:"BINARY",86:"ROW",87:"EXISTS",88:"{",89:"}",91:"|",92:"&",93:"<<",94:">>",95:"/",96:"DIV",97:"MOD",98:"%",99:"^",101:"NOT",103:"ESCAPE",105:"IN",106:"BETWEEN",107:"AND",108:"SOUNDS",109:"LIKE",110:"REGEXP",112:">=",113:">",114:"<=",115:"<",116:"<>",117:"!=",119:"ANY",121:"IS",123:"UNKNOWN",124:"&&",125:"||",126:"OR",127:"XOR",129:"WHERE",133:"WITH",134:"ROLLUP",135:"GROUP_BY",138:"ORDER_BY",141:"ASC",142:"DESC",144:"HAVING",146:"LIMIT",147:"OFFSET",150:"PROCEDURE",152:"FOR",153:"UPDATE",154:"LOCK",155:"SHARE",156:"MODE",157:"FROM",162:"OJ",164:"INNER",165:"CROSS",167:"LEFT",168:"RIGHT",170:"OUTER",173:"JOIN",177:"NATURAL",179:"ON",180:"USING",182:"PARTITION",185:"INDEX",186:"KEY",192:"USE",193:"IGNORE",194:"FORCE"},productions_:[0,[3,3],[3,3],[5,1],[5,0],[7,1],[7,3],[10,4],[10,4],[13,3],[9,4],[9,4],[4,12],[15,1],[15,1],[15,1],[15,0],[19,1],[19,0],[20,3],[20,0],[21,1],[21,0],[22,1],[22,0],[23,1],[23,0],[24,1],[24,0],[25,0],[25,1],[25,1],[26,1],[26,0],[27,3],[27,1],[44,1],[44,1],[44,2],[48,0],[48,2],[48,1],[51,1],[51,1],[54,1],[54,1],[54,1],[57,1],[57,1],[60,1],[62,1],[62,1],[62,1],[62,1],[63,4],[64,3],[64,1],[65,0],[65,1],[65,1],[65,2],[65,1],[66,1],[66,3],[68,1],[68,3],[69,0],[69,1],[70,4],[70,5],[73,0],[73,2],[75,5],[78,2],[78,2],[78,2],[78,2],[78,2],[80,1],[80,1],[80,1],[80,1],[80,3],[80,4],[80,3],[80,4],[80,4],[80,1],[90,1],[90,3],[90,3],[90,3],[90,3],[90,3],[90,3],[90,3],[90,3],[90,3],[90,3],[90,3],[90,3],[100,0],[100,1],[102,0],[102,2],[104,1],[104,6],[104,6],[104,6],[104,4],[104,5],[104,4],[111,1],[111,1],[111,1],[111,1],[111,1],[111,1],[111,1],[118,1],[118,1],[120,1],[120,4],[120,3],[120,6],[122,1],[122,1],[47,1],[47,4],[47,2],[47,3],[47,3],[47,3],[47,3],[47,3],[85,1],[85,3],[128,0],[128,2],[130,0],[130,1],[132,0],[132,2],[131,3],[11,0],[11,1],[137,3],[136,1],[136,3],[139,2],[140,0],[140,1],[140,1],[143,0],[143,2],[145,2],[145,4],[145,4],[12,0],[12,1],[148,0],[148,1],[149,2],[151,0],[151,2],[151,4],[28,0],[28,10],[158,1],[158,3],[160,1],[160,4],[163,0],[163,1],[163,1],[166,1],[166,1],[169,0],[169,1],[171,0],[171,2],[172,4],[172,5],[172,4],[172,6],[172,5],[178,0],[178,1],[176,2],[175,1],[175,4],[161,1],[161,1],[181,1],[181,3],[159,0],[159,4],[183,0],[183,2],[183,1],[184,1],[184,1],[187,0],[187,2],[187,2],[187,2],[188,0],[188,1],[189,0],[189,1],[190,1],[190,3],[191,6],[191,6],[191,6],[174,4],[174,4],[174,3]],performAction:function(e,t,r,n,i,a,s){var o=a.length-1;switch(i){case 1:case 2:return{nodeType:"Main",value:a[o-2],hasSemicolon:a[o-1]};case 3:case 142:this.$=!0;break;case 4:this.$=!1;break;case 5:case 13:case 14:case 15:case 17:case 19:case 21:case 23:case 25:case 27:case 30:case 31:case 32:case 50:case 51:case 52:case 53:case 58:case 59:case 61:case 67:case 71:case 78:case 79:case 80:case 81:case 87:case 88:case 102:case 104:case 105:case 112:case 113:case 114:case 115:case 116:case 117:case 118:case 119:case 120:case 121:case 125:case 127:case 138:case 140:case 145:case 151:case 152:case 154:case 159:case 161:case 162:case 173:case 174:case 175:case 176:case 178:case 187:case 189:case 191:case 192:case 200:case 201:case 207:case 209:this.$=a[o];break;case 6:this.$=a[o-2],this.$.orderBy=a[o-1],this.$.limit=a[o];break;case 7:case 8:this.$={type:"Union",left:a[o-3],distinctOpt:a[o-1],right:a[o]};break;case 9:this.$={type:"SelectParenthesized",value:a[o-1]};break;case 10:case 11:this.$={type:"Union",left:a[o-3],distinctOpt:a[o-1],right:a[o]};break;case 12:this.$={type:"Select",distinctOpt:a[o-10],highPriorityOpt:a[o-9],maxStateMentTimeOpt:a[o-8],straightJoinOpt:a[o-7],sqlSmallResultOpt:a[o-6],sqlBigResultOpt:a[o-5],sqlBufferResultOpt:a[o-4],sqlCacheOpt:a[o-3],sqlCalcFoundRowsOpt:a[o-2],selectItems:a[o-1],from:a[o].from,partition:a[o].partition,where:a[o].where,groupBy:a[o].groupBy,having:a[o].having,orderBy:a[o].orderBy,limit:a[o].limit,procedure:a[o].procedure,updateLockMode:a[o].updateLockMode};break;case 16:case 18:case 20:case 22:case 24:case 26:case 28:case 29:case 33:case 57:case 66:case 70:case 101:case 103:case 137:case 139:case 141:case 144:case 150:case 153:case 158:case 160:case 163:case 172:case 177:case 186:case 195:case 202:case 206:case 208:this.$=null;break;case 34:a[o-2].value.push(a[o]);break;case 35:this.$={type:"SelectExpr",value:[a[o]]};break;case 36:case 37:case 62:this.$={type:"Identifier",value:a[o]};break;case 38:this.$=a[o-1],this.$.alias=a[o].alias,this.$.hasAs=a[o].hasAs;break;case 39:case 197:this.$={alias:null,hasAs:null};break;case 40:this.$={alias:a[o],hasAs:!0};break;case 41:this.$={alias:a[o],hasAs:!1};break;case 42:case 43:this.$={type:"String",value:a[o]};break;case 44:case 45:case 46:this.$={type:"Number",value:a[o]};break;case 47:this.$={type:"Boolean",value:"TRUE"};break;case 48:this.$={type:"Boolean",value:"FALSE"};break;case 49:this.$={type:"Null",value:"null"};break;case 54:this.$={type:"FunctionCall",name:a[o-3],params:a[o-1]};break;case 55:a[o-2].push(a[o]),this.$=a[o-2];break;case 56:this.$=[a[o]];break;case 60:this.$={type:"FunctionCallParam",distinctOpt:a[o-1],value:a[o]};break;case 63:this.$=a[o-2],a[o-2].value+="."+a[o];break;case 64:this.$={type:"IdentifierList",value:[a[o]]};break;case 65:case 169:this.$=a[o-2],a[o-2].value.push(a[o]);break;case 68:this.$={type:"WhenThenList",value:[{when:a[o-2],then:a[o]}]};break;case 69:this.$=a[o-4],this.$.value.push({when:a[o-2],then:a[o]});break;case 72:this.$={type:"CaseWhen",caseExprOpt:a[o-3],whenThenList:a[o-2],else:a[o-1]};break;case 73:case 74:case 75:case 76:case 77:this.$={type:"Prefix",prefix:a[o-1],value:a[o]};break;case 82:this.$={type:"SimpleExprParentheses",value:a[o-1]};break;case 83:this.$={type:"SimpleExprParentheses",value:a[o-2],hasRow:!0};break;case 84:this.$={type:"SubQuery",value:a[o-1]};break;case 85:this.$={type:"SubQuery",value:a[o-1],hasExists:!0};break;case 86:this.$={type:"IdentifierExpr",identifier:a[o-2],value:a[o-1]};break;case 89:this.$={type:"BitExpression",operator:"|",left:a[o-2],right:a[o]};break;case 90:this.$={type:"BitExpression",operator:"&",left:a[o-2],right:a[o]};break;case 91:this.$={type:"BitExpression",operator:"<<",left:a[o-2],right:a[o]};break;case 92:this.$={type:"BitExpression",operator:">>",left:a[o-2],right:a[o]};break;case 93:this.$={type:"BitExpression",operator:"+",left:a[o-2],right:a[o]};break;case 94:this.$={type:"BitExpression",operator:"-",left:a[o-2],right:a[o]};break;case 95:this.$={type:"BitExpression",operator:"*",left:a[o-2],right:a[o]};break;case 96:this.$={type:"BitExpression",operator:"/",left:a[o-2],right:a[o]};break;case 97:this.$={type:"BitExpression",operator:"DIV",left:a[o-2],right:a[o]};break;case 98:this.$={type:"BitExpression",operator:"MOD",left:a[o-2],right:a[o]};break;case 99:this.$={type:"BitExpression",operator:"%",left:a[o-2],right:a[o]};break;case 100:this.$={type:"BitExpression",operator:"^",left:a[o-2],right:a[o]};break;case 106:this.$={type:"InSubQueryPredicate",hasNot:a[o-4],left:a[o-5],right:a[o-1]};break;case 107:this.$={type:"InExpressionListPredicate",hasNot:a[o-4],left:a[o-5],right:a[o-1]};break;case 108:this.$={type:"BetweenPredicate",hasNot:a[o-4],left:a[o-5],right:{left:a[o-2],right:a[o]}};break;case 109:this.$={type:"SoundsLikePredicate",hasNot:!1,left:a[o-3],right:a[o]};break;case 110:this.$={type:"LikePredicate",hasNot:a[o-3],left:a[o-4],right:a[o-1],escape:a[o]};break;case 111:this.$={type:"RegexpPredicate",hasNot:a[o-2],left:a[o-3],right:a[o]};break;case 122:this.$={type:"IsNullBooleanPrimary",hasNot:a[o-1],value:a[o-3]};break;case 123:this.$={type:"ComparisonBooleanPrimary",left:a[o-2],operator:a[o-1],right:a[o]};break;case 124:this.$={type:"ComparisonSubQueryBooleanPrimary",operator:a[o-4],subQueryOpt:a[o-3],left:a[o-5],right:a[o-1]};break;case 126:this.$={type:"BooleanExtra",value:a[o]};break;case 128:this.$={type:"IsExpression",hasNot:a[o-1],left:a[o-3],right:a[o]};break;case 129:this.$={type:"NotExpression",value:a[o]};break;case 130:case 133:this.$={type:"AndExpression",operator:a[o-1],left:a[o-2],right:a[o]};break;case 131:case 132:this.$={type:"OrExpression",operator:a[o-1],left:a[o-2],right:a[o]};break;case 134:this.$={type:"XORExpression",left:a[o-2],right:a[o]};break;case 135:this.$={type:"ExpressionList",value:[a[o]]};break;case 136:case 211:this.$=a[o-2],this.$.value.push(a[o]);break;case 143:this.$={type:"GroupBy",value:a[o-1],rollUp:a[o]};break;case 146:this.$={type:"OrderBy",value:a[o-1],rollUp:a[o]};break;case 147:case 193:this.$=[a[o]];break;case 148:this.$=a[o-2],a[o-2].push(a[o]);break;case 149:this.$={type:"GroupByOrderByItem",value:a[o-1],sortOpt:a[o]};break;case 155:this.$={type:"Limit",value:[a[o]]};break;case 156:this.$={type:"Limit",value:[a[o-2],a[o]]};break;case 157:this.$={type:"Limit",value:[a[o],a[o-2]],offsetMode:!0};break;case 164:this.$=a[o-1]+" "+a[o];break;case 165:this.$=a[o-3]+" "+a[o-2]+" "+a[o-1]+" "+a[o];break;case 166:this.$={};break;case 167:this.$={from:a[o-8],partition:a[o-7],where:a[o-6],groupBy:a[o-5],having:a[o-4],orderBy:a[o-3],limit:a[o-2],procedure:a[o-1],updateLockMode:a[o]};break;case 168:this.$={type:"TableReferences",value:[a[o]]};break;case 170:this.$={type:"TableReference",value:a[o]};break;case 171:this.$={type:"TableReference",hasOj:!0,value:a[o-1]};break;case 179:this.$={leftRight:null,outOpt:null};break;case 180:this.$={leftRight:a[o-1],outOpt:a[o]};break;case 181:this.$={type:"InnerCrossJoinTable",innerCrossOpt:a[o-2],left:a[o-3],right:a[o],condition:null};break;case 182:this.$={type:"InnerCrossJoinTable",innerCrossOpt:a[o-3],left:a[o-4],right:a[o-1],condition:a[o]};break;case 183:this.$={type:"StraightJoinTable",left:a[o-3],right:a[o-1],condition:a[o]};break;case 184:this.$={type:"LeftRightJoinTable",leftRight:a[o-4],outOpt:a[o-3],left:a[o-5],right:a[o-1],condition:a[o]};break;case 185:this.$={type:"NaturalJoinTable",leftRight:a[o-2].leftRight,outOpt:a[o-2].outOpt,left:a[o-4],right:a[o]};break;case 188:this.$={type:"OnJoinCondition",value:a[o]};break;case 190:this.$={type:"UsingJoinCondition",value:a[o-1]};break;case 194:this.$=a[o-2],a[o-2].push(a[o]);break;case 196:this.$={type:"Partitions",value:a[o-1]};break;case 198:this.$={hasAs:!0,alias:a[o]};break;case 199:this.$={hasAs:!1,alias:a[o]};break;case 203:case 204:case 205:this.$={type:"ForOptIndexHint",value:a[o]};break;case 210:this.$={type:"IndexHintList",value:[a[o]]};break;case 212:this.$={type:"UseIndexHint",value:a[o-1],forOpt:a[o-3],indexOrKey:a[o-4]};break;case 213:this.$={type:"IgnoreIndexHint",value:a[o-1],forOpt:a[o-3],indexOrKey:a[o-4]};break;case 214:this.$={type:"ForceIndexHint",value:a[o-1],forOpt:a[o-3],indexOrKey:a[o-4]};break;case 215:this.$={type:"TableFactor",value:a[o-3],partition:a[o-2],alias:a[o-1].alias,hasAs:a[o-1].hasAs,indexHintOpt:a[o]};break;case 216:this.$={type:"SubQuery",value:a[o-2],alias:a[o].alias,hasAs:a[o].hasAs};break;case 217:this.$=a[o-1],this.$.hasParentheses=!0}},table:[{3:1,4:2,7:3,9:5,10:6,13:7,16:t,18:r},{1:[3]},{5:9,6:n,8:i,14:a},{5:12,6:n,8:i},e([16,32,33,35,36,37,38,39,40,41,42,45,46,50,52,53,55,56,58,59,61,76,79,81,82,83,84,86,87,88,101],s,{15:13,29:o,30:c,31:l}),e(u,[2,5]),e([6,8,146],p,{11:17,137:18,138:h}),{14:d},{4:21,18:r},{6:[1,22]},{15:23,18:s,29:o,30:c,31:l},{6:[2,3]},{6:[1,24]},e(f,[2,18],{19:25,32:[1,26]}),e(y,[2,13]),e(y,[2,14]),e(y,[2,15]),e(u,v,{12:27,145:28,146:m}),e(b,[2,145]),{16:g,35:_,47:32,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33,136:30,139:31},{15:66,16:s,29:o,30:c,31:l},{17:[1,67]},{1:[2,1]},{4:68,9:69,18:r},{1:[2,2]},e(D,[2,20],{20:70,33:[1,71]}),e(f,[2,17]),e(u,[2,6]),e(j,[2,159]),{35:[1,72]},e(b,B,{132:73,43:U,133:H}),e(M,[2,147]),e(M,[2,150],{140:76,107:G,124:V,125:Q,126:W,127:X,141:[1,82],142:[1,83]}),e(J,[2,127],{111:85,34:[1,86],112:[1,87],113:[1,88],114:[1,89],115:[1,90],116:[1,91],117:[1,92],121:[1,84]}),{16:g,35:_,47:93,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},e(z,[2,121]),e(z,[2,105],{100:94,45:Y,79:Z,81:ee,91:te,92:re,93:ne,94:ie,95:ae,96:se,97:oe,98:ce,99:le,101:ue,105:pe,106:pe,109:pe,110:pe,108:[1,95]}),e(he,[2,88]),e(de,[2,78]),e(de,[2,79],{67:fe}),e(de,[2,80]),e(de,[2,81]),{4:111,16:g,18:r,35:_,47:112,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,85:110,86:q,87:F,88:K,90:36,101:P,104:35,120:33},{16:[1,113]},{16:[1,114]},{50:ye,66:115},e(de,[2,87]),e(de,[2,50]),e(de,[2,51]),e(de,[2,52]),e(de,[2,53]),e([6,8,14,17,34,36,43,45,49,50,67,71,72,74,77,79,81,89,91,92,93,94,95,96,97,98,99,101,103,105,106,107,108,109,110,112,113,114,115,116,117,121,124,125,126,127,129,133,135,138,141,142,144,146,150,152,154,157,164,165,167,168,173,177,179,180,182],ve,{16:me}),{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:118,81:C,82:A,83:L,84:N,86:q,87:F,88:K},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:119,81:C,82:A,83:L,84:N,86:q,87:F,88:K},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:120,81:C,82:A,83:L,84:N,86:q,87:F,88:K},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:121,81:C,82:A,83:L,84:N,86:q,87:F,88:K},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:122,81:C,82:A,83:L,84:N,86:q,87:F,88:K},{16:g,35:_,47:124,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,69:123,71:[2,66],75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},e(de,[2,42]),e(de,[2,43]),e(de,[2,44]),e(de,[2,45]),e(de,[2,46]),e(de,[2,47]),e(de,[2,48]),e(de,[2,49]),{10:126,13:125,16:t},e([6,8,14,138,146],[2,9]),e(u,[2,10],{14:a}),e(u,[2,11]),e(be,[2,22],{21:127,36:[1,128]}),{34:[1,129]},e(j,[2,155],{43:[1,130],147:[1,131]}),e(b,[2,146]),{16:g,35:_,47:32,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33,139:132},{134:[1,133]},e(M,[2,149]),{16:g,35:_,47:134,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},{16:g,35:_,47:135,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},{16:g,35:_,47:136,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},{16:g,35:_,47:137,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},{16:g,35:_,47:138,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},e(M,[2,151]),e(M,[2,152]),e([58,59,61,123],pe,{100:139,101:ue}),{16:g,29:[1,142],35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,104:140,118:141,119:[1,143]},e(ge,[2,112]),e(ge,[2,113]),e(ge,[2,114]),e(ge,[2,115]),e(ge,[2,116]),e(ge,[2,117]),e(ge,[2,118]),e(J,[2,129]),{105:[1,144],106:[1,145],109:[1,146],110:[1,147]},{109:[1,148]},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:149},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:150},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:151},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:152},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:153},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:154},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:155},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:156},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:157},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:158},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:159},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:160},e([58,59,61,105,106,109,110,123],[2,102]),{50:[1,161]},{17:[1,162],43:_e},{17:[1,164]},e(ke,[2,135],{107:G,124:V,125:Q,126:W,127:X}),{16:g,35:_,47:112,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,85:165,86:q,87:F,88:K,90:36,101:P,104:35,120:33},{4:166,18:r},{16:g,35:_,47:167,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,67:fe,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},e([6,8,14,16,17,35,36,43,49,50,52,53,55,56,58,59,61,67,76,79,81,82,83,84,86,87,88,89,101,129,135,138,144,146,150,152,154,164,165,167,168,173,177,179,180,182,192,193,194],ve),e(ke,Ee,{120:33,104:35,90:36,80:37,62:38,66:39,63:40,78:41,75:46,51:47,54:48,57:49,60:50,64:168,65:169,47:173,16:g,30:xe,35:_,45:we,46:Oe,50:k,52:E,53:x,55:w,56:O,58:$,59:S,61:T,76:R,79:I,81:C,82:A,83:L,84:N,86:q,87:F,88:K,101:P}),e(de,[2,73]),e(de,[2,74]),e(de,[2,75]),e(de,[2,76]),e(de,[2,77]),{70:174,71:[1,175]},{71:[2,67],107:G,124:V,125:Q,126:W,127:X},e($e,[2,7],{14:d}),e($e,[2,8]),e(Se,[2,24],{22:176,37:[1,177]}),e(be,[2,21]),{35:[1,178]},{35:[1,179]},{35:[1,180]},e(M,[2,148]),e(Te,[2,142]),e(J,[2,130]),e(Re,[2,131],{107:G,124:V}),e(Re,[2,132],{107:G,124:V}),e(J,[2,133]),e(Re,[2,134],{107:G,124:V}),{57:183,58:$,59:S,61:[1,182],122:181,123:[1,184]},e(z,[2,123]),{16:[1,185]},{16:[2,119]},{16:[2,120]},{16:[1,186]},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:187},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:188,81:C,82:A,83:L,84:N,86:q,87:F,88:K},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:189},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:190},e([6,8,14,17,34,36,43,49,50,71,72,74,77,89,91,101,105,106,107,108,109,110,112,113,114,115,116,117,121,124,125,126,127,129,133,135,138,141,142,144,146,150,152,154,157,164,165,167,168,173,177,179,180,182],[2,89],{45:Y,79:Z,81:ee,92:re,93:ne,94:ie,95:ae,96:se,97:oe,98:ce,99:le}),e([6,8,14,17,34,36,43,49,50,71,72,74,77,89,91,92,99,101,105,106,107,108,109,110,112,113,114,115,116,117,121,124,125,126,127,129,133,135,138,141,142,144,146,150,152,154,157,164,165,167,168,173,177,179,180,182],[2,90],{45:Y,79:Z,81:ee,93:ne,94:ie,95:ae,96:se,97:oe,98:ce}),e(Ie,[2,91],{45:Y,79:Z,81:ee,95:ae,96:se,97:oe,98:ce}),e(Ie,[2,92],{45:Y,79:Z,81:ee,95:ae,96:se,97:oe,98:ce}),e(Ce,[2,93],{45:Y,95:ae,96:se,97:oe,98:ce}),e(Ce,[2,94],{45:Y,95:ae,96:se,97:oe,98:ce}),e(he,[2,95]),e(he,[2,96]),e(he,[2,97]),e(he,[2,98]),e(he,[2,99]),e([6,8,14,17,34,36,43,49,50,71,72,74,77,89,91,99,101,105,106,107,108,109,110,112,113,114,115,116,117,121,124,125,126,127,129,133,135,138,141,142,144,146,150,152,154,157,164,165,167,168,173,177,179,180,182],[2,100],{45:Y,79:Z,81:ee,92:re,93:ne,94:ie,95:ae,96:se,97:oe,98:ce}),e([6,8,14,16,17,34,35,36,43,45,49,50,52,53,55,56,58,59,61,67,71,72,74,76,77,79,81,82,83,84,86,87,88,89,91,92,93,94,95,96,97,98,99,101,103,105,106,107,108,109,110,112,113,114,115,116,117,121,124,125,126,127,129,133,135,138,141,142,144,146,150,152,154,157,164,165,167,168,173,177,179,180,182,192,193,194],[2,63]),e(de,[2,82]),{16:g,35:_,47:191,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},e(de,[2,84]),{17:[1,192],43:_e},{17:[1,193]},{89:[1,194],107:G,124:V,125:Q,126:W,127:X},{17:[1,195],43:[1,196]},e(ke,[2,56]),e(ke,[2,58]),e(ke,[2,59]),{16:g,35:_,47:197,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},e(ke,[2,61],{107:G,124:V,125:Q,126:W,127:X}),{71:[1,199],73:198,74:[1,200],77:[2,70]},{16:g,35:_,47:201,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},e(Ae,[2,26],{23:202,38:[1,203]}),e(Se,[2,23]),e(D,[2,19]),e(j,[2,156]),e(j,[2,157]),e(J,[2,128]),e(z,[2,122]),e(J,[2,125]),e(J,[2,126]),{4:204,18:r},{4:205,16:g,18:r,35:_,47:112,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,85:206,86:q,87:F,88:K,90:36,101:P,104:35,120:33},{45:Y,79:Z,81:ee,91:te,92:re,93:ne,94:ie,95:ae,96:se,97:oe,98:ce,99:le,107:[1,207]},e(z,[2,103],{102:208,103:[1,209]}),e(z,[2,111],{45:Y,79:Z,81:ee,91:te,92:re,93:ne,94:ie,95:ae,96:se,97:oe,98:ce,99:le}),e(z,[2,109],{45:Y,79:Z,81:ee,91:te,92:re,93:ne,94:ie,95:ae,96:se,97:oe,98:ce,99:le}),e(ke,[2,136],{107:G,124:V,125:Q,126:W,127:X}),e(de,[2,83]),e(de,[2,85]),e(de,[2,86]),e(de,[2,54]),e(ke,Ee,{120:33,104:35,90:36,80:37,62:38,66:39,63:40,78:41,75:46,51:47,54:48,57:49,60:50,47:173,65:210,16:g,30:xe,35:_,45:we,46:Oe,50:k,52:E,53:x,55:w,56:O,58:$,59:S,61:T,76:R,79:I,81:C,82:A,83:L,84:N,86:q,87:F,88:K,101:P}),e(ke,[2,60],{107:G,124:V,125:Q,126:W,127:X}),{77:[1,211]},{16:g,35:_,47:212,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},{16:g,35:_,47:213,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},{72:[1,214],107:G,124:V,125:Q,126:W,127:X},e(Le,[2,28],{24:215,39:[1,216]}),e(Ae,[2,25]),{17:[1,217]},{17:[1,218]},{17:[1,219],43:_e},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,104:220},e(z,[2,110]),{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:221,81:C,82:A,83:L,84:N,86:q,87:F,88:K},e(ke,[2,55]),e(de,[2,72]),{72:[1,222],107:G,124:V,125:Q,126:W,127:X},{77:[2,71],107:G,124:V,125:Q,126:W,127:X},{16:g,35:_,47:223,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},e(Ne,[2,29],{25:224,40:[1,225],41:[1,226]}),e(Le,[2,27]),e(z,[2,124]),e(z,[2,106]),e(z,[2,107]),e(z,[2,108]),e(z,[2,104]),{16:g,35:_,47:227,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},e(qe,[2,68],{107:G,124:V,125:Q,126:W,127:X}),e(Fe,[2,33],{26:228,42:[1,229]}),e(Ne,[2,30]),e(Ne,[2,31]),e(qe,[2,69],{107:G,124:V,125:Q,126:W,127:X}),{16:g,27:230,35:_,44:231,45:Ke,46:Pe,47:234,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},e(Fe,[2,32]),e(De,[2,166],{28:235,43:[1,236],157:[1,237]}),e(je,[2,35]),e(je,[2,36]),e(je,[2,37]),e(je,[2,39],{48:238,49:[1,239],50:[1,240],107:G,124:V,125:Q,126:W,127:X}),e(De,[2,12]),{16:g,35:_,44:241,45:Ke,46:Pe,47:234,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},{16:Be,50:ye,66:248,88:Ue,158:242,160:243,161:244,172:247,174:246},e(je,[2,38]),{50:[1,250]},e(je,[2,41]),e(je,[2,34]),e([6,8,14,17,129,135,138,144,146,150,152,154],He,{159:251,43:Me,182:Ge}),e(Ve,[2,168]),e(Ve,[2,170],{163:254,166:256,36:Qe,164:We,165:Xe,167:Je,168:ze,173:Ye,177:Ze}),{162:[1,262]},e(et,[2,191]),e(et,[2,192]),e([6,8,14,17,36,43,49,50,89,129,135,138,144,146,150,152,154,164,165,167,168,173,177,179,180,192,193,194],He,{159:263,67:fe,182:Ge}),{4:264,16:Be,18:r,50:ye,66:248,88:Ue,158:265,160:243,161:244,172:247,174:246},e(je,[2,40]),e(tt,[2,137],{128:266,129:[1,267]}),{16:Be,50:ye,66:248,88:Ue,160:268,161:244,172:247,174:246},{16:[1,269]},{173:[1,270]},{16:Be,50:ye,66:248,174:271},{169:272,170:rt,173:nt},{166:275,167:Je,168:ze,171:274,173:[2,179]},{173:[2,173]},{173:[2,174]},e(it,[2,175]),e(it,[2,176]),{16:Be,50:ye,66:248,161:276,172:247,174:246},e(at,st,{183:277,66:279,49:ot,50:ye}),{17:[1,280]},{17:[1,281],43:Me},e(Te,[2,139],{130:282,131:283,135:[1,284]}),{16:g,35:_,47:285,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},e(Ve,[2,169]),{50:ye,66:287,181:286},{16:Be,50:ye,66:248,174:288},{176:289,179:ct},{173:[1,291]},{173:[2,178]},{173:[1,292]},{169:293,170:rt,173:nt},{36:Qe,89:[1,294],163:254,164:We,165:Xe,166:256,167:Je,168:ze,173:Ye,177:Ze},e(et,[2,208],{189:295,190:296,191:297,192:lt,193:ut,194:pt}),{50:ye,66:301},e(at,[2,199],{67:fe}),e(et,st,{66:279,183:302,49:ot,50:ye}),e(et,[2,217]),e(ht,[2,153],{143:303,144:[1,304]}),e(Te,[2,140]),{16:g,35:_,47:32,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33,136:305,139:31},e(tt,[2,138],{107:G,124:V,125:Q,126:W,127:X}),{17:[1,306],43:[1,307]},e(ke,[2,193],{67:fe}),e([6,8,14,17,36,43,89,129,135,138,144,146,150,152,154,164,165,167,168,173,177,182],[2,181],{175:308,176:309,179:ct,180:dt}),e(et,[2,183]),{16:g,35:_,47:311,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},{16:Be,50:ye,66:248,161:312,172:247,174:246},{16:Be,50:ye,66:248,174:313},{173:[2,180]},e(Ve,[2,171]),e(et,[2,215]),e(et,[2,209]),e(et,[2,210]),{184:315,185:ft,186:yt},{184:318,185:ft,186:yt},{184:319,185:ft,186:yt},e(at,[2,198],{67:fe}),e(et,[2,216]),e(b,p,{137:18,11:320,138:h}),{16:g,35:_,47:321,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},e(Te,B,{132:322,43:U,133:H}),e([6,8,14,17,36,43,49,50,89,129,135,138,144,146,150,152,154,164,165,167,168,173,177,179,180,182,192,193,194],[2,196]),{50:ye,66:323},e(et,[2,182]),e(et,[2,189]),{16:[1,324]},e(et,[2,188],{107:G,124:V,125:Q,126:W,127:X}),{36:Qe,163:254,164:We,165:Xe,166:256,167:Je,168:ze,173:Ye,175:325,176:309,177:Ze,179:ct,180:dt},e(et,[2,185]),{191:326,192:lt,193:ut,194:pt},{16:vt,152:mt,187:327},e(bt,[2,200]),e(bt,[2,201]),{16:vt,152:mt,187:329},{16:vt,152:mt,187:330},e(j,v,{145:28,12:331,146:m}),e(ht,[2,154],{107:G,124:V,125:Q,126:W,127:X}),e(Te,[2,143]),e(ke,[2,194],{67:fe}),{50:ye,66:333,68:332},e(et,[2,184]),e(et,[2,211]),{16:[1,334]},{135:[1,337],138:[1,336],173:[1,335]},{16:[1,338]},{16:[1,339]},e(gt,[2,160],{148:340,149:341,150:[1,342]}),{17:[1,343],43:_t},e(ke,[2,64],{67:fe}),{17:[2,206],50:ye,66:333,68:346,188:345},{16:[2,203]},{16:[2,204]},{16:[2,205]},{50:ye,66:333,68:347},{50:ye,66:333,68:348},e(De,[2,163],{151:349,152:[1,350],154:[1,351]}),e(gt,[2,161]),{50:[1,353],63:352},e(et,[2,190]),{50:ye,66:354},{17:[1,355]},{17:[2,207],43:_t},{17:[1,356],43:_t},{17:[1,357],43:_t},e(De,[2,167]),{153:[1,358]},{105:[1,359]},e(gt,[2,162]),{16:me},e(ke,[2,65],{67:fe}),e(et,[2,212]),e(et,[2,213]),e(et,[2,214]),e(De,[2,164]),{155:[1,360]},{156:[1,361]},e(De,[2,165])],defaultActions:{11:[2,3],22:[2,1],24:[2,2],142:[2,119],143:[2,120],258:[2,173],259:[2,174],273:[2,178],293:[2,180],335:[2,203],336:[2,204],337:[2,205]},parseError:function(e,t){if(!t.recoverable){var r=new Error(e);throw r.hash=t,r}this.trace(e)},parse:function(e){var t=this,r=[0],n=[null],i=[],a=this.table,s="",o=0,c=0,l=0,u=i.slice.call(arguments,1),p=Object.create(this.lexer),h={yy:{}};for(var d in this.yy)Object.prototype.hasOwnProperty.call(this.yy,d)&&(h.yy[d]=this.yy[d]);p.setInput(e,h.yy),h.yy.lexer=p,h.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var f=p.yylloc;i.push(f);var y=p.options&&p.options.ranges;"function"==typeof h.yy.parseError?this.parseError=h.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var v,m,b,g,_,k,E,x,w,O=function(){var e;return"number"!=typeof(e=p.lex()||1)&&(e=t.symbols_[e]||e),e},$={};;){if(b=r[r.length-1],this.defaultActions[b]?g=this.defaultActions[b]:(null!==v&&void 0!==v||(v=O()),g=a[b]&&a[b][v]),void 0===g||!g.length||!g[0]){var S="";for(k in w=[],a[b])this.terminals_[k]&&k>2&&w.push("'"+this.terminals_[k]+"'");S=p.showPosition?"Parse error on line "+(o+1)+":\n"+p.showPosition()+"\nExpecting "+w.join(", ")+", got '"+(this.terminals_[v]||v)+"'":"Parse error on line "+(o+1)+": Unexpected "+(1==v?"end of input":"'"+(this.terminals_[v]||v)+"'"),this.parseError(S,{text:p.match,token:this.terminals_[v]||v,line:p.yylineno,loc:f,expected:w})}if(g[0]instanceof Array&&g.length>1)throw new Error("Parse Error: multiple actions possible at state: "+b+", token: "+v);switch(g[0]){case 1:r.push(v),n.push(p.yytext),i.push(p.yylloc),r.push(g[1]),v=null,m?(v=m,m=null):(c=p.yyleng,s=p.yytext,o=p.yylineno,f=p.yylloc,l>0&&l--);break;case 2:if(E=this.productions_[g[1]][1],$.$=n[n.length-E],$._$={first_line:i[i.length-(E||1)].first_line,last_line:i[i.length-1].last_line,first_column:i[i.length-(E||1)].first_column,last_column:i[i.length-1].last_column},y&&($._$.range=[i[i.length-(E||1)].range[0],i[i.length-1].range[1]]),void 0!==(_=this.performAction.apply($,[s,c,o,h.yy,g[1],n,i].concat(u))))return _;E&&(r=r.slice(0,-1*E*2),n=n.slice(0,-1*E),i=i.slice(0,-1*E)),r.push(this.productions_[g[1]][0]),n.push($.$),i.push($._$),x=a[r[r.length-2]][r[r.length-1]],r.push(x);break;case 3:return!0}}return!0}},Et={EOF:1,parseError:function(e,t){if(!this.yy.parser)throw new Error(e);this.yy.parser.parseError(e,t)},setInput:function(e,t){return this.yy=t||this.yy||{},this._input=e,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var e=this._input[0];return this.yytext+=e,this.yyleng++,this.offset++,this.match+=e,this.matched+=e,e.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),e},unput:function(e){var t=e.length,r=e.split(/(?:\r\n?|\n)/g);this._input=e+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-t),this.offset-=t;var n=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),r.length-1&&(this.yylineno-=r.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:r?(r.length===n.length?this.yylloc.first_column:0)+n[n.length-r.length].length-r[0].length:this.yylloc.first_column-t},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-t]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(e){this.unput(this.match.slice(e))},pastInput:function(){var e=this.matched.substr(0,this.matched.length-this.match.length);return(e.length>20?"...":"")+e.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var e=this.match;return e.length<20&&(e+=this._input.substr(0,20-e.length)),(e.substr(0,20)+(e.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var e=this.pastInput(),t=new Array(e.length+1).join("-");return e+this.upcomingInput()+"\n"+t+"^"},test_match:function(e,t){var r,n,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(n=e[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=n.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:n?n[n.length-1].length-n[n.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+e[0].length},this.yytext+=e[0],this.match+=e[0],this.matches=e,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(e[0].length),this.matched+=e[0],r=this.performAction.call(this,this.yy,this,t,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),r)return r;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var e,t,r,n;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;at[0].length)){if(t=r,n=a,this.options.backtrack_lexer){if(!1!==(e=this.test_match(r,i[a])))return e;if(this._backtrack){t=!1;continue}return!1}if(!this.options.flex)break}return t?!1!==(e=this.test_match(t,i[n]))&&e:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var e=this.next();return e||this.lex()},begin:function(e){this.conditionStack.push(e)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(e){return(e=this.conditionStack.length-1-Math.abs(e||0))>=0?this.conditionStack[e]:"INITIAL"},pushState:function(e){this.begin(e)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(e,t,r,n){switch(r){case 0:case 1:case 2:case 3:break;case 4:case 5:case 6:return 50;case 7:return 18;case 8:return 29;case 9:return 119;case 10:return 30;case 11:return 31;case 12:return 32;case 13:return 33;case 14:return 36;case 15:return 37;case 16:return 38;case 17:return 39;case 18:return 40;case 19:return 41;case 20:return 42;case 21:return 46;case 22:return 49;case 23:return 58;case 24:return 59;case 25:return 61;case 26:return"COLLATE";case 27:return 84;case 28:return 86;case 29:return 87;case 30:return 76;case 31:return 71;case 32:return 72;case 33:return 74;case 34:return 77;case 35:return 96;case 36:return 97;case 37:return 101;case 38:return 106;case 39:return 105;case 40:return 108;case 41:return 109;case 42:return 103;case 43:return 110;case 44:return 121;case 45:return 123;case 46:return 107;case 47:return 126;case 48:return 127;case 49:return 157;case 50:return 182;case 51:return 192;case 52:return 185;case 53:return 186;case 54:return 152;case 55:return 173;case 56:return 138;case 57:return 135;case 58:return 193;case 59:return 194;case 60:return 164;case 61:return 165;case 62:return 179;case 63:return 180;case 64:return 167;case 65:return 168;case 66:return 170;case 67:return 177;case 68:return 129;case 69:return 141;case 70:return 142;case 71:return 133;case 72:return 134;case 73:return 144;case 74:return 147;case 75:return 150;case 76:return 153;case 77:return 154;case 78:return 155;case 79:return 156;case 80:return 162;case 81:return 146;case 82:return 14;case 83:return 43;case 84:return 34;case 85:return 16;case 86:return 17;case 87:return 82;case 88:return 117;case 89:return 83;case 90:return 91;case 91:return 92;case 92:return 79;case 93:return 81;case 94:return 45;case 95:return 95;case 96:return 98;case 97:return 99;case 98:return 94;case 99:return 112;case 100:return 113;case 101:return 93;case 102:return"<=>";case 103:return 114;case 104:return 116;case 105:return 115;case 106:return 88;case 107:return 89;case 108:return 8;case 109:case 110:return 53;case 111:return 56;case 112:return 35;case 113:return 55;case 114:return 50;case 115:return 67;case 116:return 52;case 117:return 6;case 118:return"INVALID"}},rules:[/^(?:[\/][*](.|\n)*?[*][\/])/i,/^(?:[-][-]\s.*\n)/i,/^(?:[#]\s.*\n)/i,/^(?:\s+)/i,/^(?:[`][a-zA-Z_\u4e00-\u9fa5][a-zA-Z0-9_\u4e00-\u9fa5]*[`])/i,/^(?:[\w]+[\u4e00-\u9fa5]+[0-9a-zA-Z_\u4e00-\u9fa5]*)/i,/^(?:[\u4e00-\u9fa5][0-9a-zA-Z_\u4e00-\u9fa5]*)/i,/^(?:SELECT\b)/i,/^(?:ALL\b)/i,/^(?:ANY\b)/i,/^(?:DISTINCT\b)/i,/^(?:DISTINCTROW\b)/i,/^(?:HIGH_PRIORITY\b)/i,/^(?:MAX_STATEMENT_TIME\b)/i,/^(?:STRAIGHT_JOIN\b)/i,/^(?:SQL_SMALL_RESULT\b)/i,/^(?:SQL_BIG_RESULT\b)/i,/^(?:SQL_BUFFER_RESULT\b)/i,/^(?:SQL_CACHE\b)/i,/^(?:SQL_NO_CACHE\b)/i,/^(?:SQL_CALC_FOUND_ROWS\b)/i,/^(?:([a-zA-Z_\u4e00-\u9fa5][a-zA-Z0-9_\u4e00-\u9fa5]*\.){1,2}\*)/i,/^(?:AS\b)/i,/^(?:TRUE\b)/i,/^(?:FALSE\b)/i,/^(?:NULL\b)/i,/^(?:COLLATE\b)/i,/^(?:BINARY\b)/i,/^(?:ROW\b)/i,/^(?:EXISTS\b)/i,/^(?:CASE\b)/i,/^(?:WHEN\b)/i,/^(?:THEN\b)/i,/^(?:ELSE\b)/i,/^(?:END\b)/i,/^(?:DIV\b)/i,/^(?:MOD\b)/i,/^(?:NOT\b)/i,/^(?:BETWEEN\b)/i,/^(?:IN\b)/i,/^(?:SOUNDS\b)/i,/^(?:LIKE\b)/i,/^(?:ESCAPE\b)/i,/^(?:REGEXP\b)/i,/^(?:IS\b)/i,/^(?:UNKNOWN\b)/i,/^(?:AND\b)/i,/^(?:OR\b)/i,/^(?:XOR\b)/i,/^(?:FROM\b)/i,/^(?:PARTITION\b)/i,/^(?:USE\b)/i,/^(?:INDEX\b)/i,/^(?:KEY\b)/i,/^(?:FOR\b)/i,/^(?:JOIN\b)/i,/^(?:ORDER\s+BY\b)/i,/^(?:GROUP\s+BY\b)/i,/^(?:IGNORE\b)/i,/^(?:FORCE\b)/i,/^(?:INNER\b)/i,/^(?:CROSS\b)/i,/^(?:ON\b)/i,/^(?:USING\b)/i,/^(?:LEFT\b)/i,/^(?:RIGHT\b)/i,/^(?:OUTER\b)/i,/^(?:NATURAL\b)/i,/^(?:WHERE\b)/i,/^(?:ASC\b)/i,/^(?:DESC\b)/i,/^(?:WITH\b)/i,/^(?:ROLLUP\b)/i,/^(?:HAVING\b)/i,/^(?:OFFSET\b)/i,/^(?:PROCEDURE\b)/i,/^(?:UPDATE\b)/i,/^(?:LOCK\b)/i,/^(?:SHARE\b)/i,/^(?:MODE\b)/i,/^(?:OJ\b)/i,/^(?:LIMIT\b)/i,/^(?:UNION\b)/i,/^(?:,)/i,/^(?:=)/i,/^(?:\()/i,/^(?:\))/i,/^(?:~)/i,/^(?:!=)/i,/^(?:!)/i,/^(?:\|)/i,/^(?:&)/i,/^(?:\+)/i,/^(?:-)/i,/^(?:\*)/i,/^(?:\/)/i,/^(?:%)/i,/^(?:\^)/i,/^(?:>>)/i,/^(?:>=)/i,/^(?:>)/i,/^(?:<<)/i,/^(?:<=>)/i,/^(?:<=)/i,/^(?:<>)/i,/^(?:<)/i,/^(?:\{)/i,/^(?:\})/i,/^(?:;)/i,/^(?:['](\\.|[^'])*['])/i,/^(?:["](\\.|[^"])*["])/i,/^(?:[0][x][0-9a-fA-F]+)/i,/^(?:[-]?[0-9]+(\.[0-9]+)?)/i,/^(?:[-]?[0-9]+(\.[0-9]+)?[eE][-][0-9]+(\.[0-9]+)?)/i,/^(?:[a-zA-Z_\u4e00-\u9fa5][a-zA-Z0-9_\u4e00-\u9fa5]*)/i,/^(?:\.)/i,/^(?:['"][a-zA-Z_\u4e00-\u9fa5][a-zA-Z0-9_\u4e00-\u9fa5]*["'])/i,/^(?:$)/i,/^(?:.)/i],conditions:{INITIAL:{rules:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118],inclusive:!0}}};function xt(){this.yy={}}return kt.lexer=Et,xt.prototype=kt,kt.Parser=xt,new xt}();function a(){this.buffer=""}i||(i={}),i.stringify=function(e){var t=new a;return t.travelMain(e),t.buffer},a.prototype.travel=function(e){if(e){if("string"==typeof e)return this.append(e);this["travel"+e.type].call(this,e)}};var s=!1;a.prototype.appendKeyword=function(e,t,r){s&&(t=!0,s=!1),this.buffer+=t?e.toUpperCase():" "+e.toUpperCase(),r&&(s=!0)},a.prototype.append=function(e,t,r){s&&(t=!0,s=!1),this.buffer+=t?e:" "+e,r&&(s=!0)},a.prototype.travelMain=function(e){this.travel(e.value),e.hasSemicolon&&this.append(";",!0)},a.prototype.travelSelect=function(e){this.appendKeyword("select"),e.distinctOpt&&this.appendKeyword(e.distinctOpt),e.highPriorityOpt&&this.appendKeyword(e.highPriorityOpt),e.maxStateMentTimeOpt&&this.append("MAX_STATEMENT_TIME = "+e.maxStateMentTimeOpt),e.straightJoinOpt&&this.appendKeyword(e.straightJoinOpt),e.sqlSmallResultOpt&&this.appendKeyword(e.sqlSmallResultOpt),e.sqlBigResultOpt&&this.appendKeyword(e.sqlBigResultOpt),e.sqlBufferResultOpt&&this.appendKeyword(e.sqlBufferResultOpt),e.sqlCacheOpt&&this.appendKeyword(e.sqlCacheOpt),e.sqlCalcFoundRowsOpt&&this.appendKeyword(e.sqlCalcFoundRowsOpt),e.selectItems&&this.travelSelectExpr(e.selectItems),e.from&&(this.appendKeyword("from"),this.travel(e.from)),e.partition&&this.travel(e.partition),e.where&&(this.appendKeyword("where"),this.travel(e.where)),e.groupBy&&this.travel(e.groupBy),e.having&&(this.appendKeyword("having"),this.travel(e.having)),e.orderBy&&this.travel(e.orderBy),e.limit&&this.travel(e.limit),e.procedure&&(this.appendKeyword("procedure"),this.travel(e.procedure)),e.updateLockMode&&this.appendKeyword(e.updateLockMode)},a.prototype.travelSelectExpr=function(e){for(var t=e.value,r=0;r0&&void 0!==arguments[0]?arguments[0]:void 0;if(this.action&&this.action.params&&this.action.params.$resource){this.$set(this.record.params,"$resource",t),this.$set(this.record,"resource",t);var r=this.action.types,n=void 0===r?[]:r;return this.$httpGet("/resources").then(function(r){var i=r.data;e.resourcesOptions=i.filter(function(e){return n.includes(e.type)}),e.$set(e.record,"resource",t)})}},loadActions:function(){var e=this;return this.$httpGet("/actions",this.params).then(function(t){e.actionsList=t.data.map(function(e){return e.label=(e.title||{})[E],e.descriptionLabel=(e.description||{})[E],e})})},renderForm:function(e){var t=this;return f()(u.a.mark(function r(){var n,i,a,s;return u.a.wrap(function(r){for(;;)switch(r.prev=r.next){case 0:if(t.formData){r.next=2;break}return r.abrupt("return");case 2:return n=t.formData||e,i=n.name,a=n.params,s=void 0===a?{}:a,r.next=5,t.handleActionChange(i);case 5:t.fillData(s);case 6:case"end":return r.stop()}},r,t)}))()},fillData:function(e){var t=this;c()(e).forEach(function(e){var r=s()(e,2),n=r[0],i=r[1];t.$set(t.record,n,i)})}},created:function(){var e=this;return f()(u.a.mark(function t(){return u.a.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,e.loadActions();case 2:return t.next=4,e.renderForm();case 4:case"end":return t.stop()}},t,e)}))()}},w={render:function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("el-dialog",e._b({staticClass:"action-dialog",attrs:{width:"500px","append-to-body":"",visible:e.dialogVisible,title:e.$t("rule.actions")},on:{"update:visible":function(t){e.dialogVisible=t},open:e.open,close:e.close}},"el-dialog",e.$attrs,!1),[r("el-form",{ref:"record",staticClass:"el-form--public",attrs:{model:e.record,rules:e.rules}},[r("el-row",{attrs:{gutter:20}},[r("el-col",{attrs:{span:12}},[r("el-form-item",{attrs:{prop:"action"}},[r("template",{slot:"label"},[e._v("\n "+e._s(e.$t("rule.action"))+"\n "),r("el-popover",{attrs:{placement:"top-start",width:"200",trigger:"hover"}},[r("div",{domProps:{innerHTML:e._s(e.action.descriptionLabel||e.$t("rule.action_type"))}}),e._v(" "),r("i",{staticClass:"el-icon-question",attrs:{slot:"reference",tabindex:"-1"},slot:"reference"})])],1),e._v(" "),r("el-select",{staticClass:"el-select--public",staticStyle:{width:"100%"},attrs:{"popper-class":"el-select--public"},on:{change:e.handleActionChange},model:{value:e.record.action,callback:function(t){e.$set(e.record,"action",t)},expression:"record.action"}},e._l(e.actionsList,function(e,t){return r("el-option",{key:t,attrs:{label:e.label,value:e.name}})}),1)],2)],1),e._v(" "),e.action.params&&e.action.params.$resource?r("el-col",{attrs:{span:12}},[r("el-form-item",{staticClass:"resource-item",attrs:{prop:"params.$resource"}},[r("template",{slot:"label"},[e._v("\n "+e._s(e.$t("rule.resource"))+"\n "),r("span",{staticClass:"btn",staticStyle:{float:"right","font-size":"12px"},on:{click:e.createResource}},[e._v("\n "+e._s(e.$t("rule.new_resource"))+"\n ")])]),e._v(" "),r("el-select",{staticClass:"el-select--public",staticStyle:{width:"100%"},attrs:{"popper-class":"el-select--public"},model:{value:e.record.params.$resource,callback:function(t){e.$set(e.record.params,"$resource",t)},expression:"record.params.$resource"}},e._l(e.resourcesOptions,function(e,t){return r("el-option",{key:t,attrs:{label:e.id,value:e.id}})}),1)],2)],1):e._e(),e._v(" "),e._l(e.paramsList,function(t,n){return r("el-col",{key:n,attrs:{span:"object"===t.type||"textarea"===t.$attrs.type?24:12}},[r("el-form-item",{attrs:{prop:"params."+t.prop}},[r("template",{slot:"label"},[e._v("\n "+e._s(t.label)+"\n\n "),t.description?r("el-popover",{attrs:{placement:"right",width:"200",trigger:"hover"}},[r("div",{domProps:{innerHTML:e._s(t.description)}}),e._v(" "),r("i",{staticClass:"el-icon-question",attrs:{slot:"reference",tabindex:"-1"},slot:"reference"})]):e._e()],1),e._v(" "),"object"===t.type?r("data-table",{model:{value:e.record.params[t.key],callback:function(r){e.$set(e.record.params,t.key,r)},expression:"record.params[item.key]"}}):"emq-select"===t.type?r("emq-select",e._b({staticClass:"el-select--public",attrs:{"popper-class":"el-select--public"},model:{value:e.record.params[t.key],callback:function(r){e.$set(e.record.params,t.key,r)},expression:"record.params[item.key]"}},"emq-select",t.$attrs,!1)):"number"===t.type?r("el-input",e._b({attrs:{type:"number"},model:{value:e.record.params[t.key],callback:function(r){e.$set(e.record.params,t.key,e._n(r))},expression:"record.params[item.key]"}},"el-input",t.$attrs,!1)):r("el-input",e._b({model:{value:e.record.params[t.key],callback:function(r){e.$set(e.record.params,t.key,r)},expression:"record.params[item.key]"}},"el-input",t.$attrs,!1))],2)],1)})],2)],1),e._v(" "),r("div",{attrs:{slot:"footer"},slot:"footer"},[r("el-button",{staticClass:"cache-btn",attrs:{type:"text"},on:{click:function(t){e.dialogVisible=!1}}},[e._v("\n "+e._s(e.$t("rule.cancel"))+"\n ")]),e._v(" "),r("el-button",{staticClass:"confirm-btn",attrs:{type:"success"},on:{click:e.handleAdd}},[e._v("\n "+e._s(e.$t("rule.confirm"))+"\n ")])],1),e._v(" "),r("resource-dialog",{attrs:{visible:e.resourceDialogVisible,"resource-type":e.resourceType,"enable-item":e.enableItem,"append-to-body":""},on:{"update:visible":function(t){e.resourceDialogVisible=t},confirm:e.handleResourceCreate}})],1)},staticRenderFns:[]};var O={name:"rule-actions",components:{ActionDialog:r("VU/8")(x,w,!1,function(e){r("yoEm")},null,null).exports},props:{record:{type:Object,required:!0},inDialog:{type:Boolean,default:!1},operations:{type:Array,default:function(){return["create","edit","delete"]}},params:{type:Object,default:function(){return{}}}},watch:{dialogVisible:function(e){e||(this.editForm=null,this.editIndex=null,this.currentAction={},this.isFallBacks=!1)}},computed:{has:function(){var e=[];return this.operations.forEach(function(t){e[t]=!0}),e}},data:function(){return{dialogVisible:!1,editForm:null,editIndex:null,isFallBacks:!1,currentAction:{}}},filters:{jsonFormat:function(e){return i()(e,null,2)}},methods:{getSum:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";if(0===e.length||!t)return 0;var r=0;return e.forEach(function(e){var n=e[t]||0;r+=n}),r},handleActionAdd:function(e,t){if(this.isFallBacks)return null!==this.editIndex&&(this.currentAction.fallbacks=[]),void this.currentAction.fallbacks.push(e);null!==t?this.record.actions.splice(t,1,e):this.record.actions.push(e)},handleActionRemove:function(e){var t=e;this.record.actions=this.record.actions.filter(function(e,r){return r!==t})},handleActionEdit:function(e,t){this.editIndex=t,this.editForm=e,this.dialogVisible=!0},handleAddFallbacks:function(e){this.currentAction=e,this.isFallBacks=!0,this.dialogVisible=!0},handleFallbackRemove:function(e){e.fallbacks=[]},handleFallbackEdit:function(e,t,r){this.currentAction=t,this.isFallBacks=!0,this.editIndex=r,this.editForm=e,this.dialogVisible=!0}}},$={render:function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("div",{staticClass:"rule-actions"},[e._l(e.record.actions,function(t,n){return r("div",{key:n,staticClass:"action-card"},[r("el-row",{staticClass:"action-body",attrs:{type:"flex"}},[r("el-col",{attrs:{span:12}},[r("div",{staticClass:"filed-item"},[r("label",{staticClass:"title"},[e._v(e._s(e.$t("rule.type"))+": ")]),e._v(" "),r("span",{staticClass:"desc"},[e._v(e._s(t.name))])]),e._v(" "),e._l(Object.entries(t.params),function(t,n){return r("div",{key:n,staticClass:"filed-item"},[r("label",{staticClass:"title"},[e._v(" "+e._s("$resource"===t[0]?e.$t("rule.rely_resource"):t[0])+": ")]),e._v(" "),r("span",{staticClass:"desc"},[e._v(e._s(t[1]))])])})],2),e._v(" "),e.has.delete||e.has.edit?r("el-col",{staticClass:"action-oper",attrs:{span:12}},[e.has.edit?r("el-button",{attrs:{type:"text"},on:{click:function(r){return e.handleActionEdit(t,n)}}},[e._v("\n "+e._s(e.$t("rule.edit"))+"\n ")]):e._e(),e._v(" "),e.has.delete?r("el-button",{staticClass:"delete-btn",attrs:{type:"text"},on:{click:function(t){return e.handleActionRemove(n)}}},[e._v("\n "+e._s(e.$t("rule.delete"))+"\n ")]):e._e(),e._v(" "),t.fallbacks.length?e._e():r("div",{staticClass:"fallbacks"},[r("el-popover",{attrs:{placement:"top-start",trigger:"hover",content:e.$t("rule.fallbackActionCreate")}},[r("el-button",{attrs:{slot:"reference",type:"text",icon:"el-icon-plus"},on:{click:function(r){return e.handleAddFallbacks(t)}},slot:"reference"},[e._v("\n "+e._s(e.$t("rule.fallbackAction"))+"\n ")])],1)],1)],1):e._e(),e._v(" "),e.has.delete||e.has.edit?e._e():r("el-col",{attrs:{span:12}},[r("div",{staticClass:"status-wrapper filed-item"},[e._l(t.metrics||[],function(t,n){return r("div",{key:n,staticClass:"status-item"},[r("div",{staticClass:"title"},[e._v(e._s(e.$t("rule.metrics"))+":")]),e._v(" "),r("span",{staticClass:"key"},[e._v("\n "+e._s(t.node)+"\n ")]),e._v(" "),r("span",{attrs:{type:"info"}},[e._v("\n "+e._s(e.$t("rule.success"))+":\n "),r("span",[e._v(e._s(t.success))])]),e._v(" "),r("span",{attrs:{type:"info"}},[e._v("\n "+e._s(e.$t("rule.failed"))+":\n "),r("span",[e._v(e._s(t.failed))])])])}),e._v(" "),r("div",{staticClass:"status-item"},[r("span",{staticClass:"key"},[e._v("\n "+e._s(e.$t("rule.all"))+"\n ")]),e._v(" "),r("span",{attrs:{type:"info"}},[e._v("\n "+e._s(e.$t("rule.success"))+":\n "),r("span",[e._v(e._s(e.getSum(t.metrics,"success")))])]),e._v(" "),r("span",{attrs:{type:"info"}},[e._v("\n "+e._s(e.$t("rule.failed"))+":\n "),r("span",[e._v(e._s(e.getSum(t.metrics,"failed")))])])])],2)])],1),e._v(" "),t.fallbacks&&t.fallbacks.length?e._l(t.fallbacks,function(n,i){return r("el-row",{key:i,staticClass:"action-footer",attrs:{type:"flex"}},[r("el-col",{attrs:{span:12}},[r("div",{staticClass:"filed-item"},[r("label",{staticClass:"title"},[e._v(e._s(e.$t("rule.type"))+": ")]),e._v(" "),r("span",{staticClass:"desc"},[e._v(e._s(n.name))])]),e._v(" "),e._l(Object.entries(n.params),function(t,n){return r("div",{key:n,staticClass:"filed-item"},[r("label",{staticClass:"title"},[e._v(" "+e._s("$resource"===t[0]?e.$t("rule.rely_resource"):t[0])+": ")]),e._v(" "),r("span",{staticClass:"desc"},[e._v(e._s(t[1]))])])})],2),e._v(" "),e.has.delete||e.has.edit?r("el-col",{staticClass:"action-oper",attrs:{span:12}},[e.has.edit?r("el-button",{attrs:{type:"text"},on:{click:function(r){return e.handleFallbackEdit(n,t,i)}}},[e._v("\n "+e._s(e.$t("rule.edit"))+"\n ")]):e._e(),e._v(" "),e.has.delete?r("el-button",{staticClass:"delete-btn",attrs:{type:"text"},on:{click:function(r){return e.handleFallbackRemove(t,i)}}},[e._v("\n "+e._s(e.$t("rule.delete"))+"\n ")]):e._e(),e._v(" "),r("div",{staticClass:"fallbacks"},[r("el-popover",{attrs:{placement:"top-start",trigger:"hover",content:e.$t("rule.fallbackActionTip")}},[r("span",{attrs:{slot:"reference"},slot:"reference"},[e._v("\n "+e._s(e.$t("rule.fallbackAction"))+"\n ")])])],1)],1):e._e(),e._v(" "),e.has.delete||e.has.edit?e._e():r("el-col",{attrs:{span:12}},[r("div",{staticClass:"status-wrapper filed-item"},[e._l(n.metrics||[],function(t,n){return r("div",{key:n,staticClass:"status-item"},[r("div",{staticClass:"title"},[e._v(e._s(e.$t("rule.metrics"))+":")]),e._v(" "),r("span",{staticClass:"key"},[e._v("\n "+e._s(t.node)+"\n ")]),e._v(" "),r("span",{attrs:{type:"info"}},[e._v("\n "+e._s(e.$t("rule.success"))+":\n "),r("span",[e._v(e._s(t.success))])]),e._v(" "),r("span",{attrs:{type:"info"}},[e._v("\n "+e._s(e.$t("rule.failed"))+":\n "),r("span",[e._v(e._s(t.failed))])])])}),e._v(" "),r("div",{staticClass:"status-item"},[r("span",{staticClass:"key"},[e._v("\n "+e._s(e.$t("rule.all"))+"\n ")]),e._v(" "),r("span",{attrs:{type:"info"}},[e._v("\n "+e._s(e.$t("rule.success"))+":\n "),r("span",[e._v(e._s(e.getSum(n.metrics,"success")))])]),e._v(" "),r("span",{attrs:{type:"info"}},[e._v("\n "+e._s(e.$t("rule.failed"))+":\n "),r("span",[e._v(e._s(e.getSum(n.metrics,"failed")))])])])],2)])],1)}):e._e()],2)}),e._v(" "),e.has.create?r("el-button",{staticStyle:{"min-width":"80px"},attrs:{type:"success",plain:"",icon:"el-icon-plus",size:"small"},on:{click:function(t){e.dialogVisible=!0}}},[e._v("\n "+e._s(e.$t("rule.add"))+"\n ")]):e._e(),e._v(" "),r("action-dialog",{attrs:{visible:e.dialogVisible,currentActions:e.record.actions,recordIndex:e.editIndex,editRecord:e.editForm,params:e.params},on:{"update:visible":function(t){e.dialogVisible=t},confirm:e.handleActionAdd}})],2)},staticRenderFns:[]};var S=r("VU/8")(O,$,!1,function(e){r("lqjQ")},null,null);t.a=S.exports},exGp:function(e,t,r){"use strict";t.__esModule=!0;var n,i=r("//Fk"),a=(n=i)&&n.__esModule?n:{default:n};t.default=function(e){return function(){var t=e.apply(this,arguments);return new a.default(function(e,r){return function n(i,s){try{var o=t[i](s),c=o.value}catch(e){return void r(e)}if(!o.done)return a.default.resolve(c).then(function(e){n("next",e)},function(e){n("throw",e)});e(c)}("next")})}}},lqjQ:function(e,t){},yoEm:function(e,t){}}); \ No newline at end of file diff --git a/apps/emqx_dashboard/priv/www/static/js/0.e5c2d59c47ae56b10376.js b/apps/emqx_dashboard/priv/www/static/js/0.e5c2d59c47ae56b10376.js new file mode 100644 index 000000000..30946810d --- /dev/null +++ b/apps/emqx_dashboard/priv/www/static/js/0.e5c2d59c47ae56b10376.js @@ -0,0 +1,8 @@ +webpackJsonp([0],{"1H6C":function(e,t,r){var n=function(){return this}()||Function("return this")(),i=n.regeneratorRuntime&&Object.getOwnPropertyNames(n).indexOf("regeneratorRuntime")>=0,a=i&&n.regeneratorRuntime;if(n.regeneratorRuntime=void 0,e.exports=r("HhN8"),i)n.regeneratorRuntime=a;else try{delete n.regeneratorRuntime}catch(e){n.regeneratorRuntime=void 0}},"3IRH":function(e,t){e.exports=function(e){return e.webpackPolyfill||(e.deprecate=function(){},e.paths=[],e.children||(e.children=[]),Object.defineProperty(e,"loaded",{enumerable:!0,get:function(){return e.l}}),Object.defineProperty(e,"id",{enumerable:!0,get:function(){return e.i}}),e.webpackPolyfill=1),e}},FcGO:function(e,t,r){"use strict";var n=r("Xxa5"),i=r.n(n),a=r("exGp"),s=r.n(a),o={name:"emq-select",components:{},props:{value:{},field:{type:Object,required:!0},fieldName:{type:Object,default:function(){return{label:"label",value:"value"}}},disabledItem:{type:Array,default:function(){return[]}},refresh:{type:Boolean}},data:function(){return{options:[],parserField:{}}},computed:{rawValue:{get:function(){return"boolean"==typeof this.value?this.value.toString():this.value},set:function(e){var t=this.fieldName.value;this.options.find(function(r){return r[t]===e})&&this.parserField[t]&&(e="true"===e),this.$emit("update:value",e)}}},watch:{refresh:function(e){e&&this.loadData()},field:{handler:function(){this.loadData()},deep:!0}},created:function(){this.loadData()},methods:{loadData:function(){var e=this;return s()(i.a.mark(function t(){var r,n,a;return i.a.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,e.getOptions();case 2:r=t.sent,e.parserField={},n=e.fieldName.value,a=e.fieldName.label,e.options=r.map(function(t){var r=t[n],i=t[a];return"boolean"==typeof r&&(e.parserField[n]="boolean",t[n]=r.toString(),"boolean"==typeof i&&(t[a]=i.toString())),t}),e.$emit("update:refresh",!1);case 8:case"end":return t.stop()}},t,e)}))()},isDisabled:function(e){return this.disabledItem.includes(e[this.fieldName.value])},getOptions:function(){var e=this;return s()(i.a.mark(function t(){var r,n,a,s,o;return i.a.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:if(r=e.field,n=r.api,r.url,a=r.options,s=r.list,o=[],!a){t.next=6;break}o=a,t.next=14;break;case 6:if(!s){t.next=10;break}o=s.map(function(e){return{label:e,value:e}}),t.next=14;break;case 10:if(!n){t.next=14;break}return t.next=13,n();case 13:o=t.sent;case 14:return t.abrupt("return",o);case 15:case"end":return t.stop()}},t,e)}))()}}},l={render:function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("el-select",e._g(e._b({staticClass:"emq-select",attrs:{value:e.rawValue}},"el-select",e.$attrs,!1),e.$listeners),[e._t("default",e._l(e.options,function(t,n){return r("el-option",{key:n,attrs:{value:t[e.fieldName.value],label:t[e.fieldName.label],disabled:e.isDisabled(t)}},[e._t("option",null,{item:t})],2)}))],2)},staticRenderFns:[]},c=r("VU/8")(o,l,!1,null,null,null);t.a=c.exports},"G5A+":function(e,t){},HhN8:function(e,t){!function(t){"use strict";var r,n=Object.prototype,i=n.hasOwnProperty,a="function"==typeof Symbol?Symbol:{},s=a.iterator||"@@iterator",o=a.asyncIterator||"@@asyncIterator",l=a.toStringTag||"@@toStringTag",c="object"==typeof e,u=t.regeneratorRuntime;if(u)c&&(e.exports=u);else{(u=t.regeneratorRuntime=c?e.exports:{}).wrap=_;var p="suspendedStart",h="suspendedYield",d="executing",f="completed",y={},v={};v[s]=function(){return this};var m=Object.getPrototypeOf,b=m&&m(m(C([])));b&&b!==n&&i.call(b,s)&&(v=b);var g=w.prototype=E.prototype=Object.create(v);x.prototype=g.constructor=w,w.constructor=x,w[l]=x.displayName="GeneratorFunction",u.isGeneratorFunction=function(e){var t="function"==typeof e&&e.constructor;return!!t&&(t===x||"GeneratorFunction"===(t.displayName||t.name))},u.mark=function(e){return Object.setPrototypeOf?Object.setPrototypeOf(e,w):(e.__proto__=w,l in e||(e[l]="GeneratorFunction")),e.prototype=Object.create(g),e},u.awrap=function(e){return{__await:e}},O($.prototype),$.prototype[o]=function(){return this},u.AsyncIterator=$,u.async=function(e,t,r,n){var i=new $(_(e,t,r,n));return u.isGeneratorFunction(t)?i:i.next().then(function(e){return e.done?e.value:i.next()})},O(g),g[l]="Generator",g[s]=function(){return this},g.toString=function(){return"[object Generator]"},u.keys=function(e){var t=[];for(var r in e)t.push(r);return t.reverse(),function r(){for(;t.length;){var n=t.pop();if(n in e)return r.value=n,r.done=!1,r}return r.done=!0,r}},u.values=C,I.prototype={constructor:I,reset:function(e){if(this.prev=0,this.next=0,this.sent=this._sent=r,this.done=!1,this.delegate=null,this.method="next",this.arg=r,this.tryEntries.forEach(R),!e)for(var t in this)"t"===t.charAt(0)&&i.call(this,t)&&!isNaN(+t.slice(1))&&(this[t]=r)},stop:function(){this.done=!0;var e=this.tryEntries[0].completion;if("throw"===e.type)throw e.arg;return this.rval},dispatchException:function(e){if(this.done)throw e;var t=this;function n(n,i){return o.type="throw",o.arg=e,t.next=n,i&&(t.method="next",t.arg=r),!!i}for(var a=this.tryEntries.length-1;a>=0;--a){var s=this.tryEntries[a],o=s.completion;if("root"===s.tryLoc)return n("end");if(s.tryLoc<=this.prev){var l=i.call(s,"catchLoc"),c=i.call(s,"finallyLoc");if(l&&c){if(this.prev=0;--r){var n=this.tryEntries[r];if(n.tryLoc<=this.prev&&i.call(n,"finallyLoc")&&this.prev=0;--t){var r=this.tryEntries[t];if(r.finallyLoc===e)return this.complete(r.completion,r.afterLoc),R(r),y}},catch:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var r=this.tryEntries[t];if(r.tryLoc===e){var n=r.completion;if("throw"===n.type){var i=n.arg;R(r)}return i}}throw new Error("illegal catch attempt")},delegateYield:function(e,t,n){return this.delegate={iterator:C(e),resultName:t,nextLoc:n},"next"===this.method&&(this.arg=r),y}}}function _(e,t,r,n){var i=t&&t.prototype instanceof E?t:E,a=Object.create(i.prototype),s=new I(n||[]);return a._invoke=function(e,t,r){var n=p;return function(i,a){if(n===d)throw new Error("Generator is already running");if(n===f){if("throw"===i)throw a;return A()}for(r.method=i,r.arg=a;;){var s=r.delegate;if(s){var o=S(s,r);if(o){if(o===y)continue;return o}}if("next"===r.method)r.sent=r._sent=r.arg;else if("throw"===r.method){if(n===p)throw n=f,r.arg;r.dispatchException(r.arg)}else"return"===r.method&&r.abrupt("return",r.arg);n=d;var l=k(e,t,r);if("normal"===l.type){if(n=r.done?f:h,l.arg===y)continue;return{value:l.arg,done:r.done}}"throw"===l.type&&(n=f,r.method="throw",r.arg=l.arg)}}}(e,r,s),a}function k(e,t,r){try{return{type:"normal",arg:e.call(t,r)}}catch(e){return{type:"throw",arg:e}}}function E(){}function x(){}function w(){}function O(e){["next","throw","return"].forEach(function(t){e[t]=function(e){return this._invoke(t,e)}})}function $(e){var t;this._invoke=function(r,n){function a(){return new Promise(function(t,a){!function t(r,n,a,s){var o=k(e[r],e,n);if("throw"!==o.type){var l=o.arg,c=l.value;return c&&"object"==typeof c&&i.call(c,"__await")?Promise.resolve(c.__await).then(function(e){t("next",e,a,s)},function(e){t("throw",e,a,s)}):Promise.resolve(c).then(function(e){l.value=e,a(l)},s)}s(o.arg)}(r,n,t,a)})}return t=t?t.then(a,a):a()}}function S(e,t){var n=e.iterator[t.method];if(n===r){if(t.delegate=null,"throw"===t.method){if(e.iterator.return&&(t.method="return",t.arg=r,S(e,t),"throw"===t.method))return y;t.method="throw",t.arg=new TypeError("The iterator does not provide a 'throw' method")}return y}var i=k(n,e.iterator,t.arg);if("throw"===i.type)return t.method="throw",t.arg=i.arg,t.delegate=null,y;var a=i.arg;return a?a.done?(t[e.resultName]=a.value,t.next=e.nextLoc,"return"!==t.method&&(t.method="next",t.arg=r),t.delegate=null,y):a:(t.method="throw",t.arg=new TypeError("iterator result is not an object"),t.delegate=null,y)}function T(e){var t={tryLoc:e[0]};1 in e&&(t.catchLoc=e[1]),2 in e&&(t.finallyLoc=e[2],t.afterLoc=e[3]),this.tryEntries.push(t)}function R(e){var t=e.completion||{};t.type="normal",delete t.arg,e.completion=t}function I(e){this.tryEntries=[{tryLoc:"root"}],e.forEach(T,this),this.reset(!0)}function C(e){if(e){var t=e[s];if(t)return t.call(e);if("function"==typeof e.next)return e;if(!isNaN(e.length)){var n=-1,a=function t(){for(;++n0&&void 0!==arguments[0]?arguments[0]:{};var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";var n=[];var i="";var a=l()({},r,{});var o={};s()(t).forEach(function(t){var s=h()(t,2),l=s[0],c=s[1];if("$resource"!==l){var p=c.format,d=c.enum,f=c.input,y=c.order,v=c.items,m=c.title,b=c.type,g=c.description,_=c.default;"object"===(void 0===m?"undefined":u()(m))&&(m=m[E]),"object"===(void 0===g?"undefined":u()(g))&&(g=g[E]);var k=_||"";w.includes(p)&&(k={url:"http://"}[p]);var x={placeholder:k=k.toString()};if((d||"boolean"===b)&&(b="emq-select",x.field=d?{options:d.map(function(e){return{value:e,label:e}})}:{options:[{label:!0,value:!0},{label:!1,value:!1}]}),"object"!==b||_||(_={}),"array"===b&&"object"===v.type){var $=v.schema;o=e($,"config"),_.length||(_=[])}"textarea"===f&&(x.type="textarea",x.rows=5),n.push({key:l,type:b,label:m||l,prop:l,defaultValue:_,$attrs:x,description:(g||"").replace(/\n/g,"
"),order:y,oneObjOfArray:o}),r?a[r][l]=O(t):a[l]=O(t)}else i="string"});n=n.sort(function(e,t){return e.order-t.order});return{model:n,rules:a,resource:i}},t.b=function(e){if("zh"===E)return _[e];return k[e]},t.e=function(e,t,r){return new i.a(function(n,i){try{var a=e.filter(function(e){if(e[t]){var n=e[t].toLowerCase().replace(/\s+/g,""),i=r.toLocaleLowerCase().replace(/\s+/g,"");return n.match(i)}return null});return n(a)}catch(e){return i(e)}})},t.h=function(e){var t=e.replace(/\"/g,""),r=null;return["message.publish","message.deliver","message.acked","message.dropped","client.connected","client.disconnected","client.subscribe","client.unsubscribe"].forEach(function(e){var n=e.split("."),i=h()(n,2),a=i[0],s=i[1],o=new RegExp(a+"\\."+s,"gim");t.match(o)&&(r=t.match(o))}),r},t.g=function(e,t){var r={"message.publish":"","message.deliver":"$events/message_delivered","message.acked":"$events/message_acked","message.dropped":"$events/message_dropped","client.connected":"$events/client_connected","client.disconnected":"$events/client_disconnected","client.subscribe":"$events/session_subscribed","client.unsubscribe":"$events/session_unsubscribed"}[t],n=e.replace(/\"/g,""),i=m.a.parse(n);""===r&&(i.value.where=null,r="#");return i.value.from.value[0].value.value.value='"'+r+'"',m.a.stringify(i)},t.a=function(e,t){var r=(t-e)%864e5,n=Math.floor(r/36e5),i=r%36e5,a=Math.floor(i/6e4),s=i%6e4,o=Math.round(s/1e3);return n+":"+a+":"+o},r.d(t,"i",function(){return S}),r.d(t,"d",function(){return T});var E=window.localStorage.language||window.EMQX_DASHBOARD_CONFIG.lang||"en",x={is_required:{en:"is required",zh:"必填"}},w=["string","number","boolean","method","regexp","integer","float","array","object","enum","date","url","hex","email"];function O(e){var t=h()(e,2),r=t[0],n=t[1],i=(n.type,n.format,n.required),a=(n.enum,n.title);"object"===(void 0===a?"undefined":u()(a))&&(a=a[E]);var s={};i&&(s.required=!0,s.message=(a||r)+" "+x.is_required[E])}function $(e,t){var r=new y.a(t.target,{text:function(){return e}});r.on("success",function(){d.default.prototype.$message({message:d.default.prototype.$t("oper.copySuccess"),type:"success",duration:1500}),r.destroy()}),r.on("error",function(){d.default.prototype.$message({message:d.default.prototype.$t("oper.copyFailed"),type:"error"}),r.destroy()}),r.onClick(t)}var S=function(e,t,r){t?t.length>64?r(new Error(d.default.prototype.$t("rule.id_len_tip"))):/^[0-9a-zA-Z_:]{1,64}$/.test(t)?r():r(new Error(d.default.prototype.$t("rule.id_char_tip"))):r(new Error("ID "+d.default.prototype.$t("rule.is_required")))},T=function(e,t){return e&&e.length>t?e.substring(0,t)+"...":e}},SHGx:function(e,t,r){"use strict";var n=r("pFYg"),i=r.n(n),a=r("fZjL"),s=r.n(a),o=r("Dd8w"),l=r.n(o),c=r("FcGO"),u=r("d7EF"),p=r.n(u),h=r("W3Iv"),d=r.n(h),f=r("woOf"),y=r.n(f),v={name:"ArrayEditor",components:{EmqSelect:c.a},model:{prop:"value",event:"update"},props:{value:{type:Array,required:!0},notNull:{type:Boolean,default:!1},data:{type:Object,required:!0}},data:function(){return{tableData:[],headers:[],oneRow:{},defaultConfig:{}}},created:function(){this.initData()},methods:{assignValue:function(){var e=this;if(this.value.length){for(var t=0;t0&&void 0!==arguments[0])||arguments[0];this.$refs.record.validate(function(r){if(r){var n=e.record.config;s()(n).forEach(function(t){var r=n[t];"true"===r&&(e.record.config[t]=!0),"false"===r&&(e.record.config[t]=!1)});var i=t?"/resources":"/resources?test=true";e.$httpPost(i,e.record).then(function(r){t?(e.$message.success(e.$t("rule.create_success")),e.dialogVisible=!1,e.$emit("confirm",r.data)):e.$message.success(e.$t("rule.conf_test_success"))}).catch(function(){})}})},handleTypeChange:function(e){this.paramsList=[],this.resourceRules={};var t=this.resourceTypes.find(function(t){return t.name===e});if(t){var r=Object(g.f)(t.params,"config"),n=r.model,i=r.rules;this.resourceRules=i,this.paramsList=n,this.initRecord(),setTimeout(this.clearTabIndex,500)}},initRecord:function(){var e=this;0===this.paramsList.length?this.$set(this.record,"config",void 0):this.record.config||this.$set(this.record,"config",{}),this.$set(this.record,"config",{}),this.paramsList.forEach(function(t){e.$set(e.record.config,t.key,t.defaultValue)}),setTimeout(function(){e.$refs.record.clearValidate()},30)},loadResourceTypes:function(){var e=this;this.$httpGet("/resource_types").then(function(t){e.record={type:"",config:{},description:"",id:"resource:"+Math.random().toString().slice(3,9)},e.resourceType&&(e.record.type=e.resourceType),e.resourceTypes=t.data.map(function(e){return e.titleLabel="object"===i()(e.title)?e.title[_]:e.title,e}),e.handleTypeChange(e.record.type),setTimeout(function(){e.$refs.record.clearValidate()},30)})}}},E={render:function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("el-dialog",e._b({staticClass:"resource-dialog",attrs:{width:"700px",visible:e.dialogVisible,title:e.$t("rule.resource_mgmt")},on:{"update:visible":function(t){e.dialogVisible=t},close:e.close,open:e.loadResourceTypes}},"el-dialog",e.$attrs,!1),[r("el-form",{ref:"record",staticClass:"el-form--public",attrs:{model:e.record,rules:e.rules}},[r("el-row",{attrs:{gutter:20}},[r("el-col",{attrs:{span:12}},[r("el-form-item",{attrs:{prop:"type",label:e.$t("rule.resource_type")}},[r("el-select",{staticClass:"el-select--public",staticStyle:{width:"100%"},attrs:{"popper-class":"el-select--public",disabled:!!e.resourceType},on:{change:e.handleTypeChange},model:{value:e.record.type,callback:function(t){e.$set(e.record,"type",t)},expression:"record.type"}},e._l(e.resourceTypes,function(t,n){return r("div",{key:n},[0===e.enableItem.length||e.enableItem.includes(t.name)?r("el-option",{attrs:{label:t.titleLabel,value:t.name}}):e._e()],1)}),0)],1)],1),e._v(" "),r("el-col",{attrs:{span:12}},[r("el-form-item",[r("template",{slot:"label"},[e._v(" ")]),e._v(" "),r("el-button",{attrs:{type:"primary"},on:{click:function(t){return e.handleCreate(!1)}}},[e._v("\n "+e._s(e.$t("rule.conf_test"))+"\n ")])],2)],1),e._v(" "),e.record.type?[r("el-col",{attrs:{span:12}},[r("el-form-item",{attrs:{prop:"id",label:e.$t("rule.resource_id")}},[r("el-input",{model:{value:e.record.id,callback:function(t){e.$set(e.record,"id",t)},expression:"record.id"}})],1)],1),e._v(" "),r("el-col",{attrs:{span:12}},[r("el-form-item",{attrs:{prop:"description",label:e.$t("rule.resource_des")}},[r("el-input",{attrs:{type:"textarea"},model:{value:e.record.description,callback:function(t){e.$set(e.record,"description",t)},expression:"record.description"}})],1)],1),e._v(" "),e._l(e.paramsList,function(t,n){return r("el-col",{key:n,attrs:{span:"object"===t.type||"array"===t.type||"textarea"===t.$attrs.type?24:12}},[r("el-form-item",{attrs:{prop:"config."+t.prop}},[r("template",{slot:"label"},[e._v("\n "+e._s(t.label)+"\n\n "),t.description?r("el-popover",{attrs:{placement:"right",width:"200",trigger:"hover"}},[r("div",{domProps:{innerHTML:e._s(t.description)}}),e._v(" "),r("span",{staticClass:"el-icon-question",attrs:{slot:"reference",tabindex:"-1"},slot:"reference"})]):e._e()],1),e._v(" "),"object"===t.type?r("data-table",{model:{value:e.record.config[t.key],callback:function(r){e.$set(e.record.config,t.key,r)},expression:"record.config[item.key]"}}):"array"===t.type?[r("array-editor",{attrs:{data:t.oneObjOfArray},model:{value:e.record.config[t.key],callback:function(r){e.$set(e.record.config,t.key,r)},expression:"record.config[item.key]"}})]:"emq-select"===t.type?r("emq-select",e._b({staticClass:"el-select--public",attrs:{"popper-class":"el-select--public"},model:{value:e.record.config[t.key],callback:function(r){e.$set(e.record.config,t.key,r)},expression:"record.config[item.key]"}},"emq-select",t.$attrs,!1)):"number"===t.type?r("el-input",e._b({attrs:{type:"number"},model:{value:e.record.config[t.key],callback:function(r){e.$set(e.record.config,t.key,e._n(r))},expression:"record.config[item.key]"}},"el-input",t.$attrs,!1)):r("el-input",e._b({model:{value:e.record.config[t.key],callback:function(r){e.$set(e.record.config,t.key,r)},expression:"record.config[item.key]"}},"el-input",t.$attrs,!1))],2)],1)})]:e._e()],2)],1),e._v(" "),r("div",{attrs:{slot:"footer"},slot:"footer"},[r("el-button",{staticClass:"cache-btn",attrs:{type:"text"},on:{click:function(t){e.dialogVisible=!1}}},[e._v("\n "+e._s(e.$t("rule.cancel"))+"\n ")]),e._v(" "),r("el-button",{staticClass:"confirm-btn",attrs:{type:"success"},on:{click:e.handleCreate}},[e._v("\n "+e._s(e.$t("rule.create"))+"\n ")])],1)],1)},staticRenderFns:[]};var x=r("VU/8")(k,E,!1,function(e){r("G5A+")},null,null);t.a=x.exports},TQvf:function(e,t,r){ +/*! + * clipboard.js v2.0.6 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */ +var n;n=function(){return function(e){var t={};function r(n){if(t[n])return t[n].exports;var i=t[n]={i:n,l:!1,exports:{}};return e[n].call(i.exports,i,i.exports,r),i.l=!0,i.exports}return r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)r.d(n,i,function(t){return e[t]}.bind(null,i));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=6)}([function(e,t){e.exports=function(e){var t;if("SELECT"===e.nodeName)e.focus(),t=e.value;else if("INPUT"===e.nodeName||"TEXTAREA"===e.nodeName){var r=e.hasAttribute("readonly");r||e.setAttribute("readonly",""),e.select(),e.setSelectionRange(0,e.value.length),r||e.removeAttribute("readonly"),t=e.value}else{e.hasAttribute("contenteditable")&&e.focus();var n=window.getSelection(),i=document.createRange();i.selectNodeContents(e),n.removeAllRanges(),n.addRange(i),t=n.toString()}return t}},function(e,t){function r(){}r.prototype={on:function(e,t,r){var n=this.e||(this.e={});return(n[e]||(n[e]=[])).push({fn:t,ctx:r}),this},once:function(e,t,r){var n=this;function i(){n.off(e,i),t.apply(r,arguments)}return i._=t,this.on(e,i,r)},emit:function(e){for(var t=[].slice.call(arguments,1),r=((this.e||(this.e={}))[e]||[]).slice(),n=0,i=r.length;n0&&void 0!==arguments[0]?arguments[0]:{};this.action=e.action,this.container=e.container,this.emitter=e.emitter,this.target=e.target,this.text=e.text,this.trigger=e.trigger,this.selectedText=""}},{key:"initSelection",value:function(){this.text?this.selectFake():this.target&&this.selectTarget()}},{key:"selectFake",value:function(){var e=this,t="rtl"==document.documentElement.getAttribute("dir");this.removeFake(),this.fakeHandlerCallback=function(){return e.removeFake()},this.fakeHandler=this.container.addEventListener("click",this.fakeHandlerCallback)||!0,this.fakeElem=document.createElement("textarea"),this.fakeElem.style.fontSize="12pt",this.fakeElem.style.border="0",this.fakeElem.style.padding="0",this.fakeElem.style.margin="0",this.fakeElem.style.position="absolute",this.fakeElem.style[t?"right":"left"]="-9999px";var r=window.pageYOffset||document.documentElement.scrollTop;this.fakeElem.style.top=r+"px",this.fakeElem.setAttribute("readonly",""),this.fakeElem.value=this.text,this.container.appendChild(this.fakeElem),this.selectedText=i()(this.fakeElem),this.copyText()}},{key:"removeFake",value:function(){this.fakeHandler&&(this.container.removeEventListener("click",this.fakeHandlerCallback),this.fakeHandler=null,this.fakeHandlerCallback=null),this.fakeElem&&(this.container.removeChild(this.fakeElem),this.fakeElem=null)}},{key:"selectTarget",value:function(){this.selectedText=i()(this.target),this.copyText()}},{key:"copyText",value:function(){var e=void 0;try{e=document.execCommand(this.action)}catch(t){e=!1}this.handleResult(e)}},{key:"handleResult",value:function(e){this.emitter.emit(e?"success":"error",{action:this.action,text:this.selectedText,trigger:this.trigger,clearSelection:this.clearSelection.bind(this)})}},{key:"clearSelection",value:function(){this.trigger&&this.trigger.focus(),document.activeElement.blur(),window.getSelection().removeAllRanges()}},{key:"destroy",value:function(){this.removeFake()}},{key:"action",set:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"copy";if(this._action=e,"copy"!==this._action&&"cut"!==this._action)throw new Error('Invalid "action" value, use either "copy" or "cut"')},get:function(){return this._action}},{key:"target",set:function(e){if(void 0!==e){if(!e||"object"!==(void 0===e?"undefined":a(e))||1!==e.nodeType)throw new Error('Invalid "target" value, use a valid Element');if("copy"===this.action&&e.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if("cut"===this.action&&(e.hasAttribute("readonly")||e.hasAttribute("disabled")))throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes');this._target=e}},get:function(){return this._target}}]),e}(),l=r(1),c=r.n(l),u=r(2),p=r.n(u),h="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},d=function(){function e(e,t){for(var r=0;r0&&void 0!==arguments[0]?arguments[0]:{};this.action="function"==typeof e.action?e.action:this.defaultAction,this.target="function"==typeof e.target?e.target:this.defaultTarget,this.text="function"==typeof e.text?e.text:this.defaultText,this.container="object"===h(e.container)?e.container:document.body}},{key:"listenClick",value:function(e){var t=this;this.listener=p()(e,"click",function(e){return t.onClick(e)})}},{key:"onClick",value:function(e){var t=e.delegateTarget||e.currentTarget;this.clipboardAction&&(this.clipboardAction=null),this.clipboardAction=new o({action:this.action(t),target:this.target(t),text:this.text(t),container:this.container,trigger:t,emitter:this})}},{key:"defaultAction",value:function(e){return y("action",e)}},{key:"defaultTarget",value:function(e){var t=y("target",e);if(t)return document.querySelector(t)}},{key:"defaultText",value:function(e){return y("text",e)}},{key:"destroy",value:function(){this.listener.destroy(),this.clipboardAction&&(this.clipboardAction.destroy(),this.clipboardAction=null)}}],[{key:"isSupported",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:["copy","cut"],t="string"==typeof e?[e]:e,r=!!document.queryCommandSupported;return t.forEach(function(e){r=r&&!!document.queryCommandSupported(e)}),r}}]),t}();function y(e,t){var r="data-clipboard-"+e;if(t.hasAttribute(r))return t.getAttribute(r)}t.default=f}]).default},e.exports=n()},Xxa5:function(e,t,r){e.exports=r("1H6C")},cMrt:function(e,t){e.exports={en:{emqx_auth_clientid:"https://docs.emqx.io/broker/latest/en/advanced/auth-clientid.html",emqx_auth_username:"https://docs.emqx.io/broker/latest/en/advanced/auth-username.html",emqx_auth_http:"https://docs.emqx.io/broker/latest/en/advanced/auth-http.html",emqx_auth_jwt:"https://docs.emqx.io/broker/latest/en/advanced/auth-jwt.html",emqx_auth_ldap:"https://docs.emqx.io/broker/latest/en/advanced/auth-ldap.html",emqx_auth_mnesia:"https://docs.emqx.io/broker/latest/en/advanced/auth-mnesia.html",emqx_auth_mongo:"https://docs.emqx.io/broker/latest/en/advanced/auth-mongodb.html",emqx_auth_mysql:"https://docs.emqx.io/broker/latest/en/advanced/auth-mysql.html",emqx_auth_pgsql:"https://docs.emqx.io/broker/latest/en/advanced/auth-postgresql.html",emqx_auth_redis:"https://docs.emqx.io/broker/latest/en/advanced/auth-redis.html",emqx_dashboard:"https://docs.emqx.io/broker/latest/en/getting-started/dashboard.html",emqx_extension_hook:"https://docs.emqx.io/broker/latest/en/advanced/multiple-language-support.html",emqx_rule_engine:"https://docs.emqx.io/broker/latest/en/rule/rule-engine.html"},zh:{emqx_auth_clientid:"https://docs.emqx.io/broker/latest/cn/advanced/auth-clientid.html",emqx_auth_username:"https://docs.emqx.io/broker/latest/cn/advanced/auth-username.html",emqx_auth_http:"https://docs.emqx.io/broker/latest/cn/advanced/auth-http.html",emqx_auth_jwt:"https://docs.emqx.io/broker/latest/cn/advanced/auth-jwt.html",emqx_auth_ldap:"https://docs.emqx.io/broker/latest/cn/advanced/auth-ldap.html",emqx_auth_mnesia:"https://docs.emqx.io/broker/latest/cn/advanced/auth-mnesia.html",emqx_auth_mongo:"https://docs.emqx.io/broker/latest/cn/advanced/auth-mongodb.html",emqx_auth_mysql:"https://docs.emqx.io/broker/latest/cn/advanced/auth-mysql.html",emqx_auth_pgsql:"https://docs.emqx.io/broker/latest/cn/advanced/auth-postgresql.html",emqx_auth_redis:"https://docs.emqx.io/broker/latest/cn/advanced/auth-redis.html",emqx_dashboard:"https://docs.emqx.io/broker/latest/cn/getting-started/dashboard.html",emqx_extension_hook:"https://docs.emqx.io/broker/latest/cn/advanced/multiple-language-support.html",emqx_rule_engine:"https://docs.emqx.io/broker/latest/cn/rule/rule-engine.html"}}},dmxg:function(e,t,r){var n,i=function(){var e=function(e,t,r,n){for(r=r||{},n=e.length;n--;r[e[n]]=t);return r},t=[1,8],r=[1,4],n=[2,4],i=[1,11],a=[1,10],s=[2,16],o=[1,14],l=[1,15],c=[1,16],u=[6,8],p=[2,144],h=[1,19],d=[1,20],f=[16,33,35,36,37,38,39,40,41,42,45,46,50,52,53,55,56,58,59,61,76,79,81,82,83,84,86,87,88,101],y=[16,18,32,33,35,36,37,38,39,40,41,42,45,46,50,52,53,55,56,58,59,61,76,79,81,82,83,84,86,87,88,101],v=[2,158],m=[1,29],b=[6,8,14,17,146,150,152,154],g=[1,42],_=[1,60],k=[1,51],E=[1,58],x=[1,59],w=[1,61],O=[1,62],$=[1,63],S=[1,64],T=[1,65],R=[1,57],I=[1,52],C=[1,53],A=[1,54],L=[1,55],N=[1,56],q=[1,43],F=[1,44],K=[1,45],P=[1,34],D=[16,35,36,37,38,39,40,41,42,45,46,50,52,53,55,56,58,59,61,76,79,81,82,83,84,86,87,88,101],j=[6,8,14,17,150,152,154],B=[2,141],U=[1,74],H=[1,75],M=[6,8,14,17,43,133,138,144,146,150,152,154],G=[1,80],V=[1,77],Q=[1,78],W=[1,79],X=[1,81],J=[6,8,14,17,36,43,49,50,71,72,74,77,89,107,124,125,126,127,129,133,135,138,141,142,144,146,150,152,154,157,164,165,167,168,173,177,179,180,182],z=[6,8,14,17,34,36,43,49,50,71,72,74,77,89,107,112,113,114,115,116,117,121,124,125,126,127,129,133,135,138,141,142,144,146,150,152,154,157,164,165,167,168,173,177,179,180,182],Y=[1,102],Z=[1,100],ee=[1,101],te=[1,96],re=[1,97],ne=[1,98],ie=[1,99],ae=[1,103],se=[1,104],oe=[1,105],le=[1,106],ce=[1,107],ue=[1,108],pe=[2,101],he=[6,8,14,17,34,36,43,45,49,50,71,72,74,77,79,81,89,91,92,93,94,95,96,97,98,99,101,105,106,107,108,109,110,112,113,114,115,116,117,121,124,125,126,127,129,133,135,138,141,142,144,146,150,152,154,157,164,165,167,168,173,177,179,180,182],de=[6,8,14,17,34,36,43,45,49,50,71,72,74,77,79,81,89,91,92,93,94,95,96,97,98,99,101,103,105,106,107,108,109,110,112,113,114,115,116,117,121,124,125,126,127,129,133,135,138,141,142,144,146,150,152,154,157,164,165,167,168,173,177,179,180,182],fe=[1,109],ye=[1,116],ve=[2,62],me=[1,117],be=[16,35,37,38,39,40,41,42,45,46,50,52,53,55,56,58,59,61,76,79,81,82,83,84,86,87,88,101],ge=[16,29,35,50,52,53,55,56,58,59,61,76,79,81,82,83,84,86,87,88,119],_e=[1,163],ke=[17,43],Ee=[2,57],xe=[1,172],we=[1,170],Oe=[1,171],$e=[6,8,138,146],Se=[16,35,38,39,40,41,42,45,46,50,52,53,55,56,58,59,61,76,79,81,82,83,84,86,87,88,101],Te=[6,8,14,17,138,144,146,150,152,154],Re=[6,8,14,17,36,43,49,50,71,72,74,77,89,125,126,127,129,133,135,138,141,142,144,146,150,152,154,157,164,165,167,168,173,177,179,180,182],Ie=[6,8,14,17,34,36,43,49,50,71,72,74,77,89,91,92,93,94,99,101,105,106,107,108,109,110,112,113,114,115,116,117,121,124,125,126,127,129,133,135,138,141,142,144,146,150,152,154,157,164,165,167,168,173,177,179,180,182],Ce=[6,8,14,17,34,36,43,49,50,71,72,74,77,79,81,89,91,92,93,94,99,101,105,106,107,108,109,110,112,113,114,115,116,117,121,124,125,126,127,129,133,135,138,141,142,144,146,150,152,154,157,164,165,167,168,173,177,179,180,182],Ae=[16,35,39,40,41,42,45,46,50,52,53,55,56,58,59,61,76,79,81,82,83,84,86,87,88,101],Le=[16,35,40,41,42,45,46,50,52,53,55,56,58,59,61,76,79,81,82,83,84,86,87,88,101],Ne=[16,35,42,45,46,50,52,53,55,56,58,59,61,76,79,81,82,83,84,86,87,88,101],qe=[71,74,77],Fe=[16,35,45,46,50,52,53,55,56,58,59,61,76,79,81,82,83,84,86,87,88,101],Ke=[1,232],Pe=[1,233],De=[6,8,14,17],je=[6,8,14,17,43,157],Be=[1,249],Ue=[1,245],He=[2,195],Me=[1,252],Ge=[1,253],Ve=[6,8,14,17,43,129,135,138,144,146,150,152,154,182],Qe=[1,255],We=[1,258],Xe=[1,259],Je=[1,260],ze=[1,261],Ye=[2,172],Ze=[1,257],et=[6,8,14,17,36,43,89,129,135,138,144,146,150,152,154,164,165,167,168,173,177,179,180,182],tt=[6,8,14,17,135,138,144,146,150,152,154],rt=[1,273],nt=[2,177],it=[170,173],at=[6,8,14,17,36,43,89,129,135,138,144,146,150,152,154,164,165,167,168,173,177,179,180,182,192,193,194],st=[2,197],ot=[1,278],lt=[1,290],ct=[1,298],ut=[1,299],pt=[1,300],ht=[6,8,14,17,138,146,150,152,154],dt=[1,310],ft=[1,316],yt=[1,317],vt=[2,202],mt=[1,328],bt=[16,152],gt=[6,8,14,17,152,154],_t=[1,344],kt={trace:function(){},yy:{},symbols_:{error:2,main:3,selectClause:4,semicolonOpt:5,EOF:6,unionClause:7,";":8,unionClauseNotParenthesized:9,unionClauseParenthesized:10,order_by_opt:11,limit_opt:12,selectClauseParenthesized:13,UNION:14,distinctOpt:15,"(":16,")":17,SELECT:18,highPriorityOpt:19,maxStateMentTimeOpt:20,straightJoinOpt:21,sqlSmallResultOpt:22,sqlBigResultOpt:23,sqlBufferResultOpt:24,sqlCacheOpt:25,sqlCalcFoundRowsOpt:26,selectExprList:27,selectDataSetOpt:28,ALL:29,DISTINCT:30,DISTINCTROW:31,HIGH_PRIORITY:32,MAX_STATEMENT_TIME:33,"=":34,NUMERIC:35,STRAIGHT_JOIN:36,SQL_SMALL_RESULT:37,SQL_BIG_RESULT:38,SQL_BUFFER_RESULT:39,SQL_CACHE:40,SQL_NO_CACHE:41,SQL_CALC_FOUND_ROWS:42,",":43,selectExpr:44,"*":45,SELECT_EXPR_STAR:46,expr:47,selectExprAliasOpt:48,AS:49,IDENTIFIER:50,string:51,QUOTED_IDENTIFIER:52,STRING:53,number:54,EXPONENT_NUMERIC:55,HEX_NUMERIC:56,boolean:57,TRUE:58,FALSE:59,null:60,NULL:61,literal:62,function_call:63,function_call_param_list:64,function_call_param:65,identifier:66,DOT:67,identifier_list:68,case_expr_opt:69,when_then_list:70,WHEN:71,THEN:72,case_when_else:73,ELSE:74,case_when:75,CASE:76,END:77,simple_expr_prefix:78,"+":79,simple_expr:80,"-":81,"~":82,"!":83,BINARY:84,expr_list:85,ROW:86,EXISTS:87,"{":88,"}":89,bit_expr:90,"|":91,"&":92,"<<":93,">>":94,"/":95,DIV:96,MOD:97,"%":98,"^":99,not_opt:100,NOT:101,escape_opt:102,ESCAPE:103,predicate:104,IN:105,BETWEEN:106,AND:107,SOUNDS:108,LIKE:109,REGEXP:110,comparison_operator:111,">=":112,">":113,"<=":114,"<":115,"<>":116,"!=":117,sub_query_data_set_opt:118,ANY:119,boolean_primary:120,IS:121,boolean_extra:122,UNKNOWN:123,"&&":124,"||":125,OR:126,XOR:127,where_opt:128,WHERE:129,group_by_opt:130,group_by:131,roll_up_opt:132,WITH:133,ROLLUP:134,GROUP_BY:135,group_by_order_by_item_list:136,order_by:137,ORDER_BY:138,group_by_order_by_item:139,sort_opt:140,ASC:141,DESC:142,having_opt:143,HAVING:144,limit:145,LIMIT:146,OFFSET:147,procedure_opt:148,procedure:149,PROCEDURE:150,for_update_lock_in_share_mode_opt:151,FOR:152,UPDATE:153,LOCK:154,SHARE:155,MODE:156,FROM:157,table_references:158,partitionOpt:159,escaped_table_reference:160,table_reference:161,OJ:162,join_inner_cross:163,INNER:164,CROSS:165,left_right:166,LEFT:167,RIGHT:168,out_opt:169,OUTER:170,left_right_out_opt:171,join_table:172,JOIN:173,table_factor:174,join_condition:175,on_join_condition:176,NATURAL:177,join_condition_opt:178,ON:179,USING:180,partition_names:181,PARTITION:182,aliasOpt:183,index_or_key:184,INDEX:185,KEY:186,for_opt:187,identifier_list_opt:188,index_hint_list_opt:189,index_hint_list:190,index_hint:191,USE:192,IGNORE:193,FORCE:194,$accept:0,$end:1},terminals_:{2:"error",6:"EOF",8:";",14:"UNION",16:"(",17:")",18:"SELECT",29:"ALL",30:"DISTINCT",31:"DISTINCTROW",32:"HIGH_PRIORITY",33:"MAX_STATEMENT_TIME",34:"=",35:"NUMERIC",36:"STRAIGHT_JOIN",37:"SQL_SMALL_RESULT",38:"SQL_BIG_RESULT",39:"SQL_BUFFER_RESULT",40:"SQL_CACHE",41:"SQL_NO_CACHE",42:"SQL_CALC_FOUND_ROWS",43:",",45:"*",46:"SELECT_EXPR_STAR",49:"AS",50:"IDENTIFIER",52:"QUOTED_IDENTIFIER",53:"STRING",55:"EXPONENT_NUMERIC",56:"HEX_NUMERIC",58:"TRUE",59:"FALSE",61:"NULL",67:"DOT",71:"WHEN",72:"THEN",74:"ELSE",76:"CASE",77:"END",79:"+",81:"-",82:"~",83:"!",84:"BINARY",86:"ROW",87:"EXISTS",88:"{",89:"}",91:"|",92:"&",93:"<<",94:">>",95:"/",96:"DIV",97:"MOD",98:"%",99:"^",101:"NOT",103:"ESCAPE",105:"IN",106:"BETWEEN",107:"AND",108:"SOUNDS",109:"LIKE",110:"REGEXP",112:">=",113:">",114:"<=",115:"<",116:"<>",117:"!=",119:"ANY",121:"IS",123:"UNKNOWN",124:"&&",125:"||",126:"OR",127:"XOR",129:"WHERE",133:"WITH",134:"ROLLUP",135:"GROUP_BY",138:"ORDER_BY",141:"ASC",142:"DESC",144:"HAVING",146:"LIMIT",147:"OFFSET",150:"PROCEDURE",152:"FOR",153:"UPDATE",154:"LOCK",155:"SHARE",156:"MODE",157:"FROM",162:"OJ",164:"INNER",165:"CROSS",167:"LEFT",168:"RIGHT",170:"OUTER",173:"JOIN",177:"NATURAL",179:"ON",180:"USING",182:"PARTITION",185:"INDEX",186:"KEY",192:"USE",193:"IGNORE",194:"FORCE"},productions_:[0,[3,3],[3,3],[5,1],[5,0],[7,1],[7,3],[10,4],[10,4],[13,3],[9,4],[9,4],[4,12],[15,1],[15,1],[15,1],[15,0],[19,1],[19,0],[20,3],[20,0],[21,1],[21,0],[22,1],[22,0],[23,1],[23,0],[24,1],[24,0],[25,0],[25,1],[25,1],[26,1],[26,0],[27,3],[27,1],[44,1],[44,1],[44,2],[48,0],[48,2],[48,1],[51,1],[51,1],[54,1],[54,1],[54,1],[57,1],[57,1],[60,1],[62,1],[62,1],[62,1],[62,1],[63,4],[64,3],[64,1],[65,0],[65,1],[65,1],[65,2],[65,1],[66,1],[66,3],[68,1],[68,3],[69,0],[69,1],[70,4],[70,5],[73,0],[73,2],[75,5],[78,2],[78,2],[78,2],[78,2],[78,2],[80,1],[80,1],[80,1],[80,1],[80,3],[80,4],[80,3],[80,4],[80,4],[80,1],[90,1],[90,3],[90,3],[90,3],[90,3],[90,3],[90,3],[90,3],[90,3],[90,3],[90,3],[90,3],[90,3],[100,0],[100,1],[102,0],[102,2],[104,1],[104,6],[104,6],[104,6],[104,4],[104,5],[104,4],[111,1],[111,1],[111,1],[111,1],[111,1],[111,1],[111,1],[118,1],[118,1],[120,1],[120,4],[120,3],[120,6],[122,1],[122,1],[47,1],[47,4],[47,2],[47,3],[47,3],[47,3],[47,3],[47,3],[85,1],[85,3],[128,0],[128,2],[130,0],[130,1],[132,0],[132,2],[131,3],[11,0],[11,1],[137,3],[136,1],[136,3],[139,2],[140,0],[140,1],[140,1],[143,0],[143,2],[145,2],[145,4],[145,4],[12,0],[12,1],[148,0],[148,1],[149,2],[151,0],[151,2],[151,4],[28,0],[28,10],[158,1],[158,3],[160,1],[160,4],[163,0],[163,1],[163,1],[166,1],[166,1],[169,0],[169,1],[171,0],[171,2],[172,4],[172,5],[172,4],[172,6],[172,5],[178,0],[178,1],[176,2],[175,1],[175,4],[161,1],[161,1],[181,1],[181,3],[159,0],[159,4],[183,0],[183,2],[183,1],[184,1],[184,1],[187,0],[187,2],[187,2],[187,2],[188,0],[188,1],[189,0],[189,1],[190,1],[190,3],[191,6],[191,6],[191,6],[174,4],[174,4],[174,3]],performAction:function(e,t,r,n,i,a,s){var o=a.length-1;switch(i){case 1:case 2:return{nodeType:"Main",value:a[o-2],hasSemicolon:a[o-1]};case 3:case 142:this.$=!0;break;case 4:this.$=!1;break;case 5:case 13:case 14:case 15:case 17:case 19:case 21:case 23:case 25:case 27:case 30:case 31:case 32:case 50:case 51:case 52:case 53:case 58:case 59:case 61:case 67:case 71:case 78:case 79:case 80:case 81:case 87:case 88:case 102:case 104:case 105:case 112:case 113:case 114:case 115:case 116:case 117:case 118:case 119:case 120:case 121:case 125:case 127:case 138:case 140:case 145:case 151:case 152:case 154:case 159:case 161:case 162:case 173:case 174:case 175:case 176:case 178:case 187:case 189:case 191:case 192:case 200:case 201:case 207:case 209:this.$=a[o];break;case 6:this.$=a[o-2],this.$.orderBy=a[o-1],this.$.limit=a[o];break;case 7:case 8:this.$={type:"Union",left:a[o-3],distinctOpt:a[o-1],right:a[o]};break;case 9:this.$={type:"SelectParenthesized",value:a[o-1]};break;case 10:case 11:this.$={type:"Union",left:a[o-3],distinctOpt:a[o-1],right:a[o]};break;case 12:this.$={type:"Select",distinctOpt:a[o-10],highPriorityOpt:a[o-9],maxStateMentTimeOpt:a[o-8],straightJoinOpt:a[o-7],sqlSmallResultOpt:a[o-6],sqlBigResultOpt:a[o-5],sqlBufferResultOpt:a[o-4],sqlCacheOpt:a[o-3],sqlCalcFoundRowsOpt:a[o-2],selectItems:a[o-1],from:a[o].from,partition:a[o].partition,where:a[o].where,groupBy:a[o].groupBy,having:a[o].having,orderBy:a[o].orderBy,limit:a[o].limit,procedure:a[o].procedure,updateLockMode:a[o].updateLockMode};break;case 16:case 18:case 20:case 22:case 24:case 26:case 28:case 29:case 33:case 57:case 66:case 70:case 101:case 103:case 137:case 139:case 141:case 144:case 150:case 153:case 158:case 160:case 163:case 172:case 177:case 186:case 195:case 202:case 206:case 208:this.$=null;break;case 34:a[o-2].value.push(a[o]);break;case 35:this.$={type:"SelectExpr",value:[a[o]]};break;case 36:case 37:case 62:this.$={type:"Identifier",value:a[o]};break;case 38:this.$=a[o-1],this.$.alias=a[o].alias,this.$.hasAs=a[o].hasAs;break;case 39:case 197:this.$={alias:null,hasAs:null};break;case 40:this.$={alias:a[o],hasAs:!0};break;case 41:this.$={alias:a[o],hasAs:!1};break;case 42:case 43:this.$={type:"String",value:a[o]};break;case 44:case 45:case 46:this.$={type:"Number",value:a[o]};break;case 47:this.$={type:"Boolean",value:"TRUE"};break;case 48:this.$={type:"Boolean",value:"FALSE"};break;case 49:this.$={type:"Null",value:"null"};break;case 54:this.$={type:"FunctionCall",name:a[o-3],params:a[o-1]};break;case 55:a[o-2].push(a[o]),this.$=a[o-2];break;case 56:this.$=[a[o]];break;case 60:this.$={type:"FunctionCallParam",distinctOpt:a[o-1],value:a[o]};break;case 63:this.$=a[o-2],a[o-2].value+="."+a[o];break;case 64:this.$={type:"IdentifierList",value:[a[o]]};break;case 65:case 169:this.$=a[o-2],a[o-2].value.push(a[o]);break;case 68:this.$={type:"WhenThenList",value:[{when:a[o-2],then:a[o]}]};break;case 69:this.$=a[o-4],this.$.value.push({when:a[o-2],then:a[o]});break;case 72:this.$={type:"CaseWhen",caseExprOpt:a[o-3],whenThenList:a[o-2],else:a[o-1]};break;case 73:case 74:case 75:case 76:case 77:this.$={type:"Prefix",prefix:a[o-1],value:a[o]};break;case 82:this.$={type:"SimpleExprParentheses",value:a[o-1]};break;case 83:this.$={type:"SimpleExprParentheses",value:a[o-2],hasRow:!0};break;case 84:this.$={type:"SubQuery",value:a[o-1]};break;case 85:this.$={type:"SubQuery",value:a[o-1],hasExists:!0};break;case 86:this.$={type:"IdentifierExpr",identifier:a[o-2],value:a[o-1]};break;case 89:this.$={type:"BitExpression",operator:"|",left:a[o-2],right:a[o]};break;case 90:this.$={type:"BitExpression",operator:"&",left:a[o-2],right:a[o]};break;case 91:this.$={type:"BitExpression",operator:"<<",left:a[o-2],right:a[o]};break;case 92:this.$={type:"BitExpression",operator:">>",left:a[o-2],right:a[o]};break;case 93:this.$={type:"BitExpression",operator:"+",left:a[o-2],right:a[o]};break;case 94:this.$={type:"BitExpression",operator:"-",left:a[o-2],right:a[o]};break;case 95:this.$={type:"BitExpression",operator:"*",left:a[o-2],right:a[o]};break;case 96:this.$={type:"BitExpression",operator:"/",left:a[o-2],right:a[o]};break;case 97:this.$={type:"BitExpression",operator:"DIV",left:a[o-2],right:a[o]};break;case 98:this.$={type:"BitExpression",operator:"MOD",left:a[o-2],right:a[o]};break;case 99:this.$={type:"BitExpression",operator:"%",left:a[o-2],right:a[o]};break;case 100:this.$={type:"BitExpression",operator:"^",left:a[o-2],right:a[o]};break;case 106:this.$={type:"InSubQueryPredicate",hasNot:a[o-4],left:a[o-5],right:a[o-1]};break;case 107:this.$={type:"InExpressionListPredicate",hasNot:a[o-4],left:a[o-5],right:a[o-1]};break;case 108:this.$={type:"BetweenPredicate",hasNot:a[o-4],left:a[o-5],right:{left:a[o-2],right:a[o]}};break;case 109:this.$={type:"SoundsLikePredicate",hasNot:!1,left:a[o-3],right:a[o]};break;case 110:this.$={type:"LikePredicate",hasNot:a[o-3],left:a[o-4],right:a[o-1],escape:a[o]};break;case 111:this.$={type:"RegexpPredicate",hasNot:a[o-2],left:a[o-3],right:a[o]};break;case 122:this.$={type:"IsNullBooleanPrimary",hasNot:a[o-1],value:a[o-3]};break;case 123:this.$={type:"ComparisonBooleanPrimary",left:a[o-2],operator:a[o-1],right:a[o]};break;case 124:this.$={type:"ComparisonSubQueryBooleanPrimary",operator:a[o-4],subQueryOpt:a[o-3],left:a[o-5],right:a[o-1]};break;case 126:this.$={type:"BooleanExtra",value:a[o]};break;case 128:this.$={type:"IsExpression",hasNot:a[o-1],left:a[o-3],right:a[o]};break;case 129:this.$={type:"NotExpression",value:a[o]};break;case 130:case 133:this.$={type:"AndExpression",operator:a[o-1],left:a[o-2],right:a[o]};break;case 131:case 132:this.$={type:"OrExpression",operator:a[o-1],left:a[o-2],right:a[o]};break;case 134:this.$={type:"XORExpression",left:a[o-2],right:a[o]};break;case 135:this.$={type:"ExpressionList",value:[a[o]]};break;case 136:case 211:this.$=a[o-2],this.$.value.push(a[o]);break;case 143:this.$={type:"GroupBy",value:a[o-1],rollUp:a[o]};break;case 146:this.$={type:"OrderBy",value:a[o-1],rollUp:a[o]};break;case 147:case 193:this.$=[a[o]];break;case 148:this.$=a[o-2],a[o-2].push(a[o]);break;case 149:this.$={type:"GroupByOrderByItem",value:a[o-1],sortOpt:a[o]};break;case 155:this.$={type:"Limit",value:[a[o]]};break;case 156:this.$={type:"Limit",value:[a[o-2],a[o]]};break;case 157:this.$={type:"Limit",value:[a[o],a[o-2]],offsetMode:!0};break;case 164:this.$=a[o-1]+" "+a[o];break;case 165:this.$=a[o-3]+" "+a[o-2]+" "+a[o-1]+" "+a[o];break;case 166:this.$={};break;case 167:this.$={from:a[o-8],partition:a[o-7],where:a[o-6],groupBy:a[o-5],having:a[o-4],orderBy:a[o-3],limit:a[o-2],procedure:a[o-1],updateLockMode:a[o]};break;case 168:this.$={type:"TableReferences",value:[a[o]]};break;case 170:this.$={type:"TableReference",value:a[o]};break;case 171:this.$={type:"TableReference",hasOj:!0,value:a[o-1]};break;case 179:this.$={leftRight:null,outOpt:null};break;case 180:this.$={leftRight:a[o-1],outOpt:a[o]};break;case 181:this.$={type:"InnerCrossJoinTable",innerCrossOpt:a[o-2],left:a[o-3],right:a[o],condition:null};break;case 182:this.$={type:"InnerCrossJoinTable",innerCrossOpt:a[o-3],left:a[o-4],right:a[o-1],condition:a[o]};break;case 183:this.$={type:"StraightJoinTable",left:a[o-3],right:a[o-1],condition:a[o]};break;case 184:this.$={type:"LeftRightJoinTable",leftRight:a[o-4],outOpt:a[o-3],left:a[o-5],right:a[o-1],condition:a[o]};break;case 185:this.$={type:"NaturalJoinTable",leftRight:a[o-2].leftRight,outOpt:a[o-2].outOpt,left:a[o-4],right:a[o]};break;case 188:this.$={type:"OnJoinCondition",value:a[o]};break;case 190:this.$={type:"UsingJoinCondition",value:a[o-1]};break;case 194:this.$=a[o-2],a[o-2].push(a[o]);break;case 196:this.$={type:"Partitions",value:a[o-1]};break;case 198:this.$={hasAs:!0,alias:a[o]};break;case 199:this.$={hasAs:!1,alias:a[o]};break;case 203:case 204:case 205:this.$={type:"ForOptIndexHint",value:a[o]};break;case 210:this.$={type:"IndexHintList",value:[a[o]]};break;case 212:this.$={type:"UseIndexHint",value:a[o-1],forOpt:a[o-3],indexOrKey:a[o-4]};break;case 213:this.$={type:"IgnoreIndexHint",value:a[o-1],forOpt:a[o-3],indexOrKey:a[o-4]};break;case 214:this.$={type:"ForceIndexHint",value:a[o-1],forOpt:a[o-3],indexOrKey:a[o-4]};break;case 215:this.$={type:"TableFactor",value:a[o-3],partition:a[o-2],alias:a[o-1].alias,hasAs:a[o-1].hasAs,indexHintOpt:a[o]};break;case 216:this.$={type:"SubQuery",value:a[o-2],alias:a[o].alias,hasAs:a[o].hasAs};break;case 217:this.$=a[o-1],this.$.hasParentheses=!0}},table:[{3:1,4:2,7:3,9:5,10:6,13:7,16:t,18:r},{1:[3]},{5:9,6:n,8:i,14:a},{5:12,6:n,8:i},e([16,32,33,35,36,37,38,39,40,41,42,45,46,50,52,53,55,56,58,59,61,76,79,81,82,83,84,86,87,88,101],s,{15:13,29:o,30:l,31:c}),e(u,[2,5]),e([6,8,146],p,{11:17,137:18,138:h}),{14:d},{4:21,18:r},{6:[1,22]},{15:23,18:s,29:o,30:l,31:c},{6:[2,3]},{6:[1,24]},e(f,[2,18],{19:25,32:[1,26]}),e(y,[2,13]),e(y,[2,14]),e(y,[2,15]),e(u,v,{12:27,145:28,146:m}),e(b,[2,145]),{16:g,35:_,47:32,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33,136:30,139:31},{15:66,16:s,29:o,30:l,31:c},{17:[1,67]},{1:[2,1]},{4:68,9:69,18:r},{1:[2,2]},e(D,[2,20],{20:70,33:[1,71]}),e(f,[2,17]),e(u,[2,6]),e(j,[2,159]),{35:[1,72]},e(b,B,{132:73,43:U,133:H}),e(M,[2,147]),e(M,[2,150],{140:76,107:G,124:V,125:Q,126:W,127:X,141:[1,82],142:[1,83]}),e(J,[2,127],{111:85,34:[1,86],112:[1,87],113:[1,88],114:[1,89],115:[1,90],116:[1,91],117:[1,92],121:[1,84]}),{16:g,35:_,47:93,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},e(z,[2,121]),e(z,[2,105],{100:94,45:Y,79:Z,81:ee,91:te,92:re,93:ne,94:ie,95:ae,96:se,97:oe,98:le,99:ce,101:ue,105:pe,106:pe,109:pe,110:pe,108:[1,95]}),e(he,[2,88]),e(de,[2,78]),e(de,[2,79],{67:fe}),e(de,[2,80]),e(de,[2,81]),{4:111,16:g,18:r,35:_,47:112,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,85:110,86:q,87:F,88:K,90:36,101:P,104:35,120:33},{16:[1,113]},{16:[1,114]},{50:ye,66:115},e(de,[2,87]),e(de,[2,50]),e(de,[2,51]),e(de,[2,52]),e(de,[2,53]),e([6,8,14,17,34,36,43,45,49,50,67,71,72,74,77,79,81,89,91,92,93,94,95,96,97,98,99,101,103,105,106,107,108,109,110,112,113,114,115,116,117,121,124,125,126,127,129,133,135,138,141,142,144,146,150,152,154,157,164,165,167,168,173,177,179,180,182],ve,{16:me}),{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:118,81:C,82:A,83:L,84:N,86:q,87:F,88:K},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:119,81:C,82:A,83:L,84:N,86:q,87:F,88:K},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:120,81:C,82:A,83:L,84:N,86:q,87:F,88:K},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:121,81:C,82:A,83:L,84:N,86:q,87:F,88:K},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:122,81:C,82:A,83:L,84:N,86:q,87:F,88:K},{16:g,35:_,47:124,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,69:123,71:[2,66],75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},e(de,[2,42]),e(de,[2,43]),e(de,[2,44]),e(de,[2,45]),e(de,[2,46]),e(de,[2,47]),e(de,[2,48]),e(de,[2,49]),{10:126,13:125,16:t},e([6,8,14,138,146],[2,9]),e(u,[2,10],{14:a}),e(u,[2,11]),e(be,[2,22],{21:127,36:[1,128]}),{34:[1,129]},e(j,[2,155],{43:[1,130],147:[1,131]}),e(b,[2,146]),{16:g,35:_,47:32,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33,139:132},{134:[1,133]},e(M,[2,149]),{16:g,35:_,47:134,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},{16:g,35:_,47:135,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},{16:g,35:_,47:136,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},{16:g,35:_,47:137,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},{16:g,35:_,47:138,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},e(M,[2,151]),e(M,[2,152]),e([58,59,61,123],pe,{100:139,101:ue}),{16:g,29:[1,142],35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,104:140,118:141,119:[1,143]},e(ge,[2,112]),e(ge,[2,113]),e(ge,[2,114]),e(ge,[2,115]),e(ge,[2,116]),e(ge,[2,117]),e(ge,[2,118]),e(J,[2,129]),{105:[1,144],106:[1,145],109:[1,146],110:[1,147]},{109:[1,148]},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:149},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:150},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:151},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:152},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:153},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:154},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:155},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:156},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:157},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:158},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:159},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:160},e([58,59,61,105,106,109,110,123],[2,102]),{50:[1,161]},{17:[1,162],43:_e},{17:[1,164]},e(ke,[2,135],{107:G,124:V,125:Q,126:W,127:X}),{16:g,35:_,47:112,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,85:165,86:q,87:F,88:K,90:36,101:P,104:35,120:33},{4:166,18:r},{16:g,35:_,47:167,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,67:fe,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},e([6,8,14,16,17,35,36,43,49,50,52,53,55,56,58,59,61,67,76,79,81,82,83,84,86,87,88,89,101,129,135,138,144,146,150,152,154,164,165,167,168,173,177,179,180,182,192,193,194],ve),e(ke,Ee,{120:33,104:35,90:36,80:37,62:38,66:39,63:40,78:41,75:46,51:47,54:48,57:49,60:50,64:168,65:169,47:173,16:g,30:xe,35:_,45:we,46:Oe,50:k,52:E,53:x,55:w,56:O,58:$,59:S,61:T,76:R,79:I,81:C,82:A,83:L,84:N,86:q,87:F,88:K,101:P}),e(de,[2,73]),e(de,[2,74]),e(de,[2,75]),e(de,[2,76]),e(de,[2,77]),{70:174,71:[1,175]},{71:[2,67],107:G,124:V,125:Q,126:W,127:X},e($e,[2,7],{14:d}),e($e,[2,8]),e(Se,[2,24],{22:176,37:[1,177]}),e(be,[2,21]),{35:[1,178]},{35:[1,179]},{35:[1,180]},e(M,[2,148]),e(Te,[2,142]),e(J,[2,130]),e(Re,[2,131],{107:G,124:V}),e(Re,[2,132],{107:G,124:V}),e(J,[2,133]),e(Re,[2,134],{107:G,124:V}),{57:183,58:$,59:S,61:[1,182],122:181,123:[1,184]},e(z,[2,123]),{16:[1,185]},{16:[2,119]},{16:[2,120]},{16:[1,186]},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:187},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:188,81:C,82:A,83:L,84:N,86:q,87:F,88:K},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:189},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:190},e([6,8,14,17,34,36,43,49,50,71,72,74,77,89,91,101,105,106,107,108,109,110,112,113,114,115,116,117,121,124,125,126,127,129,133,135,138,141,142,144,146,150,152,154,157,164,165,167,168,173,177,179,180,182],[2,89],{45:Y,79:Z,81:ee,92:re,93:ne,94:ie,95:ae,96:se,97:oe,98:le,99:ce}),e([6,8,14,17,34,36,43,49,50,71,72,74,77,89,91,92,99,101,105,106,107,108,109,110,112,113,114,115,116,117,121,124,125,126,127,129,133,135,138,141,142,144,146,150,152,154,157,164,165,167,168,173,177,179,180,182],[2,90],{45:Y,79:Z,81:ee,93:ne,94:ie,95:ae,96:se,97:oe,98:le}),e(Ie,[2,91],{45:Y,79:Z,81:ee,95:ae,96:se,97:oe,98:le}),e(Ie,[2,92],{45:Y,79:Z,81:ee,95:ae,96:se,97:oe,98:le}),e(Ce,[2,93],{45:Y,95:ae,96:se,97:oe,98:le}),e(Ce,[2,94],{45:Y,95:ae,96:se,97:oe,98:le}),e(he,[2,95]),e(he,[2,96]),e(he,[2,97]),e(he,[2,98]),e(he,[2,99]),e([6,8,14,17,34,36,43,49,50,71,72,74,77,89,91,99,101,105,106,107,108,109,110,112,113,114,115,116,117,121,124,125,126,127,129,133,135,138,141,142,144,146,150,152,154,157,164,165,167,168,173,177,179,180,182],[2,100],{45:Y,79:Z,81:ee,92:re,93:ne,94:ie,95:ae,96:se,97:oe,98:le}),e([6,8,14,16,17,34,35,36,43,45,49,50,52,53,55,56,58,59,61,67,71,72,74,76,77,79,81,82,83,84,86,87,88,89,91,92,93,94,95,96,97,98,99,101,103,105,106,107,108,109,110,112,113,114,115,116,117,121,124,125,126,127,129,133,135,138,141,142,144,146,150,152,154,157,164,165,167,168,173,177,179,180,182,192,193,194],[2,63]),e(de,[2,82]),{16:g,35:_,47:191,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},e(de,[2,84]),{17:[1,192],43:_e},{17:[1,193]},{89:[1,194],107:G,124:V,125:Q,126:W,127:X},{17:[1,195],43:[1,196]},e(ke,[2,56]),e(ke,[2,58]),e(ke,[2,59]),{16:g,35:_,47:197,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},e(ke,[2,61],{107:G,124:V,125:Q,126:W,127:X}),{71:[1,199],73:198,74:[1,200],77:[2,70]},{16:g,35:_,47:201,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},e(Ae,[2,26],{23:202,38:[1,203]}),e(Se,[2,23]),e(D,[2,19]),e(j,[2,156]),e(j,[2,157]),e(J,[2,128]),e(z,[2,122]),e(J,[2,125]),e(J,[2,126]),{4:204,18:r},{4:205,16:g,18:r,35:_,47:112,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,85:206,86:q,87:F,88:K,90:36,101:P,104:35,120:33},{45:Y,79:Z,81:ee,91:te,92:re,93:ne,94:ie,95:ae,96:se,97:oe,98:le,99:ce,107:[1,207]},e(z,[2,103],{102:208,103:[1,209]}),e(z,[2,111],{45:Y,79:Z,81:ee,91:te,92:re,93:ne,94:ie,95:ae,96:se,97:oe,98:le,99:ce}),e(z,[2,109],{45:Y,79:Z,81:ee,91:te,92:re,93:ne,94:ie,95:ae,96:se,97:oe,98:le,99:ce}),e(ke,[2,136],{107:G,124:V,125:Q,126:W,127:X}),e(de,[2,83]),e(de,[2,85]),e(de,[2,86]),e(de,[2,54]),e(ke,Ee,{120:33,104:35,90:36,80:37,62:38,66:39,63:40,78:41,75:46,51:47,54:48,57:49,60:50,47:173,65:210,16:g,30:xe,35:_,45:we,46:Oe,50:k,52:E,53:x,55:w,56:O,58:$,59:S,61:T,76:R,79:I,81:C,82:A,83:L,84:N,86:q,87:F,88:K,101:P}),e(ke,[2,60],{107:G,124:V,125:Q,126:W,127:X}),{77:[1,211]},{16:g,35:_,47:212,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},{16:g,35:_,47:213,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},{72:[1,214],107:G,124:V,125:Q,126:W,127:X},e(Le,[2,28],{24:215,39:[1,216]}),e(Ae,[2,25]),{17:[1,217]},{17:[1,218]},{17:[1,219],43:_e},{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,104:220},e(z,[2,110]),{16:g,35:_,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:221,81:C,82:A,83:L,84:N,86:q,87:F,88:K},e(ke,[2,55]),e(de,[2,72]),{72:[1,222],107:G,124:V,125:Q,126:W,127:X},{77:[2,71],107:G,124:V,125:Q,126:W,127:X},{16:g,35:_,47:223,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},e(Ne,[2,29],{25:224,40:[1,225],41:[1,226]}),e(Le,[2,27]),e(z,[2,124]),e(z,[2,106]),e(z,[2,107]),e(z,[2,108]),e(z,[2,104]),{16:g,35:_,47:227,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},e(qe,[2,68],{107:G,124:V,125:Q,126:W,127:X}),e(Fe,[2,33],{26:228,42:[1,229]}),e(Ne,[2,30]),e(Ne,[2,31]),e(qe,[2,69],{107:G,124:V,125:Q,126:W,127:X}),{16:g,27:230,35:_,44:231,45:Ke,46:Pe,47:234,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},e(Fe,[2,32]),e(De,[2,166],{28:235,43:[1,236],157:[1,237]}),e(je,[2,35]),e(je,[2,36]),e(je,[2,37]),e(je,[2,39],{48:238,49:[1,239],50:[1,240],107:G,124:V,125:Q,126:W,127:X}),e(De,[2,12]),{16:g,35:_,44:241,45:Ke,46:Pe,47:234,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},{16:Be,50:ye,66:248,88:Ue,158:242,160:243,161:244,172:247,174:246},e(je,[2,38]),{50:[1,250]},e(je,[2,41]),e(je,[2,34]),e([6,8,14,17,129,135,138,144,146,150,152,154],He,{159:251,43:Me,182:Ge}),e(Ve,[2,168]),e(Ve,[2,170],{163:254,166:256,36:Qe,164:We,165:Xe,167:Je,168:ze,173:Ye,177:Ze}),{162:[1,262]},e(et,[2,191]),e(et,[2,192]),e([6,8,14,17,36,43,49,50,89,129,135,138,144,146,150,152,154,164,165,167,168,173,177,179,180,192,193,194],He,{159:263,67:fe,182:Ge}),{4:264,16:Be,18:r,50:ye,66:248,88:Ue,158:265,160:243,161:244,172:247,174:246},e(je,[2,40]),e(tt,[2,137],{128:266,129:[1,267]}),{16:Be,50:ye,66:248,88:Ue,160:268,161:244,172:247,174:246},{16:[1,269]},{173:[1,270]},{16:Be,50:ye,66:248,174:271},{169:272,170:rt,173:nt},{166:275,167:Je,168:ze,171:274,173:[2,179]},{173:[2,173]},{173:[2,174]},e(it,[2,175]),e(it,[2,176]),{16:Be,50:ye,66:248,161:276,172:247,174:246},e(at,st,{183:277,66:279,49:ot,50:ye}),{17:[1,280]},{17:[1,281],43:Me},e(Te,[2,139],{130:282,131:283,135:[1,284]}),{16:g,35:_,47:285,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},e(Ve,[2,169]),{50:ye,66:287,181:286},{16:Be,50:ye,66:248,174:288},{176:289,179:lt},{173:[1,291]},{173:[2,178]},{173:[1,292]},{169:293,170:rt,173:nt},{36:Qe,89:[1,294],163:254,164:We,165:Xe,166:256,167:Je,168:ze,173:Ye,177:Ze},e(et,[2,208],{189:295,190:296,191:297,192:ct,193:ut,194:pt}),{50:ye,66:301},e(at,[2,199],{67:fe}),e(et,st,{66:279,183:302,49:ot,50:ye}),e(et,[2,217]),e(ht,[2,153],{143:303,144:[1,304]}),e(Te,[2,140]),{16:g,35:_,47:32,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33,136:305,139:31},e(tt,[2,138],{107:G,124:V,125:Q,126:W,127:X}),{17:[1,306],43:[1,307]},e(ke,[2,193],{67:fe}),e([6,8,14,17,36,43,89,129,135,138,144,146,150,152,154,164,165,167,168,173,177,182],[2,181],{175:308,176:309,179:lt,180:dt}),e(et,[2,183]),{16:g,35:_,47:311,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},{16:Be,50:ye,66:248,161:312,172:247,174:246},{16:Be,50:ye,66:248,174:313},{173:[2,180]},e(Ve,[2,171]),e(et,[2,215]),e(et,[2,209]),e(et,[2,210]),{184:315,185:ft,186:yt},{184:318,185:ft,186:yt},{184:319,185:ft,186:yt},e(at,[2,198],{67:fe}),e(et,[2,216]),e(b,p,{137:18,11:320,138:h}),{16:g,35:_,47:321,50:k,51:47,52:E,53:x,54:48,55:w,56:O,57:49,58:$,59:S,60:50,61:T,62:38,63:40,66:39,75:46,76:R,78:41,79:I,80:37,81:C,82:A,83:L,84:N,86:q,87:F,88:K,90:36,101:P,104:35,120:33},e(Te,B,{132:322,43:U,133:H}),e([6,8,14,17,36,43,49,50,89,129,135,138,144,146,150,152,154,164,165,167,168,173,177,179,180,182,192,193,194],[2,196]),{50:ye,66:323},e(et,[2,182]),e(et,[2,189]),{16:[1,324]},e(et,[2,188],{107:G,124:V,125:Q,126:W,127:X}),{36:Qe,163:254,164:We,165:Xe,166:256,167:Je,168:ze,173:Ye,175:325,176:309,177:Ze,179:lt,180:dt},e(et,[2,185]),{191:326,192:ct,193:ut,194:pt},{16:vt,152:mt,187:327},e(bt,[2,200]),e(bt,[2,201]),{16:vt,152:mt,187:329},{16:vt,152:mt,187:330},e(j,v,{145:28,12:331,146:m}),e(ht,[2,154],{107:G,124:V,125:Q,126:W,127:X}),e(Te,[2,143]),e(ke,[2,194],{67:fe}),{50:ye,66:333,68:332},e(et,[2,184]),e(et,[2,211]),{16:[1,334]},{135:[1,337],138:[1,336],173:[1,335]},{16:[1,338]},{16:[1,339]},e(gt,[2,160],{148:340,149:341,150:[1,342]}),{17:[1,343],43:_t},e(ke,[2,64],{67:fe}),{17:[2,206],50:ye,66:333,68:346,188:345},{16:[2,203]},{16:[2,204]},{16:[2,205]},{50:ye,66:333,68:347},{50:ye,66:333,68:348},e(De,[2,163],{151:349,152:[1,350],154:[1,351]}),e(gt,[2,161]),{50:[1,353],63:352},e(et,[2,190]),{50:ye,66:354},{17:[1,355]},{17:[2,207],43:_t},{17:[1,356],43:_t},{17:[1,357],43:_t},e(De,[2,167]),{153:[1,358]},{105:[1,359]},e(gt,[2,162]),{16:me},e(ke,[2,65],{67:fe}),e(et,[2,212]),e(et,[2,213]),e(et,[2,214]),e(De,[2,164]),{155:[1,360]},{156:[1,361]},e(De,[2,165])],defaultActions:{11:[2,3],22:[2,1],24:[2,2],142:[2,119],143:[2,120],258:[2,173],259:[2,174],273:[2,178],293:[2,180],335:[2,203],336:[2,204],337:[2,205]},parseError:function(e,t){if(!t.recoverable){var r=new Error(e);throw r.hash=t,r}this.trace(e)},parse:function(e){var t=this,r=[0],n=[null],i=[],a=this.table,s="",o=0,l=0,c=0,u=i.slice.call(arguments,1),p=Object.create(this.lexer),h={yy:{}};for(var d in this.yy)Object.prototype.hasOwnProperty.call(this.yy,d)&&(h.yy[d]=this.yy[d]);p.setInput(e,h.yy),h.yy.lexer=p,h.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var f=p.yylloc;i.push(f);var y=p.options&&p.options.ranges;"function"==typeof h.yy.parseError?this.parseError=h.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var v,m,b,g,_,k,E,x,w,O=function(){var e;return"number"!=typeof(e=p.lex()||1)&&(e=t.symbols_[e]||e),e},$={};;){if(b=r[r.length-1],this.defaultActions[b]?g=this.defaultActions[b]:(null!==v&&void 0!==v||(v=O()),g=a[b]&&a[b][v]),void 0===g||!g.length||!g[0]){var S="";for(k in w=[],a[b])this.terminals_[k]&&k>2&&w.push("'"+this.terminals_[k]+"'");S=p.showPosition?"Parse error on line "+(o+1)+":\n"+p.showPosition()+"\nExpecting "+w.join(", ")+", got '"+(this.terminals_[v]||v)+"'":"Parse error on line "+(o+1)+": Unexpected "+(1==v?"end of input":"'"+(this.terminals_[v]||v)+"'"),this.parseError(S,{text:p.match,token:this.terminals_[v]||v,line:p.yylineno,loc:f,expected:w})}if(g[0]instanceof Array&&g.length>1)throw new Error("Parse Error: multiple actions possible at state: "+b+", token: "+v);switch(g[0]){case 1:r.push(v),n.push(p.yytext),i.push(p.yylloc),r.push(g[1]),v=null,m?(v=m,m=null):(l=p.yyleng,s=p.yytext,o=p.yylineno,f=p.yylloc,c>0&&c--);break;case 2:if(E=this.productions_[g[1]][1],$.$=n[n.length-E],$._$={first_line:i[i.length-(E||1)].first_line,last_line:i[i.length-1].last_line,first_column:i[i.length-(E||1)].first_column,last_column:i[i.length-1].last_column},y&&($._$.range=[i[i.length-(E||1)].range[0],i[i.length-1].range[1]]),void 0!==(_=this.performAction.apply($,[s,l,o,h.yy,g[1],n,i].concat(u))))return _;E&&(r=r.slice(0,-1*E*2),n=n.slice(0,-1*E),i=i.slice(0,-1*E)),r.push(this.productions_[g[1]][0]),n.push($.$),i.push($._$),x=a[r[r.length-2]][r[r.length-1]],r.push(x);break;case 3:return!0}}return!0}},Et={EOF:1,parseError:function(e,t){if(!this.yy.parser)throw new Error(e);this.yy.parser.parseError(e,t)},setInput:function(e,t){return this.yy=t||this.yy||{},this._input=e,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var e=this._input[0];return this.yytext+=e,this.yyleng++,this.offset++,this.match+=e,this.matched+=e,e.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),e},unput:function(e){var t=e.length,r=e.split(/(?:\r\n?|\n)/g);this._input=e+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-t),this.offset-=t;var n=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),r.length-1&&(this.yylineno-=r.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:r?(r.length===n.length?this.yylloc.first_column:0)+n[n.length-r.length].length-r[0].length:this.yylloc.first_column-t},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-t]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(e){this.unput(this.match.slice(e))},pastInput:function(){var e=this.matched.substr(0,this.matched.length-this.match.length);return(e.length>20?"...":"")+e.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var e=this.match;return e.length<20&&(e+=this._input.substr(0,20-e.length)),(e.substr(0,20)+(e.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var e=this.pastInput(),t=new Array(e.length+1).join("-");return e+this.upcomingInput()+"\n"+t+"^"},test_match:function(e,t){var r,n,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(n=e[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=n.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:n?n[n.length-1].length-n[n.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+e[0].length},this.yytext+=e[0],this.match+=e[0],this.matches=e,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(e[0].length),this.matched+=e[0],r=this.performAction.call(this,this.yy,this,t,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),r)return r;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var e,t,r,n;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;at[0].length)){if(t=r,n=a,this.options.backtrack_lexer){if(!1!==(e=this.test_match(r,i[a])))return e;if(this._backtrack){t=!1;continue}return!1}if(!this.options.flex)break}return t?!1!==(e=this.test_match(t,i[n]))&&e:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var e=this.next();return e||this.lex()},begin:function(e){this.conditionStack.push(e)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(e){return(e=this.conditionStack.length-1-Math.abs(e||0))>=0?this.conditionStack[e]:"INITIAL"},pushState:function(e){this.begin(e)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(e,t,r,n){switch(r){case 0:case 1:case 2:case 3:break;case 4:case 5:case 6:return 50;case 7:return 18;case 8:return 29;case 9:return 119;case 10:return 30;case 11:return 31;case 12:return 32;case 13:return 33;case 14:return 36;case 15:return 37;case 16:return 38;case 17:return 39;case 18:return 40;case 19:return 41;case 20:return 42;case 21:return 46;case 22:return 49;case 23:return 58;case 24:return 59;case 25:return 61;case 26:return"COLLATE";case 27:return 84;case 28:return 86;case 29:return 87;case 30:return 76;case 31:return 71;case 32:return 72;case 33:return 74;case 34:return 77;case 35:return 96;case 36:return 97;case 37:return 101;case 38:return 106;case 39:return 105;case 40:return 108;case 41:return 109;case 42:return 103;case 43:return 110;case 44:return 121;case 45:return 123;case 46:return 107;case 47:return 126;case 48:return 127;case 49:return 157;case 50:return 182;case 51:return 192;case 52:return 185;case 53:return 186;case 54:return 152;case 55:return 173;case 56:return 138;case 57:return 135;case 58:return 193;case 59:return 194;case 60:return 164;case 61:return 165;case 62:return 179;case 63:return 180;case 64:return 167;case 65:return 168;case 66:return 170;case 67:return 177;case 68:return 129;case 69:return 141;case 70:return 142;case 71:return 133;case 72:return 134;case 73:return 144;case 74:return 147;case 75:return 150;case 76:return 153;case 77:return 154;case 78:return 155;case 79:return 156;case 80:return 162;case 81:return 146;case 82:return 14;case 83:return 43;case 84:return 34;case 85:return 16;case 86:return 17;case 87:return 82;case 88:return 117;case 89:return 83;case 90:return 91;case 91:return 92;case 92:return 79;case 93:return 81;case 94:return 45;case 95:return 95;case 96:return 98;case 97:return 99;case 98:return 94;case 99:return 112;case 100:return 113;case 101:return 93;case 102:return"<=>";case 103:return 114;case 104:return 116;case 105:return 115;case 106:return 88;case 107:return 89;case 108:return 8;case 109:case 110:return 53;case 111:return 56;case 112:return 35;case 113:return 55;case 114:return 50;case 115:return 67;case 116:return 52;case 117:return 6;case 118:return"INVALID"}},rules:[/^(?:[\/][*](.|\n)*?[*][\/])/i,/^(?:[-][-]\s.*\n)/i,/^(?:[#]\s.*\n)/i,/^(?:\s+)/i,/^(?:[`][a-zA-Z_\u4e00-\u9fa5][a-zA-Z0-9_\u4e00-\u9fa5]*[`])/i,/^(?:[\w]+[\u4e00-\u9fa5]+[0-9a-zA-Z_\u4e00-\u9fa5]*)/i,/^(?:[\u4e00-\u9fa5][0-9a-zA-Z_\u4e00-\u9fa5]*)/i,/^(?:SELECT\b)/i,/^(?:ALL\b)/i,/^(?:ANY\b)/i,/^(?:DISTINCT\b)/i,/^(?:DISTINCTROW\b)/i,/^(?:HIGH_PRIORITY\b)/i,/^(?:MAX_STATEMENT_TIME\b)/i,/^(?:STRAIGHT_JOIN\b)/i,/^(?:SQL_SMALL_RESULT\b)/i,/^(?:SQL_BIG_RESULT\b)/i,/^(?:SQL_BUFFER_RESULT\b)/i,/^(?:SQL_CACHE\b)/i,/^(?:SQL_NO_CACHE\b)/i,/^(?:SQL_CALC_FOUND_ROWS\b)/i,/^(?:([a-zA-Z_\u4e00-\u9fa5][a-zA-Z0-9_\u4e00-\u9fa5]*\.){1,2}\*)/i,/^(?:AS\b)/i,/^(?:TRUE\b)/i,/^(?:FALSE\b)/i,/^(?:NULL\b)/i,/^(?:COLLATE\b)/i,/^(?:BINARY\b)/i,/^(?:ROW\b)/i,/^(?:EXISTS\b)/i,/^(?:CASE\b)/i,/^(?:WHEN\b)/i,/^(?:THEN\b)/i,/^(?:ELSE\b)/i,/^(?:END\b)/i,/^(?:DIV\b)/i,/^(?:MOD\b)/i,/^(?:NOT\b)/i,/^(?:BETWEEN\b)/i,/^(?:IN\b)/i,/^(?:SOUNDS\b)/i,/^(?:LIKE\b)/i,/^(?:ESCAPE\b)/i,/^(?:REGEXP\b)/i,/^(?:IS\b)/i,/^(?:UNKNOWN\b)/i,/^(?:AND\b)/i,/^(?:OR\b)/i,/^(?:XOR\b)/i,/^(?:FROM\b)/i,/^(?:PARTITION\b)/i,/^(?:USE\b)/i,/^(?:INDEX\b)/i,/^(?:KEY\b)/i,/^(?:FOR\b)/i,/^(?:JOIN\b)/i,/^(?:ORDER\s+BY\b)/i,/^(?:GROUP\s+BY\b)/i,/^(?:IGNORE\b)/i,/^(?:FORCE\b)/i,/^(?:INNER\b)/i,/^(?:CROSS\b)/i,/^(?:ON\b)/i,/^(?:USING\b)/i,/^(?:LEFT\b)/i,/^(?:RIGHT\b)/i,/^(?:OUTER\b)/i,/^(?:NATURAL\b)/i,/^(?:WHERE\b)/i,/^(?:ASC\b)/i,/^(?:DESC\b)/i,/^(?:WITH\b)/i,/^(?:ROLLUP\b)/i,/^(?:HAVING\b)/i,/^(?:OFFSET\b)/i,/^(?:PROCEDURE\b)/i,/^(?:UPDATE\b)/i,/^(?:LOCK\b)/i,/^(?:SHARE\b)/i,/^(?:MODE\b)/i,/^(?:OJ\b)/i,/^(?:LIMIT\b)/i,/^(?:UNION\b)/i,/^(?:,)/i,/^(?:=)/i,/^(?:\()/i,/^(?:\))/i,/^(?:~)/i,/^(?:!=)/i,/^(?:!)/i,/^(?:\|)/i,/^(?:&)/i,/^(?:\+)/i,/^(?:-)/i,/^(?:\*)/i,/^(?:\/)/i,/^(?:%)/i,/^(?:\^)/i,/^(?:>>)/i,/^(?:>=)/i,/^(?:>)/i,/^(?:<<)/i,/^(?:<=>)/i,/^(?:<=)/i,/^(?:<>)/i,/^(?:<)/i,/^(?:\{)/i,/^(?:\})/i,/^(?:;)/i,/^(?:['](\\.|[^'])*['])/i,/^(?:["](\\.|[^"])*["])/i,/^(?:[0][x][0-9a-fA-F]+)/i,/^(?:[-]?[0-9]+(\.[0-9]+)?)/i,/^(?:[-]?[0-9]+(\.[0-9]+)?[eE][-][0-9]+(\.[0-9]+)?)/i,/^(?:[a-zA-Z_\u4e00-\u9fa5][a-zA-Z0-9_\u4e00-\u9fa5]*)/i,/^(?:\.)/i,/^(?:['"][a-zA-Z_\u4e00-\u9fa5][a-zA-Z0-9_\u4e00-\u9fa5]*["'])/i,/^(?:$)/i,/^(?:.)/i],conditions:{INITIAL:{rules:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118],inclusive:!0}}};function xt(){this.yy={}}return kt.lexer=Et,xt.prototype=kt,kt.Parser=xt,new xt}();function a(){this.buffer=""}i||(i={}),i.stringify=function(e){var t=new a;return t.travelMain(e),t.buffer},a.prototype.travel=function(e){if(e){if("string"==typeof e)return this.append(e);this["travel"+e.type].call(this,e)}};var s=!1;a.prototype.appendKeyword=function(e,t,r){s&&(t=!0,s=!1),this.buffer+=t?e.toUpperCase():" "+e.toUpperCase(),r&&(s=!0)},a.prototype.append=function(e,t,r){s&&(t=!0,s=!1),this.buffer+=t?e:" "+e,r&&(s=!0)},a.prototype.travelMain=function(e){this.travel(e.value),e.hasSemicolon&&this.append(";",!0)},a.prototype.travelSelect=function(e){this.appendKeyword("select"),e.distinctOpt&&this.appendKeyword(e.distinctOpt),e.highPriorityOpt&&this.appendKeyword(e.highPriorityOpt),e.maxStateMentTimeOpt&&this.append("MAX_STATEMENT_TIME = "+e.maxStateMentTimeOpt),e.straightJoinOpt&&this.appendKeyword(e.straightJoinOpt),e.sqlSmallResultOpt&&this.appendKeyword(e.sqlSmallResultOpt),e.sqlBigResultOpt&&this.appendKeyword(e.sqlBigResultOpt),e.sqlBufferResultOpt&&this.appendKeyword(e.sqlBufferResultOpt),e.sqlCacheOpt&&this.appendKeyword(e.sqlCacheOpt),e.sqlCalcFoundRowsOpt&&this.appendKeyword(e.sqlCalcFoundRowsOpt),e.selectItems&&this.travelSelectExpr(e.selectItems),e.from&&(this.appendKeyword("from"),this.travel(e.from)),e.partition&&this.travel(e.partition),e.where&&(this.appendKeyword("where"),this.travel(e.where)),e.groupBy&&this.travel(e.groupBy),e.having&&(this.appendKeyword("having"),this.travel(e.having)),e.orderBy&&this.travel(e.orderBy),e.limit&&this.travel(e.limit),e.procedure&&(this.appendKeyword("procedure"),this.travel(e.procedure)),e.updateLockMode&&this.appendKeyword(e.updateLockMode)},a.prototype.travelSelectExpr=function(e){for(var t=e.value,r=0;r0&&void 0!==arguments[0]?arguments[0]:void 0;if(this.action&&this.action.params&&this.action.params.$resource){this.$set(this.record.params,"$resource",t),this.$set(this.record,"resource",t);var r=this.action.types,n=void 0===r?[]:r;return this.$httpGet("/resources").then(function(r){var i=r.data;e.resourcesOptions=i.filter(function(e){return n.includes(e.type)}),e.$set(e.record,"resource",t)})}},loadActions:function(){var e=this;return this.$httpGet("/actions",this.params).then(function(t){e.actionsList=t.data.map(function(e){return e.label=(e.title||{})[E],e.descriptionLabel=(e.description||{})[E],e})})},renderForm:function(e){var t=this;return f()(u.a.mark(function r(){var n,i,a,s;return u.a.wrap(function(r){for(;;)switch(r.prev=r.next){case 0:if(t.formData){r.next=2;break}return r.abrupt("return");case 2:return n=t.formData||e,i=n.name,a=n.params,s=void 0===a?{}:a,r.next=5,t.handleActionChange(i);case 5:t.fillData(s);case 6:case"end":return r.stop()}},r,t)}))()},fillData:function(e){var t=this;l()(e).forEach(function(e){var r=s()(e,2),n=r[0],i=r[1];t.$set(t.record,n,i)})}},created:function(){var e=this;return f()(u.a.mark(function t(){return u.a.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,e.loadActions();case 2:return t.next=4,e.renderForm();case 4:case"end":return t.stop()}},t,e)}))()}},w={render:function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("el-dialog",e._b({staticClass:"action-dialog",attrs:{width:"500px","append-to-body":"",visible:e.dialogVisible,title:e.$t("rule.actions")},on:{"update:visible":function(t){e.dialogVisible=t},open:e.open,close:e.close}},"el-dialog",e.$attrs,!1),[r("el-form",{ref:"record",staticClass:"el-form--public",attrs:{model:e.record,rules:e.rules}},[r("el-row",{attrs:{gutter:20}},[r("el-col",{attrs:{span:12}},[r("el-form-item",{attrs:{prop:"action"}},[r("template",{slot:"label"},[e._v("\n "+e._s(e.$t("rule.action"))+"\n "),r("el-popover",{attrs:{placement:"top-start",width:"200",trigger:"hover"}},[r("div",{domProps:{innerHTML:e._s(e.action.descriptionLabel||e.$t("rule.action_type"))}}),e._v(" "),r("i",{staticClass:"el-icon-question",attrs:{slot:"reference",tabindex:"-1"},slot:"reference"})])],1),e._v(" "),r("el-select",{staticClass:"el-select--public",staticStyle:{width:"100%"},attrs:{"popper-class":"el-select--public"},on:{change:e.handleActionChange},model:{value:e.record.action,callback:function(t){e.$set(e.record,"action",t)},expression:"record.action"}},e._l(e.actionsList,function(e,t){return r("el-option",{key:t,attrs:{label:e.label,value:e.name}})}),1)],2)],1),e._v(" "),e.action.params&&e.action.params.$resource?r("el-col",{attrs:{span:12}},[r("el-form-item",{staticClass:"resource-item",attrs:{prop:"params.$resource"}},[r("template",{slot:"label"},[e._v("\n "+e._s(e.$t("rule.resource"))+"\n "),r("span",{staticClass:"btn",staticStyle:{float:"right","font-size":"12px"},on:{click:e.createResource}},[e._v("\n "+e._s(e.$t("rule.new_resource"))+"\n ")])]),e._v(" "),r("el-select",{staticClass:"el-select--public",staticStyle:{width:"100%"},attrs:{"popper-class":"el-select--public"},model:{value:e.record.params.$resource,callback:function(t){e.$set(e.record.params,"$resource",t)},expression:"record.params.$resource"}},e._l(e.resourcesOptions,function(e,t){return r("el-option",{key:t,attrs:{label:e.id,value:e.id}})}),1)],2)],1):e._e(),e._v(" "),e._l(e.paramsList,function(t,n){return r("el-col",{key:n,attrs:{span:"object"===t.type||"textarea"===t.$attrs.type?24:12}},[r("el-form-item",{attrs:{prop:"params."+t.prop}},[r("template",{slot:"label"},[e._v("\n "+e._s(t.label)+"\n\n "),t.description?r("el-popover",{attrs:{placement:"right",width:"200",trigger:"hover"}},[r("div",{domProps:{innerHTML:e._s(t.description)}}),e._v(" "),r("i",{staticClass:"el-icon-question",attrs:{slot:"reference",tabindex:"-1"},slot:"reference"})]):e._e()],1),e._v(" "),"object"===t.type?r("data-table",{model:{value:e.record.params[t.key],callback:function(r){e.$set(e.record.params,t.key,r)},expression:"record.params[item.key]"}}):"emq-select"===t.type?r("emq-select",e._b({staticClass:"el-select--public",attrs:{"popper-class":"el-select--public"},model:{value:e.record.params[t.key],callback:function(r){e.$set(e.record.params,t.key,r)},expression:"record.params[item.key]"}},"emq-select",t.$attrs,!1)):"number"===t.type?r("el-input",e._b({attrs:{type:"number"},model:{value:e.record.params[t.key],callback:function(r){e.$set(e.record.params,t.key,e._n(r))},expression:"record.params[item.key]"}},"el-input",t.$attrs,!1)):r("el-input",e._b({model:{value:e.record.params[t.key],callback:function(r){e.$set(e.record.params,t.key,r)},expression:"record.params[item.key]"}},"el-input",t.$attrs,!1))],2)],1)})],2)],1),e._v(" "),r("div",{attrs:{slot:"footer"},slot:"footer"},[r("el-button",{staticClass:"cache-btn",attrs:{type:"text"},on:{click:function(t){e.dialogVisible=!1}}},[e._v("\n "+e._s(e.$t("rule.cancel"))+"\n ")]),e._v(" "),r("el-button",{staticClass:"confirm-btn",attrs:{type:"success"},on:{click:e.handleAdd}},[e._v("\n "+e._s(e.$t("rule.confirm"))+"\n ")])],1),e._v(" "),r("resource-dialog",{attrs:{visible:e.resourceDialogVisible,"resource-type":e.resourceType,"enable-item":e.enableItem,"append-to-body":""},on:{"update:visible":function(t){e.resourceDialogVisible=t},confirm:e.handleResourceCreate}})],1)},staticRenderFns:[]};var O={name:"rule-actions",components:{ActionDialog:r("VU/8")(x,w,!1,function(e){r("yoEm")},null,null).exports},props:{record:{type:Object,required:!0},inDialog:{type:Boolean,default:!1},operations:{type:Array,default:function(){return["create","edit","delete"]}},params:{type:Object,default:function(){return{}}}},watch:{dialogVisible:function(e){e||(this.editForm=null,this.editIndex=null,this.currentAction={},this.isFallBacks=!1)}},computed:{has:function(){var e=[];return this.operations.forEach(function(t){e[t]=!0}),e}},data:function(){return{dialogVisible:!1,editForm:null,editIndex:null,isFallBacks:!1,currentAction:{}}},filters:{jsonFormat:function(e){return i()(e,null,2)}},methods:{getSum:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";if(0===e.length||!t)return 0;var r=0;return e.forEach(function(e){var n=e[t]||0;r+=n}),r},handleActionAdd:function(e,t){if(this.isFallBacks)return null!==this.editIndex&&(this.currentAction.fallbacks=[]),void this.currentAction.fallbacks.push(e);null!==t?this.record.actions.splice(t,1,e):this.record.actions.push(e)},handleActionRemove:function(e){var t=e;this.record.actions=this.record.actions.filter(function(e,r){return r!==t})},handleActionEdit:function(e,t){this.editIndex=t,this.editForm=e,this.dialogVisible=!0},handleAddFallbacks:function(e){this.currentAction=e,this.isFallBacks=!0,this.dialogVisible=!0},handleFallbackRemove:function(e){e.fallbacks=[]},handleFallbackEdit:function(e,t,r){this.currentAction=t,this.isFallBacks=!0,this.editIndex=r,this.editForm=e,this.dialogVisible=!0}}},$={render:function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("div",{staticClass:"rule-actions"},[e._l(e.record.actions,function(t,n){return r("div",{key:n,staticClass:"action-card"},[r("el-row",{staticClass:"action-body",attrs:{type:"flex"}},[r("el-col",{attrs:{span:12}},[r("div",{staticClass:"filed-item"},[r("label",{staticClass:"title"},[e._v(e._s(e.$t("rule.type"))+": ")]),e._v(" "),r("span",{staticClass:"desc"},[e._v(e._s(t.name))])]),e._v(" "),e._l(Object.entries(t.params),function(t,n){return r("div",{key:n,staticClass:"filed-item"},[r("label",{staticClass:"title"},[e._v(" "+e._s("$resource"===t[0]?e.$t("rule.rely_resource"):t[0])+": ")]),e._v(" "),r("span",{staticClass:"desc"},[e._v(e._s(t[1]))])])})],2),e._v(" "),e.has.delete||e.has.edit?r("el-col",{staticClass:"action-oper",attrs:{span:12}},[e.has.edit?r("el-button",{attrs:{type:"text"},on:{click:function(r){return e.handleActionEdit(t,n)}}},[e._v("\n "+e._s(e.$t("rule.edit"))+"\n ")]):e._e(),e._v(" "),e.has.delete?r("el-button",{staticClass:"delete-btn",attrs:{type:"text"},on:{click:function(t){return e.handleActionRemove(n)}}},[e._v("\n "+e._s(e.$t("rule.delete"))+"\n ")]):e._e(),e._v(" "),t.fallbacks.length?e._e():r("div",{staticClass:"fallbacks"},[r("el-popover",{attrs:{placement:"top-start",trigger:"hover",content:e.$t("rule.fallbackActionCreate")}},[r("el-button",{attrs:{slot:"reference",type:"text",icon:"el-icon-plus"},on:{click:function(r){return e.handleAddFallbacks(t)}},slot:"reference"},[e._v("\n "+e._s(e.$t("rule.fallbackAction"))+"\n ")])],1)],1)],1):e._e(),e._v(" "),e.has.delete||e.has.edit?e._e():r("el-col",{attrs:{span:12}},[r("div",{staticClass:"status-wrapper filed-item"},[e._l(t.metrics||[],function(t,n){return r("div",{key:n,staticClass:"status-item"},[r("div",{staticClass:"title"},[e._v(e._s(e.$t("rule.metrics"))+":")]),e._v(" "),r("span",{staticClass:"key"},[e._v("\n "+e._s(t.node)+"\n ")]),e._v(" "),r("span",{attrs:{type:"info"}},[e._v("\n "+e._s(e.$t("rule.success"))+":\n "),r("span",[e._v(e._s(t.success))])]),e._v(" "),r("span",{attrs:{type:"info"}},[e._v("\n "+e._s(e.$t("rule.failed"))+":\n "),r("span",[e._v(e._s(t.failed))])])])}),e._v(" "),r("div",{staticClass:"status-item"},[r("span",{staticClass:"key"},[e._v("\n "+e._s(e.$t("rule.all"))+"\n ")]),e._v(" "),r("span",{attrs:{type:"info"}},[e._v("\n "+e._s(e.$t("rule.success"))+":\n "),r("span",[e._v(e._s(e.getSum(t.metrics,"success")))])]),e._v(" "),r("span",{attrs:{type:"info"}},[e._v("\n "+e._s(e.$t("rule.failed"))+":\n "),r("span",[e._v(e._s(e.getSum(t.metrics,"failed")))])])])],2)])],1),e._v(" "),t.fallbacks&&t.fallbacks.length?e._l(t.fallbacks,function(n,i){return r("el-row",{key:i,staticClass:"action-footer",attrs:{type:"flex"}},[r("el-col",{attrs:{span:12}},[r("div",{staticClass:"filed-item"},[r("label",{staticClass:"title"},[e._v(e._s(e.$t("rule.type"))+": ")]),e._v(" "),r("span",{staticClass:"desc"},[e._v(e._s(n.name))])]),e._v(" "),e._l(Object.entries(n.params),function(t,n){return r("div",{key:n,staticClass:"filed-item"},[r("label",{staticClass:"title"},[e._v(" "+e._s("$resource"===t[0]?e.$t("rule.rely_resource"):t[0])+": ")]),e._v(" "),r("span",{staticClass:"desc"},[e._v(e._s(t[1]))])])})],2),e._v(" "),e.has.delete||e.has.edit?r("el-col",{staticClass:"action-oper",attrs:{span:12}},[e.has.edit?r("el-button",{attrs:{type:"text"},on:{click:function(r){return e.handleFallbackEdit(n,t,i)}}},[e._v("\n "+e._s(e.$t("rule.edit"))+"\n ")]):e._e(),e._v(" "),e.has.delete?r("el-button",{staticClass:"delete-btn",attrs:{type:"text"},on:{click:function(r){return e.handleFallbackRemove(t,i)}}},[e._v("\n "+e._s(e.$t("rule.delete"))+"\n ")]):e._e(),e._v(" "),r("div",{staticClass:"fallbacks"},[r("el-popover",{attrs:{placement:"top-start",trigger:"hover",content:e.$t("rule.fallbackActionTip")}},[r("span",{attrs:{slot:"reference"},slot:"reference"},[e._v("\n "+e._s(e.$t("rule.fallbackAction"))+"\n ")])])],1)],1):e._e(),e._v(" "),e.has.delete||e.has.edit?e._e():r("el-col",{attrs:{span:12}},[r("div",{staticClass:"status-wrapper filed-item"},[e._l(n.metrics||[],function(t,n){return r("div",{key:n,staticClass:"status-item"},[r("div",{staticClass:"title"},[e._v(e._s(e.$t("rule.metrics"))+":")]),e._v(" "),r("span",{staticClass:"key"},[e._v("\n "+e._s(t.node)+"\n ")]),e._v(" "),r("span",{attrs:{type:"info"}},[e._v("\n "+e._s(e.$t("rule.success"))+":\n "),r("span",[e._v(e._s(t.success))])]),e._v(" "),r("span",{attrs:{type:"info"}},[e._v("\n "+e._s(e.$t("rule.failed"))+":\n "),r("span",[e._v(e._s(t.failed))])])])}),e._v(" "),r("div",{staticClass:"status-item"},[r("span",{staticClass:"key"},[e._v("\n "+e._s(e.$t("rule.all"))+"\n ")]),e._v(" "),r("span",{attrs:{type:"info"}},[e._v("\n "+e._s(e.$t("rule.success"))+":\n "),r("span",[e._v(e._s(e.getSum(n.metrics,"success")))])]),e._v(" "),r("span",{attrs:{type:"info"}},[e._v("\n "+e._s(e.$t("rule.failed"))+":\n "),r("span",[e._v(e._s(e.getSum(n.metrics,"failed")))])])])],2)])],1)}):e._e()],2)}),e._v(" "),e.has.create?r("el-button",{staticStyle:{"min-width":"80px"},attrs:{type:"success",plain:"",icon:"el-icon-plus",size:"small"},on:{click:function(t){e.dialogVisible=!0}}},[e._v("\n "+e._s(e.$t("rule.add"))+"\n ")]):e._e(),e._v(" "),r("action-dialog",{attrs:{visible:e.dialogVisible,currentActions:e.record.actions,recordIndex:e.editIndex,editRecord:e.editForm,params:e.params},on:{"update:visible":function(t){e.dialogVisible=t},confirm:e.handleActionAdd}})],2)},staticRenderFns:[]};var S=r("VU/8")(O,$,!1,function(e){r("lqjQ")},null,null);t.a=S.exports},exGp:function(e,t,r){"use strict";t.__esModule=!0;var n,i=r("//Fk"),a=(n=i)&&n.__esModule?n:{default:n};t.default=function(e){return function(){var t=e.apply(this,arguments);return new a.default(function(e,r){return function n(i,s){try{var o=t[i](s),l=o.value}catch(e){return void r(e)}if(!o.done)return a.default.resolve(l).then(function(e){n("next",e)},function(e){n("throw",e)});e(l)}("next")})}}},lqjQ:function(e,t){},yoEm:function(e,t){}}); \ No newline at end of file diff --git a/apps/emqx_dashboard/priv/www/static/js/1.fcd6fde8b053e80bc68f.js b/apps/emqx_dashboard/priv/www/static/js/1.fcd6fde8b053e80bc68f.js new file mode 100644 index 000000000..0a49cb931 --- /dev/null +++ b/apps/emqx_dashboard/priv/www/static/js/1.fcd6fde8b053e80bc68f.js @@ -0,0 +1 @@ +webpackJsonp([1],{g2pX:function(e,t){},zXyA:function(e,t,a){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var s=a("Dd8w"),i=a.n(s),l=a("zL8q"),n=a("NYxO"),o={name:"data-view",components:{"el-pagination":l.Pagination,"el-input":l.Input,"el-select":l.Select,"el-option":l.Option,"el-table":l.Table,"el-table-column":l.TableColumn,"el-date-picker":l.DatePicker},data:function(){return{searchView:!1,cluster:!1,popoverVisible:!1,count:0,hasnext:!1,params:{_page:1,_limit:10},nodeName:"",nodes:[],activeTab:"clients",searchKey:"",searchValue:"",searchPlaceholder:this.$t("clients.clientId"),clients:[],fuzzyParams:{comparator:"_gte",match:"_match_topic"},topics:[],subscriptions:[],showMoreQuery:!1,protoNames:["MQTT","MQTT-SN","CoAP","LwM2M"]}},watch:{$route:"init",activeTab:function(){this.fuzzyParams={comparator:"_gte",match:"_match_topic"}}},computed:{iconStatus:function(){return this.searchView?"el-icon-close":"el-icon-search"}},methods:i()({},Object(n.b)(["CURRENT_NODE"]),{stashNode:function(){this.cluster="cluster"===this.nodeName,this.cluster||this.CURRENT_NODE(this.nodeName)},init:function(){switch(this.activeTab=this.$route.path.split("/")[1],this.params._page=1,this.activeTab){case"topics":this.searchPlaceholder="Topic";break;default:this.searchPlaceholder=this.$t("clients.clientId")}this.loadData()},loadData:function(){var e=this;this.searchValue="",this.$httpGet("/nodes").then(function(t){var a=e.$store.state.nodeName||t.data[0].node;e.nodeName=e.cluster?"cluster":a,e.nodes=t.data,e.loadChild()}).catch(function(t){e.$message.error(t||e.$t("error.networkError"))})},loadChild:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]&&arguments[0],a=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;if(this.stashNode(),this.searchView=!1,this.searchValue="",!0===t&&(this.params._page=1),this.nodeName||"topics"===this.activeTab){var s="/nodes/"+this.nodeName+"/"+this.activeTab;("topics"===this.activeTab||this.cluster)&&(s="topics"===this.activeTab?"routes":this.activeTab);var l={};l=a?i()({},a,this.params):i()({},this.params),this.$httpGet(s,l).then(function(t){e[e.activeTab]=t.data.items,e.count=t.data.meta.count||0,e.hasnext=t.data.meta.hasnext}).catch(function(t){e.$message.error(t||e.$t("error.networkError"))})}},searchChild:function(){var e=this;if(this.searchView)this.loadChild();else if(this.searchValue){var t="/nodes/"+this.nodeName+"/"+this.activeTab+"/"+encodeURIComponent(this.searchValue);if("topics"===this.activeTab||this.cluster)t="/"+("topics"===this.activeTab?"routes":this.activeTab)+"/"+encodeURIComponent(this.searchValue);this.$httpGet(t).then(function(t){e.count=0,e.params={_page:1,_limit:10},e.searchView=!0,e[e.activeTab]=t.data}).catch(function(t){e.$message.error(t||e.$t("error.networkError"))})}else this.loadData()},handleSizeChange:function(e){this.params._limit=e,this.loadChild(!0)},handlePrevClick:function(){if(1!==this.params._page){this.params._page-=1;var e=this.genQueryParams(this.fuzzyParams);this.loadChild(!1,e)}},handleNextClick:function(){if(this.hasnext){this.params._page+=1;var e=this.genQueryParams(this.fuzzyParams);this.loadChild(!1,e)}},handleDisconnect:function(e,t,a){var s=this;this.$httpDelete("/clients/"+encodeURIComponent(e.clientid)).then(function(){s.loadData(),a.$refs["popover-"+t].doClose()}).catch(function(e){s.$message.error(e||s.$t("error.networkError"))})},genQueryParams:function(e){var t={};if("clients"===this.activeTab){var a=e._like_clientid,s=e._like_username,i=e.ip_address,l=e.conn_state,n=e.proto_name,o=e.comparator,r=e._connected_at;if(t={_like_clientid:a||void 0,_like_username:s||void 0,ip_address:i||void 0,conn_state:l||void 0,proto_name:n||void 0},r)t[o+"_connected_at"]=Math.floor(r/1e3)}else if("subscriptions"===this.activeTab){var c=e._like_clientid,p=e.topic,u=e.qos,d=e.share,m=e.match;t={clientid:c||void 0,qos:""===u?void 0:u,share:d||void 0},p&&(t[m]=p)}return t},clientQuerySearch:function(){var e=this.genQueryParams(this.fuzzyParams);this.loadChild(!0,e)},resetClientQuerySearch:function(){this.fuzzyParams={comparator:">=",match:"_match_topic"},this.init()}}),created:function(){this.init()}},r={render:function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("div",{staticClass:"data-view"},[a("div",{staticClass:"page-title"},[e._v("\n "+e._s(e.$t("leftbar."+e.activeTab))+"\n "),a("div",{staticStyle:{float:"right"},nativeOn:{keyup:function(t){return!t.type.indexOf("key")&&e._k(t.keyCode,"enter",13,t.key,"Enter")?null:e.searchChild(t)}}},["topics"!==e.activeTab?a("el-select",{staticClass:"select-radius",attrs:{placeholder:e.$t("select.placeholder"),disabled:e.$store.state.loading},on:{change:function(t){return e.loadChild(!0)}},model:{value:e.nodeName,callback:function(t){e.nodeName=t},expression:"nodeName"}},e._l(e.nodes,function(e){return a("el-option",{key:e.node,attrs:{label:e.node,value:e.node}})}),1):e._e()],1)]),e._v(" "),"topics"!==e.activeTab?a("el-card",{staticClass:"el-card--self search-card"},[a("el-form",{ref:"fuzzyParams",attrs:{model:e.fuzzyParams,"label-position":"left","label-width":"110px"}},[a("el-row",{attrs:{gutter:20}},[a("el-col",{attrs:{span:8}},[a("el-form-item",{attrs:{label:e.$t("clients.clientId")}},[a("el-input",{attrs:{type:"text",size:"small"},model:{value:e.fuzzyParams._like_clientid,callback:function(t){e.$set(e.fuzzyParams,"_like_clientid",t)},expression:"fuzzyParams._like_clientid"}})],1)],1),e._v(" "),"clients"===e.activeTab?a("el-col",{attrs:{span:8}},[a("el-form-item",{attrs:{label:e.$t("clients.username")}},[a("el-input",{attrs:{type:"text",size:"small"},model:{value:e.fuzzyParams._like_username,callback:function(t){e.$set(e.fuzzyParams,"_like_username",t)},expression:"fuzzyParams._like_username"}})],1)],1):"subscriptions"===e.activeTab?a("el-col",{attrs:{span:8}},[a("el-form-item",{attrs:{label:e.$t("topics.topic")}},[a("el-row",{staticClass:"form-item-row"},[a("el-col",{attrs:{span:9}},[a("el-select",{staticClass:"match",model:{value:e.fuzzyParams.match,callback:function(t){e.$set(e.fuzzyParams,"match",t)},expression:"fuzzyParams.match"}},[a("el-option",{attrs:{label:"filter",value:"_match_topic"}}),e._v(" "),a("el-option",{attrs:{label:"topic",value:"topic"}})],1)],1),e._v(" "),a("el-col",{attrs:{span:15}},[a("el-input",{attrs:{type:"text",size:"small"},model:{value:e.fuzzyParams.topic,callback:function(t){e.$set(e.fuzzyParams,"topic",t)},expression:"fuzzyParams.topic"}})],1)],1)],1)],1):e._e(),e._v(" "),e.showMoreQuery?["clients"===e.activeTab?[a("el-col",{attrs:{span:8}},[a("el-form-item",{attrs:{label:e.$t("clients.ipAddr")}},[a("el-input",{attrs:{type:"text",size:"small"},model:{value:e.fuzzyParams.ip_address,callback:function(t){e.$set(e.fuzzyParams,"ip_address",t)},expression:"fuzzyParams.ip_address"}})],1)],1),e._v(" "),a("el-col",{attrs:{span:8}},[a("el-form-item",{attrs:{label:e.$t("clients.connected")}},[a("el-select",{model:{value:e.fuzzyParams.conn_state,callback:function(t){e.$set(e.fuzzyParams,"conn_state",t)},expression:"fuzzyParams.conn_state"}},[a("el-option",{attrs:{value:"connected"}}),e._v(" "),a("el-option",{attrs:{value:"disconnected"}})],1)],1)],1),e._v(" "),a("el-col",{attrs:{span:8}},[a("el-form-item",{attrs:{label:e.$t("clients.createdAt")}},[a("el-row",{staticClass:"form-item-row"},[a("el-col",{attrs:{span:8}},[a("el-select",{staticClass:"comparator",model:{value:e.fuzzyParams.comparator,callback:function(t){e.$set(e.fuzzyParams,"comparator",t)},expression:"fuzzyParams.comparator"}},[a("el-option",{attrs:{label:">=",value:"_gte"}}),e._v(" "),a("el-option",{attrs:{label:"<=",value:"_lte"}})],1)],1),e._v(" "),a("el-col",{attrs:{span:16}},[a("el-date-picker",{staticClass:"datatime",attrs:{type:"datetime","value-format":"timestamp"},model:{value:e.fuzzyParams._connected_at,callback:function(t){e.$set(e.fuzzyParams,"_connected_at",t)},expression:"fuzzyParams._connected_at"}})],1)],1)],1)],1),e._v(" "),a("el-col",{attrs:{span:8}},[a("el-form-item",{attrs:{label:e.$t("clients.protoName")}},[a("el-select",{model:{value:e.fuzzyParams.proto_name,callback:function(t){e.$set(e.fuzzyParams,"proto_name",t)},expression:"fuzzyParams.proto_name"}},e._l(e.protoNames,function(e){return a("el-option",{key:e,attrs:{value:e}})}),1)],1)],1)]:"subscriptions"===e.activeTab?[a("el-col",{attrs:{span:8}},[a("el-form-item",{attrs:{label:"QoS"}},[a("el-select",{attrs:{clearable:""},model:{value:e.fuzzyParams.qos,callback:function(t){e.$set(e.fuzzyParams,"qos",t)},expression:"fuzzyParams.qos"}},[a("el-option",{attrs:{value:0}}),e._v(" "),a("el-option",{attrs:{value:1}}),e._v(" "),a("el-option",{attrs:{value:2}})],1)],1)],1),e._v(" "),a("el-col",{staticClass:"col-share",attrs:{span:8}},[a("el-form-item",{attrs:{label:e.$t("subscriptions.share")}},[a("el-input",{attrs:{type:"text",size:"small",placeholder:"group_name"},model:{value:e.fuzzyParams.share,callback:function(t){e.$set(e.fuzzyParams,"share",t)},expression:"fuzzyParams.share"}})],1)],1)]:e._e()]:e._e(),e._v(" "),a("span",{staticClass:"col-oper"},[a("el-button",{attrs:{size:"small",type:"primary",plain:""},on:{click:e.clientQuerySearch}},[e._v("\n "+e._s(e.$t("oper.search"))+"\n ")]),e._v(" "),a("el-button",{attrs:{size:"small",plain:""},on:{click:e.resetClientQuerySearch}},[e._v("\n "+e._s(e.$t("oper.reset"))+"\n ")]),e._v(" "),a("a",{staticClass:"show-more",attrs:{href:"javascript:;"},on:{click:function(t){e.showMoreQuery=!e.showMoreQuery}}},[e._v("\n "+e._s(e.showMoreQuery?e.$t("oper.collapse"):e.$t("oper.expand"))+"\n "),a("i",{class:e.showMoreQuery?"el-icon-arrow-up":"el-icon-arrow-down"})])],1)],2)],1)],1):e._e(),e._v(" "),a("el-table",{directives:[{name:"show",rawName:"v-show",value:"clients"===e.activeTab,expression:"activeTab === 'clients'"},{name:"loading",rawName:"v-loading",value:e.$store.state.loading,expression:"$store.state.loading"}],attrs:{border:"",data:e.clients}},[a("el-table-column",{attrs:{prop:"clientid",label:e.$t("clients.clientId"),width:"160px","show-overflow-tooltip":""},scopedSlots:e._u([{key:"default",fn:function(t){var s=t.row;return[a("a",{attrs:{href:"javascript:;"},on:{click:function(t){e.$router.push({path:"/clients/"+encodeURIComponent(s.clientid)})}}},[e._v("\n "+e._s(s.clientid)+"\n ")])]}}])}),e._v(" "),a("el-table-column",{attrs:{prop:"username","min-width":"100px",label:e.$t("clients.username"),"show-overflow-tooltip":""}}),e._v(" "),a("el-table-column",{attrs:{prop:"ip_address",label:e.$t("clients.ipAddr"),"min-width":"140px","show-overflow-tooltip":""},scopedSlots:e._u([{key:"default",fn:function(t){var a=t.row;return[e._v("\n "+e._s(a.ip_address)+":"+e._s(a.port)+"\n ")]}}])}),e._v(" "),a("el-table-column",{attrs:{prop:"keepalive","min-width":"100px",label:e.$t("clients.keepalive")}}),e._v(" "),a("el-table-column",{attrs:{prop:"expiry_interval","min-width":"150px",label:e.$t("clients.expiryInterval")}}),e._v(" "),a("el-table-column",{attrs:{prop:"subscriptions_cnt","min-width":"160px",label:e.$t("clients.subscriptionsCount")}}),e._v(" "),a("el-table-column",{attrs:{prop:"connected","min-width":"140px",label:e.$t("clients.connected")},scopedSlots:e._u([{key:"default",fn:function(t){var s=t.row;return[a("span",{class:[s.connected?"connected":"disconnected","status-circle"]}),e._v("\n "+e._s(s.connected?e.$t("websocket.connected"):e.$t("websocket.disconnected"))+"\n ")]}}])}),e._v(" "),a("el-table-column",{attrs:{prop:"created_at",label:e.$t("clients.createdAt"),"min-width":"160px"}}),e._v(" "),a("el-table-column",{attrs:{fixed:"right",width:"120px",label:e.$t("oper.oper")},scopedSlots:e._u([{key:"default",fn:function(t){var s=t.row,i=t.$index,l=t._self;return[a("el-popover",{ref:"popover-"+i,attrs:{placement:"right",trigger:"click"}},[a("p",[e._v(e._s(s.connected?e.$t("oper.confirmKickOut"):e.$t("oper.confirmCleanSession")))]),e._v(" "),a("div",{staticStyle:{"text-align":"right"}},[a("el-button",{staticClass:"cache-btn",attrs:{size:"mini",type:"text"},on:{click:function(e){l.$refs["popover-"+i].doClose()}}},[e._v("\n "+e._s(e.$t("oper.cancel"))+"\n ")]),e._v(" "),a("el-button",{attrs:{size:"mini",type:"success"},on:{click:function(t){return e.handleDisconnect(s,i,l)}}},[e._v("\n "+e._s(e.$t("oper.confirm"))+"\n ")])],1),e._v(" "),a("el-button",{attrs:{slot:"reference",size:"mini",type:"danger",plain:""},slot:"reference"},[e._v("\n "+e._s(s.connected?e.$t("clients.kickOut"):e.$t("websocket.cleanSession"))+"\n ")])],1)]}}])})],1),e._v(" "),a("el-table",{directives:[{name:"show",rawName:"v-show",value:"topics"===e.activeTab,expression:"activeTab === 'topics'"},{name:"loading",rawName:"v-loading",value:e.$store.state.loading,expression:"$store.state.loading"}],attrs:{border:"",data:e.topics}},[a("el-table-column",{attrs:{prop:"topic",label:e.$t("topics.topic")}}),e._v(" "),a("el-table-column",{attrs:{prop:"node",label:e.$t("topics.node")}})],1),e._v(" "),a("el-table",{directives:[{name:"show",rawName:"v-show",value:"subscriptions"===e.activeTab,expression:"activeTab === 'subscriptions'"},{name:"loading",rawName:"v-loading",value:e.$store.state.loading,expression:"$store.state.loading"}],attrs:{border:"",data:e.subscriptions}},[e.cluster?a("el-table-column",{attrs:{prop:"node","min-width":"160",label:e.$t("clients.node")}}):e._e(),e._v(" "),a("el-table-column",{attrs:{prop:"clientid",label:e.$t("subscriptions.clientId")}}),e._v(" "),a("el-table-column",{attrs:{prop:"topic",label:e.$t("subscriptions.topic")}}),e._v(" "),a("el-table-column",{attrs:{prop:"qos",label:e.$t("subscriptions.qoS")}})],1),e._v(" "),a("div",{staticClass:"center-align"},[e.count>10?a("el-pagination",{attrs:{background:"",layout:"total, sizes, prev, pager, next","page-sizes":[10,50,100,300,500],"current-page":e.params._page,"page-size":e.params._limit,total:e.count},on:{"update:currentPage":function(t){return e.$set(e.params,"_page",t)},"update:current-page":function(t){return e.$set(e.params,"_page",t)},"size-change":e.handleSizeChange,"current-change":e.loadChild}}):e._e(),e._v(" "),-1===e.count&&(e.clients.length||e.subscriptions.length)?a("div",{staticClass:"custom-pagination"},[a("a",{class:["prev",1===e.params._page?"disabled":""],attrs:{href:"javascript:;"},on:{click:e.handlePrevClick}},[a("i",{staticClass:"el-icon-arrow-left"}),e._v("\n "+e._s(e.$t("oper.prev"))+"\n ")]),e._v(" "),a("a",{class:["next",e.hasnext?"":"disabled"],attrs:{href:"javascript:;"},on:{click:e.handleNextClick}},[e._v("\n "+e._s(e.$t("oper.next"))+"\n "),a("i",{staticClass:"el-icon-arrow-right"})])]):e._e()],1)],1)},staticRenderFns:[]};var c=a("VU/8")(o,r,!1,function(e){a("g2pX")},null,null);t.default=c.exports}}); \ No newline at end of file diff --git a/apps/emqx_dashboard/priv/www/static/js/10.188c5e479f887d471dde.js b/apps/emqx_dashboard/priv/www/static/js/10.188c5e479f887d471dde.js new file mode 100644 index 000000000..5480c6f23 --- /dev/null +++ b/apps/emqx_dashboard/priv/www/static/js/10.188c5e479f887d471dde.js @@ -0,0 +1 @@ +webpackJsonp([10],{QSR2:function(e,s,r){"use strict";Object.defineProperty(s,"__esModule",{value:!0});var t=r("Dd8w"),a=r.n(t),o=r("zL8q"),n=r("NYxO"),i={name:"users-view",components:{"el-dialog":o.Dialog,"el-input":o.Input,"el-button":o.Button,"el-table":o.Table,"el-table-column":o.TableColumn,"el-popover":o.Popover,"el-form":o.Form,"el-form-item":o.FormItem,"el-row":o.Row,"el-col":o.Col},data:function(){var e=this;return{changePassword:!1,dialogVisible:!1,oper:"new",users:[],record:{username:"",password:"",newPassword:"",repeatPassword:"",tags:""},rules:{username:[{required:!0,message:this.$t("users.usernameRequired")},{min:2,max:32,message:this.$t("users.usernameIllegal"),trigger:"change"}],tags:[{required:!0,message:this.$t("users.remarkRequired")}],password:[{required:!0,message:this.$t("users.passwordRequired")},{min:3,max:255,message:this.$t("users.passwordIllegal"),trigger:"change"}],newPassword:[{required:!0,message:this.$t("users.passwordRequired")},{min:3,max:255,message:this.$t("users.passwordIllegal"),trigger:"change"}],repeatPassword:[{required:!0,message:this.$t("users.passwordRequired")},{validator:function(s,r,t){r!==e.record.newPassword?t(new Error(e.$t("users.passwordInconsistent"))):t()},trigger:"change"}]}}},computed:{username:function(){return this.$store.state.user.username}},methods:a()({},Object(n.b)(["USER_LOGIN"]),{handleOperation:function(){var e=this,s=!(arguments.length>0&&void 0!==arguments[0])||arguments[0],r=arguments[1];this.changePassword=!1,this.dialogVisible=!0,s?(this.oper="new",this.record={username:"",password:"",newPassword:"",repeatPassword:"",tags:"viewer"},setTimeout(function(){e.$refs.record.clearValidate()},10)):(this.oper="edit",this.record=a()({},r),this.$set(this.record,"password",""))},loadData:function(){var e=this;this.$httpGet("/users").then(function(s){e.users=s.data}).catch(function(s){e.$message.error(s||e.$t("error.networkError"))})},createUser:function(){var e=this;"edit"!==this.oper?this.$refs.record.validate(function(s){s&&e.$httpPost("/users",e.record).then(function(){e.$message.success(""+e.$t("users.createUser")),e.loadData(),e.dialogVisible=!1}).catch(function(s){e.$message.error(s||e.$t("error.networkError"))})}):this.updateUser()},updateUser:function(){var e=this;this.$refs.record.validate(function(s){if(s)if(e.changePassword){var r={old_pwd:e.record.password,new_pwd:e.record.newPassword};e.$httpPut("/users/"+e.record.username,e.record).then(function(){e.$httpPut("/change_pwd/"+e.record.username,r).then(function(){e.$store.state.user.username===e.record.username&&e.record.password!==e.record.newPassword?(e.$message.error(e.$t("users.authenticate")),e.USER_LOGIN({isLogOut:!0}),e.$router.push("/login")):(e.$message.success(""+e.$t("oper.edit")+e.$t("alert.success")),e.dialogVisible=!1,e.loadData())}).catch(function(s){e.$message.error(s||e.$t("error.networkError"))})})}else e.$httpPut("/users/"+e.record.username,e.record).then(function(){e.$message.success(""+e.$t("oper.edit")+e.$t("alert.success")),e.dialogVisible=!1,e.loadData()}).catch(function(s){e.$message.error(s||e.$t("error.networkError"))})})},deleteUser:function(e,s,r){var t=this;this.$httpDelete("/users/"+e.username).then(function(){t.$message.success(""+t.$t("oper.delete")+t.$t("alert.success")),t.loadData(),r.$refs["popover-"+s].doClose()}).catch(function(e){t.$message.error(e||t.$t("error.networkError"))})}}),created:function(){this.loadData()}},l={render:function(){var e=this,s=e.$createElement,r=e._self._c||s;return r("div",{staticClass:"users-view"},[r("div",{staticClass:"page-title"},[e._v("\n "+e._s(e.$t("leftbar.users"))+"\n "),r("el-button",{staticClass:"confirm-btn",staticStyle:{float:"right"},attrs:{round:"",plain:"",type:"success",icon:"el-icon-plus",size:"medium",disabled:e.$store.state.loading},on:{click:function(s){return e.handleOperation(!0)}}},[e._v("\n "+e._s(e.$t("users.newUser"))+"\n ")])],1),e._v(" "),r("el-table",{directives:[{name:"loading",rawName:"v-loading",value:e.$store.state.loading,expression:"$store.state.loading"}],attrs:{border:"",data:e.users}},[r("el-table-column",{attrs:{prop:"username",label:e.$t("users.username")}}),e._v(" "),r("el-table-column",{attrs:{prop:"tags",label:e.$t("users.remark")}}),e._v(" "),r("el-table-column",{attrs:{width:"140",label:e.$t("oper.oper")},scopedSlots:e._u([{key:"default",fn:function(s){var t=s.row,a=s.$index,o=s._self;return[r("el-button",{attrs:{size:"mini",type:"warning",plain:""},on:{click:function(s){return e.handleOperation(!1,t)}}},[e._v("\n "+e._s(e.$t("oper.edit"))+"\n ")]),e._v(" "),r("el-popover",{ref:"popover-"+a,attrs:{placement:"right",trigger:"click"}},[r("p",[e._v(e._s(e.$t("oper.confirmDelete")))]),e._v(" "),r("div",{staticStyle:{"text-align":"right"}},[r("el-button",{staticClass:"cache-btn",attrs:{size:"mini",type:"text"},on:{click:function(e){o.$refs["popover-"+a].doClose()}}},[e._v("\n "+e._s(e.$t("oper.cancel"))+"\n ")]),e._v(" "),r("el-button",{attrs:{size:"mini",type:"success"},on:{click:function(s){return e.deleteUser(t,a,o)}}},[e._v("\n "+e._s(e.$t("oper.confirm"))+"\n ")])],1),e._v(" "),r("el-button",{directives:[{name:"show",rawName:"v-show",value:"admin"!==t.username&&e.username!==t.username,expression:"row.username !== 'admin' && username !== row.username"}],attrs:{slot:"reference",size:"mini",type:"danger",plain:""},slot:"reference"},[e._v("\n "+e._s(e.$t("oper.delete"))+"\n ")])],1)]}}])})],1),e._v(" "),r("el-dialog",{attrs:{width:"500px",visible:e.dialogVisible,title:"new"===e.oper?e.$t("users.newUser"):e.$t("users.editUser")},on:{"update:visible":function(s){e.dialogVisible=s}},nativeOn:{keyup:function(s){return!s.type.indexOf("key")&&e._k(s.keyCode,"enter",13,s.key,"Enter")?null:e.createUser(s)}}},[r("el-form",{ref:"record",staticClass:"el-form--public",attrs:{"label-position":"top",size:"medium",model:e.record,rules:e.rules}},[r("el-row",{attrs:{gutter:20}},[r("el-col",{attrs:{span:24}},[r("el-form-item",{attrs:{prop:"username",label:e.$t("users.username")}},[r("el-input",{attrs:{disabled:"edit"===e.oper},model:{value:e.record.username,callback:function(s){e.$set(e.record,"username",s)},expression:"record.username"}})],1)],1),e._v(" "),"new"===e.oper?r("el-col",{attrs:{span:24}},[r("el-form-item",{attrs:{prop:"password",label:e.$t("users.password")}},[r("el-input",{attrs:{type:"password"},model:{value:e.record.password,callback:function(s){e.$set(e.record,"password",s)},expression:"record.password"}})],1)],1):e._e(),e._v(" "),e.changePassword&&"edit"===e.oper?r("div",[r("el-col",{attrs:{span:24}},[r("el-form-item",{attrs:{prop:"password",label:e.$t("users.oldPassword")}},[r("el-input",{attrs:{type:"password"},model:{value:e.record.password,callback:function(s){e.$set(e.record,"password",s)},expression:"record.password"}})],1)],1),e._v(" "),r("el-col",{attrs:{span:24}},[r("el-form-item",{attrs:{prop:"newPassword",label:e.$t("users.newPassword")}},[r("el-input",{attrs:{type:"password"},model:{value:e.record.newPassword,callback:function(s){e.$set(e.record,"newPassword",s)},expression:"record.newPassword"}})],1)],1),e._v(" "),r("el-col",{attrs:{span:24}},[r("el-form-item",{attrs:{prop:"repeatPassword",label:e.$t("users.confirmNewPassword")}},[r("el-input",{attrs:{type:"password"},model:{value:e.record.repeatPassword,callback:function(s){e.$set(e.record,"repeatPassword",s)},expression:"record.repeatPassword"}})],1)],1)],1):e._e(),e._v(" "),r("el-col",{attrs:{span:24}},[r("el-form-item",{attrs:{prop:"tags",label:e.$t("users.remark")}},[r("el-input",{model:{value:e.record.tags,callback:function(s){e.$set(e.record,"tags",s)},expression:"record.tags"}})],1)],1),e._v(" "),r("el-col",{attrs:{span:24}},[r("el-form-item",["edit"===e.oper?r("el-button",{staticClass:"cache-btn change-password",attrs:{type:"text"},on:{click:function(s){e.changePassword=!e.changePassword}}},[e._v("\n "+e._s(e.changePassword?e.$t("users.dontChangePassword"):e.$t("users.changePassword"))+"\n ")]):e._e()],1)],1)],1)],1),e._v(" "),r("div",{attrs:{slot:"footer"},slot:"footer"},[r("el-button",{staticClass:"cache-btn",attrs:{type:"text"},on:{click:function(s){e.dialogVisible=!1}}},[e._v("\n "+e._s(e.$t("oper.cancel"))+"\n ")]),e._v(" "),r("el-button",{staticClass:"confirm-btn",attrs:{type:"success",loading:e.$store.state.loading},on:{click:e.createUser}},[e._v("\n "+e._s(e.$t("oper.save"))+"\n ")])],1)],1)],1)},staticRenderFns:[]};var c=r("VU/8")(i,l,!1,function(e){r("gHf8")},null,null);s.default=c.exports},gHf8:function(e,s){}}); \ No newline at end of file diff --git a/apps/emqx_dashboard/priv/www/static/js/11.3861aeb3036b8f41a6e8.js b/apps/emqx_dashboard/priv/www/static/js/11.3861aeb3036b8f41a6e8.js new file mode 100644 index 000000000..3aae89ad8 --- /dev/null +++ b/apps/emqx_dashboard/priv/www/static/js/11.3861aeb3036b8f41a6e8.js @@ -0,0 +1 @@ +webpackJsonp([11],{DoQ2:function(t,e){},GQ4E:function(t,e,s){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=s("woOf"),n=s.n(a),o={name:"topic-metrics",components:{},props:{},watch:{currentExpandRow:{deep:!0,handler:function(){clearInterval(this.timer)}}},data:function(){return{expands:[],addVisible:!1,popoverVisible:!1,modClosed:!1,topicQos:"all",timer:0,topics:[],currentExpandRow:{},currentTopic:{},record:{},rules:{topic:{required:!0,message:this.$t("oper.pleaseEnter")}}}},methods:{getRowKeys:function(t){return t.topic},loadData:function(){var t=this;this.$httpGet("/topic-metrics").then(function(e){var s=e.data;t.topics=s.map(function(t){var e=t.metrics;return{topic:t.topic,messageIn:e["messages.in.count"],messageOut:e["messages.out.count"],messageDrop:e["messages.dropped.count"]}}),t.modClosed=!1}).catch(function(e){t.$message.warning(t.$t("error."+e.message)),t.modClosed=!0})},hidePopover:function(){var t=this;this.popoverVisible=!0,setTimeout(function(){t.popoverVisible=!1},0)},handleOperation:function(){this.addVisible=!0},handleModLoad:function(){var t=this;this.$httpPut("/modules/emqx_mod_topic_metrics/load").then(function(){t.$message.success(t.$t("oper.enableSuccess")),t.loadData(),t.modClosed=!1}).catch(function(e){t.$message.error(e||t.$t("error.networkError"))})},deleteTopicMetric:function(t){var e=this;this.$httpDelete("/topic-metrics/"+encodeURIComponent(t.topic)).then(function(){e.loadData(),e.hidePopover()}).catch(function(t){e.$message.error(t||e.$t("error.networkError"))})},handleAdd:function(){var t=this;this.$refs.record.validate(function(e){if(e){var s={};n()(s,t.record),t.$httpPost("/topic-metrics",s).then(function(){t.handleClose(),t.loadData()}).catch(function(){})}})},handleClose:function(){this.addVisible=!1,this.$refs.record.resetFields()},viewTopicDetails:function(t,e){var s=document.querySelectorAll(".el-table__expand-icon")[e];s&&s.click()},loadDetail:function(){var t=this;this.$httpGet("/topic-metrics/"+encodeURIComponent(this.currentTopic.topic)).then(function(e){t.currentTopic=e.data,t.loadData()}).catch(function(){})},setLoadDetailInterval:function(){var t=this;this.timer=setInterval(function(){t.$httpGet("/topic-metrics/"+encodeURIComponent(t.currentExpandRow.topic)).then(function(e){t.currentTopic=e.data}).catch(function(){})},1e4)},handleExpandChange:function(t,e){var s=this;if(!e.length)return this.currentExpandRow={},void clearInterval(this.timer);this.currentExpandRow=t,this.currentTopic={},this.$httpGet("/topic-metrics/"+encodeURIComponent(t.topic)).then(function(a){s.currentTopic=a.data,s.$refs.crudTable.store.states.expandRows=e.length?[t]:[],s.loadData(),s.setLoadDetailInterval()}).catch(function(){})},getCurrentTopicData:function(t,e){var s={all:"messages",qos0:"messages.qos0",qos1:"messages.qos1",qos2:"messages.qos2"}[this.topicQos],a=this.currentTopic[s+"."+t+"."+e];return"rate"===e&&a?a.toFixed(2):a},getCurrentTopicDropRate:function(t){return t?t.toFixed(2):t}},created:function(){this.loadData()},beforeRouteLeave:function(t,e,s){clearInterval(this.timer),s()},beforeDestroy:function(){clearInterval(this.timer)}},i={render:function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("div",{staticClass:"topic-metrics"},[s("div",{staticClass:"page-title"},[t._v("\n "+t._s(t.$t("analysis.topicMetrics"))+"\n "),s("span",{staticClass:"sub-tip"},[t._v(t._s(t.$t("analysis.metricsTip")))]),t._v(" "),t.modClosed?s("el-button",{staticClass:"confirm-btn",staticStyle:{float:"right"},attrs:{round:"",plain:"",type:"success",size:"medium",disable:t.$store.state.loading},on:{click:t.handleModLoad}},[t._v("\n "+t._s(t.$t("modules.enable"))+"\n ")]):s("el-button",{staticClass:"confirm-btn",staticStyle:{float:"right"},attrs:{round:"",plain:"",type:"success",icon:"el-icon-plus",size:"medium",disable:t.$store.state.loading},on:{click:t.handleOperation}},[t._v("\n "+t._s(t.$t("rule.create"))+"\n ")])],1),t._v(" "),s("el-table",{directives:[{name:"loading",rawName:"v-loading",value:t.$store.state.loading,expression:"$store.state.loading"}],ref:"crudTable",attrs:{border:"",data:t.topics,"row-key":t.getRowKeys,"expand-row-keys":t.expands},on:{"expand-change":t.handleExpandChange}},[s("el-table-column",{attrs:{type:"expand"},scopedSlots:t._u([{key:"default",fn:function(e){return[s("div",{staticClass:"expand-header"},[t._v("\n "+t._s(t.$t("analysis.details"))+"\n "),s("el-radio-group",{staticClass:"topic-qos-radio",attrs:{prop:e,size:"mini"},model:{value:t.topicQos,callback:function(e){t.topicQos=e},expression:"topicQos"}},[s("el-radio-button",{attrs:{label:"all"}},[t._v(t._s(t.$t("analysis.all")))]),t._v(" "),s("el-radio-button",{attrs:{label:"qos0"}},[t._v("QoS 0")]),t._v(" "),s("el-radio-button",{attrs:{label:"qos1"}},[t._v("QoS 1")]),t._v(" "),s("el-radio-button",{attrs:{label:"qos2"}},[t._v("QoS 2")])],1)],1),t._v(" "),s("el-row",{staticClass:"expand-body",attrs:{gutter:20}},[s("el-col",{attrs:{span:8}},[s("div",{staticClass:"message-card in"},[s("div",[t._v("\n "+t._s(t.$t("analysis.messageIn"))+"\n "),s("span",{staticClass:"message-rate"},[t._v("\n "+t._s(t.$t("analysis.rateItem",[t.getCurrentTopicData("in","rate")]))+"\n "+t._s(t.$t("analysis.rate"))+"\n ")])]),t._v(" "),s("div",{staticClass:"message-card--body"},[t._v("\n "+t._s(t.getCurrentTopicData("in","count"))+"\n ")])])]),t._v(" "),s("el-col",{attrs:{span:8}},[s("div",{staticClass:"message-card out"},[s("div",[t._v("\n "+t._s(t.$t("analysis.messageOut"))+"\n "),s("span",{staticClass:"message-rate"},[t._v("\n "+t._s(t.$t("analysis.rateItem",[t.getCurrentTopicData("out","rate")]))+"\n "+t._s(t.$t("analysis.rate"))+"\n ")])]),t._v(" "),s("div",{staticClass:"message-card--body"},[t._v("\n "+t._s(t.getCurrentTopicData("out","count"))+"\n ")])])]),t._v(" "),s("el-col",{attrs:{span:8}},[s("div",{staticClass:"message-card drop"},[s("div",[t._v("\n "+t._s(t.$t("analysis.messageDrop"))+"\n "),s("span",{staticClass:"message-rate"},[t._v("\n "+t._s(t.$t("analysis.rateItem",[t.getCurrentTopicDropRate(t.currentTopic["messages.dropped.rate"])]))+"\n "+t._s(t.$t("analysis.rate"))+"\n ")])]),t._v(" "),s("div",{staticClass:"message-card--body"},[t._v("\n "+t._s(t.currentTopic["messages.dropped.count"])+"\n ")])])])],1)]}}])}),t._v(" "),s("el-table-column",{attrs:{prop:"topic",label:t.$t("topics.topic")}}),t._v(" "),s("el-table-column",{attrs:{prop:"messageIn",label:t.$t("analysis.messageIn")}}),t._v(" "),s("el-table-column",{attrs:{prop:"messageOut",label:t.$t("analysis.messageOut")}}),t._v(" "),s("el-table-column",{attrs:{prop:"messageDrop",label:t.$t("analysis.messageDrop")}}),t._v(" "),s("el-table-column",{attrs:{width:"180px",label:t.$t("oper.oper")},scopedSlots:t._u([{key:"default",fn:function(e){return[s("el-button",{attrs:{type:"success",size:"mini",plain:""},on:{click:function(s){return t.viewTopicDetails(e.row,e.$index)}}},[t._v("\n "+t._s(t.$t("oper.view"))+"\n ")]),t._v(" "),s("el-popover",{attrs:{placement:"right",trigger:"click",value:t.popoverVisible}},[s("p",[t._v(t._s(t.$t("oper.confirmDelete")))]),t._v(" "),s("div",{staticStyle:{"text-align":"right"}},[s("el-button",{staticClass:"cache-btn",attrs:{size:"mini",type:"text"},on:{click:t.hidePopover}},[t._v("\n "+t._s(t.$t("oper.cancel"))+"\n ")]),t._v(" "),s("el-button",{attrs:{size:"mini",type:"success"},on:{click:function(s){return t.deleteTopicMetric(e.row)}}},[t._v("\n "+t._s(t.$t("oper.confirm"))+"\n ")])],1),t._v(" "),s("el-button",{attrs:{slot:"reference",size:"mini",type:"danger",plain:""},slot:"reference"},[t._v("\n "+t._s(t.$t("oper.delete"))+"\n ")])],1)]}}])})],1),t._v(" "),s("el-dialog",{staticClass:"create-subscribe",attrs:{title:t.$t("analysis.addTopic"),width:"400px",visible:t.addVisible},on:{"update:visible":function(e){t.addVisible=e}},nativeOn:{keyup:function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"enter",13,e.key,"Enter")?null:t.handleAdd(e)}}},[s("el-form",{ref:"record",staticClass:"el-form--public",attrs:{model:t.record,rules:t.rules,size:"small","label-position":"top"}},[s("el-form-item",{attrs:{prop:"topic",label:t.$t("subscriptions.topic")}},[s("el-input",{attrs:{placeholder:"Topic"},model:{value:t.record.topic,callback:function(e){t.$set(t.record,"topic",e)},expression:"record.topic"}})],1)],1),t._v(" "),s("div",{attrs:{slot:"footer"},slot:"footer"},[s("el-button",{staticClass:"cache-btn",attrs:{type:"text"},on:{click:t.handleClose}},[t._v("\n "+t._s(t.$t("oper.cancel"))+"\n ")]),t._v(" "),s("el-button",{staticClass:"confirm-btn",attrs:{type:"success",loading:t.$store.state.loading},on:{click:t.handleAdd}},[t._v("\n "+t._s(t.$t("oper.add"))+"\n ")])],1)],1)],1)},staticRenderFns:[]};var r=s("VU/8")(o,i,!1,function(t){s("DoQ2")},null,null);e.default=r.exports}}); \ No newline at end of file diff --git a/apps/emqx_dashboard/priv/www/static/js/12.43feccc8f1584bdba5c2.js b/apps/emqx_dashboard/priv/www/static/js/12.43feccc8f1584bdba5c2.js new file mode 100644 index 000000000..ae12b78ce --- /dev/null +++ b/apps/emqx_dashboard/priv/www/static/js/12.43feccc8f1584bdba5c2.js @@ -0,0 +1 @@ +webpackJsonp([12],{BYOx:function(t,e){},VKKr:function(t,e,s){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=s("mvHQ"),o=s.n(a),i=s("zL8q"),n=s("VOAv"),l={name:"settings-view",components:{"el-radio":i.Radio,"el-radio-group":i.RadioGroup,"el-button":i.Button,"el-form":i.Form,"el-form-item":i.FormItem,"el-row":i.Row,"el-col":i.Col,"el-card":i.Card},data:function(){return{options:{themes:"",language:""},defaultConfig:"",defaultThemes:"",defaultLanguage:""}},computed:{notChanged:function(){return this.defaultConfig===o()(this.options)}},methods:{init:function(){var t=window.localStorage.getItem("themes")||"dark-themes";t="light-themes"===t?"light-themes":"dark-themes",this.options.themes=t,this.defaultThemes=t,this.options.language=window.localStorage.getItem("language")||"en",this.options.language=["zh","en","ja"].includes(this.options.language)?this.options.language:"en",this.defaultLanguage=this.options.language,this.defaultConfig=o()(this.options)},themesToggle:function(){Object(n.b)(this.options.themes)},applySetting:function(){this.$message.success(this.$t("settings.success")),this.themesToggle(),this.defaultThemes=this.options.themes,window.localStorage.setItem("language",this.options.language),window.localStorage.setItem("themes",this.options.themes),this.defaultLanguage!==this.options.language&&setTimeout(function(){location.reload()},600),this.defaultConfig=o()(this.options)}},created:function(){this.init()},beforeRouteLeave:function(t,e,s){this.defaultThemes!==this.options.themes&&Object(n.b)(this.defaultThemes),s()}},r={render:function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("div",{staticClass:"settings-view"},[s("div",{staticClass:"page-title"},[t._v(t._s(t.$t("leftbar.settings")))]),t._v(" "),s("el-card",{staticClass:"el-card--self"},[s("el-row",{attrs:{gutter:20}},[s("el-form",{ref:"options",attrs:{model:t.options,"label-width":"100px","label-position":"top"}},[s("el-col",{attrs:{span:12}},[s("el-form-item",{attrs:{label:t.$t("settings.themes")}},[s("el-radio-group",{on:{change:t.themesToggle},model:{value:t.options.themes,callback:function(e){t.$set(t.options,"themes",e)},expression:"options.themes"}},[s("el-radio",{attrs:{label:"dark-themes"}},[t._v("Dark")]),t._v(" "),s("el-radio",{attrs:{label:"light-themes"}},[t._v("Light")])],1)],1)],1),t._v(" "),s("el-col",{attrs:{span:12}},[s("el-form-item",{attrs:{label:t.$t("settings.language")}},[s("el-radio-group",{model:{value:t.options.language,callback:function(e){t.$set(t.options,"language",e)},expression:"options.language"}},[s("el-radio",{attrs:{label:"en"}},[t._v("EN")]),t._v(" "),s("el-radio",{attrs:{label:"zh"}},[t._v("中文")]),t._v(" "),s("el-radio",{attrs:{label:"ja"}},[t._v("日本語")])],1)],1)],1),t._v(" "),s("el-col",{staticClass:"operation-area",attrs:{span:24}},[s("el-form-item",[s("el-button",{staticClass:"confirm-btn",attrs:{type:"success",disabled:t.notChanged},on:{click:t.applySetting}},[t._v("\n "+t._s(t.$t("settings.apply"))+"\n ")])],1)],1)],1)],1)],1)],1)},staticRenderFns:[]};var g=s("VU/8")(l,r,!1,function(t){s("BYOx")},null,null);e.default=g.exports}}); \ No newline at end of file diff --git a/apps/emqx_dashboard/priv/www/static/js/13.026a13a2a59abd354bd5.js b/apps/emqx_dashboard/priv/www/static/js/13.026a13a2a59abd354bd5.js new file mode 100644 index 000000000..22e38efdb --- /dev/null +++ b/apps/emqx_dashboard/priv/www/static/js/13.026a13a2a59abd354bd5.js @@ -0,0 +1 @@ +webpackJsonp([13],{IvP6:function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var n=i("Xxa5"),a=i.n(n),s=i("exGp"),l=i.n(s),r={name:"rules-view",components:{RuleActions:i("eDC2").a},props:{},data:function(){return{ruleDialogLoading:!1,timer:0,rule:{for:[],metrics:{}},dialogVisible:!1,tableData:[]}},methods:{getMatchedCount:function(){var t=(arguments.length>0&&void 0!==arguments[0]?arguments[0]:{}).metrics,e=0;return(void 0===t?[]:t).forEach(function(t){var i=t.matched;e+=i}),e},getHitRate:function(t){var e=t.matched,i=void 0===e?0:e,n=t.nomatch,a=i/(i+(void 0===n?0:n))*100;return a.toString().split(".")[1]&&a.toString().split(".")[1].length>2?a.toFixed(2):a},viewRule:function(t){var e=this;return l()(a.a.mark(function i(){var n;return a.a.wrap(function(i){for(;;)switch(i.prev=i.next){case 0:if(!t.id){i.next=3;break}return e.$router.push("/rules/"+t.id),i.abrupt("return");case 3:return i.next=5,e.$httpGet("/rules/"+t.id);case 5:if(i.t1=i.sent,i.t1){i.next=8;break}i.t1={};case 8:if(i.t0=i.t1.data,i.t0){i.next=11;break}i.t0={};case 11:n=i.t0,e.rule=n||t,e.dialogVisible=!0,clearTimeout(e.timer),e.timer=setTimeout(function(){e.viewRule(t)},1e4);case 16:case"end":return i.stop()}},i,e)}))()},editRule:function(t){this.$router.push("/rules/create?rule="+t.id)},loadDetails:function(t){var e=this;this.ruleDialogLoading=!0,this.$httpGet("/rules/"+t).then(function(t){var i=t.data;e.rule=i,setTimeout(function(){e.ruleDialogLoading=!1},500)}).catch(function(){e.ruleDialogLoading=!1})},closeDialog:function(){clearInterval(this.timer),this.loadData()},handleDelete:function(t){var e=this;this.$confirm(this.$t("rule.confirm_stop_delete"),"Notice",{confirmButtonClass:"confirm-btn",confirmButtonText:this.$t("oper.confirm"),cancelButtonClass:"cache-btn el-button--text",cancelButtonText:this.$t("oper.cancel"),type:"warning"}).then(function(){e.$httpDelete("/rules/"+t.id).then(function(){e.$message.success(e.$t("rule.delete_success")),e.loadData()})}).catch()},handleOperation:function(){this.$router.push("/rules/create")},loadData:function(){var t=this;this.$httpGet("/rules").then(function(e){t.tableData=e.data;var i=t.tableData.find(function(e){return e.id===t.rule.id});i&&(t.rule=i)})},updateRule:function(t){var e=this,i=t.id,n=t.enabled;this.$httpPut("/rules/"+i,{enabled:n}).then(function(){e.$message.success(e.$t("oper.editSuccess"))})}},filters:{actionsFilter:function(t){return t.map(function(t){return t.name}).join(", ")}},created:function(){this.loadData(),clearInterval(this.timer)},beforeRouteLeave:function(t,e,i){clearInterval(this.timer),i()}},o={render:function(){var t=this,e=t.$createElement,i=t._self._c||e;return i("div",{staticClass:"rules-view"},[i("div",{staticClass:"page-title"},[t._v("\n "+t._s(t.$t("rule.message_rule"))+"\n "),i("el-button",{staticClass:"confirm-btn",staticStyle:{float:"right"},attrs:{round:"",plain:"",type:"success",icon:"el-icon-plus",size:"medium",disable:t.$store.state.loading},on:{click:t.handleOperation}},[t._v("\n "+t._s(t.$t("rule.create"))+"\n ")])],1),t._v(" "),i("el-table",{directives:[{name:"loading",rawName:"v-loading",value:t.$store.state.loading,expression:"$store.state.loading"}],attrs:{border:"",data:t.tableData}},[i("el-table-column",{attrs:{prop:"id",label:t.$t("rule.id")},scopedSlots:t._u([{key:"default",fn:function(e){var n=e.row;return[i("span",{staticClass:"btn",on:{click:function(e){return t.viewRule(n)}}},[t._v("\n "+t._s(n.id)+"\n ")])]}}])}),t._v(" "),i("el-table-column",{attrs:{prop:"for",label:t.$t("rule.topic")}}),t._v(" "),i("el-table-column",{attrs:{prop:"rawsql","min-width":"150px",label:"SQL"}}),t._v(" "),i("el-table-column",{attrs:{prop:"actions",label:t.$t("rule.actions")},scopedSlots:t._u([{key:"default",fn:function(e){var n=e.row;return t._l(n.actions,function(e,n){return i("div",{key:n,staticClass:"action-item"},[t._v("\n "+t._s(e.name)+"\n ")])})}}])}),t._v(" "),i("el-table-column",{attrs:{prop:"metrics.matched","min-width":"110px",label:t.$t("rule.rule_matched_1"),formatter:t.getMatchedCount}}),t._v(" "),i("el-table-column",{attrs:{label:t.$t("rule.viewStates")},scopedSlots:t._u([{key:"default",fn:function(e){return[i("el-tooltip",{attrs:{content:e.row.enabled?t.$t("rule.ruleEnabled"):t.$t("rule.ruleDisabled"),placement:"left"}},[i("el-switch",{attrs:{"active-text":"","inactive-text":"","active-color":"#13ce66","inactive-color":"#ff4949"},on:{change:function(i){return t.updateRule(e.row)}},model:{value:e.row.enabled,callback:function(i){t.$set(e.row,"enabled",i)},expression:"props.row.enabled"}})],1)]}}])}),t._v(" "),i("el-table-column",{attrs:{label:t.$t("rule.oper"),"min-width":"120px"},scopedSlots:t._u([{key:"default",fn:function(e){var n=e.row;return[i("el-button",{attrs:{type:"success",size:"mini",plain:""},on:{click:function(e){return t.editRule(n)}}},[t._v("\n "+t._s(t.$t("rule.edit"))+"\n ")]),t._v(" "),i("el-button",{attrs:{size:"mini",type:"danger",plain:""},on:{click:function(e){return t.handleDelete(n)}}},[t._v("\n "+t._s(t.$t("rule.delete"))+"\n ")])]}}])})],1),t._v(" "),i("el-dialog",{attrs:{title:t.$t("rule.rule_details"),visible:t.dialogVisible},on:{"update:visible":function(e){t.dialogVisible=e},close:t.closeDialog}},[i("div",{staticClass:"dialog-preview"},[i("div",{staticClass:"option-item"},[i("div",{staticClass:"option-title"},[t._v(t._s(t.$t("rule.id")))]),t._v(" "),i("div",{staticClass:"option-value"},[t._v(t._s(t.rule.id))])]),t._v(" "),i("div",{staticClass:"option-item"},[i("div",{staticClass:"option-title"},[t._v(t._s(t.$t("rule.trigger_events")))]),t._v(" "),i("div",{staticClass:"option-value"},[t._v(t._s((t.rule.for||[]).join(",")))])]),t._v(" "),i("div",{staticClass:"option-item"},[i("div",{staticClass:"option-title"},[t._v(t._s(t.$t("rule.rule_desc")))]),t._v(" "),i("div",{staticClass:"option-value"},[t._v(t._s(t.rule.description))])]),t._v(" "),i("div",{staticClass:"option-item"},[i("div",{staticClass:"option-title"},[t._v("SQL")]),t._v(" "),i("div",{staticClass:"option-all"},[i("code",[t._v("\n "+t._s(t.rule.rawsql)+"\n ")])])]),t._v(" "),i("div",{staticClass:"option-item"},[i("div",{staticClass:"option-title"},[t._v("\n "+t._s(t.$t("rule.metrics"))+"\n "),i("i",{directives:[{name:"show",rawName:"v-show",value:t.ruleDialogLoading,expression:"ruleDialogLoading"}],staticClass:"el-icon-loading"})]),t._v(" "),i("div",{staticClass:"option-all"},[i("span",{attrs:{size:"mini",type:"info"}},[t._v("\n "+t._s(t.$t("rule.rule_matched_1"))+": "),i("span",[t._v(t._s(t.rule.metrics.matched))]),t._v(" "+t._s(t.$t("rule.match_unit"))+"\n ")]),t._v(" "),i("span",{attrs:{size:"mini",type:"info"}},[t._v("\n "+t._s(t.$t("rule.speed_current"))+": "),i("span",[t._v(t._s(t.rule.metrics.speed))]),t._v(" "+t._s(t.$t("rule.speed_unit"))+"\n ")]),t._v(" "),i("span",{attrs:{size:"mini",type:"info"}},[t._v("\n "+t._s(t.$t("rule.speed_max_1"))+": "),i("span",[t._v(t._s(t.rule.metrics.speed_max))]),t._v(" "+t._s(t.$t("rule.speed_unit"))+"\n ")]),t._v(" "),i("span",{attrs:{size:"mini",type:"info"}},[t._v("\n "+t._s(t.$t("rule.speed_last5m_1"))+": "),i("span",[t._v(t._s(t.rule.metrics.speed_last5m))]),t._v(" "+t._s(t.$t("rule.speed_unit"))+"\n ")])])]),t._v(" "),i("el-table-column",{attrs:{prop:"description",label:t.$t("rule.description")}}),t._v(" "),i("div",{staticClass:"option-item"},[i("div",{staticClass:"option-title"},[t._v("\n "+t._s(t.$t("rule.actions"))+"\n "),i("i",{directives:[{name:"show",rawName:"v-show",value:t.ruleDialogLoading,expression:"ruleDialogLoading"}],staticClass:"el-icon-loading"})]),t._v(" "),i("div",{staticClass:"option-all"},[i("rule-actions",{attrs:{"in-dialog":"",record:t.rule,operations:[]}})],1)])],1),t._v(" "),i("div",{attrs:{slot:"footer"},slot:"footer"},[i("el-button",{staticClass:"confirm-btn",attrs:{type:"success"},on:{click:function(e){t.dialogVisible=!1}}},[t._v("\n "+t._s(t.$t("rule.confirm"))+"\n ")])],1)])],1)},staticRenderFns:[]};var u=i("VU/8")(r,o,!1,function(t){i("SVmr")},null,null);e.default=u.exports},SVmr:function(t,e){}}); \ No newline at end of file diff --git a/apps/emqx_dashboard/priv/www/static/js/14.0342a1a3d29f1adca947.js b/apps/emqx_dashboard/priv/www/static/js/14.0342a1a3d29f1adca947.js new file mode 100644 index 000000000..4f2f11065 --- /dev/null +++ b/apps/emqx_dashboard/priv/www/static/js/14.0342a1a3d29f1adca947.js @@ -0,0 +1 @@ +webpackJsonp([14],{JWuK:function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var a=r("Xxa5"),s=r.n(a),l=r("exGp"),n=r.n(l),o={name:"RuleView",components:{RuleActions:r("eDC2").a},props:{},data:function(){return{record:{actions:[{id:"inspect_1562305995013447740",metrics:[{failed:0,node:"emqx@127.0.0.1",success:0}],name:"inspect",params:{}}],description:"",enabled:!0,for:["message.publish"],id:"rule:b35e3e59",metrics:[{matched:0,node:"emqx@127.0.0.1",speed:0,speed_last5m:0,speed_max:0}],rawsql:"SELECT\n *\nFROM\n \"message.publish\"\nWHERE\n topic =~ '#'"}}},methods:{loadData:function(){var e=this;return n()(s.a.mark(function t(){var r;return s.a.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:if(e.id){t.next=2;break}return t.abrupt("return");case 2:return t.next=4,e.$httpGet("/rules/"+e.id);case 4:r=t.sent,e.record=r.data;case 6:case"end":return t.stop()}},t,e)}))()}},created:function(){this.loadData()},computed:{id:function(){return this.$route.params.id}}},c={render:function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("div",{staticClass:"rule-view"},[r("div",{staticClass:"page-title"},[r("el-breadcrumb",{attrs:{separator:"/"}},[r("el-breadcrumb-item",{attrs:{to:{path:"/rules"}}},[e._v("\n "+e._s(e.$t("rule.message_rule"))+"\n ")]),e._v(" "),r("el-breadcrumb-item",{staticClass:"breadcrumb-name"},[e._v(e._s(e.id))])],1)],1),e._v(" "),r("el-card",{staticClass:"el-card--self"},[r("div",{staticClass:"config-dialog",attrs:{slot:"header"},slot:"header"},[e._v("\n "+e._s(e.$t("rule.basic_info"))+"\n ")]),e._v(" "),r("el-form",{attrs:{model:e.record,"label-position":"left","label-width":"100px","label-suffix":":"}},[r("el-form-item",{attrs:{label:e.$t("rule.topic")}},[r("span",[e._v(e._s(e.record.for.join(",")))])]),e._v(" "),r("el-form-item",{attrs:{label:e.$t("rule.description")}},[r("span",[e._v(e._s(e.record.description))])]),e._v(" "),r("el-form-item",{attrs:{label:e.$t("rule.rule_sql")}},[r("code",[e._v(e._s(e.record.rawsql))])])],1)],1),e._v(" "),r("el-card",{staticClass:"el-card--self"},[r("div",{staticClass:"config-dialog",attrs:{slot:"header"},slot:"header"},[e._v("\n "+e._s(e.$t("rule.metrics"))+"\n ")]),e._v(" "),r("el-table",{attrs:{border:"",data:e.record.metrics}},[r("el-table-column",{attrs:{prop:"node",label:e.$t("rule.node")}}),e._v(" "),r("el-table-column",{attrs:{prop:"matched",sortable:"",label:e.$t("rule.rule_matched_1")}}),e._v(" "),r("el-table-column",{attrs:{prop:"speed",sortable:"",label:e.$t("rule.speed_current")}}),e._v(" "),r("el-table-column",{attrs:{prop:"speed_max",label:e.$t("rule.speed_max_1")}}),e._v(" "),r("el-table-column",{attrs:{prop:"speed_last5m",label:e.$t("rule.speed_last5m_1")}})],1)],1),e._v(" "),r("el-card",{staticClass:"el-card--self"},[r("div",{staticClass:"config-dialog",attrs:{slot:"header"},slot:"header"},[e._v("\n "+e._s(e.$t("rule.set_action"))+"\n ")]),e._v(" "),r("rule-actions",{attrs:{record:e.record,operations:[]}})],1)],1)},staticRenderFns:[]};var i=r("VU/8")(o,c,!1,function(e){r("g3JU")},null,null);t.default=i.exports},g3JU:function(e,t){}}); \ No newline at end of file diff --git a/apps/emqx_dashboard/priv/www/static/js/15.7d11711536eb5b2ca561.js b/apps/emqx_dashboard/priv/www/static/js/15.7d11711536eb5b2ca561.js new file mode 100644 index 000000000..54486f22f --- /dev/null +++ b/apps/emqx_dashboard/priv/www/static/js/15.7d11711536eb5b2ca561.js @@ -0,0 +1 @@ +webpackJsonp([15],{DGQ0:function(t,e){},xPbZ:function(t,e,s){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var i=s("Dd8w"),n=s.n(i),a={name:"resources-view",components:{ResourceDialog:s("SHGx").a},props:{},data:function(){return{dialogVisible:!1,viewDialogVisible:!1,tableData:[],res:{},reloadLoading:!1,currentResource:""}},methods:{viewRunningStatus:function(t,e){var s=document.querySelectorAll(".el-table__expand-icon")[e];s&&s.click&&s.click()},handleReconnect:function(t,e){var s=this;this.reloadLoading=!0,this.currentResource=t.id,this.$httpPost("/resources/"+t.id).then(function(){setTimeout(function(){s.reloadLoading=!1,s.$message.success(s.$t("rule.connectSuccess"));try{t.status[e].is_alive=!0}catch(t){console.log(t)}},300)}).catch(function(){s.reloadLoading=!1})},handleDelete:function(t){var e=this;this.$confirm(this.$t("rule.confirm_stop_delete"),"Notice",{confirmButtonClass:"confirm-btn",confirmButtonText:this.$t("oper.confirm"),cancelButtonClass:"cache-btn el-button--text",cancelButtonText:this.$t("oper.cancel"),type:"warning"}).then(function(){e.$httpDelete("/resources/"+t.id).then(function(){e.$message.success(e.$t("rule.delete_success")),e.loadData()})}).catch()},viewResource:function(t){this.res=n()({},t),this.viewDialogVisible=!0},handleOperation:function(){this.dialogVisible=!0},loadData:function(){var t=this;this.$httpGet("/resources").then(function(e){var s=e.data;t.tableData=s.map(function(t){return t.status=t.status||[],t})})},handExpand:function(t){var e=this;t.status&&t.status.length>0||this.$httpGet("/resources/"+t.id).then(function(s){e.$set(t,"status",s.data.status)})}},created:function(){this.loadData()}},o={render:function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("div",{staticClass:"resources-view"},[s("div",{staticClass:"page-title"},[t._v("\n "+t._s(t.$t("rule.resource_title"))+"\n "),s("el-button",{staticClass:"confirm-btn",staticStyle:{float:"right"},attrs:{round:"",plain:"",type:"success",icon:"el-icon-plus",size:"medium",disable:t.$store.state.loading},on:{click:t.handleOperation}},[t._v("\n "+t._s(t.$t("rule.create"))+"\n ")])],1),t._v(" "),s("el-table",{attrs:{border:"",data:t.tableData},on:{"expand-change":t.handExpand}},[s("el-table-column",{attrs:{prop:"id",type:"expand","class-name":"expand-column",width:"1px"},scopedSlots:t._u([{key:"default",fn:function(e){var i=e.row;return[s("ul",{staticClass:"status-wrapper"},t._l(i.status||[],function(e,n){return s("li",{key:n,staticClass:"status-item"},[s("span",{staticClass:"key"},[t._v("\n "+t._s(e.node)+"\n ")]),t._v(" "),s("span",{class:[e.is_alive?"running":"stopped danger","status"]},[t._v("\n "+t._s(e.is_alive?t.$t("rule.enabled"):t.$t("rule.disabled"))+"\n ")]),t._v(" "),e.is_alive?t._e():s("el-button",{attrs:{loading:t.reloadLoading&&t.currentResource===i.id,plain:"",type:"success",size:"mini"},on:{click:function(e){return t.handleReconnect(i,n)}}},[t._v("\n "+t._s(t.$t("rule.reconnect"))+"\n ")])],1)}),0)]}}])}),t._v(" "),s("el-table-column",{attrs:{prop:"id",label:t.$t("rule.id")},scopedSlots:t._u([{key:"default",fn:function(e){var i=e.row;return[s("span",{on:{click:function(e){return t.viewResource(i)}}},[t._v("\n "+t._s(i.id)+"\n ")])]}}])}),t._v(" "),s("el-table-column",{attrs:{prop:"description",label:t.$t("rule.resource_des")}}),t._v(" "),s("el-table-column",{attrs:{prop:"type",label:t.$t("rule.resource_type")}}),t._v(" "),s("el-table-column",{attrs:{label:t.$t("rule.oper")},scopedSlots:t._u([{key:"default",fn:function(e){var i=e.row,n=e.$index;return[s("el-button",{attrs:{plain:"",type:"success",size:"mini"},on:{click:function(e){return t.viewResource(i)}}},[t._v("\n "+t._s(t.$t("rule.view"))+"\n ")]),t._v(" "),s("el-button",{attrs:{plain:"",size:"mini",type:"warning"},on:{click:function(e){return t.handleDelete(i)}}},[t._v("\n "+t._s(t.$t("rule.delete"))+"\n ")]),t._v(" "),s("el-button",{attrs:{plain:"",type:"success",size:"mini"},on:{click:function(e){return t.viewRunningStatus(i,n)}}},[t._v("\n "+t._s(t.$t("rule.viewStates"))+"\n ")])]}}])})],1),t._v(" "),s("resource-dialog",{ref:"resourceDialog",attrs:{visible:t.dialogVisible},on:{"update:visible":function(e){t.dialogVisible=e},confirm:t.loadData}}),t._v(" "),s("el-dialog",{attrs:{title:t.$t("rule.resource_details"),visible:t.viewDialogVisible},on:{"update:visible":function(e){t.viewDialogVisible=e}}},[s("div",{staticClass:"dialog-preview"},[s("div",{staticClass:"option-item"},[s("div",{staticClass:"option-title"},[t._v("\n "+t._s(t.$t("rule.id"))+"\n ")]),t._v(" "),s("div",{staticClass:"option-value"},[t._v(t._s(t.res.id))])]),t._v(" "),s("div",{staticClass:"option-item"},[s("div",{staticClass:"option-title"},[t._v("\n "+t._s(t.$t("rule.resource_type"))+"\n ")]),t._v(" "),s("div",{staticClass:"option-value"},[t._v(t._s(t.res.type))])]),t._v(" "),s("div",{staticClass:"option-item"},[s("div",{staticClass:"option-title"},[t._v("\n "+t._s(t.$t("rule.resource_des"))+"\n ")]),t._v(" "),s("div",{staticClass:"option-value"},[t._v(t._s(t.res.description))])]),t._v(" "),t.res.config&&Object.keys(t.res.config).length>0?s("div",{staticClass:"option-item"},[s("div",{staticClass:"option-title"},[t._v("\n "+t._s(t.$t("rule.config_info"))+"\n ")]),t._v(" "),s("div",{staticClass:"option-all"},t._l(Object.entries(t.res.config),function(e,i){return s("div",{key:i,staticClass:"option-item"},["object"!=typeof e[1]||Array.isArray(e[1])?[s("div",{staticClass:"option-title"},[t._v("\n "+t._s(e[0])+"\n ")]),t._v(" "),s("div",{staticClass:"option-value"},[t._v("\n "+t._s(e[1])+"\n ")])]:[s("div",{staticClass:"option-title"},[t._v("\n "+t._s(e[0])+"\n ")]),t._v(" "),s("div",{staticClass:"option-value"},[e[1]&&0!==Object.keys(e[1]).length?s("data-table",{staticStyle:{"margin-top":"0"},attrs:{disabled:""},model:{value:e[1],callback:function(s){t.$set(e,1,s)},expression:"item[1]"}}):s("span",[t._v("\n N/A\n ")])],1)]],2)}),0)]):t._e()]),t._v(" "),s("div",{attrs:{slot:"footer"},slot:"footer"},[s("el-button",{staticClass:"confirm-btn",attrs:{type:"success"},on:{click:function(e){t.viewDialogVisible=!1}}},[t._v("\n "+t._s(t.$t("rule.confirm"))+"\n ")])],1)])],1)},staticRenderFns:[]};var l=s("VU/8")(a,o,!1,function(t){s("DGQ0")},null,null);e.default=l.exports}}); \ No newline at end of file diff --git a/apps/emqx_dashboard/priv/www/static/js/16.6bfd6f3eb9216e73149c.js b/apps/emqx_dashboard/priv/www/static/js/16.6bfd6f3eb9216e73149c.js new file mode 100644 index 000000000..7ed55e988 --- /dev/null +++ b/apps/emqx_dashboard/priv/www/static/js/16.6bfd6f3eb9216e73149c.js @@ -0,0 +1 @@ +webpackJsonp([16],{RjBg:function(e,t,s){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var a=s("fZjL"),l=s.n(a),o=s("d7EF"),n=s.n(o),r=s("W3Iv"),i=s.n(r),c=s("Dd8w"),d=s.n(c),v=s("zL8q"),u=s("NYxO"),m={name:"overview-view",components:{"el-select":v.Select,"el-option":v.Option,"el-table":v.Table,"el-table-column":v.TableColumn,"el-row":v.Row,"el-col":v.Col},data:function(){return{nodeName:"",brokers:{},nodes:[],stats:[],timer:0,metrics:{packets:[],messages:[],bytes:[],client:[],session:[],delivery:[]}}},methods:d()({},Object(u.b)(["CURRENT_NODE"]),{init:function(){var e=this;this.$httpGet("/nodes").then(function(t){e.nodeName=e.$store.state.nodeName||t.data[0].node,e.nodes=t.data,e.CURRENT_NODE(e.nodeName),e.refreshInterval()}).catch(function(t){e.$message.error(t||e.$t("error.networkError")),setTimeout(function(){e.init()},2e4)})},refreshInterval:function(){this.loadData(),clearInterval(this.timer),this.timer=setInterval(this.loadData,1e4)},loadData:function(){var e=this;this.CURRENT_NODE(this.nodeName),this.$httpGet("/nodes").then(function(t){e.nodes=t.data.sort(function(t,s){return t.node===e.nodeName?-1:t.uptime>s.uptime?-1:1})}),this.$httpGet("/stats").then(function(t){var s=t.data;s.forEach(function(e){var t=d()({node:e.node},e.stats);i()(t).forEach(function(t){var s=n()(t,2),a=s[0],l=s[1],o=a.replace(/\./g,"_");e[o]=l,a.includes(".")&&delete e[a]})}),e.stats=s}),this.$httpGet("/brokers/"+this.nodeName).then(function(t){e.brokers=t.data}),this.$httpGet("/nodes/"+this.nodeName+"/metrics").then(function(t){e.metrics={packets:[],messages:[],bytes:[],client:[],session:[],delivery:[]};var s=d()({},t.data),a={packets:["received","sent","connect","connack","auth","disconnect.sent","disconnect.received","pingreq","pingresp","publish.received","publish.sent","puback.received","puback.sent","puback.missed","pubcomp.received","pubcomp.sent","pubcomp.missed","pubrec.received","pubrec.sent","pubrec.missed","pubrel.received","pubrel.sent","pubrel.missed","subscribe","suback","unsubscribe","unsuback"],messages:["received","sent","dropped","retained","qos0.received","qos0.sent","qos1.received","qos1.sent","qos2.received","qos2.expired","qos2.sent","qos2.dropped"],bytes:["received","sent"],client:["connected","authenticate","auth.anonymous","check_acl","subscribe","unsubscribe","disconnected"],session:["created","resumed","takeovered","discarded","terminated"],delivery:["dropped","dropped.no_local","dropped.too_large","dropped.qos0_msg","dropped.queue_full","dropped.expired"]};l()(a).forEach(function(l){a[l].forEach(function(a){var o=l+"."+a;delete s[o],void 0!==t.data[o]&&e.metrics[l].push({key:a,value:t.data[o]})})}),l()(s).forEach(function(t){var a=t.split(".")[0];e.metrics[a]&&void 0!==s[t]&&e.metrics[a].push({key:t.split(".").slice(1).join("."),value:s[t]})})})}}),created:function(){this.init()},beforeRouteLeave:function(e,t,s){clearInterval(this.timer),s()},beforeDestroy:function(){clearInterval(this.timer)}},p={render:function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"overview-view"},[s("div",{staticClass:"page-title"},[e._v("\n "+e._s(e.$t("leftbar.overview"))+"\n "),s("el-select",{staticClass:"select-radius",attrs:{placeholder:e.$t("select.placeholder")},on:{change:e.loadData},model:{value:e.nodeName,callback:function(t){e.nodeName=t},expression:"nodeName"}},e._l(e.nodes,function(e){return s("el-option",{key:e.node,attrs:{label:e.node,value:e.node}})}),1)],1),e._v(" "),s("div",{staticClass:"card-box",staticStyle:{"margin-top":"54px"}},[s("div",{staticClass:"card-title"},[e._v(e._s(e.$t("overview.broker")))]),e._v(" "),s("el-row",{staticClass:"broker-card",attrs:{gutter:10}},[s("el-col",{attrs:{span:6}},[s("div",{staticClass:"card-item"},[s("div",{staticClass:"icon"},[s("i",{staticClass:"iconfont icon-systemname"})]),e._v(" "),s("div",{staticClass:"desc"},[s("h3",[e._v(e._s(e.$t("overview.systemName")))]),e._v(" "),s("p",[e._v(e._s(e.brokers.sysdescr))])])])]),e._v(" "),s("el-col",{attrs:{span:6}},[s("div",{staticClass:"card-item"},[s("div",{staticClass:"icon"},[s("i",{staticClass:"iconfont icon-version",staticStyle:{"font-weight":"600"}})]),e._v(" "),s("div",{staticClass:"desc"},[s("h3",[e._v(e._s(e.$t("overview.version")))]),e._v(" "),s("p",[e._v(e._s(e.brokers.version))])])])]),e._v(" "),s("el-col",{attrs:{span:6}},[s("div",{staticClass:"card-item"},[s("div",{staticClass:"icon"},[s("i",{staticClass:"iconfont icon-uptime"})]),e._v(" "),s("div",{staticClass:"desc"},[s("h3",[e._v(e._s(e.$t("overview.uptime")))]),e._v(" "),s("p",[e._v(e._s(e.brokers.uptime))])])])]),e._v(" "),s("el-col",{attrs:{span:6}},[s("div",{staticClass:"card-item"},[s("div",{staticClass:"icon",staticStyle:{"line-height":"46px"}},[s("i",{staticClass:"iconfont icon-Systemtime",staticStyle:{"font-size":"36px",top:"2px"}})]),e._v(" "),s("div",{staticClass:"desc"},[s("h3",[e._v(e._s(e.$t("overview.systemTime")))]),e._v(" "),s("p",[e._v(e._s(e.brokers.datetime))])])])])],1)],1),e._v(" "),s("div",{staticClass:"card-box"},[s("div",{staticClass:"card-title"},[e._v(e._s(e.$t("overview.nodes"))+"("+e._s(e.nodes.length)+")")]),e._v(" "),s("el-table",{attrs:{data:e.nodes,border:""}},[s("el-table-column",{attrs:{prop:"node","min-width":"200",label:e.$t("overview.name")}}),e._v(" "),s("el-table-column",{attrs:{prop:"otp_release","min-width":"200",label:e.$t("overview.erlangOTPRelease")}}),e._v(" "),s("el-table-column",{attrs:{label:e.$t("overview.erlangProcesses")}},[s("el-table-column",{attrs:{"min-width":"150",prop:"process",label:"(used/avaliable)"},scopedSlots:e._u([{key:"default",fn:function(t){return[e._v("\n "+e._s(t.row.process_used+" / "+t.row.process_available)+"\n ")]}}])})],1),e._v(" "),s("el-table-column",{attrs:{label:e.$t("overview.cpuInfo")}},[s("el-table-column",{attrs:{"min-width":"180",label:" (1load/5load/15load)"},scopedSlots:e._u([{key:"default",fn:function(t){return[e._v("\n "+e._s(t.row.load1+" / "+t.row.load5+" / "+t.row.load15)+"\n ")]}}])})],1),e._v(" "),s("el-table-column",{attrs:{"min-width":"200",label:e.$t("overview.memoryInfo")}},[s("el-table-column",{attrs:{"min-width":"180",label:" (used/total)"},scopedSlots:e._u([{key:"default",fn:function(t){return[e._v("\n "+e._s(t.row.memory_used+" / "+t.row.memory_total)+"\n ")]}}])})],1),e._v(" "),s("el-table-column",{attrs:{prop:"max_fds","min-width":"120",label:e.$t("overview.maxFds")}}),e._v(" "),s("el-table-column",{attrs:{"min-width":"120",label:e.$t("overview.status")},scopedSlots:e._u([{key:"default",fn:function(t){return[s("span",{class:["Running"===t.row.node_status?"running":"stopped","status"]},[e._v("\n "+e._s(t.row.node_status)+"\n ")])]}}])})],1)],1),e._v(" "),s("div",{staticClass:"card-box"},[s("div",{staticClass:"card-title"},[e._v(e._s(e.$t("overview.stats"))+"("+e._s(e.stats.length)+")")]),e._v(" "),s("el-table",{staticClass:"stats-table",attrs:{data:e.stats,border:""}},[s("el-table-column",{attrs:{prop:"node","min-width":"150",label:e.$t("overview.name")}}),e._v(" "),s("el-table-column",{attrs:{label:e.$t("overview.connectionsCount")}},[s("el-table-column",{attrs:{"min-width":"150",label:"(count/max)"},scopedSlots:e._u([{key:"default",fn:function(t){var s=t.row;return[e._v("\n "+e._s(s.connections_count)+" / "+e._s(s.connections_max)+"\n ")]}}])})],1),e._v(" "),s("el-table-column",{attrs:{label:e.$t("overview.topicsCount")}},[s("el-table-column",{attrs:{"min-width":"150",label:"(count/max)"},scopedSlots:e._u([{key:"default",fn:function(t){var s=t.row;return[e._v("\n "+e._s(s.topics_count)+" / "+e._s(s.topics_max)+"\n ")]}}])})],1),e._v(" "),s("el-table-column",{attrs:{label:e.$t("overview.retainedCount")}},[s("el-table-column",{attrs:{"min-width":"150",label:"(count/max)"},scopedSlots:e._u([{key:"default",fn:function(t){var s=t.row;return[e._v("\n "+e._s(s.retained_count)+" / "+e._s(s.retained_max)+"\n ")]}}])})],1),e._v(" "),s("el-table-column",{attrs:{label:e.$t("overview.sessionsCount")}},[s("el-table-column",{attrs:{"min-width":"150",label:"(count/max)"},scopedSlots:e._u([{key:"default",fn:function(t){var s=t.row;return[e._v("\n "+e._s(s.sessions_count)+" / "+e._s(s.sessions_max)+"\n ")]}}])})],1),e._v(" "),s("el-table-column",{attrs:{label:e.$t("overview.subscriptionsCount")}},[s("el-table-column",{attrs:{"min-width":"150",label:"(count/max)"},scopedSlots:e._u([{key:"default",fn:function(t){var s=t.row;return[e._v("\n "+e._s(s.subscriptions_count)+" / "+e._s(s.subscriptions_max)+"\n ")]}}])})],1),e._v(" "),s("el-table-column",{attrs:{label:e.$t("overview.subscriptionsSharedCount")}},[s("el-table-column",{attrs:{"min-width":"150",label:"(count/max)"},scopedSlots:e._u([{key:"default",fn:function(t){var s=t.row;return[e._v("\n "+e._s(s.subscriptions_shared_count)+" / "+e._s(s.subscriptions_shared_max)+"\n ")]}}])})],1)],1)],1),e._v(" "),s("div",{staticClass:"card-box"},[s("div",{staticClass:"card-title"},[e._v(e._s(e.$t("overview.metrics")))]),e._v(" "),s("el-row",{attrs:{gutter:20}},[s("el-col",{attrs:{span:8}},[s("el-table",{attrs:{data:e.metrics.client}},[s("el-table-column",{attrs:{"min-width":"200",prop:"key",label:e.$t("overview.client")}}),e._v(" "),s("el-table-column",{attrs:{sortable:"",prop:"value",label:""}})],1)],1),e._v(" "),s("el-col",{attrs:{span:8}},[s("el-table",{attrs:{data:e.metrics.delivery}},[s("el-table-column",{attrs:{"min-width":"160",prop:"key",label:e.$t("overview.delivery")}}),e._v(" "),s("el-table-column",{attrs:{sortable:"",prop:"value",label:""}})],1)],1),e._v(" "),s("el-col",{attrs:{span:8}},[s("el-table",{attrs:{data:e.metrics.session}},[s("el-table-column",{attrs:{"min-width":"200",prop:"key",label:e.$t("overview.session")}}),e._v(" "),s("el-table-column",{attrs:{sortable:"",prop:"value",label:""}})],1)],1)],1),e._v(" "),s("el-row",{attrs:{gutter:20}},[s("el-col",{attrs:{span:8}},[s("el-table",{attrs:{data:e.metrics.packets}},[s("el-table-column",{attrs:{"min-width":"200",prop:"key",label:e.$t("overview.packetsData")}}),e._v(" "),s("el-table-column",{attrs:{sortable:"",prop:"value",label:""}})],1)],1),e._v(" "),s("el-col",{attrs:{span:8}},[s("el-table",{attrs:{data:e.metrics.messages}},[s("el-table-column",{attrs:{"min-width":"200",prop:"key",label:e.$t("overview.messagesData")}}),e._v(" "),s("el-table-column",{attrs:{sortable:"",prop:"value",label:""}})],1)],1),e._v(" "),s("el-col",{attrs:{span:8}},[s("el-table",{attrs:{data:e.metrics.bytes}},[s("el-table-column",{attrs:{"min-width":"160",prop:"key",label:e.$t("overview.bytesData")}}),e._v(" "),s("el-table-column",{attrs:{sortable:"",prop:"value",label:""}})],1)],1)],1)],1)])},staticRenderFns:[]};var b=s("VU/8")(m,p,!1,function(e){s("Xk+3")},null,null);t.default=b.exports},"Xk+3":function(e,t){}}); \ No newline at end of file diff --git a/apps/emqx_dashboard/priv/www/static/js/17.1d56280c16e6e2b81cff.js b/apps/emqx_dashboard/priv/www/static/js/17.1d56280c16e6e2b81cff.js new file mode 100644 index 000000000..b73d3de57 --- /dev/null +++ b/apps/emqx_dashboard/priv/www/static/js/17.1d56280c16e6e2b81cff.js @@ -0,0 +1 @@ +webpackJsonp([17],{EsSr:function(t,e){},wkqA:function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"not-found"},[n("p",[t._v("404 Not Found")]),t._v(" "),n("router-link",{attrs:{to:"/"}},[t._v("Homepage")]),t._v(" "),n("router-link",{attrs:{to:"#"},on:{click:function(e){return t.$router.go(-2)}}},[t._v("Back up")])],1)},staticRenderFns:[]};var o=n("VU/8")({name:"NotFound"},r,!1,function(t){n("EsSr")},null,null);e.default=o.exports}}); \ No newline at end of file diff --git a/apps/emqx_dashboard/priv/www/static/js/18.a0c394cb4b55bee2fa82.js b/apps/emqx_dashboard/priv/www/static/js/18.a0c394cb4b55bee2fa82.js new file mode 100644 index 000000000..48c45305b --- /dev/null +++ b/apps/emqx_dashboard/priv/www/static/js/18.a0c394cb4b55bee2fa82.js @@ -0,0 +1 @@ +webpackJsonp([18],{"6xQH":function(e,r){},lmfZ:function(e,r,s){"use strict";Object.defineProperty(r,"__esModule",{value:!0});var o=s("Dd8w"),t=s.n(o),n=s("zL8q"),l=s("NYxO"),i={name:"login-view",components:{"el-col":n.Col,"el-row":n.Row,"el-card":n.Card,"el-form":n.Form,"el-form-item":n.FormItem,"el-input":n.Input,"el-checkbox":n.Checkbox,"el-button":n.Button},data:function(){return{remember:!1,user:{username:"",password:""},loginError:{username:"",password:""}}},methods:t()({},Object(l.b)(["USER_LOGIN"]),{login:function(){var e=this;return this.user.username?this.user.password?void this.$axios.post("/auth",this.user).then(function(){e.USER_LOGIN({user:e.user,remember:e.remember}),e.$router.push(e.$route.query.redirect||"/")}).catch(function(){e.loginError.username=e.$t("login.error"),e.user={username:"",password:""}}):(this.loginError.password=this.$t("login.passwordRequired"),!1):(this.loginError.username=this.$t("login.usernameRequired"),!1)}})},a={render:function(){var e=this,r=e.$createElement,s=e._self._c||r;return s("div",{staticClass:"login-view"},[s("el-card",[s("div",{attrs:{slot:"header"},slot:"header"},[e._v("\n "+e._s(e.$t("login.title"))+"\n ")]),e._v(" "),s("el-form",{staticClass:"el-form--public",attrs:{size:"medium","label-position":"top",model:e.user},nativeOn:{keyup:function(r){return!r.type.indexOf("key")&&e._k(r.keyCode,"enter",13,r.key,"Enter")?null:e.login(r)}}},[s("el-form-item",{attrs:{label:e.$t("login.username")}},[s("el-input",{class:{error:e.loginError.username},attrs:{placeholder:e.loginError.username},on:{focus:function(r){e.loginError.username=""}},model:{value:e.user.username,callback:function(r){e.$set(e.user,"username",r)},expression:"user.username"}})],1),e._v(" "),s("el-form-item",{attrs:{label:e.$t("login.password")}},[s("el-input",{class:{error:e.loginError.password},attrs:{type:"password",placeholder:e.loginError.password},on:{focus:function(r){e.loginError.password=""}},model:{value:e.user.password,callback:function(r){e.$set(e.user,"password",r)},expression:"user.password"}})],1)],1),e._v(" "),s("div",{staticClass:"login-footer"},[s("el-checkbox",{model:{value:e.remember,callback:function(r){e.remember=r},expression:"remember"}},[e._v("\n "+e._s(e.$t("login.remember"))+"\n ")]),e._v(" "),s("el-button",{staticClass:"confirm-btn",attrs:{type:"success",loading:e.$store.state.loading,disabled:e.$store.state.loading},on:{click:e.login}},[e._v(e._s(e.$t("login.loginButton"))+"\n ")])],1),e._v(" "),s("div",{staticClass:"clear-fix"})],1)],1)},staticRenderFns:[]};var u=s("VU/8")(i,a,!1,function(e){s("6xQH")},null,null);r.default=u.exports}}); \ No newline at end of file diff --git a/apps/emqx_dashboard/priv/www/static/js/19.060521bb4ba4f7a81ac0.js b/apps/emqx_dashboard/priv/www/static/js/19.060521bb4ba4f7a81ac0.js new file mode 100644 index 000000000..beb98a621 --- /dev/null +++ b/apps/emqx_dashboard/priv/www/static/js/19.060521bb4ba4f7a81ac0.js @@ -0,0 +1 @@ +webpackJsonp([19],{IHTQ:function(e,t){},uuOo:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var s=n("Dd8w"),a=n.n(s),o=n("NYxO"),l=n("zL8q"),r={name:"listeners-view",components:{"el-select":l.Select,"el-option":l.Option,"el-table":l.Table,"el-table-column":l.TableColumn},data:function(){return{nodeName:"",nodes:[],listeners:[]}},methods:a()({},Object(o.b)(["CURRENT_NODE"]),{loadData:function(){var e=this;this.$httpGet("/nodes").then(function(t){e.nodeName=e.$store.state.nodeName||t.data[0].node,e.nodes=t.data,e.loadListeners()}).catch(function(t){e.$message.error(t||e.$t("error.networkError"))})},loadListeners:function(){var e=this;this.CURRENT_NODE(this.nodeName),this.$httpGet("/nodes/"+this.nodeName+"/listeners").then(function(t){e.listeners=t.data}).catch(function(t){e.$message.error(t||e.$t("error.networkError"))})}}),created:function(){this.loadData()}},i={render:function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"listeners-view"},[n("div",{staticClass:"page-title"},[e._v("\n "+e._s(e.$t("leftbar.listeners"))+"\n "),n("el-select",{staticClass:"select-radius",attrs:{placeholder:e.$t("select.placeholder"),disabled:e.$store.state.loading},on:{change:e.loadListeners},model:{value:e.nodeName,callback:function(t){e.nodeName=t},expression:"nodeName"}},e._l(e.nodes,function(e){return n("el-option",{key:e.node,attrs:{label:e.node,value:e.node}})}),1)],1),e._v(" "),n("el-table",{directives:[{name:"loading",rawName:"v-loading",value:e.$store.state.loading,expression:"$store.state.loading"}],attrs:{border:"",data:e.listeners}},[n("el-table-column",{attrs:{prop:"protocol",width:"240",label:e.$t("listeners.protocol")}}),e._v(" "),n("el-table-column",{attrs:{prop:"listen_on","min-width":"240",label:e.$t("listeners.listenOn")}}),e._v(" "),n("el-table-column",{attrs:{prop:"max_conns","min-width":"180",label:e.$t("listeners.maxConnections")}}),e._v(" "),n("el-table-column",{attrs:{prop:"current_conns","min-width":"120",label:e.$t("listeners.currentConnections")}})],1)],1)},staticRenderFns:[]};var c=n("VU/8")(r,i,!1,function(e){n("IHTQ")},null,null);t.default=c.exports}}); \ No newline at end of file diff --git a/apps/emqx_dashboard/priv/www/static/js/2.0aed9f93bfe094e9099c.js b/apps/emqx_dashboard/priv/www/static/js/2.0aed9f93bfe094e9099c.js new file mode 100644 index 000000000..9d6fb1400 --- /dev/null +++ b/apps/emqx_dashboard/priv/www/static/js/2.0aed9f93bfe094e9099c.js @@ -0,0 +1,8 @@ +webpackJsonp([2],{"+0Qw":function(e,t){},"+AxE":function(e,t){},"+HRN":function(e,t,n){"use strict";var i=n("kkc6").Buffer,r=n(2);e.exports=function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.head=null,this.tail=null,this.length=0}return e.prototype.push=function(e){var t={data:e,next:null};this.length>0?this.tail.next=t:this.head=t,this.tail=t,++this.length},e.prototype.unshift=function(e){var t={data:e,next:this.head};0===this.length&&(this.tail=t),this.head=t,++this.length},e.prototype.shift=function(){if(0!==this.length){var e=this.head.data;return 1===this.length?this.head=this.tail=null:this.head=this.head.next,--this.length,e}},e.prototype.clear=function(){this.head=this.tail=null,this.length=0},e.prototype.join=function(e){if(0===this.length)return"";for(var t=this.head,n=""+t.data;t=t.next;)n+=e+t.data;return n},e.prototype.concat=function(e){if(0===this.length)return i.alloc(0);if(1===this.length)return this.head.data;for(var t,n,r,o=i.allocUnsafe(e>>>0),s=this.head,a=0;s;)t=s.data,n=o,r=a,t.copy(n,r),a+=s.data.length,s=s.next;return o},e}(),r&&r.inspect&&r.inspect.custom&&(e.exports.prototype[r.inspect.custom]=function(){var e=r.inspect({length:this.length});return this.constructor.name+" "+e})},"+Tn7":function(e,t){},"+e0g":function(e,t,n){"use strict";var i=n("3PYz"),r=n("lZ6o"),o=r.utils,s=o.assert,a=o.parseBytes,u=n("RzOE"),c=n("hkfz");function l(e){if(s("ed25519"===e,"only tested with ed25519 so far"),!(this instanceof l))return new l(e);e=r.curves[e].curve;this.curve=e,this.g=e.g,this.g.precompute(e.n.bitLength()+1),this.pointClass=e.point().constructor,this.encodingLength=Math.ceil(e.n.bitLength()/8),this.hash=i.sha512}e.exports=l,l.prototype.sign=function(e,t){e=a(e);var n=this.keyFromSecret(t),i=this.hashInt(n.messagePrefix(),e),r=this.g.mul(i),o=this.encodePoint(r),s=this.hashInt(o,n.pubBytes(),e).mul(n.priv()),u=i.add(s).umod(this.curve.n);return this.makeSignature({R:r,S:u,Rencoded:o})},l.prototype.verify=function(e,t,n){e=a(e),t=this.makeSignature(t);var i=this.keyFromPublic(n),r=this.hashInt(t.Rencoded(),i.pubBytes(),e),o=this.g.mul(t.S());return t.R().add(i.pub().mul(r)).eq(o)},l.prototype.hashInt=function(){for(var e=this.hash(),t=0;t16)throw new Error("unable to decrypt data");var n=-1;for(;++n16)return t=this.cache.slice(0,16),this.cache=this.cache.slice(16),t}else if(this.cache.length>=16)return t=this.cache.slice(0,16),this.cache=this.cache.slice(16),t;return null},d.prototype.flush=function(){if(this.cache.length)return this.cache},t.createDecipher=function(e,t){var n=o[e.toLowerCase()];if(!n)throw new TypeError("invalid suite type");var i=c(t,!1,n.key,n.iv);return h(e,i.key,i.iv)},t.createDecipheriv=h},"+jct":function(e,t,n){"use strict";n.d(t,"b",function(){return i}),n.d(t,"a",function(){return r}),t.c=function(e){var t=r;if(e&&e instanceof RegExp)if(e.global)t=e;else{var n="g";e.ignoreCase&&(n+="i"),e.multiline&&(n+="m"),e.unicode&&(n+="u"),t=new RegExp(e.source,n)}return t.lastIndex=0,t},t.d=function(e,t,n,i){t.lastIndex=0;var r=t.exec(n);if(!r)return null;var o=r[0].indexOf(" ")>=0?function(e,t,n,i){var r,o=e-1-i;t.lastIndex=0;for(;r=t.exec(n);){var s=r.index||0;if(s>o)return null;if(t.lastIndex>=o)return{word:r[0],startColumn:i+1+s,endColumn:i+1+t.lastIndex}}return null}(e,t,n,i):function(e,t,n,i){var r,o=e-1-i,s=n.lastIndexOf(" ",o-1)+1;t.lastIndex=s;for(;r=t.exec(n);){var a=r.index||0;if(a<=o&&t.lastIndex>=o)return{word:r[0],startColumn:i+1+a,endColumn:i+1+t.lastIndex}}return null}(e,t,n,i);return t.lastIndex=0,o};var i="`~!@#$%^&*()-=+[{]}\\|;:'\",.<>/?";var r=function(e){void 0===e&&(e="");for(var t="(-?\\d*\\.\\d\\w*)|([^",n=0,r=i;n=0||(t+="\\"+o)}return t+="\\s]+)",new RegExp(t,"g")}()},"+oh4":function(e,t,n){"use strict";var i;n.d(t,"a",function(){return i}),n.d(t,"b",function(){return r}),function(e){e[e.None=0]="None",e[e.Indent=1]="Indent",e[e.IndentOutdent=2]="IndentOutdent",e[e.Outdent=3]="Outdent"}(i||(i={}));var r=function(){function e(e){if(this.open=e.open,this.close=e.close,this._standardTokenMask=0,Array.isArray(e.notIn))for(var t=0,n=e.notIn.length;t200)return t;if("object"==typeof t){switch(t.$mid){case 1:return i.a.revive(t);case 2:return new RegExp(t.source,t.flags)}for(var r in t)Object.hasOwnProperty.call(t,r)&&(t[r]=e(t[r],n+1))}return t}(t,0)};var i=n("mrx5")},"/9db":function(e,t,n){"use strict";n.d(t,"a",function(){return i});var i,r=n("7g0X");!function(e){e.editorTextFocus=new r.d("editorTextFocus",!1),e.focus=new r.d("editorFocus",!1),e.textInputFocus=new r.d("textInputFocus",!1),e.readOnly=new r.d("editorReadonly",!1),e.writable=e.readOnly.toNegated(),e.hasNonEmptySelection=new r.d("editorHasSelection",!1),e.hasOnlyEmptySelection=e.hasNonEmptySelection.toNegated(),e.hasMultipleSelections=new r.d("editorHasMultipleSelections",!1),e.hasSingleSelection=e.hasMultipleSelections.toNegated(),e.tabMovesFocus=new r.d("editorTabMovesFocus",!1),e.tabDoesNotMoveFocus=e.tabMovesFocus.toNegated(),e.isInEmbeddedEditor=new r.d("isInEmbeddedEditor",!1),e.canUndo=new r.d("canUndo",!1),e.canRedo=new r.d("canRedo",!1),e.languageId=new r.d("editorLangId",""),e.hasCompletionItemProvider=new r.d("editorHasCompletionItemProvider",!1),e.hasCodeActionsProvider=new r.d("editorHasCodeActionsProvider",!1),e.hasCodeLensProvider=new r.d("editorHasCodeLensProvider",!1),e.hasDefinitionProvider=new r.d("editorHasDefinitionProvider",!1),e.hasDeclarationProvider=new r.d("editorHasDeclarationProvider",!1),e.hasImplementationProvider=new r.d("editorHasImplementationProvider",!1),e.hasTypeDefinitionProvider=new r.d("editorHasTypeDefinitionProvider",!1),e.hasHoverProvider=new r.d("editorHasHoverProvider",!1),e.hasDocumentHighlightProvider=new r.d("editorHasDocumentHighlightProvider",!1),e.hasDocumentSymbolProvider=new r.d("editorHasDocumentSymbolProvider",!1),e.hasReferenceProvider=new r.d("editorHasReferenceProvider",!1),e.hasRenameProvider=new r.d("editorHasRenameProvider",!1),e.hasSignatureHelpProvider=new r.d("editorHasSignatureHelpProvider",!1),e.hasDocumentFormattingProvider=new r.d("editorHasDocumentFormattingProvider",!1),e.hasDocumentSelectionFormattingProvider=new r.d("editorHasDocumentSelectionFormattingProvider",!1),e.hasMultipleDocumentFormattingProvider=new r.d("editorHasMultipleDocumentFormattingProvider",!1),e.hasMultipleDocumentSelectionFormattingProvider=new r.d("editorHasMultipleDocumentSelectionFormattingProvider",!1)}(i||(i={}))},"/MLu":function(e,t,n){e.exports=n("cSWu").PassThrough},"/bUF":function(module,exports){var indexOf=function(e,t){if(e.indexOf)return e.indexOf(t);for(var n=0;n=s&&e<=u||e>=a&&e<=c}function _(e,t,n,i){for(var r,o="",s=0,a=-1,u=0,c=0;c<=e.length;++c){if(c2){var h=o.lastIndexOf(n);-1===h?(o="",s=0):s=(o=o.slice(0,h)).length-1-o.lastIndexOf(n),a=c,u=0;continue}if(2===o.length||1===o.length){o="",s=0,a=c,u=0;continue}}t&&(o.length>0?o+=n+"..":o="..",s=2)}else o.length>0?o+=n+e.slice(a+1,c):o=e.slice(a+1,c),s=c-a-1;a=c,u=0}else r===l&&-1!==u?++u:u=-1}return o}function b(e,t){var n=t.dir||t.root,i=t.base||(t.name||"")+(t.ext||"");return n?n===t.root?n+i:n+e+i:i}var y={resolve:function(){for(var e=[],t=0;t=-1;s--){var a=void 0;if(s>=0?a=e[s]:n?void 0!==(a=r.b["="+n]||r.a())&&a.slice(0,3).toLowerCase()===n.toLowerCase()+"\\"||(a=n+"\\"):a=r.a(),p(a,"path"),0!==a.length){var u=a.length,c=0,l="",d=!1,h=a.charCodeAt(0);if(u>1)if(g(h))if(d=!0,g(a.charCodeAt(1))){for(var f=2,m=f;f2&&g(a.charCodeAt(2))&&(d=!0,c=3));else g(h)&&(c=1,d=!0);if(!(l.length>0&&n.length>0&&l.toLowerCase()!==n.toLowerCase())&&(0===n.length&&l.length>0&&(n=l),o||(i=a.slice(c)+"\\"+i,o=d),n.length>0&&o))break}}return i=_(i,!o,"\\",g),n+(o?"\\":"")+i||"."},normalize:function(e){p(e,"path");var t=e.length;if(0===t)return".";var n,i,r=0,o=!1,s=e.charCodeAt(0);if(t>1)if(g(s))if(o=!0,g(e.charCodeAt(1))){for(var a=2,u=a;a2&&g(e.charCodeAt(2))&&(o=!0,r=3));else if(g(s))return"\\";return 0!==(i=r0&&g(e.charCodeAt(t-1))&&(i+="\\"),void 0===n?o?i.length>0?"\\"+i:"\\":i.length>0?i:"":o?i.length>0?n+"\\"+i:n+"\\":i.length>0?n+i:n},isAbsolute:function(e){p(e,"path");var t=e.length;if(0===t)return!1;var n=e.charCodeAt(0);return!!g(n)||!!(v(n)&&t>2&&58===e.charCodeAt(1)&&g(e.charCodeAt(2)))},join:function(){for(var e,t,n=[],i=0;i0&&(void 0===e?e=t=o:e+="\\"+o)}if(void 0===e)return".";var s=!0,a=0;if("string"==typeof t&&g(t.charCodeAt(0))){++a;var u=t.length;u>1&&g(t.charCodeAt(1))&&(++a,u>2&&(g(t.charCodeAt(2))?++a:s=!1))}if(s){for(;a=2&&(e="\\"+e.slice(a))}return y.normalize(e)},relative:function(e,t){if(p(e,"from"),p(t,"to"),e===t)return"";var n=y.resolve(e),i=y.resolve(t);if(n===i)return"";if((e=n.toLowerCase())===(t=i.toLowerCase()))return"";for(var r=0;rr&&e.charCodeAt(o-1)===h;--o);for(var s=o-r,a=0;aa&&t.charCodeAt(u-1)===h;--u);for(var c=u-a,l=sl){if(t.charCodeAt(a+f)===h)return i.slice(a+f+1);if(2===f)return i.slice(a+f)}s>l&&(e.charCodeAt(r+f)===h?d=f:2===f&&(d=3));break}var g=e.charCodeAt(r+f);if(g!==t.charCodeAt(a+f))break;g===h&&(d=f)}if(f!==l&&-1===d)return i;var m="";for(-1===d&&(d=0),f=r+d+1;f<=o;++f)f!==o&&e.charCodeAt(f)!==h||(0===m.length?m+="..":m+="\\..");return m.length>0?m+i.slice(a+d,u):(a+=d,i.charCodeAt(a)===h&&++a,i.slice(a,u))},toNamespacedPath:function(e){if("string"!=typeof e)return e;if(0===e.length)return"";var t=y.resolve(e);if(t.length>=3)if(t.charCodeAt(0)===h){if(t.charCodeAt(1)===h){var n=t.charCodeAt(2);if(63!==n&&n!==l)return"\\\\?\\UNC\\"+t.slice(2)}}else if(v(t.charCodeAt(0))&&58===t.charCodeAt(1)&&t.charCodeAt(2)===h)return"\\\\?\\"+t;return e},dirname:function(e){p(e,"path");var t=e.length;if(0===t)return".";var n=-1,i=-1,r=!0,o=0,s=e.charCodeAt(0);if(t>1)if(g(s)){if(n=o=1,g(e.charCodeAt(1))){for(var a=2,u=a;a2&&g(e.charCodeAt(2))&&(n=o=3));else if(g(s))return e;for(var c=t-1;c>=o;--c)if(g(e.charCodeAt(c))){if(!r){i=c;break}}else r=!1;if(-1===i){if(-1===n)return".";i=n}return e.slice(0,i)},basename:function(e,t){void 0!==t&&p(t,"ext"),p(e,"path");var n,i=0,r=-1,o=!0;e.length>=2&&(v(e.charCodeAt(0))&&58===e.charCodeAt(1)&&(i=2));if(void 0!==t&&t.length>0&&t.length<=e.length){if(t.length===e.length&&t===e)return"";var s=t.length-1,a=-1;for(n=e.length-1;n>=i;--n){var u=e.charCodeAt(n);if(g(u)){if(!o){i=n+1;break}}else-1===a&&(o=!1,a=n+1),s>=0&&(u===t.charCodeAt(s)?-1==--s&&(r=n):(s=-1,r=a))}return i===r?r=a:-1===r&&(r=e.length),e.slice(i,r)}for(n=e.length-1;n>=i;--n)if(g(e.charCodeAt(n))){if(!o){i=n+1;break}}else-1===r&&(o=!1,r=n+1);return-1===r?"":e.slice(i,r)},extname:function(e){p(e,"path");var t=0,n=-1,i=0,r=-1,o=!0,s=0;e.length>=2&&58===e.charCodeAt(1)&&v(e.charCodeAt(0))&&(t=i=2);for(var a=e.length-1;a>=t;--a){var u=e.charCodeAt(a);if(g(u)){if(!o){i=a+1;break}}else-1===r&&(o=!1,r=a+1),u===l?-1===n?n=a:1!==s&&(s=1):-1!==n&&(s=-1)}return-1===n||-1===r||0===s||1===s&&n===r-1&&n===i+1?"":e.slice(n,r)},format:function(e){if(null===e||"object"!=typeof e)throw new f("pathObject","Object",e);return b("\\",e)},parse:function(e){p(e,"path");var t={root:"",dir:"",base:"",ext:"",name:""};if(0===e.length)return t;var n=e.length,i=0,r=e.charCodeAt(0);if(n>1){if(g(r)){if(i=1,g(e.charCodeAt(1))){for(var o=2,s=o;o2))return t.root=t.dir=e,t;if(g(e.charCodeAt(2))){if(3===n)return t.root=t.dir=e,t;i=3}}}else if(g(r))return t.root=t.dir=e,t;i>0&&(t.root=e.slice(0,i));for(var a=-1,u=i,c=-1,d=!0,h=e.length-1,f=0;h>=i;--h)if(g(r=e.charCodeAt(h))){if(!d){u=h+1;break}}else-1===c&&(d=!1,c=h+1),r===l?-1===a?a=h:1!==f&&(f=1):-1!==a&&(f=-1);return-1===a||-1===c||0===f||1===f&&a===c-1&&a===u+1?-1!==c&&(t.base=t.name=e.slice(u,c)):(t.name=e.slice(u,a),t.base=e.slice(u,c),t.ext=e.slice(a,c)),t.dir=u>0&&u!==i?e.slice(0,u-1):t.root,t},sep:"\\",delimiter:";",win32:null,posix:null},w={resolve:function(){for(var e=[],t=0;t=-1&&!i;o--){var s=void 0;p(s=o>=0?e[o]:r.a(),"path"),0!==s.length&&(n=s+"/"+n,i=s.charCodeAt(0)===d)}return n=_(n,!i,"/",m),i?n.length>0?"/"+n:"/":n.length>0?n:"."},normalize:function(e){if(p(e,"path"),0===e.length)return".";var t=e.charCodeAt(0)===d,n=e.charCodeAt(e.length-1)===d;return 0!==(e=_(e,!t,"/",m)).length||t||(e="."),e.length>0&&n&&(e+="/"),t?"/"+e:e},isAbsolute:function(e){return p(e,"path"),e.length>0&&e.charCodeAt(0)===d},join:function(){for(var e,t=[],n=0;n0&&(void 0===e?e=r:e+="/"+r)}return void 0===e?".":w.normalize(e)},relative:function(e,t){if(p(e,"from"),p(t,"to"),e===t)return"";if((e=w.resolve(e))===(t=w.resolve(t)))return"";for(var n=1;na){if(t.charCodeAt(o+c)===d)return t.slice(o+c+1);if(0===c)return t.slice(o+c)}else r>a&&(e.charCodeAt(n+c)===d?u=c:0===c&&(u=0));break}var l=e.charCodeAt(n+c);if(l!==t.charCodeAt(o+c))break;l===d&&(u=c)}var h="";for(c=n+u+1;c<=i;++c)c!==i&&e.charCodeAt(c)!==d||(0===h.length?h+="..":h+="/..");return h.length>0?h+t.slice(o+u):(o+=u,t.charCodeAt(o)===d&&++o,t.slice(o))},toNamespacedPath:function(e){return e},dirname:function(e){if(p(e,"path"),0===e.length)return".";for(var t=e.charCodeAt(0)===d,n=-1,i=!0,r=e.length-1;r>=1;--r)if(e.charCodeAt(r)===d){if(!i){n=r;break}}else i=!1;return-1===n?t?"/":".":t&&1===n?"//":e.slice(0,n)},basename:function(e,t){void 0!==t&&p(t,"ext"),p(e,"path");var n,i=0,r=-1,o=!0;if(void 0!==t&&t.length>0&&t.length<=e.length){if(t.length===e.length&&t===e)return"";var s=t.length-1,a=-1;for(n=e.length-1;n>=0;--n){var u=e.charCodeAt(n);if(u===d){if(!o){i=n+1;break}}else-1===a&&(o=!1,a=n+1),s>=0&&(u===t.charCodeAt(s)?-1==--s&&(r=n):(s=-1,r=a))}return i===r?r=a:-1===r&&(r=e.length),e.slice(i,r)}for(n=e.length-1;n>=0;--n)if(e.charCodeAt(n)===d){if(!o){i=n+1;break}}else-1===r&&(o=!1,r=n+1);return-1===r?"":e.slice(i,r)},extname:function(e){p(e,"path");for(var t=-1,n=0,i=-1,r=!0,o=0,s=e.length-1;s>=0;--s){var a=e.charCodeAt(s);if(a!==d)-1===i&&(r=!1,i=s+1),a===l?-1===t?t=s:1!==o&&(o=1):-1!==t&&(o=-1);else if(!r){n=s+1;break}}return-1===t||-1===i||0===o||1===o&&t===i-1&&t===n+1?"":e.slice(t,i)},format:function(e){if(null===e||"object"!=typeof e)throw new f("pathObject","Object",e);return b("/",e)},parse:function(e){p(e,"path");var t={root:"",dir:"",base:"",ext:"",name:""};if(0===e.length)return t;var n,i=e.charCodeAt(0)===d;i?(t.root="/",n=1):n=0;for(var r=-1,o=0,s=-1,a=!0,u=e.length-1,c=0;u>=n;--u){var h=e.charCodeAt(u);if(h!==d)-1===s&&(a=!1,s=u+1),h===l?-1===r?r=u:1!==c&&(c=1):-1!==r&&(c=-1);else if(!a){o=u+1;break}}return-1===r||-1===s||0===c||1===c&&r===s-1&&r===o+1?-1!==s&&(t.base=t.name=0===o&&i?e.slice(1,s):e.slice(o,s)):(0===o&&i?(t.name=e.slice(1,r),t.base=e.slice(1,s)):(t.name=e.slice(o,r),t.base=e.slice(o,s)),t.ext=e.slice(r,s)),o>0?t.dir=e.slice(0,o-1):i&&(t.dir="/"),t},sep:"/",delimiter:":",win32:null,posix:null};w.win32=y.win32=y,w.posix=y.posix=w;var C="win32"===r.c?y.normalize:w.normalize,S="win32"===r.c?y.join:w.join,x="win32"===r.c?y.relative:w.relative,L="win32"===r.c?y.dirname:w.dirname,O="win32"===r.c?y.basename:w.basename,k="win32"===r.c?y.extname:w.extname,N="win32"===r.c?y.sep:w.sep},"/vd3":function(e,t,n){t.pbkdf2=n("GUE9"),t.pbkdf2Sync=n("Zq1s")},"/y0r":function(e,t,n){var i=n("BEbT"),r=n("X3l8").Buffer,o=n("z+8S"),s=n("LC74"),a=n("UPHp"),u=n("H2Pp"),c=n("4sPJ");function l(e,t,n,s){o.call(this);var u=r.alloc(4,0);this._cipher=new i.AES(t);var l=this._cipher.encryptBlock(u);this._ghash=new a(l),n=function(e,t,n){if(12===t.length)return e._finID=r.concat([t,r.from([0,0,0,1])]),r.concat([t,r.from([0,0,0,2])]);var i=new a(n),o=t.length,s=o%16;i.update(t),s&&(s=16-s,i.update(r.alloc(s,0))),i.update(r.alloc(8,0));var u=8*o,l=r.alloc(8);l.writeUIntBE(u,0,8),i.update(l),e._finID=i.state;var d=r.from(e._finID);return c(d),d}(this,n,l),this._prev=r.from(n),this._cache=r.allocUnsafe(0),this._secCache=r.allocUnsafe(0),this._decrypt=s,this._alen=0,this._len=0,this._mode=e,this._authTag=null,this._called=!1}s(l,o),l.prototype._update=function(e){if(!this._called&&this._alen){var t=16-this._alen%16;t<16&&(t=r.alloc(t,0),this._ghash.update(t))}this._called=!0;var n=this._mode.encrypt(this,e);return this._decrypt?this._ghash.update(e):this._ghash.update(n),this._len+=e.length,n},l.prototype._final=function(){if(this._decrypt&&!this._authTag)throw new Error("Unsupported state or unable to authenticate data");var e=u(this._ghash.final(8*this._alen,8*this._len),this._cipher.encryptBlock(this._finID));if(this._decrypt&&function(e,t){var n=0;e.length!==t.length&&n++;for(var i=Math.min(e.length,t.length),r=0;r0&&r[r.length-1])&&(6===o[0]||2===o[0])){s=0;continue}if(3===o[0]&&(!r||o[1]>r[0]&&o[1]=0;a--)(r=e[a])&&(s=(o<3?r(s):o>3?r(t,n,s):r(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},k=this&&this.__param||function(e,t){return function(n,i){t(n,i,e)}};!function(e){e.Hidden=new(function(){return function(){this.type=0}}());var t=function(){return function(e,t,n){this.actions=e,this.editorPosition=t,this.widgetPosition=n,this.type=1}}();e.Showing=t}(r||(r={}));var N,E=function(e){function t(t,n,i){var o=e.call(this)||this;return o._editor=t,o._quickFixActionId=n,o._keybindingService=i,o._onClick=o._register(new C.a),o.onClick=o._onClick.event,o._state=r.Hidden,o._domNode=document.createElement("div"),o._domNode.className="lightbulb-glyph",o._editor.addContentWidget(o),o._register(o._editor.onDidChangeModelContent(function(e){var t=o._editor.getModel();(1!==o._state.type||!t||o._state.editorPosition.lineNumber>=t.getLineCount())&&o.hide()})),o._register(p.k(o._domNode,"mousedown",function(e){if(1===o._state.type){o._editor.focus(),e.preventDefault();var t=p.x(o._domNode),n=t.top,i=t.height,r=o._editor.getConfiguration().lineHeight,s=Math.floor(r/3);null!==o._state.widgetPosition.position&&o._state.widgetPosition.position.lineNumber2&&i._editor.getTopForLineNumber(e)===i._editor.getTopForLineNumber(e-1)},f=s;if(!(o.fontInfo.spaceWidth*d>22))if(s>1&&!h(s-1))f-=1;else if(h(s+1)){if(a*o.fontInfo.spaceWidth<22)return this.hide()}else f+=1;this._state=new r.Showing(e,n,{position:{lineNumber:f,column:1},preference:t._posPref}),p.R(this._domNode,"autofixable",e.hasAutoFix),this._editor.layoutContentWidget(this)},Object.defineProperty(t.prototype,"title",{set:function(e){this._domNode.title=e},enumerable:!0,configurable:!0}),t.prototype.hide=function(){this._state=r.Hidden,this._editor.layoutContentWidget(this)},t.prototype._updateLightBulbTitle=function(){var e,t=this._keybindingService.lookupKeybinding(this._quickFixActionId);e=t?x.a("quickFixWithKb","Show Fixes ({0})",t.getLabel()):x.a("quickFix","Show Fixes"),this.title=e},t._posPref=[0],t=O([k(2,f.a)],t)}(o.a),I=this&&this.__extends||function(){var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(t,n)};return function(t,n){function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}}(),D=this&&this.__decorate||function(e,t,n,i){var r,o=arguments.length,s=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,n):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,i);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(s=(o<3?r(s):o>3?r(t,n,s):r(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},M=this&&this.__param||function(e,t){return function(n,i){t(n,i,e)}},T=this&&this.__awaiter||function(e,t,n,i){return new(n||(n=Promise))(function(r,o){function s(e){try{u(i.next(e))}catch(e){o(e)}}function a(e){try{u(i.throw(e))}catch(e){o(e)}}function u(e){e.done?r(e.value):new n(function(t){t(e.value)}).then(s,a)}u((i=i.apply(e,t||[])).next())})},P=this&&this.__generator||function(e,t){var n,i,r,o,s={label:0,sent:function(){if(1&r[0])throw r[1];return r[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,i&&(r=2&o[0]?i.return:o[0]?i.throw||((r=i.return)&&r.call(i),0):i.next)&&!(r=r.call(i,o[1])).done)return r;switch(i=0,r&&(o=[2&o[0],r.value]),o[0]){case 0:case 1:r=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,i=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(r=(r=s.trys).length>0&&r[r.length-1])&&(6===o[0]||2===o[0])){s=0;continue}if(3===o[0]&&(!r||o[1]>r[0]&&o[1]0))return[3,9];if(1!==e.trigger.autoApply&&(0!==e.trigger.autoApply||1!==t.actions.length))return[3,9];i.label=5;case 5:return i.trys.push([5,,7,8]),[4,this.delegate.applyCodeAction(t.actions[0],!1)];case 6:return i.sent(),[3,8];case 7:return t.dispose(),[7];case 8:return[2];case 9:return this._activeCodeActions.value=t,this._codeActionWidget.show(t,e.position),[3,11];case 10:this._codeActionWidget.isVisible?t.dispose():this._activeCodeActions.value=t,i.label=11;case 11:return[2]}})})},t.prototype.showCodeActionList=function(e,t){return T(this,void 0,void 0,function(){return P(this,function(n){return this._codeActionWidget.show(e,t),[2]})})},t.prototype._handleLightBulbSelect=function(e){this._codeActionWidget.show(e.actions,e)},t=D([M(3,h.a),M(4,f.a)],t)}(o.a),R=n("ItKl"),F=n("7g0X"),j=n("OHx0"),W=n("DBt1"),B=n("odeJ"),V=n("vTy2"),H=n("PCC9"),z=n("OBuU"),U=this&&this.__extends||function(){var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(t,n)};return function(t,n){function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}}(),K=new F.d("supportedCodeAction",""),q=function(e){function t(t,n,i,r){void 0===r&&(r=250);var o=e.call(this)||this;return o._editor=t,o._markerService=n,o._signalChange=i,o._delay=r,o._autoTriggerTimer=o._register(new B.e),o._register(o._markerService.onMarkerChanged(function(e){return o._onMarkerChanges(e)})),o._register(o._editor.onDidChangeCursorPosition(function(){return o._onCursorChange()})),o}return U(t,e),t.prototype.trigger=function(e){var t=this._getRangeOfSelectionUnlessWhitespaceEnclosed(e);return this._createEventAndSignalChange(e,t)},t.prototype._onMarkerChanges=function(e){var t=this,n=this._editor.getModel();n&&e.some(function(e){return e.toString()===n.uri.toString()})&&this._autoTriggerTimer.cancelAndSet(function(){t.trigger({type:"auto"})},this._delay)},t.prototype._onCursorChange=function(){var e=this;this._autoTriggerTimer.cancelAndSet(function(){e.trigger({type:"auto"})},this._delay)},t.prototype._getRangeOfMarker=function(e){var t=this._editor.getModel();if(t)for(var n=0,i=this._markerService.read({resource:t.uri});n=0;a--)(r=e[a])&&(s=(o<3?r(s):o>3?r(t,n,s):r(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},$=this&&this.__param||function(e,t){return function(n,i){t(n,i,e)}},J=this&&this.__awaiter||function(e,t,n,i){return new(n||(n=Promise))(function(r,o){function s(e){try{u(i.next(e))}catch(e){o(e)}}function a(e){try{u(i.throw(e))}catch(e){o(e)}}function u(e){e.done?r(e.value):new n(function(t){t(e.value)}).then(s,a)}u((i=i.apply(e,t||[])).next())})},Q=this&&this.__generator||function(e,t){var n,i,r,o,s={label:0,sent:function(){if(1&r[0])throw r[1];return r[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,i&&(r=2&o[0]?i.return:o[0]?i.throw||((r=i.return)&&r.call(i),0):i.next)&&!(r=r.call(i,o[1])).done)return r;switch(i=0,r&&(o=[2&o[0],r.value]),o[0]){case 0:case 1:r=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,i=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(r=(r=s.trys).length>0&&r[r.length-1])&&(6===o[0]||2===o[0])){s=0;continue}if(3===o[0]&&(!r||o[1]>r[0]&&o[1]=0;t--)this.editOperations[t]={operations:e.applyEdits(this.editOperations[t].operations)}},e.prototype.redo=function(e){for(var t=0;t0){var e=this.past.pop();try{e.undo(this.model)}catch(e){return Object(i.e)(e),this.clear(),null}return this.future.push(e),{selections:e.beforeCursorState,recordedVersionId:e.beforeVersionId}}return null},e.prototype.canUndo=function(){return this.past.length>0||null!==this.currentOpenStackElement},e.prototype.redo=function(){if(this.future.length>0){var e=this.future.pop();try{e.redo(this.model)}catch(e){return Object(i.e)(e),this.clear(),null}return this.past.push(e),{selections:e.afterCursorState,recordedVersionId:e.afterVersionId}}return null},e.prototype.canRedo=function(){return this.future.length>0},e}(),v=function(){return function(){this.spacesDiff=0,this.looksLikeAlignment=!1}}();function _(e,t,n,i,r){var o;for(r.spacesDiff=0,r.looksLikeAlignment=!1,o=0;o0&&a>0||c>0&&l>0)){var d=Math.abs(a-l),h=Math.abs(s-c);if(0===d)return r.spacesDiff=h,void(h>0&&0<=c-1&&c-10?r++:m>1&&o++,_(s,a,h,g,c),!c.looksLikeAlignment||n&&t===c.spacesDiff)){var S=c.spacesDiff;S<=8&&u[S]++,s=h,a=g}}var x=n;r!==o&&(x=rO&&(O=t,L=e)}),4===L&&u[4]>0&&u[2]>0&&u[2]>=u[4]/2&&(L=2)}return{insertSpaces:x,tabSize:L}}function y(e){return(1&e.metadata)>>>0}function w(e,t){e.metadata=254&e.metadata|t<<0}function C(e){return(2&e.metadata)>>>1==1}function S(e,t){e.metadata=253&e.metadata|(t?1:0)<<1}function x(e){return(4&e.metadata)>>>2==1}function L(e,t){e.metadata=251&e.metadata|(t?1:0)<<2}function O(e){return(8&e.metadata)>>>3==1}function k(e,t){e.metadata=247&e.metadata|(t?1:0)<<3}function N(e,t){e.metadata=207&e.metadata|t<<4}function E(e,t){e.metadata=191&e.metadata|(t?1:0)<<6}var I=function(){function e(e,t,n){this.metadata=0,this.parent=this,this.left=this,this.right=this,w(this,1),this.start=t,this.end=n,this.delta=0,this.maxEnd=n,this.id=e,this.ownerId=0,this.options=null,L(this,!1),N(this,1),k(this,!1),E(this,!1),this.cachedVersionId=0,this.cachedAbsoluteStart=t,this.cachedAbsoluteEnd=n,this.range=null,S(this,!1)}return e.prototype.reset=function(e,t,n,i){this.start=t,this.end=n,this.maxEnd=n,this.cachedVersionId=e,this.cachedAbsoluteStart=t,this.cachedAbsoluteEnd=n,this.range=i},e.prototype.setOptions=function(e){this.options=e;var t=this.options.className;L(this,"squiggly-error"===t||"squiggly-warning"===t||"squiggly-info"===t),N(this,this.options.stickiness),k(this,!(!this.options.overviewRuler||!this.options.overviewRuler.color)),E(this,this.options.collapseOnReplaceEdit)},e.prototype.setCachedOffsets=function(e,t,n){this.cachedVersionId!==n&&(this.range=null),this.cachedVersionId=n,this.cachedAbsoluteStart=e,this.cachedAbsoluteEnd=t},e.prototype.detach=function(){this.parent=null,this.left=null,this.right=null},e}(),D=new I(null,0,0);D.parent=D,D.left=D,D.right=D,w(D,0);var M=function(){function e(){this.root=D,this.requestNormalizeDelta=!1}return e.prototype.intervalSearch=function(e,t,n,i,r){return this.root===D?[]:function(e,t,n,i,r,o){var s=e.root,a=0,u=0,c=0,l=[],d=0;for(;s!==D;)if(C(s))S(s.left,!1),S(s.right,!1),s===s.parent.right&&(a-=s.parent.delta),s=s.parent;else{if(!C(s.left)){if(a+s.maxEndn)S(s,!0);else{if((c=a+s.end)>=t){s.setCachedOffsets(u,c,o);var h=!0;i&&s.ownerId&&s.ownerId!==i&&(h=!1),r&&x(s)&&(h=!1),h&&(l[d++]=s)}S(s,!0),s.right===D||C(s.right)||(a+=s.delta,s=s.right)}}return S(e.root,!1),l}(this,e,t,n,i,r)},e.prototype.search=function(e,t,n){return this.root===D?[]:function(e,t,n,i){var r=e.root,o=0,s=0,a=0,u=[],c=0;for(;r!==D;)if(C(r))S(r.left,!1),S(r.right,!1),r===r.parent.right&&(o-=r.parent.delta),r=r.parent;else if(r.left===D||C(r.left)){s=o+r.start,a=o+r.end,r.setCachedOffsets(s,a,i);var l=!0;t&&r.ownerId&&r.ownerId!==t&&(l=!1),n&&x(r)&&(l=!1),l&&(u[c++]=r),S(r,!0),r.right===D||C(r.right)||(o+=r.delta,r=r.right)}else r=r.left;return S(e.root,!1),u}(this,e,t,n)},e.prototype.collectNodesFromOwner=function(e){return function(e,t){var n=e.root,i=[],r=0;for(;n!==D;)C(n)?(S(n.left,!1),S(n.right,!1),n=n.parent):n.left===D||C(n.left)?(n.ownerId===t&&(i[r++]=n),S(n,!0),n.right===D||C(n.right)||(n=n.right)):n=n.left;return S(e.root,!1),i}(this,e)},e.prototype.collectNodesPostOrder=function(){return function(e){var t=e.root,n=[],i=0;for(;t!==D;)C(t)?(S(t.left,!1),S(t.right,!1),t=t.parent):t.left===D||C(t.left)?t.right===D||C(t.right)?(n[i++]=t,S(t,!0)):t=t.right:t=t.left;return S(e.root,!1),n}(this)},e.prototype.insert=function(e){A(this,e),this._normalizeDeltaIfNecessary()},e.prototype.delete=function(e){R(this,e),this._normalizeDeltaIfNecessary()},e.prototype.resolveNode=function(e,t){for(var n=e,i=0;e!==this.root;)e===e.parent.right&&(i+=e.parent.delta),e=e.parent;var r=n.start+i,o=n.end+i;n.setCachedOffsets(r,o,t)},e.prototype.acceptReplace=function(e,t,n,i){for(var r=function(e,t,n){var i=e.root,r=0,o=0,s=0,a=[],u=0;for(;i!==D;)if(C(i))S(i.left,!1),S(i.right,!1),i===i.parent.right&&(r-=i.parent.delta),i=i.parent;else{if(!C(i.left)){if(r+i.maxEndn?S(i,!0):((s=r+i.end)>=t&&(i.setCachedOffsets(o,s,0),a[u++]=i),S(i,!0),i.right===D||C(i.right)||(r+=i.delta,i=i.right))}return S(e.root,!1),a}(this,e,e+t),o=0,s=r.length;on?(r.start+=s,r.end+=s,r.delta+=s,(r.delta<-1073741824||r.delta>1073741824)&&(e.requestNormalizeDelta=!0),S(r,!0)):(S(r,!0),r.right===D||C(r.right)||(o+=r.delta,r=r.right))}S(e.root,!1)}(this,e,e+t,n),this._normalizeDeltaIfNecessary();for(o=0,s=r.length;on)&&(1!==i&&(2===i||t))}function P(e,t,n,i,r){var o=function(e){return(48&e.metadata)>>>4}(e),s=0===o||2===o,a=1===o||2===o,u=n-t,c=i,l=Math.min(u,c),d=e.start,h=!1,f=e.end,p=!1;t<=d&&f<=n&&function(e){return(64&e.metadata)>>>6==1}(e)&&(e.start=t,h=!0,e.end=t,p=!0);var g=r?1:u>0?2:0;if(!h&&T(d,s,t,g)&&(h=!0),!p&&T(f,a,t,g)&&(p=!0),l>0&&!r){g=u>c?2:0;!h&&T(d,s,t+l,g)&&(h=!0),!p&&T(f,a,t+l,g)&&(p=!0)}g=r?1:0;!h&&T(d,s,n,g)&&(e.start=t+c,h=!0),!p&&T(f,a,n,g)&&(e.end=t+c,p=!0);var m=c-u;h||(e.start=Math.max(0,d+m)),p||(e.end=Math.max(0,f+m)),e.start>e.end&&(e.end=e.start)}function A(e,t){if(e.root===D)return t.parent=D,t.left=D,t.right=D,w(t,0),e.root=t,e.root;!function(e,t){var n=0,i=e.root,r=t.start,o=t.end;for(;;){var s=z(r,o,i.start+n,i.end+n);if(s<0){if(i.left===D){t.start-=n,t.end-=n,t.maxEnd-=n,i.left=t;break}i=i.left}else{if(i.right===D){t.start-=n+i.delta,t.end-=n+i.delta,t.maxEnd-=n+i.delta,i.right=t;break}n+=i.delta,i=i.right}}t.parent=i,t.left=D,t.right=D,w(t,1)}(e,t),H(t.parent);for(var n=t;n!==e.root&&1===y(n.parent);){var i;if(n.parent===n.parent.parent.left)1===y(i=n.parent.parent.right)?(w(n.parent,0),w(i,0),w(n.parent.parent,1),n=n.parent.parent):(n===n.parent.right&&j(e,n=n.parent),w(n.parent,0),w(n.parent.parent,1),W(e,n.parent.parent));else 1===y(i=n.parent.parent.left)?(w(n.parent,0),w(i,0),w(n.parent.parent,1),n=n.parent.parent):(n===n.parent.left&&W(e,n=n.parent),w(n.parent,0),w(n.parent.parent,1),j(e,n.parent.parent))}return w(e.root,0),t}function R(e,t){var n,i;if(t.left===D?(i=t,(n=t.right).delta+=t.delta,(n.delta<-1073741824||n.delta>1073741824)&&(e.requestNormalizeDelta=!0),n.start+=t.delta,n.end+=t.delta):t.right===D?(n=t.left,i=t):((n=(i=function(e){for(;e.left!==D;)e=e.left;return e}(t.right)).right).start+=i.delta,n.end+=i.delta,n.delta+=i.delta,(n.delta<-1073741824||n.delta>1073741824)&&(e.requestNormalizeDelta=!0),i.start+=t.delta,i.end+=t.delta,i.delta=t.delta,(i.delta<-1073741824||i.delta>1073741824)&&(e.requestNormalizeDelta=!0)),i===e.root)return e.root=n,w(n,0),t.detach(),F(),V(n),void(e.root.parent=D);var r,o=1===y(i);if(i===i.parent.left?i.parent.left=n:i.parent.right=n,i===t?n.parent=i.parent:(i.parent===t?n.parent=i:n.parent=i.parent,i.left=t.left,i.right=t.right,i.parent=t.parent,w(i,y(t)),t===e.root?e.root=i:t===t.parent.left?t.parent.left=i:t.parent.right=i,i.left!==D&&(i.left.parent=i),i.right!==D&&(i.right.parent=i)),t.detach(),o)return H(n.parent),i!==t&&(H(i),H(i.parent)),void F();for(H(n),H(n.parent),i!==t&&(H(i),H(i.parent));n!==e.root&&0===y(n);)n===n.parent.left?(1===y(r=n.parent.right)&&(w(r,0),w(n.parent,1),j(e,n.parent),r=n.parent.right),0===y(r.left)&&0===y(r.right)?(w(r,1),n=n.parent):(0===y(r.right)&&(w(r.left,0),w(r,1),W(e,r),r=n.parent.right),w(r,y(n.parent)),w(n.parent,0),w(r.right,0),j(e,n.parent),n=e.root)):(1===y(r=n.parent.left)&&(w(r,0),w(n.parent,1),W(e,n.parent),r=n.parent.left),0===y(r.left)&&0===y(r.right)?(w(r,1),n=n.parent):(0===y(r.left)&&(w(r.right,0),w(r,1),j(e,r),r=n.parent.left),w(r,y(n.parent)),w(n.parent,0),w(r.left,0),W(e,n.parent),n=e.root));w(n,0),F()}function F(){D.parent=D,D.delta=0,D.start=0,D.end=0}function j(e,t){var n=t.right;n.delta+=t.delta,(n.delta<-1073741824||n.delta>1073741824)&&(e.requestNormalizeDelta=!0),n.start+=t.delta,n.end+=t.delta,t.right=n.left,n.left!==D&&(n.left.parent=t),n.parent=t.parent,t.parent===D?e.root=n:t===t.parent.left?t.parent.left=n:t.parent.right=n,n.left=t,t.parent=n,V(t),V(n)}function W(e,t){var n=t.left;t.delta-=n.delta,(t.delta<-1073741824||t.delta>1073741824)&&(e.requestNormalizeDelta=!0),t.start-=n.delta,t.end-=n.delta,t.left=n.right,n.right!==D&&(n.right.parent=t),n.parent=t.parent,t.parent===D?e.root=n:t===t.parent.right?t.parent.right=n:t.parent.left=n,n.right=t,t.parent=n,V(t),V(n)}function B(e){var t=e.end;if(e.left!==D){var n=e.left.maxEnd;n>t&&(t=n)}if(e.right!==D){var i=e.right.maxEnd+e.delta;i>t&&(t=i)}return t}function V(e){e.maxEnd=B(e)}function H(e){for(;e!==D;){var t=B(e);if(e.maxEnd===t)return;e.maxEnd=t,e=e.parent}}function z(e,t,n,i){return e===n?t-i:e-n}var U=function(){function e(e,t){this.piece=e,this.color=t,this.size_left=0,this.lf_left=0,this.parent=this,this.left=this,this.right=this}return e.prototype.next=function(){if(this.right!==K)return q(this.right);for(var e=this;e.parent!==K&&e.parent.left!==e;)e=e.parent;return e.parent===K?K:e.parent},e.prototype.prev=function(){if(this.left!==K)return G(this.left);for(var e=this;e.parent!==K&&e.parent.right!==e;)e=e.parent;return e.parent===K?K:e.parent},e.prototype.detach=function(){this.parent=null,this.left=null,this.right=null},e}(),K=new U(null,0);function q(e){for(;e.left!==K;)e=e.left;return e}function G(e){for(;e.right!==K;)e=e.right;return e}function Z(e){return e===K?0:e.size_left+e.piece.length+Z(e.right)}function Y(e){return e===K?0:e.lf_left+e.piece.lineFeedCnt+Y(e.right)}function X(){K.parent=K}function $(e,t){var n=t.right;n.size_left+=t.size_left+(t.piece?t.piece.length:0),n.lf_left+=t.lf_left+(t.piece?t.piece.lineFeedCnt:0),t.right=n.left,n.left!==K&&(n.left.parent=t),n.parent=t.parent,t.parent===K?e.root=n:t.parent.left===t?t.parent.left=n:t.parent.right=n,n.left=t,t.parent=n}function J(e,t){var n=t.left;t.left=n.right,n.right!==K&&(n.right.parent=t),n.parent=t.parent,t.size_left-=n.size_left+(n.piece?n.piece.length:0),t.lf_left-=n.lf_left+(n.piece?n.piece.lineFeedCnt:0),t.parent===K?e.root=n:t===t.parent.right?t.parent.right=n:t.parent.left=n,n.right=t,t.parent=n}function Q(e,t){var n,i;if(n=t.left===K?(i=t).right:t.right===K?(i=t).left:(i=q(t.right)).right,i===e.root)return e.root=n,n.color=0,t.detach(),X(),void(e.root.parent=K);var r=1===i.color;if(i===i.parent.left?i.parent.left=n:i.parent.right=n,i===t?(n.parent=i.parent,ne(e,n)):(i.parent===t?n.parent=i:n.parent=i.parent,ne(e,n),i.left=t.left,i.right=t.right,i.parent=t.parent,i.color=t.color,t===e.root?e.root=i:t===t.parent.left?t.parent.left=i:t.parent.right=i,i.left!==K&&(i.left.parent=i),i.right!==K&&(i.right.parent=i),i.size_left=t.size_left,i.lf_left=t.lf_left,ne(e,i)),t.detach(),n.parent.left===n){var o=Z(n),s=Y(n);if(o!==n.parent.size_left||s!==n.parent.lf_left){var a=o-n.parent.size_left,u=s-n.parent.lf_left;n.parent.size_left=o,n.parent.lf_left=s,te(e,n.parent,a,u)}}if(ne(e,n.parent),r)X();else{for(var c;n!==e.root&&0===n.color;)n===n.parent.left?(1===(c=n.parent.right).color&&(c.color=0,n.parent.color=1,$(e,n.parent),c=n.parent.right),0===c.left.color&&0===c.right.color?(c.color=1,n=n.parent):(0===c.right.color&&(c.left.color=0,c.color=1,J(e,c),c=n.parent.right),c.color=n.parent.color,n.parent.color=0,c.right.color=0,$(e,n.parent),n=e.root)):(1===(c=n.parent.left).color&&(c.color=0,n.parent.color=1,J(e,n.parent),c=n.parent.left),0===c.left.color&&0===c.right.color?(c.color=1,n=n.parent):(0===c.left.color&&(c.right.color=0,c.color=1,$(e,c),c=n.parent.left),c.color=n.parent.color,n.parent.color=0,c.left.color=0,J(e,n.parent),n=e.root));n.color=0,X()}}function ee(e,t){for(ne(e,t);t!==e.root&&1===t.parent.color;){var n;if(t.parent===t.parent.parent.left)1===(n=t.parent.parent.right).color?(t.parent.color=0,n.color=0,t.parent.parent.color=1,t=t.parent.parent):(t===t.parent.right&&$(e,t=t.parent),t.parent.color=0,t.parent.parent.color=1,J(e,t.parent.parent));else 1===(n=t.parent.parent.left).color?(t.parent.color=0,n.color=0,t.parent.parent.color=1,t=t.parent.parent):(t===t.parent.left&&J(e,t=t.parent),t.parent.color=0,t.parent.parent.color=1,$(e,t.parent.parent))}e.root.color=0}function te(e,t,n,i){for(;t!==e.root&&t!==K;)t.parent.left===t&&(t.parent.size_left+=n,t.parent.lf_left+=i),t=t.parent}function ne(e,t){var n=0,i=0;if(t!==e.root){if(0===n){for(;t!==e.root&&t===t.parent.right;)t=t.parent;if(t===e.root)return;n=Z((t=t.parent).left)-t.size_left,i=Y(t.left)-t.lf_left,t.size_left+=n,t.lf_left+=i}for(;t!==e.root&&(0!==n||0!==i);)t.parent.left===t&&(t.parent.size_left+=n,t.parent.lf_left+=i),t=t.parent}}K.parent=K,K.left=K,K.right=K,K.color=0;var ie=n("IErJ");function re(e){var t;return(t=e[e.length-1]<65536?new Uint16Array(e.length):new Uint32Array(e.length)).set(e,0),t}var oe=function(){return function(e,t,n,i,r){this.lineStarts=e,this.cr=t,this.lf=n,this.crlf=i,this.isBasicASCII=r}}();function se(e,t){void 0===t&&(t=!0);for(var n=[0],i=1,r=0,o=e.length;r=0;t--){var n=this._cache[t];if(n.nodeStartOffset<=e&&n.nodeStartOffset+n.node.piece.length>=e)return n}return null},e.prototype.get2=function(e){for(var t=this._cache.length-1;t>=0;t--){var n=this._cache[t];if(n.nodeStartLineNumber&&n.nodeStartLineNumber=e)return n}return null},e.prototype.set=function(e){this._cache.length>=this._limit&&this._cache.shift(),this._cache.push(e)},e.prototype.valdiate=function(e){for(var t=!1,n=this._cache,i=0;i=e)&&(n[i]=null,t=!0)}if(t){for(var o=[],s=0,a=n;s0){e[r].lineStarts||(e[r].lineStarts=se(e[r].buffer));var s=new ae(r+1,{line:0,column:0},{line:e[r].lineStarts.length-1,column:e[r].buffer.length-e[r].lineStarts[e[r].lineStarts.length-1]},e[r].lineStarts.length-1,e[r].buffer.length);this._buffers.push(e[r]),i=this.rbInsertRight(i,s)}this._searchCache=new ce(1),this._lastVisitedLine={lineNumber:0,value:""},this.computeBufferMetadata()},e.prototype.normalizeEOL=function(e){var t=this,n=65535-Math.floor(21845),i=2*n,r="",o=0,s=[];if(this.iterate(this.root,function(a){var u=t.getNodeContent(a),c=u.length;if(o<=n||o+c0){var a=r.replace(/\r\n|\r|\n/g,e);s.push(new ue(a,se(a)))}this.create(s,e,!0)},e.prototype.getEOL=function(){return this._EOL},e.prototype.setEOL=function(e){this._EOL=e,this._EOLLength=this._EOL.length,this.normalizeEOL(e)},e.prototype.getOffsetAt=function(e,t){for(var n=0,i=this.root;i!==K;)if(i.left!==K&&i.lf_left+1>=e)i=i.left;else{if(i.lf_left+i.piece.lineFeedCnt+1>=e)return(n+=i.size_left)+(this.getAccumulatedValue(i,e-i.lf_left-2)+t-1);e-=i.lf_left+i.piece.lineFeedCnt,n+=i.size_left+i.piece.length,i=i.right}return n},e.prototype.getPositionAt=function(e){e=Math.floor(e),e=Math.max(0,e);for(var t=this.root,n=0,i=e;t!==K;)if(0!==t.size_left&&t.size_left>=e)t=t.left;else{if(t.size_left+t.piece.length>=e){var r=this.getIndexOf(t,e-t.size_left);if(n+=t.lf_left+r.index,0===r.index){var o=i-this.getOffsetAt(n+1,1);return new c.a(n+1,o+1)}return new c.a(n+1,r.remainder+1)}if(e-=t.size_left+t.piece.length,n+=t.lf_left+t.piece.lineFeedCnt,t.right===K){o=i-e-this.getOffsetAt(n+1,1);return new c.a(n+1,o+1)}t=t.right}return new c.a(1,1)},e.prototype.getValueInRange=function(e,t){if(e.startLineNumber===e.endLineNumber&&e.startColumn===e.endColumn)return"";var n=this.nodeAt2(e.startLineNumber,e.startColumn),i=this.nodeAt2(e.endLineNumber,e.endColumn),r=this.getValueInRange2(n,i);return t?t===this._EOL&&this._EOLNormalized&&t===this.getEOL()&&this._EOLNormalized?r:r.replace(/\r\n|\r|\n/g,t):r},e.prototype.getValueInRange2=function(e,t){if(e.node===t.node){var n=e.node,i=this._buffers[n.piece.bufferIndex].buffer,r=this.offsetInBuffer(n.piece.bufferIndex,n.piece.start);return i.substring(r+e.remainder,r+t.remainder)}var o=e.node,s=this._buffers[o.piece.bufferIndex].buffer,a=this.offsetInBuffer(o.piece.bufferIndex,o.piece.start),u=s.substring(a+e.remainder,a+o.piece.length);for(o=o.next();o!==K;){var c=this._buffers[o.piece.bufferIndex].buffer,l=this.offsetInBuffer(o.piece.bufferIndex,o.piece.start);if(o===t.node){u+=c.substring(l,l+t.remainder);break}u+=c.substr(l,o.piece.length),o=o.next()}return u},e.prototype.getLinesContent=function(){return this.getContentOfSubTree(this.root).split(/\r\n|\r|\n/)},e.prototype.getLength=function(){return this._length},e.prototype.getLineCount=function(){return this._lineCnt},e.prototype.getLineContent=function(e){return this._lastVisitedLine.lineNumber===e?this._lastVisitedLine.value:(this._lastVisitedLine.lineNumber=e,e===this._lineCnt?this._lastVisitedLine.value=this.getLineRawContent(e):this._EOLNormalized?this._lastVisitedLine.value=this.getLineRawContent(e,this._EOLLength):this._lastVisitedLine.value=this.getLineRawContent(e).replace(/(\r\n|\r|\n)$/,""),this._lastVisitedLine.value)},e.prototype.getLineCharCode=function(e,t){var n=this.nodeAt2(e,t+1);if(n.remainder===n.node.piece.length){var i=n.node.next();if(!i)return 0;var r=this._buffers[i.piece.bufferIndex],o=this.offsetInBuffer(i.piece.bufferIndex,i.piece.start);return r.buffer.charCodeAt(o)}r=this._buffers[n.node.piece.bufferIndex];var s=(o=this.offsetInBuffer(n.node.piece.bufferIndex,n.node.piece.start))+n.remainder;return r.buffer.charCodeAt(s)},e.prototype.getLineLength=function(e){if(e===this.getLineCount()){var t=this.getOffsetAt(e,1);return this.getLength()-t}return this.getOffsetAt(e+1,1)-this.getOffsetAt(e,1)-this._EOLLength},e.prototype.findMatchesInNode=function(e,t,n,i,r,o,s,a,u,c,d){var h,f=this._buffers[e.piece.bufferIndex],p=this.offsetInBuffer(e.piece.bufferIndex,e.piece.start),g=this.offsetInBuffer(e.piece.bufferIndex,r),m=this.offsetInBuffer(e.piece.bufferIndex,o);t.reset(g);var v={line:0,column:0};do{if(h=t.next(f.buffer)){if(h.index>=m)return c;this.positionInBuffer(e,h.index-p,v);var _=this.getLineFeedCnt(e.piece.bufferIndex,r,v),b=v.line===r.line?v.column-r.column+i:v.column+1,y=b+h[0].length;if(d[c++]=Object(ie.d)(new l.a(n+_,b,n+_,y),h,a),h.index+h[0].length>=m)return c;if(c>=u)return c}}while(h);return c},e.prototype.findMatchesLineByLine=function(e,t,n,i){var r=[],o=0,s=new ie.b(t.wordSeparators,t.regex),a=this.nodeAt2(e.startLineNumber,e.startColumn);if(null===a)return[];var u=this.nodeAt2(e.endLineNumber,e.endColumn);if(null===u)return[];var c=this.positionInBuffer(a.node,a.remainder),l=this.positionInBuffer(u.node,u.remainder);if(a.node===u.node)return this.findMatchesInNode(a.node,s,e.startLineNumber,e.startColumn,c,l,t,n,i,o,r),r;for(var d=e.startLineNumber,h=a.node;h!==u.node;){var f=this.getLineFeedCnt(h.piece.bufferIndex,c,h.piece.end);if(f>=1){var p=this._buffers[h.piece.bufferIndex].lineStarts,g=this.offsetInBuffer(h.piece.bufferIndex,h.piece.start),m=p[c.line+f],v=d===e.startLineNumber?e.startColumn:1;if((o=this.findMatchesInNode(h,s,d,v,c,this.positionInBuffer(h,m-g),t,n,i,o,r))>=i)return r;d+=f}var _=d===e.startLineNumber?e.startColumn-1:0;if(d===e.endLineNumber){var b=this.getLineContent(d).substring(_,e.endColumn-1);return o=this._findMatchesInLine(t,s,b,e.endLineNumber,_,o,r,n,i),r}if((o=this._findMatchesInLine(t,s,this.getLineContent(d).substr(_),d,_,o,r,n,i))>=i)return r;d++,h=(a=this.nodeAt2(d,1)).node,c=this.positionInBuffer(a.node,a.remainder)}if(d===e.endLineNumber){var y=d===e.startLineNumber?e.startColumn-1:0;b=this.getLineContent(d).substring(y,e.endColumn-1);return o=this._findMatchesInLine(t,s,b,e.endLineNumber,y,o,r,n,i),r}var w=d===e.startLineNumber?e.startColumn:1;return o=this.findMatchesInNode(u.node,s,d,w,c,l,t,n,i,o,r),r},e.prototype._findMatchesInLine=function(e,t,n,i,r,o,s,a,u){var c,d=e.wordSeparators;if(!a&&e.simpleSearch){for(var f=e.simpleSearch,p=f.length,g=n.length,m=-p;-1!==(m=n.indexOf(f,m+p));)if((!d||Object(ie.e)(d,n,g,m,p))&&(s[o++]=new h.b(new l.a(i,m+1+r,i,m+1+p+r),null),o>=u))return o;return o}t.reset(0);do{if((c=t.next(n))&&(s[o++]=Object(ie.d)(new l.a(i,c.index+1+r,i,c.index+1+c[0].length+r),c,a),o>=u))return o}while(c);return o},e.prototype.insert=function(e,t,n){if(void 0===n&&(n=!1),this._EOLNormalized=this._EOLNormalized&&n,this._lastVisitedLine.lineNumber=0,this._lastVisitedLine.value="",this.root!==K){var i=this.nodeAt(e),r=i.node,o=i.remainder,s=i.nodeStartOffset,a=r.piece,u=a.bufferIndex,c=this.positionInBuffer(r,o);if(0===r.piece.bufferIndex&&a.end.line===this._lastChangeBufferPos.line&&a.end.column===this._lastChangeBufferPos.column&&s+a.length===e&&t.length<65535)return this.appendToNode(r,t),void this.computeBufferMetadata();if(s===e)this.insertContentToNodeLeft(t,r),this._searchCache.valdiate(e);else if(s+r.piece.length>e){var l=[],d=new ae(a.bufferIndex,c,a.end,this.getLineFeedCnt(a.bufferIndex,c,a.end),this.offsetInBuffer(u,a.end)-this.offsetInBuffer(u,c));if(this.shouldCheckCRLF()&&this.endWithCR(t))if(10===this.nodeCharCodeAt(r,o)){var h={line:d.start.line+1,column:0};d=new ae(d.bufferIndex,h,d.end,this.getLineFeedCnt(d.bufferIndex,h,d.end),d.length-1),t+="\n"}if(this.shouldCheckCRLF()&&this.startWithLF(t))if(13===this.nodeCharCodeAt(r,o-1)){var f=this.positionInBuffer(r,o-1);this.deleteNodeTail(r,f),t="\r"+t,0===r.piece.length&&l.push(r)}else this.deleteNodeTail(r,c);else this.deleteNodeTail(r,c);var p=this.createNewPieces(t);d.length>0&&this.rbInsertRight(r,d);for(var g=r,m=0;m=0;u--)a=this.rbInsertLeft(a,s[u]);this.validateCRLFWithPrevNode(a),this.deleteNodes(n)},e.prototype.insertContentToNodeRight=function(e,t){this.adjustCarriageReturnFromNext(e,t)&&(e+="\n");for(var n=this.createNewPieces(e),i=this.rbInsertRight(t,n[0]),r=i,o=1;o=l))break;a=c+1}return n?(n.line=c,n.column=s-d,null):{line:c,column:s-d}},e.prototype.getLineFeedCnt=function(e,t,n){if(0===n.column)return n.line-t.line;var i=this._buffers[e].lineStarts;if(n.line===i.length-1)return n.line-t.line;var r=i[n.line+1],o=i[n.line]+n.column;if(r>o+1)return n.line-t.line;var s=o-1;return 13===this._buffers[e].buffer.charCodeAt(s)?n.line-t.line+1:n.line-t.line},e.prototype.offsetInBuffer=function(e,t){return this._buffers[e].lineStarts[t.line]+t.column},e.prototype.deleteNodes=function(e){for(var t=0;t65535){for(var t=[];e.length>65535;){var n=e.charCodeAt(65534),i=void 0;13===n||n>=55296&&n<=56319?(i=e.substring(0,65534),e=e.substring(65534)):(i=e.substring(0,65535),e=e.substring(65535));var r=se(i);t.push(new ae(this._buffers.length,{line:0,column:0},{line:r.length-1,column:i.length-r[r.length-1]},r.length-1,i.length)),this._buffers.push(new ue(i,r))}var o=se(e);return t.push(new ae(this._buffers.length,{line:0,column:0},{line:o.length-1,column:e.length-o[o.length-1]},o.length-1,e.length)),this._buffers.push(new ue(e,o)),t}var s=this._buffers[0].buffer.length,a=se(e,!1),u=this._lastChangeBufferPos;if(this._buffers[0].lineStarts[this._buffers[0].lineStarts.length-1]===s&&0!==s&&this.startWithLF(e)&&this.endWithCR(this._buffers[0].buffer)){this._lastChangeBufferPos={line:this._lastChangeBufferPos.line,column:this._lastChangeBufferPos.column+1},u=this._lastChangeBufferPos;for(var c=0;c=e-1)n=n.left;else{if(n.lf_left+n.piece.lineFeedCnt>e-1){o=this.getAccumulatedValue(n,e-n.lf_left-2),u=this.getAccumulatedValue(n,e-n.lf_left-1),s=this._buffers[n.piece.bufferIndex].buffer,a=this.offsetInBuffer(n.piece.bufferIndex,n.piece.start);return c+=n.size_left,this._searchCache.set({node:n,nodeStartOffset:c,nodeStartLineNumber:l-(e-1-n.lf_left)}),s.substring(a+o,a+u-t)}if(n.lf_left+n.piece.lineFeedCnt===e-1){o=this.getAccumulatedValue(n,e-n.lf_left-2),s=this._buffers[n.piece.bufferIndex].buffer,a=this.offsetInBuffer(n.piece.bufferIndex,n.piece.start);i=s.substring(a+o,a+n.piece.length);break}e-=n.lf_left+n.piece.lineFeedCnt,c+=n.size_left+n.piece.length,n=n.right}for(n=n.next();n!==K;){s=this._buffers[n.piece.bufferIndex].buffer;if(n.piece.lineFeedCnt>0){u=this.getAccumulatedValue(n,0),a=this.offsetInBuffer(n.piece.bufferIndex,n.piece.start);return i+=s.substring(a,a+u-t)}a=this.offsetInBuffer(n.piece.bufferIndex,n.piece.start);i+=s.substr(a,n.piece.length),n=n.next()}return i},e.prototype.computeBufferMetadata=function(){for(var e=this.root,t=1,n=0;e!==K;)t+=e.lf_left+e.piece.lineFeedCnt,n+=e.size_left+e.piece.length,e=e.right;this._lineCnt=t,this._length=n,this._searchCache.valdiate(this._length)},e.prototype.getIndexOf=function(e,t){var n=e.piece,i=this.positionInBuffer(e,t),r=i.line-n.start.line;if(this.offsetInBuffer(n.bufferIndex,n.end)-this.offsetInBuffer(n.bufferIndex,n.start)===t){var o=this.getLineFeedCnt(e.piece.bufferIndex,n.start,i);if(o!==r)return{index:o,remainder:0}}return{index:r,remainder:i.column}},e.prototype.getAccumulatedValue=function(e,t){if(t<0)return 0;var n=e.piece,i=this._buffers[n.bufferIndex].lineStarts,r=n.start.line+t+1;return r>n.end.line?i[n.end.line]+n.end.column-i[n.start.line]-n.start.column:i[r]-i[n.start.line]-n.start.column},e.prototype.deleteNodeTail=function(e,t){var n=e.piece,i=n.lineFeedCnt,r=this.offsetInBuffer(n.bufferIndex,n.end),o=t,s=this.offsetInBuffer(n.bufferIndex,o),a=this.getLineFeedCnt(n.bufferIndex,n.start,o),u=a-i,c=s-r,l=n.length+c;e.piece=new ae(n.bufferIndex,n.start,o,a,l),te(this,e,c,u)},e.prototype.deleteNodeHead=function(e,t){var n=e.piece,i=n.lineFeedCnt,r=this.offsetInBuffer(n.bufferIndex,n.start),o=t,s=this.getLineFeedCnt(n.bufferIndex,o,n.end),a=s-i,u=r-this.offsetInBuffer(n.bufferIndex,o),c=n.length+u;e.piece=new ae(n.bufferIndex,o,n.end,s,c),te(this,e,u,a)},e.prototype.shrinkNode=function(e,t,n){var i=e.piece,r=i.start,o=i.end,s=i.length,a=i.lineFeedCnt,u=t,c=this.getLineFeedCnt(i.bufferIndex,i.start,u),l=this.offsetInBuffer(i.bufferIndex,t)-this.offsetInBuffer(i.bufferIndex,r);e.piece=new ae(i.bufferIndex,i.start,u,c,l),te(this,e,l-s,c-a);var d=new ae(i.bufferIndex,n,o,this.getLineFeedCnt(i.bufferIndex,n,o),this.offsetInBuffer(i.bufferIndex,o)-this.offsetInBuffer(i.bufferIndex,n)),h=this.rbInsertRight(e,d);this.validateCRLFWithPrevNode(h)},e.prototype.appendToNode=function(e,t){this.adjustCarriageReturnFromNext(t,e)&&(t+="\n");var n=this.shouldCheckCRLF()&&this.startWithLF(t)&&this.endWithCR(e),i=this._buffers[0].buffer.length;this._buffers[0].buffer+=t;for(var r=se(t,!1),o=0;oe)t=t.left;else{if(t.size_left+t.piece.length>=e){i+=t.size_left;var r={node:t,remainder:e-t.size_left,nodeStartOffset:i};return this._searchCache.set(r),r}e-=t.size_left+t.piece.length,i+=t.size_left+t.piece.length,t=t.right}return null},e.prototype.nodeAt2=function(e,t){for(var n=this.root,i=0;n!==K;)if(n.left!==K&&n.lf_left>=e-1)n=n.left;else{if(n.lf_left+n.piece.lineFeedCnt>e-1){var r=this.getAccumulatedValue(n,e-n.lf_left-2),o=this.getAccumulatedValue(n,e-n.lf_left-1);return i+=n.size_left,{node:n,remainder:Math.min(r+t-1,o),nodeStartOffset:i}}if(n.lf_left+n.piece.lineFeedCnt===e-1){if((r=this.getAccumulatedValue(n,e-n.lf_left-2))+t-1<=n.piece.length)return{node:n,remainder:r+t-1,nodeStartOffset:i};t-=n.piece.length-r;break}e-=n.lf_left+n.piece.lineFeedCnt,i+=n.size_left+n.piece.length,n=n.right}for(n=n.next();n!==K;){if(n.piece.lineFeedCnt>0){o=this.getAccumulatedValue(n,0);var s=this.offsetOfNode(n);return{node:n,remainder:Math.min(t-1,o),nodeStartOffset:s}}if(n.piece.length>=t-1)return{node:n,remainder:t-1,nodeStartOffset:this.offsetOfNode(n)};t-=n.piece.length,n=n.next()}return null},e.prototype.nodeCharCodeAt=function(e,t){if(e.piece.lineFeedCnt<1)return-1;var n=this._buffers[e.piece.bufferIndex],i=this.offsetInBuffer(e.piece.bufferIndex,e.piece.start)+t;return n.buffer.charCodeAt(i)},e.prototype.offsetOfNode=function(e){if(!e)return 0;for(var t=e.size_left;e!==this.root;)e.parent.right===e&&(t+=e.parent.size_left+e.parent.piece.length),e=e.parent;return t},e.prototype.shouldCheckCRLF=function(){return!(this._EOLNormalized&&"\n"===this._EOL)},e.prototype.startWithLF=function(e){if("string"==typeof e)return 10===e.charCodeAt(0);if(e===K||0===e.piece.lineFeedCnt)return!1;var t=e.piece,n=this._buffers[t.bufferIndex].lineStarts,i=t.start.line,r=n[i]+t.start.column;return i!==n.length-1&&(!(n[i+1]>r+1)&&10===this._buffers[t.bufferIndex].buffer.charCodeAt(r))},e.prototype.endWithCR=function(e){return"string"==typeof e?13===e.charCodeAt(e.length-1):e!==K&&0!==e.piece.lineFeedCnt&&13===this.nodeCharCodeAt(e,e.piece.length-1)},e.prototype.validateCRLFWithPrevNode=function(e){if(this.shouldCheckCRLF()&&this.startWithLF(e)){var t=e.prev();this.endWithCR(t)&&this.fixCRLF(t,e)}},e.prototype.validateCRLFWithNextNode=function(e){if(this.shouldCheckCRLF()&&this.endWithCR(e)){var t=e.next();this.startWithLF(t)&&this.fixCRLF(e,t)}},e.prototype.fixCRLF=function(e,t){var n,i=[],r=this._buffers[e.piece.bufferIndex].lineStarts;n=0===e.piece.end.column?{line:e.piece.end.line-1,column:r[e.piece.end.line]-r[e.piece.end.line-1]-1}:{line:e.piece.end.line,column:e.piece.end.column-1};var o=e.piece.length-1,s=e.piece.lineFeedCnt-1;e.piece=new ae(e.piece.bufferIndex,e.piece.start,n,s,o),te(this,e,-1,-1),0===e.piece.length&&i.push(e);var a={line:t.piece.start.line+1,column:0},u=t.piece.length-1,c=this.getLineFeedCnt(t.piece.bufferIndex,a,t.piece.end);t.piece=new ae(t.piece.bufferIndex,a,t.piece.end,c,u),te(this,t,-1,-1),0===t.piece.length&&i.push(t);var l=this.createNewPieces("\r\n");this.rbInsertRight(e,l[0]);for(var d=0;d0){v.sort(function(e,t){return t.lineNumber-e.lineNumber}),S=[];u=0;for(var x=v.length;u0&&v[u-1].lineNumber===b)){var L=v[u].oldContent,O=this.getLineContent(b);0!==O.length&&O!==L&&-1===s.q(O)&&S.push(b)}}}return new h.a(w,C,S)},e.prototype._reduceOperations=function(e){return e.length<1e3?e:[this._toSingleEditOperation(e)]},e.prototype._toSingleEditOperation=function(e){for(var t=!1,n=e[0].range,i=e[e.length-1].range,r=new l.a(n.startLineNumber,n.startColumn,i.endLineNumber,i.endColumn),o=n.startLineNumber,s=n.startColumn,a=[],u=0,c=e.length;u0){var h=a.lines.length,f=a.lines[0],p=a.lines[h-1];d=1===h?new l.a(u,c,u,c+f.length):new l.a(u,c,u+h-1,p.length+1)}else d=new l.a(u,c,u,c);n=d.endLineNumber,i=d.endColumn,t.push(d),r=a}return t},e._sortOpsAscending=function(e,t){var n=l.a.compareRangesUsingEnds(e.range,t.range);return 0===n?e.sortIndex-t.sortIndex:n},e._sortOpsDescending=function(e,t){var n=l.a.compareRangesUsingEnds(e.range,t.range);return 0===n?t.sortIndex-e.sortIndex:-n},e}(),he=function(){function e(e,t,n,i,r,o,s,a){this._chunks=e,this._bom=t,this._cr=n,this._lf=i,this._crlf=r,this._containsRTL=o,this._isBasicASCII=s,this._normalizeEOL=a}return e.prototype._getEOL=function(e){var t=this._cr+this._lf+this._crlf,n=this._cr+this._crlf;return 0===t?1===e?"\n":"\r\n":n>t/2?"\r\n":"\n"},e.prototype.create=function(e){var t=this._getEOL(e),n=this._chunks;if(this._normalizeEOL&&("\r\n"===t&&(this._cr>0||this._lf>0)||"\n"===t&&(this._cr>0||this._crlf>0)))for(var i=0,r=n.length;i=55296&&t<=56319?(this._acceptChunk1(e.substr(0,e.length-1),!1),this._hasPreviousChar=!0,this._previousChar=t):(this._acceptChunk1(e,!1),this._hasPreviousChar=!1,this._previousChar=t)}},e.prototype._acceptChunk1=function(e,t){(t||0!==e.length)&&(this._hasPreviousChar?this._acceptChunk2(String.fromCharCode(this._previousChar)+e):this._acceptChunk2(e))},e.prototype._acceptChunk2=function(e){var t=function(e,t){e.length=0,e[0]=0;for(var n=1,i=0,r=0,o=0,s=!0,a=0,u=t.length;a126)&&(s=!1)}var l=new oe(re(e),i,r,o,s);return e.length=0,l}(this._tmpLineStarts,e);this.chunks.push(new ue(e,t.lineStarts)),this.cr+=t.cr,this.lf+=t.lf,this.crlf+=t.crlf,this.isBasicASCII&&(this.isBasicASCII=t.isBasicASCII),this.isBasicASCII||this.containsRTL||(this.containsRTL=s.h(e))},e.prototype.finish=function(e){return void 0===e&&(e=!0),this._finish(),new he(this.chunks,this.BOM,this.cr,this.lf,this.crlf,this.containsRTL,this.isBasicASCII,e)},e.prototype._finish=function(){if(0===this.chunks.length&&this._acceptChunk1("",!0),this._hasPreviousChar){this._hasPreviousChar=!1;var e=this.chunks[this.chunks.length-1];e.buffer+=String.fromCharCode(this._previousChar);var t=se(e.buffer);e.lineStarts=t,13===this._previousChar&&this.cr++}},e}(),pe=function(){return function(){this.changeType=1}}(),ge=function(){return function(e,t){this.changeType=2,this.lineNumber=e,this.detail=t}}(),me=function(){return function(e,t){this.changeType=3,this.fromLineNumber=e,this.toLineNumber=t}}(),ve=function(){return function(e,t,n){this.changeType=4,this.fromLineNumber=e,this.toLineNumber=t,this.detail=n}}(),_e=function(){return function(){this.changeType=5}}(),be=function(){function e(e,t,n,i){this.changes=e,this.versionId=t,this.isUndoing=n,this.isRedoing=i}return e.prototype.containsEvent=function(e){for(var t=0,n=this.changes.length;t>>0}var Ne=new Uint32Array(0).buffer,Ee=function(){function e(){this.tokens=[]}return e.prototype.add=function(e,t){if(this.tokens.length>0){var n=this.tokens[this.tokens.length-1];if(n.startLineNumber+n.tokens.length-1+1===e)return void n.tokens.push(t)}this.tokens.push(new Ie(e,[t]))},e}(),Ie=function(){return function(e,t){this.startLineNumber=e,this.tokens=t}}();function De(e){return e instanceof Uint32Array?e:new Uint32Array(e)}var Me,Te=function(){function e(){this._lineTokens=[],this._len=0}return e.prototype.flush=function(){this._lineTokens=[],this._len=0},e.prototype.getTokens=function(e,t,n){var i=null;if(t1&&(r=Se.x.getLanguageId(i[1])!==e),!r)return Ne}if(!i||0===i.length){var o=new Uint32Array(2);return o[0]=t,o[1]=ke(e),o.buffer}return i[i.length-2]=t,0===i.byteOffset&&i.byteLength===i.buffer.byteLength?i.buffer:i},e.prototype._ensureLine=function(e){for(;e>=this._len;)this._lineTokens[this._len]=null,this._len++},e.prototype._deleteLines=function(e,t){0!==t&&(e+t>this._len&&(t=this._len-e),this._lineTokens.splice(e,t),this._len-=t)},e.prototype._insertLines=function(e,t){if(0!==t){for(var n=[],i=0;i=this._len))if(t.startLineNumber!==t.endLineNumber){this._lineTokens[n]=e._deleteEnding(this._lineTokens[n],t.startColumn-1);var i=t.endLineNumber-1,r=null;i=this._len||(0!==n?(this._lineTokens[r]=e._deleteEnding(this._lineTokens[r],t.column-1),this._lineTokens[r]=e._insert(this._lineTokens[r],t.column-1,i),this._insertLines(t.lineNumber,n)):this._lineTokens[r]=e._insert(this._lineTokens[r],t.column-1,i))}},e._deleteBeginning=function(t,n){return null===t||t===Ne?t:e._delete(t,0,n)},e._deleteEnding=function(t,n){if(null===t||t===Ne)return t;var i=De(t),r=i[i.length-2];return e._delete(t,n,r)},e._delete=function(e,t,n){if(null===e||e===Ne||t===n)return e;var i=De(e),r=i.length>>>1;if(0===t&&i[i.length-2]===n)return Ne;var o,s,a=Ce.a.findIndexInTokensArray(i,t),u=a>0?i[a-1<<1]:0;if(ns&&(i[o++]=f,i[o++]=i[1+(h<<1)],s=f)}if(o===i.length)return e;var p=new Uint32Array(o);return p.set(i.subarray(0,o),0),p.buffer},e._append=function(e,t){if(t===Ne)return e;if(e===Ne)return t;if(null===e)return e;if(null===t)return null;var n=De(e),i=De(t),r=i.length>>>1,o=new Uint32Array(n.length+i.length);o.set(n,0);for(var s=n.length,a=n[n.length-2],u=0;u>>1,o=Ce.a.findIndexInTokensArray(i,t);o>0&&(i[o-1<<1]===t&&o--);for(var s=o;s=this._len;)this._beginState[this._len]=null,this._valid[this._len]=!1,this._len++},e.prototype._deleteLines=function(e,t){0!==t&&(e+t>this._len&&(t=this._len-e),this._beginState.splice(e,t),this._valid.splice(e,t),this._len-=t)},e.prototype._insertLines=function(e,t){if(0!==t){for(var n=[],i=[],r=0;r=0;r--)this._invalidateLine(e.startLineNumber+r-1);this._acceptDeleteRange(e),this._acceptInsertText(new c.a(e.startLineNumber,e.startColumn),t)},e.prototype._acceptDeleteRange=function(e){e.startLineNumber-1>=this._len||this._deleteLines(e.startLineNumber,e.endLineNumber-e.startLineNumber)},e.prototype._acceptInsertText=function(e,t){e.lineNumber-1>=this._len||this._insertLines(e.lineNumber,t)},e}(),Re=function(e){function t(t){var n=e.call(this)||this;return n._textModel=t,n._tokenizationStateStore=new Ae,n._revalidateTokensTimeout=-1,n._tokenizationSupport=null,n._register(Se.y.onDidChange(function(e){var t=n._textModel.getLanguageIdentifier();-1!==e.changedLanguages.indexOf(t.language)&&(n._resetTokenizationState(),n._textModel.clearTokens())})),n._register(n._textModel.onDidChangeRawContentFast(function(e){e.containsEvent(1)&&n._resetTokenizationState()})),n._register(n._textModel.onDidChangeContentFast(function(e){for(var t=0,i=e.changes.length;t20);){if(this._tokenizeOneInvalidLine(t)>=e)break}this._beginBackgroundTokenization(),this._textModel.setTokens(t.tokens)},t.prototype.tokenizeViewport=function(e,t){var n=new Ee;this._tokenizeViewport(n,e,t),this._textModel.setTokens(n.tokens)},t.prototype.reset=function(){this._resetTokenizationState(),this._textModel.clearTokens()},t.prototype.forceTokenization=function(e){var t=new Ee;this._updateTokensUntilLine(t,e),this._textModel.setTokens(t.tokens)},t.prototype.isCheapToTokenize=function(e){if(!this._tokenizationSupport)return!0;var t=this._tokenizationStateStore.invalidLineStartIndex+1;return!(e>t)&&(e0&&s>=1;s--){var a=this._textModel.getLineFirstNonWhitespaceColumn(s);if(0!==a&&a=0;s--){c=(h=Fe(u,this._tokenizationSupport,r[s],c)).endState}for(var l=t;l<=n;l++){var d=this._textModel.getLineContent(l),h=Fe(u,this._tokenizationSupport,d,c);e.add(l,h.tokens),this._tokenizationStateStore.setFakeTokens(l-1),c=h.endState}}},t}(o.a);function Fe(e,t,n,r){var o=null;if(t)try{o=t.tokenize2(n,r.clone(),0)}catch(e){Object(i.e)(e)}return o||(o=Object(xe.e)(e.id,n,r,0)),Ce.a.convertToEndOffset(o.tokens,n.length),o}var je=n("+jct"),We=n("Fllr"),Be=n("Eeyw"),Ve=n("iNUG"),He=n("KIxu"),ze=n("TNPA");n.d(t,"b",function(){return Ye}),n.d(t,"a",function(){return tt});var Ue=this&&this.__extends||function(){var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(t,n)};return function(t,n){function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}}();function Ke(e){var t=new fe;return t.acceptChunk(e),t.finish()}function qe(e,t){return("string"==typeof e?Ke(e):e).create(t)}var Ge=0,Ze=function(){throw new Error("Invalid change accessor")},Ye=function(e){function t(n,i,o,u){void 0===u&&(u=null);var c=e.call(this)||this;c._onWillDispose=c._register(new r.a),c.onWillDispose=c._onWillDispose.event,c._onDidChangeDecorations=c._register(new rt),c.onDidChangeDecorations=c._onDidChangeDecorations.event,c._onDidChangeLanguage=c._register(new r.a),c.onDidChangeLanguage=c._onDidChangeLanguage.event,c._onDidChangeLanguageConfiguration=c._register(new r.a),c.onDidChangeLanguageConfiguration=c._onDidChangeLanguageConfiguration.event,c._onDidChangeTokens=c._register(new r.a),c.onDidChangeTokens=c._onDidChangeTokens.event,c._onDidChangeOptions=c._register(new r.a),c.onDidChangeOptions=c._onDidChangeOptions.event,c._onDidChangeAttached=c._register(new r.a),c.onDidChangeAttached=c._onDidChangeAttached.event,c._eventEmitter=c._register(new ot),Ge++,c.id="$model"+Ge,c.isForSimpleWidget=i.isForSimpleWidget,c._associatedResource=void 0===u||null===u?a.a.parse("inmemory://model/"+Ge):u,c._attachedEditorCount=0,c._buffer=qe(n,i.defaultEOL),c._options=t.resolveOptions(c._buffer,i);var d=c._buffer.getLineCount(),h=c._buffer.getValueLengthInRange(new l.a(1,1,d,c._buffer.getLineLength(d)+1),0);return i.largeFileOptimizations?c._isTooLargeForTokenization=h>t.LARGE_FILE_SIZE_THRESHOLD||d>t.LARGE_FILE_LINE_COUNT_THRESHOLD:c._isTooLargeForTokenization=!1,c._isTooLargeForSyncing=h>t.MODEL_SYNC_LIMIT,c._versionId=1,c._alternativeVersionId=1,c._isDisposed=!1,c._isDisposing=!1,c._languageIdentifier=o||xe.a,c._languageRegistryListener=We.a.onDidChange(function(e){e.languageIdentifier.id===c._languageIdentifier.id&&c._onDidChangeLanguageConfiguration.fire({})}),c._instanceId=s.I(Ge),c._lastDecorationId=0,c._decorations=Object.create(null),c._decorationsTree=new Xe,c._commandManager=new m(c),c._isUndoing=!1,c._isRedoing=!1,c._trimAutoWhitespaceLines=null,c._tokens=new Te,c._tokenization=new Re(c),c}return Ue(t,e),t.createFromString=function(e,n,i,r){return void 0===n&&(n=t.DEFAULT_CREATION_OPTIONS),void 0===i&&(i=null),void 0===r&&(r=null),new t(e,n,i,r)},t.resolveOptions=function(e,t){if(t.detectIndentation){var n=b(e,t.tabSize,t.insertSpaces);return new h.e({tabSize:n.tabSize,indentSize:n.tabSize,insertSpaces:n.insertSpaces,trimAutoWhitespace:t.trimAutoWhitespace,defaultEOL:t.defaultEOL})}return new h.e({tabSize:t.tabSize,indentSize:t.indentSize,insertSpaces:t.insertSpaces,trimAutoWhitespace:t.trimAutoWhitespace,defaultEOL:t.defaultEOL})},t.prototype.onDidChangeRawContentFast=function(e){return this._eventEmitter.fastEvent(function(t){return e(t.rawContentChangedEvent)})},t.prototype.onDidChangeRawContent=function(e){return this._eventEmitter.slowEvent(function(t){return e(t.rawContentChangedEvent)})},t.prototype.onDidChangeContentFast=function(e){return this._eventEmitter.fastEvent(function(t){return e(t.contentChangedEvent)})},t.prototype.onDidChangeContent=function(e){return this._eventEmitter.slowEvent(function(t){return e(t.contentChangedEvent)})},t.prototype.dispose=function(){this._isDisposing=!0,this._onWillDispose.fire(),this._languageRegistryListener.dispose(),this._tokenization.dispose(),this._isDisposed=!0,e.prototype.dispose.call(this),this._isDisposing=!1},t.prototype._assertNotDisposed=function(){if(this._isDisposed)throw new Error("Model is disposed!")},t.prototype._emitContentChangedEvent=function(e,t){this._isDisposing||this._eventEmitter.fire(new ye(e,t))},t.prototype.setValue=function(e){if(this._assertNotDisposed(),null!==e){var t=qe(e,this._options.defaultEOL);this.setValueFromTextBuffer(t)}},t.prototype._createContentChanged2=function(e,t,n,i,r,o,s){return{changes:[{range:e,rangeOffset:t,rangeLength:n,text:i}],eol:this._buffer.getEOL(),versionId:this.getVersionId(),isUndoing:r,isRedoing:o,isFlush:s}},t.prototype.setValueFromTextBuffer=function(e){if(this._assertNotDisposed(),null!==e){var t=this.getFullModelRange(),n=this.getValueLengthInRange(t),i=this.getLineCount(),r=this.getLineMaxColumn(i);this._buffer=e,this._increaseVersionId(),this._tokens.flush(),this._decorations=Object.create(null),this._decorationsTree=new Xe,this._commandManager=new m(this),this._trimAutoWhitespaceLines=null,this._emitContentChangedEvent(new be([new pe],this._versionId,!1,!1),this._createContentChanged2(new l.a(1,1,i,r),0,n,this.getValue(),!1,!1,!0))}},t.prototype.setEOL=function(e){this._assertNotDisposed();var t=1===e?"\r\n":"\n";if(this._buffer.getEOL()!==t){var n=this.getFullModelRange(),i=this.getValueLengthInRange(n),r=this.getLineCount(),o=this.getLineMaxColumn(r);this._onBeforeEOLChange(),this._buffer.setEOL(t),this._increaseVersionId(),this._onAfterEOLChange(),this._emitContentChangedEvent(new be([new _e],this._versionId,!1,!1),this._createContentChanged2(new l.a(1,1,r,o),0,i,this.getValue(),!1,!1,!1))}},t.prototype._onBeforeEOLChange=function(){var e=this.getVersionId(),t=this._decorationsTree.search(0,!1,!1,e);this._ensureNodesHaveRanges(t)},t.prototype._onAfterEOLChange=function(){for(var e=this.getVersionId(),t=this._decorationsTree.collectNodesPostOrder(),n=0,i=t.length;n0},t.prototype.getAttachedEditorCount=function(){return this._attachedEditorCount},t.prototype.isTooLargeForSyncing=function(){return this._isTooLargeForSyncing},t.prototype.isTooLargeForTokenization=function(){return this._isTooLargeForTokenization},t.prototype.isDisposed=function(){return this._isDisposed},t.prototype.isDominatedByLongLines=function(){if(this._assertNotDisposed(),this.isTooLargeForTokenization())return!1;for(var e=0,t=0,n=this._buffer.getLineCount(),i=1;i<=n;i++){var r=this._buffer.getLineLength(i);r>=1e4?t+=r:e+=r}return t>e},Object.defineProperty(t.prototype,"uri",{get:function(){return this._associatedResource},enumerable:!0,configurable:!0}),t.prototype.getOptions=function(){return this._assertNotDisposed(),this._options},t.prototype.getFormattingOptions=function(){return{tabSize:this._options.indentSize,insertSpaces:this._options.insertSpaces}},t.prototype.updateOptions=function(e){this._assertNotDisposed();var t=void 0!==e.tabSize?e.tabSize:this._options.tabSize,n=void 0!==e.indentSize?e.indentSize:this._options.indentSize,i=void 0!==e.insertSpaces?e.insertSpaces:this._options.insertSpaces,r=void 0!==e.trimAutoWhitespace?e.trimAutoWhitespace:this._options.trimAutoWhitespace,o=new h.e({tabSize:t,indentSize:n,insertSpaces:i,defaultEOL:this._options.defaultEOL,trimAutoWhitespace:r});if(!this._options.equals(o)){var s=this._options.createChangeEvent(o);this._options=o,this._onDidChangeOptions.fire(s)}},t.prototype.detectIndentation=function(e,t){this._assertNotDisposed();var n=b(this._buffer,t,e);this.updateOptions({insertSpaces:n.insertSpaces,tabSize:n.tabSize,indentSize:n.tabSize})},t._normalizeIndentationFromWhitespace=function(e,t,n){for(var i=0,r=0;rthis.getLineCount())throw new Error("Illegal value for lineNumber");return this._buffer.getLineContent(e)},t.prototype.getLineLength=function(e){if(this._assertNotDisposed(),e<1||e>this.getLineCount())throw new Error("Illegal value for lineNumber");return this._buffer.getLineLength(e)},t.prototype.getLinesContent=function(){return this._assertNotDisposed(),this._buffer.getLinesContent()},t.prototype.getEOL=function(){return this._assertNotDisposed(),this._buffer.getEOL()},t.prototype.getLineMinColumn=function(e){return this._assertNotDisposed(),1},t.prototype.getLineMaxColumn=function(e){if(this._assertNotDisposed(),e<1||e>this.getLineCount())throw new Error("Illegal value for lineNumber");return this._buffer.getLineLength(e)+1},t.prototype.getLineFirstNonWhitespaceColumn=function(e){if(this._assertNotDisposed(),e<1||e>this.getLineCount())throw new Error("Illegal value for lineNumber");return this._buffer.getLineFirstNonWhitespaceColumn(e)},t.prototype.getLineLastNonWhitespaceColumn=function(e){if(this._assertNotDisposed(),e<1||e>this.getLineCount())throw new Error("Illegal value for lineNumber");return this._buffer.getLineLastNonWhitespaceColumn(e)},t.prototype._validateRangeRelaxedNoAllocations=function(e){var t,n,i=this._buffer.getLineCount(),r=e.startLineNumber,o=e.startColumn;if(r<1)t=1,n=1;else if(r>i)t=i,n=this.getLineMaxColumn(t);else{if(t=0|r,o<=1)n=1;else n=o>=(h=this.getLineMaxColumn(t))?h:0|o}var s,a,u=e.endLineNumber,c=e.endColumn;if(u<1)s=1,a=1;else if(u>i)s=i,a=this.getLineMaxColumn(s);else{var h;if(s=0|u,c<=1)a=1;else a=c>=(h=this.getLineMaxColumn(s))?h:0|c}return r===t&&o===n&&u===s&&c===a&&e instanceof l.a&&!(e instanceof d.a)?e:new l.a(t,n,s,a)},t.prototype._isValidPosition=function(e,t,n){if("number"!=typeof e||"number"!=typeof t)return!1;if(isNaN(e)||isNaN(t))return!1;if(e<1||t<1)return!1;if((0|e)!==e||(0|t)!==t)return!1;if(e>this._buffer.getLineCount())return!1;if(t>this.getLineMaxColumn(e))return!1;if(n&&t>1){var i=this._buffer.getLineCharCode(e,t-2);if(s.w(i))return!1}return!0},t.prototype._validatePosition=function(e,t,n){var i=Math.floor("number"!=typeof e||isNaN(e)?1:e),r=Math.floor("number"!=typeof t||isNaN(t)?1:t),o=this._buffer.getLineCount();if(i<1)return new c.a(1,1);if(i>o)return new c.a(o,this.getLineMaxColumn(o));if(r<=1)return new c.a(i,1);var a=this.getLineMaxColumn(i);if(r>=a)return new c.a(i,a);if(n){var u=this._buffer.getLineCharCode(i,r-2);if(s.w(u))return new c.a(i,r-1)}return new c.a(i,r)},t.prototype.validatePosition=function(e){return this._assertNotDisposed(),e instanceof c.a&&this._isValidPosition(e.lineNumber,e.column,!0)?e:this._validatePosition(e.lineNumber,e.column,!0)},t.prototype._isValidRange=function(e,t){var n=e.startLineNumber,i=e.startColumn,r=e.endLineNumber,o=e.endColumn;if(!this._isValidPosition(n,i,!1))return!1;if(!this._isValidPosition(r,o,!1))return!1;if(t){var a=i>1?this._buffer.getLineCharCode(n,i-2):0,u=o>1&&o<=this._buffer.getLineLength(r)?this._buffer.getLineCharCode(r,o-2):0,c=s.w(a),l=s.w(u);return!c&&!l}return!0},t.prototype.validateRange=function(e){if(this._assertNotDisposed(),e instanceof l.a&&!(e instanceof d.a)&&this._isValidRange(e,!0))return e;var t=this._validatePosition(e.startLineNumber,e.startColumn,!1),n=this._validatePosition(e.endLineNumber,e.endColumn,!1),i=t.lineNumber,r=t.column,o=n.lineNumber,a=n.column,u=r>1?this._buffer.getLineCharCode(i,r-2):0,c=a>1&&a<=this._buffer.getLineLength(o)?this._buffer.getLineCharCode(o,a-2):0,h=s.w(u),f=s.w(c);return h||f?i===o&&r===a?new l.a(i,r-1,o,a-1):h&&f?new l.a(i,r-1,o,a+1):h?new l.a(i,r-1,o,a):new l.a(i,r,o,a+1):new l.a(i,r,o,a)},t.prototype.modifyPosition=function(e,t){this._assertNotDisposed();var n=this.getOffsetAt(e)+t;return this.getPositionAt(Math.min(this._buffer.getLength(),Math.max(0,n)))},t.prototype.getFullModelRange=function(){this._assertNotDisposed();var e=this.getLineCount();return new l.a(1,1,e,this.getLineMaxColumn(e))},t.prototype.findMatchesLineByLine=function(e,t,n,i){return this._buffer.findMatchesLineByLine(e,t,n,i)},t.prototype.findMatches=function(e,t,n,i,r,o,s){var a;if(void 0===s&&(s=999),this._assertNotDisposed(),a=l.a.isIRange(t)?this.validateRange(t):this.getFullModelRange(),!n&&e.indexOf("\n")<0){var u=new ie.a(e,n,i,r).parseSearchRequest();return u?this.findMatchesLineByLine(a,u,o,s):[]}return ie.c.findMatches(this,new ie.a(e,n,i,r),a,o,s)},t.prototype.findNextMatch=function(e,t,n,i,r,o){this._assertNotDisposed();var s=this.validatePosition(t);if(!n&&e.indexOf("\n")<0){var a=new ie.a(e,n,i,r).parseSearchRequest();if(!a)return null;var u=this.getLineCount(),c=new l.a(s.lineNumber,s.column,u,this.getLineMaxColumn(u)),d=this.findMatchesLineByLine(c,a,o,1);return ie.c.findNextMatch(this,new ie.a(e,n,i,r),s,o),d.length>0?d[0]:(c=new l.a(1,1,s.lineNumber,this.getLineMaxColumn(s.lineNumber)),(d=this.findMatchesLineByLine(c,a,o,1)).length>0?d[0]:null)}return ie.c.findNextMatch(this,new ie.a(e,n,i,r),s,o)},t.prototype.findPreviousMatch=function(e,t,n,i,r,o){this._assertNotDisposed();var s=this.validatePosition(t);return ie.c.findPreviousMatch(this,new ie.a(e,n,i,r),s,o)},t.prototype.pushStackElement=function(){this._commandManager.pushStackElement()},t.prototype.pushEOL=function(e){if(("\n"===this.getEOL()?0:1)!==e)try{this._onDidChangeDecorations.beginDeferredEmit(),this._eventEmitter.beginDeferredEmit(),this._commandManager.pushEOL(e)}finally{this._eventEmitter.endDeferredEmit(),this._onDidChangeDecorations.endDeferredEmit()}},t.prototype.pushEditOperations=function(e,t,n){try{return this._onDidChangeDecorations.beginDeferredEmit(),this._eventEmitter.beginDeferredEmit(),this._pushEditOperations(e,t,n)}finally{this._eventEmitter.endDeferredEmit(),this._onDidChangeDecorations.endDeferredEmit()}},t.prototype._pushEditOperations=function(e,t,n){var i=this;if(this._options.trimAutoWhitespace&&this._trimAutoWhitespaceLines){for(var r=t.map(function(e){return{range:i.validateRange(e.range),text:e.text}}),o=!0,s=0,a=e.length;su.endLineNumber,p=u.startLineNumber>_.endLineNumber;if(!f&&!p){c=!0;break}}if(!c){o=!1;break}}if(o)for(s=0,a=this._trimAutoWhitespaceLines.length;s_.endLineNumber)&&!(g===_.startLineNumber&&_.startColumn===m&&_.isEmpty()&&b&&b.length>0&&"\n"===b.charAt(0)||g===_.startLineNumber&&1===_.startColumn&&_.isEmpty()&&b&&b.length>0&&"\n"===b.charAt(b.length-1))){v=!1;break}}v&&t.push({range:new l.a(g,1,g,m),text:null})}this._trimAutoWhitespaceLines=null}return this._commandManager.pushEditOperation(e,t,n)},t.prototype.applyEdits=function(e){try{return this._onDidChangeDecorations.beginDeferredEmit(),this._eventEmitter.beginDeferredEmit(),this._applyEdits(e)}finally{this._eventEmitter.endDeferredEmit(),this._onDidChangeDecorations.endDeferredEmit()}},t.prototype._applyEdits=function(e){for(var t=0,n=e.length;t=0;b--){var y=f+b,w=o-u-_+y;a.push(new ge(y,this.getLineContent(w)))}if(vthis.getLineCount()?[]:this.getLinesDecorations(e,e,t,n)},t.prototype.getLinesDecorations=function(e,t,n,i){void 0===n&&(n=0),void 0===i&&(i=!1);var r=this.getLineCount(),o=Math.min(r,Math.max(1,e)),s=Math.min(r,Math.max(1,t)),a=this.getLineMaxColumn(s);return this._getDecorationsInRange(new l.a(o,1,s,a),n,i)},t.prototype.getDecorationsInRange=function(e,t,n){void 0===t&&(t=0),void 0===n&&(n=!1);var i=this.validateRange(e);return this._getDecorationsInRange(i,t,n)},t.prototype.getOverviewRulerDecorations=function(e,t){void 0===e&&(e=0),void 0===t&&(t=!1);var n=this.getVersionId(),i=this._decorationsTree.search(e,t,!0,n);return this._ensureNodesHaveRanges(i)},t.prototype.getAllDecorations=function(e,t){void 0===e&&(e=0),void 0===t&&(t=!1);var n=this.getVersionId(),i=this._decorationsTree.search(e,t,!1,n);return this._ensureNodesHaveRanges(i)},t.prototype._getDecorationsInRange=function(e,t,n){var i=this._buffer.getOffsetAt(e.startLineNumber,e.startColumn),r=this._buffer.getOffsetAt(e.endLineNumber,e.endColumn),o=this.getVersionId(),s=this._decorationsTree.intervalSearch(i,r,t,n,o);return this._ensureNodesHaveRanges(s)},t.prototype._ensureNodesHaveRanges=function(e){for(var t=0,n=e.length;tthis.getLineCount())throw new Error("Illegal value for lineNumber");this._tokens.setTokens(this._languageIdentifier.id,e-1,this._buffer.getLineLength(e),t)},t.prototype.setTokens=function(e){if(0!==e.length){for(var t=[],n=0,i=e.length;nthis.getLineCount())throw new Error("Illegal value for lineNumber");this._tokenization.forceTokenization(e)},t.prototype.isCheapToTokenize=function(e){return this._tokenization.isCheapToTokenize(e)},t.prototype.tokenizeIfCheap=function(e){this.isCheapToTokenize(e)&&this.forceTokenization(e)},t.prototype.getLineTokens=function(e){if(e<1||e>this.getLineCount())throw new Error("Illegal value for lineNumber");return this._getLineTokens(e)},t.prototype._getLineTokens=function(e){var t=this.getLineContent(e);return this._tokens.getTokens(this._languageIdentifier.id,e-1,t)},t.prototype.getLanguageIdentifier=function(){return this._languageIdentifier},t.prototype.getModeId=function(){return this._languageIdentifier.language},t.prototype.setMode=function(e){if(this._languageIdentifier.id!==e.id){var t={oldLanguage:this._languageIdentifier.language,newLanguage:e.language};this._languageIdentifier=e,this._onDidChangeLanguage.fire(t),this._onDidChangeLanguageConfiguration.fire({})}},t.prototype.getLanguageIdAtPosition=function(e,t){var n=this.validatePosition(new c.a(e,t)),i=this.getLineTokens(n.lineNumber);return i.getLanguageId(i.findTokenIndexAtOffset(n.column-1))},t.prototype.getWordAtPosition=function(e){this._assertNotDisposed();var n=this.validatePosition(e),i=this.getLineContent(n.lineNumber),r=this._getLineTokens(n.lineNumber),o=r.findTokenIndexAtOffset(n.column-1),s=t._findLanguageBoundaries(r,o),a=s[0],u=s[1],c=Object(je.d)(n.column,We.a.getWordDefinition(r.getLanguageId(o)),i.substring(a,u),a);if(c&&c.startColumn<=e.column&&e.column<=c.endColumn)return c;if(o>0&&a===n.column-1){var l=t._findLanguageBoundaries(r,o-1),d=l[0],h=l[1],f=Object(je.d)(n.column,We.a.getWordDefinition(r.getLanguageId(o-1)),i.substring(d,h),d);if(f&&f.startColumn<=e.column&&e.column<=f.endColumn)return f}return null},t._findLanguageBoundaries=function(e,t){for(var n=e.getLanguageId(t),i=0,r=t;r>=0&&e.getLanguageId(r)===n;r--)i=e.getStartOffset(r);for(var o=e.getLineContent().length,s=(r=t,e.getCount());r0&&n.getStartOffset(r)===e.column-1){a=n.getStartOffset(r);r--;var c=We.a.getBracketsSupport(n.getLanguageId(r));if(c&&!Object(Be.b)(n.getStandardTokenType(r))){var l,d,h;s=Math.max(n.getStartOffset(r),e.column-1-c.maxBracketLength);if((l=Ve.a.findPrevBracketInToken(c.reversedRegex,t,i,s,a))&&l.startColumn<=e.column&&e.column<=l.endColumn)if(d=(d=i.substring(l.startColumn-1,l.endColumn-1)).toLowerCase(),h=this._matchFoundBracket(l,c.textIsBracket[d],c.textIsOpenBracket[d]))return h}}return null},t.prototype._matchFoundBracket=function(e,t,n){if(!t)return null;var i;if(n){if(i=this._findMatchingBracketDown(t,e.getEndPosition()))return[e,i]}else if(i=this._findMatchingBracketUp(t,e.getStartPosition()))return[e,i];return null},t.prototype._findMatchingBracketUp=function(e,t){for(var n=e.languageIdentifier.id,i=e.reversedRegex,r=-1,o=t.lineNumber;o>=1;o--){var s=this._getLineTokens(o),a=s.getCount(),u=this._buffer.getLineContent(o),c=a-1,l=-1;for(o===t.lineNumber&&(c=s.findTokenIndexAtOffset(t.column-1),l=t.column-1);c>=0;c--){var d=s.getLanguageId(c),h=s.getStandardTokenType(c),f=s.getStartOffset(c),p=s.getEndOffset(c);if(-1===l&&(l=p),d===n&&!Object(Be.b)(h))for(;;){var g=Ve.a.findPrevBracketInToken(i,o,u,f,l);if(!g)break;var m=u.substring(g.startColumn-1,g.endColumn-1);if((m=m.toLowerCase())===e.open?r++:m===e.close&&r--,0===r)return g;l=g.startColumn-1}l=-1}}return null},t.prototype._findMatchingBracketDown=function(e,t){for(var n=e.languageIdentifier.id,i=e.forwardRegex,r=1,o=t.lineNumber,s=this.getLineCount();o<=s;o++){var a=this._getLineTokens(o),u=a.getCount(),c=this._buffer.getLineContent(o),l=0,d=0;for(o===t.lineNumber&&(l=a.findTokenIndexAtOffset(t.column-1),d=t.column-1);l=1;r--){var o=this._getLineTokens(r),s=o.getCount(),a=this._buffer.getLineContent(r),u=s-1,c=-1;for(r===t.lineNumber&&(u=o.findTokenIndexAtOffset(t.column-1),c=t.column-1);u>=0;u--){var l=o.getLanguageId(u),d=o.getStandardTokenType(u),h=o.getStartOffset(u),f=o.getEndOffset(u);if(-1===c&&(c=f),n!==l&&(n=l,i=We.a.getBracketsSupport(n)),i&&!Object(Be.b)(d)){var p=Ve.a.findPrevBracketInToken(i.reversedRegex,r,a,h,c);if(p)return this._toFoundBracket(i,p)}c=-1}}return null},t.prototype.findNextBracket=function(e){for(var t=this.validatePosition(e),n=-1,i=null,r=t.lineNumber,o=this.getLineCount();r<=o;r++){var s=this._getLineTokens(r),a=s.getCount(),u=this._buffer.getLineContent(r),c=0,l=0;for(r===t.lineNumber&&(c=s.findTokenIndexAtOffset(t.column-1),l=t.column-1);cr)throw new Error("Illegal value for lineNumber");for(var o=We.a.getFoldingRules(this._languageIdentifier.id),s=Boolean(o&&o.offSide),a=-2,u=-1,c=-2,l=-1,d=function(e){if(-1!==a&&(-2===a||a>e-1)){a=-1,u=-1;for(var t=e-2;t>=0;t--){var n=i._computeIndentLevel(t);if(n>=0){a=t,u=n;break}}}if(-2===c){c=-1,l=-1;for(t=e;t=0){c=t,l=o;break}}}},h=-2,f=-1,p=-2,g=-1,m=function(e){if(-2===h){h=-1,f=-1;for(var t=e-2;t>=0;t--){var n=i._computeIndentLevel(t);if(n>=0){h=t,f=n;break}}}if(-1!==p&&(-2===p||p=0){p=t,g=o;break}}}},v=0,_=!0,b=0,y=!0,w=0,C=0;_||y;C++){var S=e-C,x=e+C;if(0!==C&&(S<1||Sr||x>n)&&(y=!1),C>5e4&&(_=!1,y=!1),_){var L=void 0;if((O=this._computeIndentLevel(S-1))>=0?(c=S-1,l=O,L=Math.ceil(O/this._options.indentSize)):(d(S),L=this._getIndentLevelForWhitespaceLine(s,u,l)),0===C){if(v=S,b=x,0===(w=L))return{startLineNumber:v,endLineNumber:b,indent:w};continue}L>=w?v=S:_=!1}if(y){var O,k=void 0;(O=this._computeIndentLevel(x-1))>=0?(h=x-1,f=O,k=Math.ceil(O/this._options.indentSize)):(m(x),k=this._getIndentLevelForWhitespaceLine(s,f,g)),k>=w?b=x:y=!1}}return{startLineNumber:v,endLineNumber:b,indent:w}},t.prototype.getLinesIndentGuides=function(e,t){this._assertNotDisposed();var n=this.getLineCount();if(e<1||e>n)throw new Error("Illegal value for startLineNumber");if(t<1||t>n)throw new Error("Illegal value for endLineNumber");for(var i=We.a.getFoldingRules(this._languageIdentifier.id),r=Boolean(i&&i.offSide),o=new Array(t-e+1),s=-2,a=-1,u=-2,c=-1,l=e;l<=t;l++){var d=l-e,h=this._computeIndentLevel(l-1);if(h>=0)s=l-1,a=h,o[d]=Math.ceil(h/this._options.indentSize);else{if(-2===s){s=-1,a=-1;for(var f=l-2;f>=0;f--){if((p=this._computeIndentLevel(f))>=0){s=f,a=p;break}}}if(-1!==u&&(-2===u||u=0){u=f,c=p;break}}}o[d]=this._getIndentLevelForWhitespaceLine(r,a,c)}}return o},t.prototype._getIndentLevelForWhitespaceLine=function(e,t,n){return-1===t||-1===n?0:t0?this._deferredEvent?this._deferredEvent=this._deferredEvent.merge(e):this._deferredEvent=e:(this._fastEmitter.fire(e),this._slowEmitter.fire(e))},t}(o.a)},"0u1n":function(e,t){},1:function(e,t){},"16On":function(e,t,n){var i=n("LC74");function r(e){this._reporterState={obj:null,path:[],options:e||{},errors:[]}}function o(e,t){this.path=e,this.rethrow(t)}t.Reporter=r,r.prototype.isError=function(e){return e instanceof o},r.prototype.save=function(){var e=this._reporterState;return{obj:e.obj,pathLen:e.path.length}},r.prototype.restore=function(e){var t=this._reporterState;t.obj=e.obj,t.path=t.path.slice(0,e.pathLen)},r.prototype.enterKey=function(e){return this._reporterState.path.push(e)},r.prototype.exitKey=function(e){var t=this._reporterState;t.path=t.path.slice(0,e-1)},r.prototype.leaveKey=function(e,t,n){var i=this._reporterState;this.exitKey(e),null!==i.obj&&(i.obj[t]=n)},r.prototype.path=function(){return this._reporterState.path.join("/")},r.prototype.enterObject=function(){var e=this._reporterState,t=e.obj;return e.obj={},t},r.prototype.leaveObject=function(e){var t=this._reporterState,n=t.obj;return t.obj=e,n},r.prototype.error=function(e){var t,n=this._reporterState,i=e instanceof o;if(t=i?e:new o(n.path.map(function(e){return"["+JSON.stringify(e)+"]"}).join(""),e.message||e,e.stack),!n.options.partial)throw t;return i||n.errors.push(t),t},r.prototype.wrapResult=function(e){var t=this._reporterState;return t.options.partial?{result:this.isError(e)?null:e,errors:t.errors}:e},i(o,Error),o.prototype.rethrow=function(e){if(this.message=e+" at: "+(this.path||"(shallow)"),Error.captureStackTrace&&Error.captureStackTrace(this,o),!this.stack)try{throw new Error(this.message)}catch(e){this.stack=e.stack}return this}},"19bf":function(e,t,n){"use strict";var i=n("KDHK");t.certificate=n("lQBd");var r=i.define("RSAPrivateKey",function(){this.seq().obj(this.key("version").int(),this.key("modulus").int(),this.key("publicExponent").int(),this.key("privateExponent").int(),this.key("prime1").int(),this.key("prime2").int(),this.key("exponent1").int(),this.key("exponent2").int(),this.key("coefficient").int())});t.RSAPrivateKey=r;var o=i.define("RSAPublicKey",function(){this.seq().obj(this.key("modulus").int(),this.key("publicExponent").int())});t.RSAPublicKey=o;var s=i.define("SubjectPublicKeyInfo",function(){this.seq().obj(this.key("algorithm").use(a),this.key("subjectPublicKey").bitstr())});t.PublicKey=s;var a=i.define("AlgorithmIdentifier",function(){this.seq().obj(this.key("algorithm").objid(),this.key("none").null_().optional(),this.key("curve").objid().optional(),this.key("params").seq().obj(this.key("p").int(),this.key("q").int(),this.key("g").int()).optional())}),u=i.define("PrivateKeyInfo",function(){this.seq().obj(this.key("version").int(),this.key("algorithm").use(a),this.key("subjectPrivateKey").octstr())});t.PrivateKey=u;var c=i.define("EncryptedPrivateKeyInfo",function(){this.seq().obj(this.key("algorithm").seq().obj(this.key("id").objid(),this.key("decrypt").seq().obj(this.key("kde").seq().obj(this.key("id").objid(),this.key("kdeparams").seq().obj(this.key("salt").octstr(),this.key("iters").int())),this.key("cipher").seq().obj(this.key("algo").objid(),this.key("iv").octstr()))),this.key("subjectPrivateKey").octstr())});t.EncryptedPrivateKey=c;var l=i.define("DSAPrivateKey",function(){this.seq().obj(this.key("version").int(),this.key("p").int(),this.key("q").int(),this.key("g").int(),this.key("pub_key").int(),this.key("priv_key").int())});t.DSAPrivateKey=l,t.DSAparam=i.define("DSAparam",function(){this.int()});var d=i.define("ECPrivateKey",function(){this.seq().obj(this.key("version").int(),this.key("privateKey").octstr(),this.key("parameters").optional().explicit(0).use(h),this.key("publicKey").optional().explicit(1).bitstr())});t.ECPrivateKey=d;var h=i.define("ECParameters",function(){this.choice({namedCurve:this.objid()})});t.signature=i.define("signature",function(){this.seq().obj(this.key("r").int(),this.key("s").int())})},"1LBi":function(e,t){},"1O6n":function(e,t){},"1Z8u":function(e,t){},"1lLf":function(e,t,n){"use strict";var i=n("08Lv"),r=n("LC74");function o(e,t){return 55296==(64512&e.charCodeAt(t))&&(!(t<0||t+1>=e.length)&&56320==(64512&e.charCodeAt(t+1)))}function s(e){return(e>>>24|e>>>8&65280|e<<8&16711680|(255&e)<<24)>>>0}function a(e){return 1===e.length?"0"+e:e}function u(e){return 7===e.length?"0"+e:6===e.length?"00"+e:5===e.length?"000"+e:4===e.length?"0000"+e:3===e.length?"00000"+e:2===e.length?"000000"+e:1===e.length?"0000000"+e:e}t.inherits=r,t.toArray=function(e,t){if(Array.isArray(e))return e.slice();if(!e)return[];var n=[];if("string"==typeof e)if(t){if("hex"===t)for((e=e.replace(/[^a-z0-9]+/gi,"")).length%2!=0&&(e="0"+e),r=0;r>6|192,n[i++]=63&s|128):o(e,r)?(s=65536+((1023&s)<<10)+(1023&e.charCodeAt(++r)),n[i++]=s>>18|240,n[i++]=s>>12&63|128,n[i++]=s>>6&63|128,n[i++]=63&s|128):(n[i++]=s>>12|224,n[i++]=s>>6&63|128,n[i++]=63&s|128)}else for(r=0;r>>0}return s},t.split32=function(e,t){for(var n=new Array(4*e.length),i=0,r=0;i>>24,n[r+1]=o>>>16&255,n[r+2]=o>>>8&255,n[r+3]=255&o):(n[r+3]=o>>>24,n[r+2]=o>>>16&255,n[r+1]=o>>>8&255,n[r]=255&o)}return n},t.rotr32=function(e,t){return e>>>t|e<<32-t},t.rotl32=function(e,t){return e<>>32-t},t.sum32=function(e,t){return e+t>>>0},t.sum32_3=function(e,t,n){return e+t+n>>>0},t.sum32_4=function(e,t,n,i){return e+t+n+i>>>0},t.sum32_5=function(e,t,n,i,r){return e+t+n+i+r>>>0},t.sum64=function(e,t,n,i){var r=e[t],o=i+e[t+1]>>>0,s=(o>>0,e[t+1]=o},t.sum64_hi=function(e,t,n,i){return(t+i>>>0>>0},t.sum64_lo=function(e,t,n,i){return t+i>>>0},t.sum64_4_hi=function(e,t,n,i,r,o,s,a){var u=0,c=t;return u+=(c=c+i>>>0)>>0)>>0)>>0},t.sum64_4_lo=function(e,t,n,i,r,o,s,a){return t+i+o+a>>>0},t.sum64_5_hi=function(e,t,n,i,r,o,s,a,u,c){var l=0,d=t;return l+=(d=d+i>>>0)>>0)>>0)>>0)>>0},t.sum64_5_lo=function(e,t,n,i,r,o,s,a,u,c){return t+i+o+a+c>>>0},t.rotr64_hi=function(e,t,n){return(t<<32-n|e>>>n)>>>0},t.rotr64_lo=function(e,t,n){return(e<<32-n|t>>>n)>>>0},t.shr64_hi=function(e,t,n){return e>>>n},t.shr64_lo=function(e,t,n){return(e<<32-n|t>>>n)>>>0}},"1mBN":function(e,t){},"1sup":function(e,t,n){"use strict";t.b=function(e,t,n){"string"==typeof e&&(e=i.a.file(e));if(n){var h=n.getWorkspaceFolder(e);if(h){var f=n.getWorkspace().folders.length>1,p=void 0;if(p=Object(u.e)(h.uri,e)?"":Object(u.h)(h.uri,e),f){var g=h&&h.name?h.name:Object(u.b)(h.uri);p=p?g+" • "+p:g}return p}}if(e.scheme!==s.b.file&&e.scheme!==s.b.untitled)return e.with({query:null,fragment:null}).toString(!0);if(c(e.fsPath))return Object(r.normalize)(l(e.fsPath));var m=Object(r.normalize)(e.fsPath);!a.g&&t&&(m=function(e,t){if(a.g||!e||!t)return e;var n=d.original===t?d.normalized:void 0;n||(n=""+Object(o.G)(t,r.posix.sep)+r.posix.sep,d={original:t,normalized:n});(a.c?Object(o.J)(e,n):Object(o.K)(e,n))&&(e="~/"+e.substr(n.length));return e}(m,t.userHome));return m},t.a=function(e){if(!e)return;"string"==typeof e&&(e=i.a.file(e));var t=Object(u.b)(e)||(e.scheme===s.b.file?e.fsPath:e.path);if(c(t))return l(t);return t};var i=n("mrx5"),r=n("/uRs"),o=n("aL7J"),s=n("lapT"),a=n("ZfGv"),u=n("ZYUE");function c(e){return!(!a.g||!e||":"!==e[1])}function l(e){return c(e)?e.charAt(0).toUpperCase()+e.slice(1):e}var d=Object.create(null)},"1xIj":function(e,t,n){"use strict";n.d(t,"a",function(){return r}),n.d(t,"b",function(){return o});var i=n("JVO/"),r=Object(i.c)("logService"),o=function(){function e(){}return e.prototype.trace=function(e){for(var t=[],n=1;n":""},l.prototype.isInfinity=function(){return 0===this.x.cmpn(0)&&(0===this.y.cmp(this.z)||this.zOne&&0===this.y.cmp(this.curve.c))},l.prototype._extDbl=function(){var e=this.x.redSqr(),t=this.y.redSqr(),n=this.z.redSqr();n=n.redIAdd(n);var i=this.curve._mulA(e),r=this.x.redAdd(this.y).redSqr().redISub(e).redISub(t),o=i.redAdd(t),s=o.redSub(n),a=i.redSub(t),u=r.redMul(s),c=o.redMul(a),l=r.redMul(a),d=s.redMul(o);return this.curve.point(u,c,d,l)},l.prototype._projDbl=function(){var e,t,n,i=this.x.redAdd(this.y).redSqr(),r=this.x.redSqr(),o=this.y.redSqr();if(this.curve.twisted){var s=(c=this.curve._mulA(r)).redAdd(o);if(this.zOne)e=i.redSub(r).redSub(o).redMul(s.redSub(this.curve.two)),t=s.redMul(c.redSub(o)),n=s.redSqr().redSub(s).redSub(s);else{var a=this.z.redSqr(),u=s.redSub(a).redISub(a);e=i.redSub(r).redISub(o).redMul(u),t=s.redMul(c.redSub(o)),n=s.redMul(u)}}else{var c=r.redAdd(o);a=this.curve._mulC(this.z).redSqr(),u=c.redSub(a).redSub(a);e=this.curve._mulC(i.redISub(c)).redMul(u),t=this.curve._mulC(c).redMul(r.redISub(o)),n=c.redMul(u)}return this.curve.point(e,t,n)},l.prototype.dbl=function(){return this.isInfinity()?this:this.curve.extended?this._extDbl():this._projDbl()},l.prototype._extAdd=function(e){var t=this.y.redSub(this.x).redMul(e.y.redSub(e.x)),n=this.y.redAdd(this.x).redMul(e.y.redAdd(e.x)),i=this.t.redMul(this.curve.dd).redMul(e.t),r=this.z.redMul(e.z.redAdd(e.z)),o=n.redSub(t),s=r.redSub(i),a=r.redAdd(i),u=n.redAdd(t),c=o.redMul(s),l=a.redMul(u),d=o.redMul(u),h=s.redMul(a);return this.curve.point(c,l,h,d)},l.prototype._projAdd=function(e){var t,n,i=this.z.redMul(e.z),r=i.redSqr(),o=this.x.redMul(e.x),s=this.y.redMul(e.y),a=this.curve.d.redMul(o).redMul(s),u=r.redSub(a),c=r.redAdd(a),l=this.x.redAdd(this.y).redMul(e.x.redAdd(e.y)).redISub(o).redISub(s),d=i.redMul(u).redMul(l);return this.curve.twisted?(t=i.redMul(c).redMul(s.redSub(this.curve._mulA(o))),n=u.redMul(c)):(t=i.redMul(c).redMul(s.redSub(o)),n=this.curve._mulC(u).redMul(c)),this.curve.point(d,t,n)},l.prototype.add=function(e){return this.isInfinity()?e:e.isInfinity()?this:this.curve.extended?this._extAdd(e):this._projAdd(e)},l.prototype.mul=function(e){return this._hasDoubles(e)?this.curve._fixedNafMul(this,e):this.curve._wnafMul(this,e)},l.prototype.mulAdd=function(e,t,n){return this.curve._wnafMulAdd(1,[this,t],[e,n],2,!1)},l.prototype.jmulAdd=function(e,t,n){return this.curve._wnafMulAdd(1,[this,t],[e,n],2,!0)},l.prototype.normalize=function(){if(this.zOne)return this;var e=this.z.redInvm();return this.x=this.x.redMul(e),this.y=this.y.redMul(e),this.t&&(this.t=this.t.redMul(e)),this.z=this.curve.one,this.zOne=!0,this},l.prototype.neg=function(){return this.curve.point(this.x.redNeg(),this.y,this.z,this.t&&this.t.redNeg())},l.prototype.getX=function(){return this.normalize(),this.x.fromRed()},l.prototype.getY=function(){return this.normalize(),this.y.fromRed()},l.prototype.eq=function(e){return this===e||0===this.getX().cmp(e.getX())&&0===this.getY().cmp(e.getY())},l.prototype.eqXToP=function(e){var t=e.toRed(this.curve.red).redMul(this.z);if(0===this.x.cmp(t))return!0;for(var n=e.clone(),i=this.curve.redN.redMul(this.z);;){if(n.iadd(this.curve.n),n.cmp(this.curve.p)>=0)return!1;if(t.redIAdd(i),0===this.x.cmp(t))return!0}},l.prototype.toP=l.prototype.normalize,l.prototype.mixedAdd=l.prototype.add},"2Ayt":function(e,t,n){"use strict";n.d(t,"a",function(){return u});var i=n("aL7J"),r=n("Ao9X"),o=n("6boo"),s=n("ZSmM"),a=n("vTy2"),u=function(){function e(){}return e.deleteRight=function(e,t,n,i){for(var o=[],u=3!==e,c=0,l=i.length;c1){var m=n.getLineContent(g.lineNumber),v=i.q(m),_=-1===v?m.length+1:v+1;if(g.column<=_){var b=o.a.visibleColumnFromColumn2(t,n,g),y=o.a.prevIndentTabStop(b,t.indentSize),w=o.a.columnFromVisibleColumn2(t,n,g.lineNumber,y);p=new a.a(g.lineNumber,w,g.lineNumber,g.column)}else p=new a.a(g.lineNumber,g.column-1,g.lineNumber,g.column)}else{var C=s.a.left(t,n,g.lineNumber,g.column);p=new a.a(C.lineNumber,C.column,g.lineNumber,g.column)}}p.isEmpty()?c[d]=null:(p.startLineNumber!==p.endLineNumber&&(l=!0),c[d]=new r.a(p,""))}return[l,c]},e.cut=function(e,t,n){for(var i=[],s=0,u=n.length;s1?(d=l.lineNumber-1,h=t.getLineMaxColumn(l.lineNumber-1),f=l.lineNumber,p=t.getLineMaxColumn(l.lineNumber)):(d=l.lineNumber,h=1,f=l.lineNumber,p=t.getLineMaxColumn(l.lineNumber));var g=new a.a(d,h,f,p);g.isEmpty()?i[s]=null:i[s]=new r.a(g,"")}else i[s]=null;else i[s]=new r.a(c,"")}return new o.e(0,i,{shouldPushStackElementBefore:!0,shouldPushStackElementAfter:!0})},e}()},"2JY6":function(e,t,n){(function(t){var n=Math.pow(2,30)-1;function i(e,n){if("string"!=typeof e&&!t.isBuffer(e))throw new TypeError(n+" must be a buffer or string")}e.exports=function(e,t,r,o){if(i(e,"Password"),i(t,"Salt"),"number"!=typeof r)throw new TypeError("Iterations not a number");if(r<0)throw new TypeError("Bad iterations");if("number"!=typeof o)throw new TypeError("Key length not a number");if(o<0||o>n||o!=o)throw new TypeError("Bad key length")}}).call(t,n("EuP9").Buffer)},"2LSJ":function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),n.d(t,"InsertCursorAbove",function(){return y}),n.d(t,"InsertCursorBelow",function(){return w}),n.d(t,"MultiCursorSessionResult",function(){return L}),n.d(t,"MultiCursorSession",function(){return O}),n.d(t,"MultiCursorSelectionController",function(){return k}),n.d(t,"MultiCursorSelectionControllerAction",function(){return N}),n.d(t,"AddSelectionToNextFindMatchAction",function(){return E}),n.d(t,"AddSelectionToPreviousFindMatchAction",function(){return I}),n.d(t,"MoveSelectionToNextFindMatchAction",function(){return D}),n.d(t,"MoveSelectionToPreviousFindMatchAction",function(){return M}),n.d(t,"SelectHighlightsAction",function(){return T}),n.d(t,"CompatChangeAll",function(){return P}),n.d(t,"SelectionHighlighter",function(){return R});var i,r=n("hK2W"),o=n("odeJ"),s=n("uNfg"),a=n("tqet"),u=n("03Zz"),c=n("HAT9"),l=n("vTy2"),d=n("iHM7"),h=n("/9db"),f=n("D2uo"),p=n("0ly5"),g=n("PCC9"),m=n("T1Qz"),v=n("L5KM"),_=n("eoic"),b=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),y=function(e){function t(){return e.call(this,{id:"editor.action.insertCursorAbove",label:r.a("mutlicursor.insertAbove","Add Cursor Above"),alias:"Add Cursor Above",precondition:void 0,kbOpts:{kbExpr:h.a.editorTextFocus,primary:2576,linux:{primary:1552,secondary:[3088]},weight:100},menubarOpts:{menuId:22,group:"3_multi",title:r.a({key:"miInsertCursorAbove",comment:["&& denotes a mnemonic"]},"&&Add Cursor Above"),order:2}})||this}return b(t,e),t.prototype.run=function(e,t,n){if(t.hasModel()){var i=n&&!0===n.logicalLine,r=t._getCursors(),o=r.context;o.config.readOnly||(o.model.pushStackElement(),r.setStates(n.source,3,c.b.addCursorUp(o,r.getAll(),i)),r.reveal(!0,1,0))}},t}(u.b),w=function(e){function t(){return e.call(this,{id:"editor.action.insertCursorBelow",label:r.a("mutlicursor.insertBelow","Add Cursor Below"),alias:"Add Cursor Below",precondition:void 0,kbOpts:{kbExpr:h.a.editorTextFocus,primary:2578,linux:{primary:1554,secondary:[3090]},weight:100},menubarOpts:{menuId:22,group:"3_multi",title:r.a({key:"miInsertCursorBelow",comment:["&& denotes a mnemonic"]},"A&&dd Cursor Below"),order:3}})||this}return b(t,e),t.prototype.run=function(e,t,n){if(t.hasModel()){var i=n&&!0===n.logicalLine,r=t._getCursors(),o=r.context;o.config.readOnly||(o.model.pushStackElement(),r.setStates(n.source,3,c.b.addCursorDown(o,r.getAll(),i)),r.reveal(!0,2,0))}},t}(u.b),C=function(e){function t(){return e.call(this,{id:"editor.action.insertCursorAtEndOfEachLineSelected",label:r.a("mutlicursor.insertAtEndOfEachLineSelected","Add Cursors to Line Ends"),alias:"Add Cursors to Line Ends",precondition:void 0,kbOpts:{kbExpr:h.a.editorTextFocus,primary:1575,weight:100},menubarOpts:{menuId:22,group:"3_multi",title:r.a({key:"miInsertCursorAtEndOfEachLineSelected",comment:["&& denotes a mnemonic"]},"Add C&&ursors to Line Ends"),order:4}})||this}return b(t,e),t.prototype.getCursorsForSelection=function(e,t,n){if(!e.isEmpty()){for(var i=e.startLineNumber;i1&&n.push(new d.a(e.endLineNumber,e.endColumn,e.endLineNumber,e.endColumn))}},t.prototype.run=function(e,t){var n=this;if(t.hasModel()){var i=t.getModel(),r=[];t.getSelections().forEach(function(e){return n.getCursorsForSelection(e,i,r)}),r.length>0&&t.setSelections(r)}},t}(u.b),S=function(e){function t(){return e.call(this,{id:"editor.action.addCursorsToBottom",label:r.a("mutlicursor.addCursorsToBottom","Add Cursors To Bottom"),alias:"Add Cursors To Bottom",precondition:void 0})||this}return b(t,e),t.prototype.run=function(e,t){if(t.hasModel()){for(var n=t.getSelections(),i=t.getModel().getLineCount(),r=[],o=n[0].startLineNumber;o<=i;o++)r.push(new d.a(o,n[0].startColumn,o,n[0].endColumn));r.length>0&&t.setSelections(r)}},t}(u.b),x=function(e){function t(){return e.call(this,{id:"editor.action.addCursorsToTop",label:r.a("mutlicursor.addCursorsToTop","Add Cursors To Top"),alias:"Add Cursors To Top",precondition:void 0})||this}return b(t,e),t.prototype.run=function(e,t){if(t.hasModel()){for(var n=t.getSelections(),i=[],r=n[0].startLineNumber;r>=1;r--)i.push(new d.a(r,n[0].startColumn,r,n[0].endColumn));i.length>0&&t.setSelections(i)}},t}(u.b),L=function(){return function(e,t,n){this.selections=e,this.revealRange=t,this.revealScrollType=n}}(),O=function(){function e(e,t,n,i,r,o,s){this._editor=e,this.findController=t,this.isDisconnectedFromFindController=n,this.searchText=i,this.wholeWord=r,this.matchCase=o,this.currentMatch=s}return e.create=function(t,n){if(!t.hasModel())return null;var i=n.getState();if(!t.hasTextFocus()&&i.isRevealed&&i.searchString.length>0)return new e(t,n,!1,i.searchString,i.wholeWord,i.matchCase,null);var r,o,s=!1,a=t.getSelections();1===a.length&&a[0].isEmpty()?(s=!0,r=!0,o=!0):(r=i.wholeWord,o=i.matchCase);var u,c=t.getSelection(),l=null;if(c.isEmpty()){var h=t.getModel().getWordAtPosition(c.getStartPosition());if(!h)return null;u=h.word,l=new d.a(c.startLineNumber,h.startColumn,c.startLineNumber,h.endColumn)}else u=t.getModel().getValueInRange(c).replace(/\r\n/g,"\n");return new e(t,n,s,u,r,o,l)},e.prototype.addSelectionToNextFindMatch=function(){if(!this._editor.hasModel())return null;var e=this._getNextMatch();if(!e)return null;var t=this._editor.getSelections();return new L(t.concat(e),e,0)},e.prototype.moveSelectionToNextFindMatch=function(){if(!this._editor.hasModel())return null;var e=this._getNextMatch();if(!e)return null;var t=this._editor.getSelections();return new L(t.slice(0,t.length-1).concat(e),e,0)},e.prototype._getNextMatch=function(){if(!this._editor.hasModel())return null;if(this.currentMatch){var e=this.currentMatch;return this.currentMatch=null,e}this.findController.highlightFindOptions();var t=this._editor.getSelections(),n=t[t.length-1],i=this._editor.getModel().findNextMatch(this.searchText,n.getEndPosition(),!1,this.matchCase,this.wholeWord?this._editor.getConfiguration().wordSeparators:null,!1);return i?new d.a(i.range.startLineNumber,i.range.startColumn,i.range.endLineNumber,i.range.endColumn):null},e.prototype.addSelectionToPreviousFindMatch=function(){if(!this._editor.hasModel())return null;var e=this._getPreviousMatch();if(!e)return null;var t=this._editor.getSelections();return new L(t.concat(e),e,0)},e.prototype.moveSelectionToPreviousFindMatch=function(){if(!this._editor.hasModel())return null;var e=this._getPreviousMatch();if(!e)return null;var t=this._editor.getSelections();return new L(t.slice(0,t.length-1).concat(e),e,0)},e.prototype._getPreviousMatch=function(){if(!this._editor.hasModel())return null;if(this.currentMatch){var e=this.currentMatch;return this.currentMatch=null,e}this.findController.highlightFindOptions();var t=this._editor.getSelections(),n=t[t.length-1],i=this._editor.getModel().findPreviousMatch(this.searchText,n.getStartPosition(),!1,this.matchCase,this.wholeWord?this._editor.getConfiguration().wordSeparators:null,!1);return i?new d.a(i.range.startLineNumber,i.range.startColumn,i.range.endLineNumber,i.range.endColumn):null},e.prototype.selectAll=function(){return this._editor.hasModel()?(this.findController.highlightFindOptions(),this._editor.getModel().findMatches(this.searchText,!0,!1,this.matchCase,this.wholeWord?this._editor.getConfiguration().wordSeparators:null,!1,1073741824)):[]},e}(),k=function(e){function t(t){var n=e.call(this)||this;return n._sessionDispose=n._register(new a.b),n._editor=t,n._ignoreSelectionChange=!1,n._session=null,n}return b(t,e),t.get=function(e){return e.getContribution(t.ID)},t.prototype.dispose=function(){this._endSession(),e.prototype.dispose.call(this)},t.prototype.getId=function(){return t.ID},t.prototype._beginSessionIfNeeded=function(e){var t=this;if(!this._session){var n=O.create(this._editor,e);if(!n)return;this._session=n;var i={searchString:this._session.searchText};this._session.isDisconnectedFromFindController&&(i.wholeWordOverride=1,i.matchCaseOverride=1,i.isRegexOverride=2),e.getState().change(i,!1),this._sessionDispose.add(this._editor.onDidChangeCursorSelection(function(e){t._ignoreSelectionChange||t._endSession()})),this._sessionDispose.add(this._editor.onDidBlurEditorText(function(){t._endSession()})),this._sessionDispose.add(e.getState().onFindReplaceStateChange(function(e){(e.matchCase||e.wholeWord)&&t._endSession()}))}},t.prototype._endSession=function(){if(this._sessionDispose.clear(),this._session&&this._session.isDisconnectedFromFindController){this._session.findController.getState().change({wholeWordOverride:0,matchCaseOverride:0,isRegexOverride:0},!1)}this._session=null},t.prototype._setSelections=function(e){this._ignoreSelectionChange=!0,this._editor.setSelections(e),this._ignoreSelectionChange=!1},t.prototype._expandEmptyToWord=function(e,t){if(!t.isEmpty())return t;var n=e.getWordAtPosition(t.getStartPosition());return n?new d.a(t.startLineNumber,n.startColumn,t.startLineNumber,n.endColumn):t},t.prototype._applySessionResult=function(e){e&&(this._setSelections(e.selections),e.revealRange&&this._editor.revealRangeInCenterIfOutsideViewport(e.revealRange,e.revealScrollType))},t.prototype.getSession=function(e){return this._session},t.prototype.addSelectionToNextFindMatch=function(e){if(this._editor.hasModel()){if(!this._session){var t=this._editor.getSelections();if(t.length>1){var n=e.getState().matchCase;if(!F(this._editor.getModel(),t,n)){for(var i=this._editor.getModel(),r=[],o=0,s=t.length;o0&&n.isRegex)t=this._editor.getModel().findMatches(n.searchString,!0,n.isRegex,n.matchCase,n.wholeWord?this._editor.getConfiguration().wordSeparators:null,!1,1073741824);else{if(this._beginSessionIfNeeded(e),!this._session)return;t=this._session.selectAll()}if(t.length>0){for(var i=this._editor.getSelection(),r=0,o=t.length;r1){var a=r.getState().matchCase;if(!F(t.getModel(),s,a))return null}o=O.create(t,r)}if(!o)return null;if(o.currentMatch)return null;if(/^[ \t]+$/.test(o.searchText))return null;if(o.searchText.length>200)return null;var u=r.getState(),c=u.matchCase;if(u.isRevealed){var l=u.searchString;c||(l=l.toLowerCase());var d=o.searchText;if(c||(d=d.toLowerCase()),l===d&&o.matchCase===u.matchCase&&o.wholeWord===u.wholeWord&&!u.isRegex)return null}return new A(o.searchText,o.matchCase,o.wholeWord?t.getConfiguration().wordSeparators:null)},t.prototype._setState=function(e){if(A.softEquals(this.state,e))this.state=e;else if(this.state=e,this.state){if(this.editor.hasModel()){var n=this.editor.getModel();if(!n.isTooLargeForTokenization()){var i=g.i.has(n),r=n.findMatches(this.state.searchText,!0,!1,this.state.matchCase,this.state.wordSeparators,!1).map(function(e){return e.range});r.sort(l.a.compareRangesUsingStarts);var o=this.editor.getSelections();o.sort(l.a.compareRangesUsingStarts);for(var s=[],a=0,u=0,c=r.length,d=o.length;a=d)s.push(h),a++;else{var f=l.a.compareRangesUsingStarts(h,o[u]);f<0?(!o[u].isEmpty()&&l.a.areIntersecting(h,o[u])||s.push(h),a++):f>0?u++:(a++,u++)}}var p=s.map(function(e){return{range:e,options:i?t._SELECTION_HIGHLIGHT:t._SELECTION_HIGHLIGHT_OVERVIEW}});this.decorations=this.editor.deltaDecorations(this.decorations,p)}}}else this.decorations=this.editor.deltaDecorations(this.decorations,[])},t.prototype.dispose=function(){this._setState(null),e.prototype.dispose.call(this)},t.ID="editor.contrib.selectionHighlighter",t._SELECTION_HIGHLIGHT_OVERVIEW=p.a.register({stickiness:1,className:"selectionHighlight",overviewRuler:{color:Object(_.g)(v._32),position:f.d.Center}}),t._SELECTION_HIGHLIGHT=p.a.register({stickiness:1,className:"selectionHighlight"}),t}(a.a);function F(e,t,n){for(var i=j(e,t[0],!n),r=1,o=t.length;r=0;a--)(r=e[a])&&(s=(o<3?r(s):o>3?r(t,n,s):r(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},w=this&&this.__param||function(e,t){return function(n,i){t(n,i,e)}},C=Object(v._36)("editor.wordHighlightBackground",{dark:"#575757B8",light:"#57575740",hc:null},r.a("wordHighlight","Background color of a symbol during read-access, like reading a variable. The color must not be opaque so as not to hide underlying decorations."),!0),S=Object(v._36)("editor.wordHighlightStrongBackground",{dark:"#004972B8",light:"#0e639c40",hc:null},r.a("wordHighlightStrong","Background color of a symbol during write-access, like writing to a variable. The color must not be opaque so as not to hide underlying decorations."),!0),x=Object(v._36)("editor.wordHighlightBorder",{light:null,dark:null,hc:v.b},r.a("wordHighlightBorder","Border color of a symbol during read-access, like reading a variable.")),L=Object(v._36)("editor.wordHighlightStrongBorder",{light:null,dark:null,hc:v.b},r.a("wordHighlightStrongBorder","Border color of a symbol during write-access, like writing to a variable.")),O=Object(v._36)("editorOverviewRuler.wordHighlightForeground",{dark:"#A0A0A0CC",light:"#A0A0A0CC",hc:"#A0A0A0CC"},r.a("overviewRulerWordHighlightForeground","Overview ruler marker color for symbol highlights. The color must not be opaque so as not to hide underlying decorations."),!0),k=Object(v._36)("editorOverviewRuler.wordHighlightStrongForeground",{dark:"#C0A0C0CC",light:"#C0A0C0CC",hc:"#C0A0C0CC"},r.a("overviewRulerWordHighlightStrongForeground","Overview ruler marker color for write-access symbol highlights. The color must not be opaque so as not to hide underlying decorations."),!0),N=new m.d("hasWordHighlights",!1);function E(e,t,n){var i=g.i.ordered(e);return Object(s.h)(i.map(function(i){return function(){return Promise.resolve(i.provideDocumentHighlights(e,t,n)).then(void 0,u.f)}}),o.n)}var I=function(){function e(e,t,n){var i=this;this._wordRange=this._getCurrentWordRange(e,t),this.result=Object(s.f)(function(r){return i._compute(e,t,n,r)})}return e.prototype._getCurrentWordRange=function(e,t){var n=e.getWordAtPosition(t.getPosition());return n?new d.a(t.startLineNumber,n.startColumn,t.startLineNumber,n.endColumn):null},e.prototype.isValid=function(e,t,n){for(var i=t.startLineNumber,r=t.startColumn,o=t.endColumn,s=this._getCurrentWordRange(e,t),a=Boolean(this._wordRange&&this._wordRange.equalsRange(s)),u=0,c=n.length;!a&&u=o&&(a=!0)}return a},e.prototype.cancel=function(){this.result.cancel()},e}(),D=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return b(t,e),t.prototype._compute=function(e,t,n,i){return E(e,t.getPosition(),i).then(function(e){return e||[]})},t}(I),M=function(e){function t(t,n,i){var r=e.call(this,t,n,i)||this;return r._selectionIsEmpty=n.isEmpty(),r}return b(t,e),t.prototype._compute=function(e,t,n,i){return Object(s.l)(250,i).then(function(){if(!t.isEmpty())return[];var i=e.getWordAtPosition(t.getPosition());return i?e.findMatches(i.word,!0,!1,!0,n,!1).map(function(e){return{range:e.range,kind:g.h.Text}}):[]})},t.prototype.isValid=function(t,n,i){var r=n.isEmpty();return this._selectionIsEmpty===r&&e.prototype.isValid.call(this,t,n,i)},t}(I);Object(l.e)("_executeDocumentHighlights",function(e,t){return E(e,t,a.a.None)});var T=function(){function e(e,t){var n=this;this.toUnhook=new c.b,this.workerRequestTokenId=0,this.workerRequestCompleted=!1,this.workerRequestValue=[],this.lastCursorPositionChangeTime=0,this.renderDecorationsTimer=-1,this.editor=e,this._hasWordHighlights=N.bindTo(t),this._ignorePositionChangeEvent=!1,this.occurrencesHighlight=this.editor.getConfiguration().contribInfo.occurrencesHighlight,this.model=this.editor.getModel(),this.toUnhook.add(e.onDidChangeCursorPosition(function(e){n._ignorePositionChangeEvent||n.occurrencesHighlight&&n._onPositionChanged(e)})),this.toUnhook.add(e.onDidChangeModelContent(function(e){n._stopAll()})),this.toUnhook.add(e.onDidChangeConfiguration(function(e){var t=n.editor.getConfiguration().contribInfo.occurrencesHighlight;n.occurrencesHighlight!==t&&(n.occurrencesHighlight=t,n._stopAll())})),this._decorationIds=[],this.workerRequestTokenId=0,this.workerRequest=null,this.workerRequestCompleted=!1,this.lastCursorPositionChangeTime=0,this.renderDecorationsTimer=-1}return e.prototype.hasDecorations=function(){return this._decorationIds.length>0},e.prototype.restore=function(){this.occurrencesHighlight&&this._run()},e.prototype._getSortedHighlights=function(){var e=this;return o.d(this._decorationIds.map(function(t){return e.model.getDecorationRange(t)}).sort(d.a.compareRangesUsingStarts))},e.prototype.moveNext=function(){var e=this,t=this._getSortedHighlights(),n=t[(o.j(t,function(t){return t.containsPosition(e.editor.getPosition())})+1)%t.length];try{this._ignorePositionChangeEvent=!0,this.editor.setPosition(n.getStartPosition()),this.editor.revealRangeInCenterIfOutsideViewport(n)}finally{this._ignorePositionChangeEvent=!1}},e.prototype.moveBack=function(){var e=this,t=this._getSortedHighlights(),n=t[(o.j(t,function(t){return t.containsPosition(e.editor.getPosition())})-1+t.length)%t.length];try{this._ignorePositionChangeEvent=!0,this.editor.setPosition(n.getStartPosition()),this.editor.revealRangeInCenterIfOutsideViewport(n)}finally{this._ignorePositionChangeEvent=!1}},e.prototype._removeDecorations=function(){this._decorationIds.length>0&&(this._decorationIds=this.editor.deltaDecorations(this._decorationIds,[]),this._hasWordHighlights.set(!1))},e.prototype._stopAll=function(){this._removeDecorations(),-1!==this.renderDecorationsTimer&&(clearTimeout(this.renderDecorationsTimer),this.renderDecorationsTimer=-1),null!==this.workerRequest&&(this.workerRequest.cancel(),this.workerRequest=null),this.workerRequestCompleted||(this.workerRequestTokenId++,this.workerRequestCompleted=!0)},e.prototype._onPositionChanged=function(e){this.occurrencesHighlight&&3===e.reason?this._run():this._stopAll()},e.prototype._run=function(){var e=this,t=this.editor.getSelection();if(t.startLineNumber===t.endLineNumber){var n=t.startLineNumber,i=t.startColumn,r=t.endColumn,o=this.model.getWordAtPosition({lineNumber:n,column:i});if(!o||o.startColumn>i||o.endColumn=n?(this.renderDecorationsTimer=-1,this.renderDecorations()):this.renderDecorationsTimer=setTimeout(function(){e.renderDecorations()},n-t)},e.prototype.renderDecorations=function(){this.renderDecorationsTimer=-1;for(var t=[],n=0,i=this.workerRequestValue.length;n=6?"utf-8":"binary";e.exports=n}).call(t,n("W2nU"))},"3Clc":function(e,t){},"3PYz":function(e,t,n){var i=t;i.utils=n("1lLf"),i.common=n("YSDb"),i.sha=n("NCTB"),i.ripemd=n("CKAI"),i.hmac=n("3kRU"),i.sha1=i.sha.sha1,i.sha256=i.sha.sha256,i.sha224=i.sha.sha224,i.sha384=i.sha.sha384,i.sha512=i.sha.sha512,i.ripemd160=i.ripemd.ripemd160},"3UJ8":function(e,t,n){"use strict";n.d(t,"a",function(){return i});var i=function(){function e(){for(var e=[],t=0;te;)n.ishrn(1);if(n.isEven()&&n.iadd(a),n.testn(1)||n.iadd(u),t.cmp(u)){if(!t.cmp(c))for(;n.mod(l).cmp(d);)n.iadd(f)}else for(;n.mod(o).cmp(h);)n.iadd(f);if(m(p=n.shrn(1))&&m(n)&&v(p)&&v(n)&&s.test(p)&&s.test(n))return n}}},"3j2o":function(e,t){},"3kRU":function(e,t,n){"use strict";var i=n("1lLf"),r=n("08Lv");function o(e,t,n){if(!(this instanceof o))return new o(e,t,n);this.Hash=e,this.blockSize=e.blockSize/8,this.outSize=e.outSize/8,this.inner=null,this.outer=null,this._init(i.toArray(t,n))}e.exports=o,o.prototype._init=function(e){e.length>this.blockSize&&(e=(new this.Hash).update(e).digest()),r(e.length<=this.blockSize);for(var t=e.length;t>>3},t.g1_256=function(e){return i(e,17)^i(e,19)^e>>>10}},"3uSZ":function(e,t,n){"use strict";n.d(t,"a",function(){return r}),t.b=function e(t){return o(t)?!t.value:!Array.isArray(t)||t.every(e)},t.c=function(e,t){return!e&&!t||!(!e||!t)&&(Array.isArray(e)&&Array.isArray(t)?Object(i.g)(e,t,s):!(!o(e)||!o(t))&&s(e,t))},t.e=function(e){if(!e)return e;return e.replace(/\\([\\`*_{}[\]()#+\-.!])/g,"$1")},t.d=function(e){var t=[],n=e.split("|").map(function(e){return e.trim()});e=n[0];var i=n[1];if(i){var r=/height=(\d+)/.exec(i),o=/width=(\d+)/.exec(i),s=r?r[1]:"",a=o?o[1]:"",u=isFinite(parseInt(a)),c=isFinite(parseInt(s));u&&t.push('width="'+a+'"'),c&&t.push('height="'+s+'"')}return{href:e,dimensions:t}};var i=n("X6iQ"),r=function(){function e(e){void 0===e&&(e=""),this.value=e}return e.prototype.appendText=function(e){return this.value+=e.replace(/[\\`*_{}[\]()#+\-.!]/g,"\\$&"),this},e.prototype.appendMarkdown=function(e){return this.value+=e,this},e.prototype.appendCodeblock=function(e,t){return this.value+="\n```",this.value+=e,this.value+="\n",this.value+=t,this.value+="\n```\n",this},e}();function o(e){return e instanceof r||!(!e||"object"!=typeof e)&&("string"==typeof e.value&&("boolean"==typeof e.isTrusted||void 0===e.isTrusted))}function s(e,t){return e===t||!(!e||!t)&&(e.value===t.value&&e.isTrusted===t.isTrusted)}},4:function(e,t){},"4/4u":function(e,t,n){e.exports=n("cSWu").Transform},"44YW":function(e,t,n){"use strict";n.d(t,"a",function(){return r});var i=n("JVO/"),r=Object(i.c)("clipboardService")},"4JIo":function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i,r=n("3j2o"),o=(n.n(r),n("hK2W")),s=n("lAcG"),a=n("ZfGv"),u=n("4QaN"),c=n("03Zz"),l=n("vORD"),d=n("/9db"),h=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),f="9_cutcopypaste",p=a.e||document.queryCommandSupported("cut"),g=a.e||document.queryCommandSupported("copy"),m=g&&!s.g,v=a.e||!s.e&&document.queryCommandSupported("paste"),_=function(e){function t(t,n){var i=e.call(this,n)||this;return i.browserCommand=t,i}return h(t,e),t.prototype.runCommand=function(e,t){var n=e.get(l.a).getFocusedCodeEditor();n&&n.hasTextFocus()?n.trigger("keyboard",this.id,t):document.execCommand(this.browserCommand)},t.prototype.run=function(e,t){t.focus(),document.execCommand(this.browserCommand)},t}(c.b),b=function(e){function t(){var t={kbExpr:d.a.textInputFocus,primary:2102,win:{primary:2102,secondary:[1044]},weight:100};return a.e||(t=void 0),e.call(this,"cut",{id:"editor.action.clipboardCutAction",label:o.a("actions.clipboard.cutLabel","Cut"),alias:"Cut",precondition:d.a.writable,kbOpts:t,menuOpts:{group:f,order:1},menubarOpts:{menuId:14,group:"2_ccp",title:o.a({key:"miCut",comment:["&& denotes a mnemonic"]},"Cu&&t"),order:1}})||this}return h(t,e),t.prototype.run=function(t,n){n.hasModel()&&(!n.getConfiguration().emptySelectionClipboard&&n.getSelection().isEmpty()||e.prototype.run.call(this,t,n))},t}(_),y=function(e){function t(){var t={kbExpr:d.a.textInputFocus,primary:2081,win:{primary:2081,secondary:[2067]},weight:100};return a.e||(t=void 0),e.call(this,"copy",{id:"editor.action.clipboardCopyAction",label:o.a("actions.clipboard.copyLabel","Copy"),alias:"Copy",precondition:void 0,kbOpts:t,menuOpts:{group:f,order:2},menubarOpts:{menuId:14,group:"2_ccp",title:o.a({key:"miCopy",comment:["&& denotes a mnemonic"]},"&&Copy"),order:2}})||this}return h(t,e),t.prototype.run=function(t,n){n.hasModel()&&(!n.getConfiguration().emptySelectionClipboard&&n.getSelection().isEmpty()||e.prototype.run.call(this,t,n))},t}(_),w=function(e){function t(){var t={kbExpr:d.a.textInputFocus,primary:2100,win:{primary:2100,secondary:[1043]},weight:100};return a.e||(t=void 0),e.call(this,"paste",{id:"editor.action.clipboardPasteAction",label:o.a("actions.clipboard.pasteLabel","Paste"),alias:"Paste",precondition:d.a.writable,kbOpts:t,menuOpts:{group:f,order:3},menubarOpts:{menuId:14,group:"2_ccp",title:o.a({key:"miPaste",comment:["&& denotes a mnemonic"]},"&&Paste"),order:3}})||this}return h(t,e),t}(_),C=function(e){function t(){return e.call(this,"copy",{id:"editor.action.clipboardCopyWithSyntaxHighlightingAction",label:o.a("actions.clipboard.copyWithSyntaxHighlightingLabel","Copy With Syntax Highlighting"),alias:"Copy With Syntax Highlighting",precondition:void 0,kbOpts:{kbExpr:d.a.textInputFocus,primary:0,weight:100}})||this}return h(t,e),t.prototype.run=function(t,n){n.hasModel()&&(!n.getConfiguration().emptySelectionClipboard&&n.getSelection().isEmpty()||(u.a.forceCopyWithSyntaxHighlighting=!0,e.prototype.run.call(this,t,n),u.a.forceCopyWithSyntaxHighlighting=!1))},t}(_);p&&Object(c.f)(b),g&&Object(c.f)(y),v&&Object(c.f)(w),m&&Object(c.f)(C)},"4QaN":function(e,t,n){"use strict";n.d(t,"a",function(){return p}),n.d(t,"b",function(){return g});var i,r=n("lAcG"),o=n("7/Cv"),s=n("odeJ"),a=n("Kp7x"),u=n("tqet"),c=n("ZfGv"),l=n("aL7J"),d=n("ZWAj"),h=n("iHM7"),f=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),p={forceCopyWithSyntaxHighlighting:!1},g=function(e){function t(t,n){var i=e.call(this)||this;i._onFocus=i._register(new a.a),i.onFocus=i._onFocus.event,i._onBlur=i._register(new a.a),i.onBlur=i._onBlur.event,i._onKeyDown=i._register(new a.a),i.onKeyDown=i._onKeyDown.event,i._onKeyUp=i._register(new a.a),i.onKeyUp=i._onKeyUp.event,i._onCut=i._register(new a.a),i.onCut=i._onCut.event,i._onPaste=i._register(new a.a),i.onPaste=i._onPaste.event,i._onType=i._register(new a.a),i.onType=i._onType.event,i._onCompositionStart=i._register(new a.a),i.onCompositionStart=i._onCompositionStart.event,i._onCompositionUpdate=i._register(new a.a),i.onCompositionUpdate=i._onCompositionUpdate.event,i._onCompositionEnd=i._register(new a.a),i.onCompositionEnd=i._onCompositionEnd.event,i._onSelectionChangeRequest=i._register(new a.a),i.onSelectionChangeRequest=i._onSelectionChangeRequest.event,i._host=t,i._textArea=i._register(new v(n)),i._lastTextAreaEvent=0,i._asyncTriggerCut=i._register(new s.d(function(){return i._onCut.fire()},0)),i._textAreaState=d.b.EMPTY,i._selectionChangeListener=null,i.writeScreenReaderContent("ctor"),i._hasFocus=!1,i._isDoingComposition=!1,i._nextCommand=0,i._register(o.k(n.domNode,"keydown",function(e){!i._isDoingComposition||109!==e.keyCode&&1!==e.keyCode||e.stopPropagation(),e.equals(9)&&e.preventDefault(),i._onKeyDown.fire(e)})),i._register(o.k(n.domNode,"keyup",function(e){i._onKeyUp.fire(e)})),i._register(o.h(n.domNode,"compositionstart",function(e){i._lastTextAreaEvent=1,i._isDoingComposition||(i._isDoingComposition=!0,r.g||i._setAndWriteTextAreaState("compositionstart",d.b.EMPTY),i._onCompositionStart.fire())}));var u=function(e,t){var n=i._textAreaState,r=d.b.readFromTextArea(i._textArea);return[r,d.b.deduceInput(n,r,e,t)]},h=function(e){var t=i._textAreaState,n=d.b.selectedText(e);return[n,{text:n.value,replaceCharCnt:t.selectionEnd-t.selectionStart}]},f=function(e){return!(!r.g||"ja"!==e)||!(!r.j||0!==e.indexOf("zh-Han"))};return i._register(o.h(n.domNode,"compositionupdate",function(e){if(i._lastTextAreaEvent=2,f(e.locale)){var t=u(!1,!1),n=t[0],r=t[1];return i._textAreaState=n,i._onType.fire(r),void i._onCompositionUpdate.fire(e)}var o=h(e.data),s=o[0],a=o[1];i._textAreaState=s,i._onType.fire(a),i._onCompositionUpdate.fire(e)})),i._register(o.h(n.domNode,"compositionend",function(e){if(i._lastTextAreaEvent=3,f(e.locale)){var t=u(!1,!1),n=t[0],o=t[1];i._textAreaState=n,i._onType.fire(o)}else{var s=h(e.data);n=s[0],o=s[1];i._textAreaState=n,i._onType.fire(o)}(r.g||r.e)&&(i._textAreaState=d.b.readFromTextArea(i._textArea)),i._isDoingComposition&&(i._isDoingComposition=!1,i._onCompositionEnd.fire())})),i._register(o.h(n.domNode,"input",function(){var e=8===i._lastTextAreaEvent;if(i._lastTextAreaEvent=4,i._textArea.setIgnoreSelectionChangeTime("received input event"),!i._isDoingComposition){var t=u(c.d,e&&c.d),n=t[0],r=t[1];0===r.replaceCharCnt&&1===r.text.length&&l.w(r.text.charCodeAt(0))||(i._textAreaState=n,0===i._nextCommand?""!==r.text&&i._onType.fire(r):(""!==r.text&&i._onPaste.fire({text:r.text}),i._nextCommand=0))}})),i._register(o.h(n.domNode,"cut",function(e){i._lastTextAreaEvent=5,i._textArea.setIgnoreSelectionChangeTime("received cut event"),i._ensureClipboardGetsEditorSelection(e),i._asyncTriggerCut.schedule()})),i._register(o.h(n.domNode,"copy",function(e){i._lastTextAreaEvent=6,i._ensureClipboardGetsEditorSelection(e)})),i._register(o.h(n.domNode,"paste",function(e){if(i._lastTextAreaEvent=7,i._textArea.setIgnoreSelectionChangeTime("received paste event"),m.canUseTextData(e)){var t=m.getTextData(e);""!==t&&i._onPaste.fire({text:t})}else i._textArea.getSelectionStart()!==i._textArea.getSelectionEnd()&&i._setAndWriteTextAreaState("paste",d.b.EMPTY),i._nextCommand=1})),i._register(o.h(n.domNode,"focus",function(){i._lastTextAreaEvent=8,i._setHasFocus(!0)})),i._register(o.h(n.domNode,"blur",function(){i._lastTextAreaEvent=9,i._setHasFocus(!1)})),i}return f(t,e),t.prototype._installSelectionChangeListener=function(){var e=this,t=0;return o.h(document,"selectionchange",function(n){if(e._hasFocus&&!e._isDoingComposition&&r.e&&c.g){var i=Date.now(),o=i-t;if(t=i,!(o<5)){var s=i-e._textArea.getIgnoreSelectionChangeTime();if(e._textArea.resetSelectionChangeTime(),!(s<100)&&e._textAreaState.selectionStartPosition&&e._textAreaState.selectionEndPosition){var a=e._textArea.getValue();if(e._textAreaState.value===a){var u=e._textArea.getSelectionStart(),l=e._textArea.getSelectionEnd();if(e._textAreaState.selectionStart!==u||e._textAreaState.selectionEnd!==l){var d=e._textAreaState.deduceEditorPosition(u),f=e._host.deduceModelPosition(d[0],d[1],d[2]),p=e._textAreaState.deduceEditorPosition(l),g=e._host.deduceModelPosition(p[0],p[1],p[2]),m=new h.a(f.lineNumber,f.column,g.lineNumber,g.column);e._onSelectionChangeRequest.fire(m)}}}}}})},t.prototype.dispose=function(){e.prototype.dispose.call(this),this._selectionChangeListener&&(this._selectionChangeListener.dispose(),this._selectionChangeListener=null)},t.prototype.focusTextArea=function(){this._setHasFocus(!0)},t.prototype.isFocused=function(){return this._hasFocus},t.prototype._setHasFocus=function(e){this._hasFocus!==e&&(this._hasFocus=e,this._selectionChangeListener&&(this._selectionChangeListener.dispose(),this._selectionChangeListener=null),this._hasFocus&&(this._selectionChangeListener=this._installSelectionChangeListener()),this._hasFocus&&(r.f?this._setAndWriteTextAreaState("focusgain",d.b.EMPTY):this.writeScreenReaderContent("focusgain")),this._hasFocus?this._onFocus.fire():this._onBlur.fire())},t.prototype._setAndWriteTextAreaState=function(e,t){this._hasFocus||(t=t.collapseSelection()),t.writeToTextArea(e,this._textArea,this._hasFocus),this._textAreaState=t},t.prototype.writeScreenReaderContent=function(e){this._isDoingComposition||this._setAndWriteTextAreaState(e,this._host.getScreenReaderContent(this._textAreaState))},t.prototype._ensureClipboardGetsEditorSelection=function(e){var t=this._host.getPlainTextToCopy();if(m.canUseTextData(e)){var n=null;r.d()&&(t.length<65536||p.forceCopyWithSyntaxHighlighting)&&(n=this._host.getHTMLToCopy()),m.setTextData(e,t,n)}else this._setAndWriteTextAreaState("copy or cut",d.b.selectedText(t))},t}(u.a),m=function(){function e(){}return e.canUseTextData=function(e){return!!e.clipboardData||!!window.clipboardData},e.getTextData=function(e){if(e.clipboardData)return e.preventDefault(),e.clipboardData.getData("text/plain");if(window.clipboardData)return e.preventDefault(),window.clipboardData.getData("Text");throw new Error("ClipboardEventUtils.getTextData: Cannot use text data!")},e.setTextData=function(e,t,n){if(e.clipboardData)return e.clipboardData.setData("text/plain",t),null!==n&&e.clipboardData.setData("text/html",n),void e.preventDefault();if(window.clipboardData)return window.clipboardData.setData("Text",t),void e.preventDefault();throw new Error("ClipboardEventUtils.setTextData: Cannot use text data!")},e}(),v=function(e){function t(t){var n=e.call(this)||this;return n._actual=t,n._ignoreSelectionChangeTime=0,n}return f(t,e),t.prototype.setIgnoreSelectionChangeTime=function(e){this._ignoreSelectionChangeTime=Date.now()},t.prototype.getIgnoreSelectionChangeTime=function(){return this._ignoreSelectionChangeTime},t.prototype.resetSelectionChangeTime=function(){this._ignoreSelectionChangeTime=0},t.prototype.getValue=function(){return this._actual.domNode.value},t.prototype.setValue=function(e,t){var n=this._actual.domNode;n.value!==t&&(this.setIgnoreSelectionChangeTime("setValue"),n.value=t)},t.prototype.getSelectionStart=function(){return this._actual.domNode.selectionStart},t.prototype.getSelectionEnd=function(){return this._actual.domNode.selectionEnd},t.prototype.setSelectionRange=function(e,t,n){var i=this._actual.domNode,s=document.activeElement===i,a=i.selectionStart,u=i.selectionEnd;if(s&&a===t&&u===n)r.i&&window.parent!==window&&i.focus();else{if(s)return this.setIgnoreSelectionChangeTime("setSelectionRange"),i.setSelectionRange(t,n),void(r.i&&window.parent!==window&&i.focus());try{var c=o.O(i);this.setIgnoreSelectionChangeTime("setSelectionRange"),i.focus(),i.setSelectionRange(t,n),o.M(i,c)}catch(e){}}},t}(u.a)},"4R/o":function(e,t,n){"use strict";(function(e,i){function r(){throw new Error("secure random number generation not supported by this browser\nuse chrome, FireFox or Internet Explorer 11")}var o=n("X3l8"),s=n("rOku"),a=o.Buffer,u=o.kMaxLength,c=e.crypto||e.msCrypto,l=Math.pow(2,32)-1;function d(e,t){if("number"!=typeof e||e!=e)throw new TypeError("offset must be a number");if(e>l||e<0)throw new TypeError("offset must be a uint32");if(e>u||e>t)throw new RangeError("offset out of range")}function h(e,t,n){if("number"!=typeof e||e!=e)throw new TypeError("size must be a number");if(e>l||e<0)throw new TypeError("size must be a uint32");if(e+t>n||e>u)throw new RangeError("buffer too small")}function f(e,t,n,r){if(i.browser){var o=e.buffer,a=new Uint8Array(o,t,n);return c.getRandomValues(a),r?void i.nextTick(function(){r(null,e)}):e}if(!r)return s(n).copy(e,t),e;s(n,function(n,i){if(n)return r(n);i.copy(e,t),r(null,e)})}c&&c.getRandomValues||!i.browser?(t.randomFill=function(t,n,i,r){if(!(a.isBuffer(t)||t instanceof e.Uint8Array))throw new TypeError('"buf" argument must be a Buffer or Uint8Array');if("function"==typeof n)r=n,n=0,i=t.length;else if("function"==typeof i)r=i,i=t.length-n;else if("function"!=typeof r)throw new TypeError('"cb" argument must be a function');return d(n,t.length),h(i,n,t.length),f(t,n,i,r)},t.randomFillSync=function(t,n,i){void 0===n&&(n=0);if(!(a.isBuffer(t)||t instanceof e.Uint8Array))throw new TypeError('"buf" argument must be a Buffer or Uint8Array');d(n,t.length),void 0===i&&(i=t.length-n);return h(i,n,t.length),f(t,n,i)}):(t.randomFill=r,t.randomFillSync=r)}).call(t,n("DuR2"),n("W2nU"))},"4Vh3":function(e,t){e.exports={modp1:{gen:"02",prime:"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a63a3620ffffffffffffffff"},modp2:{gen:"02",prime:"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece65381ffffffffffffffff"},modp5:{gen:"02",prime:"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca237327ffffffffffffffff"},modp14:{gen:"02",prime:"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aacaa68ffffffffffffffff"},modp15:{gen:"02",prime:"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a93ad2caffffffffffffffff"},modp16:{gen:"02",prime:"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c934063199ffffffffffffffff"},modp17:{gen:"02",prime:"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dcc4024ffffffffffffffff"},modp18:{gen:"02",prime:"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dbe115974a3926f12fee5e438777cb6a932df8cd8bec4d073b931ba3bc832b68d9dd300741fa7bf8afc47ed2576f6936ba424663aab639c5ae4f5683423b4742bf1c978238f16cbe39d652de3fdb8befc848ad922222e04a4037c0713eb57a81a23f0c73473fc646cea306b4bcbc8862f8385ddfa9d4b7fa2c087e879683303ed5bdd3a062b3cf5b3a278a66d2a13f83f44f82ddf310ee074ab6a364597e899a0255dc164f31cc50846851df9ab48195ded7ea1b1d510bd7ee74d73faf36bc31ecfa268359046f4eb879f924009438b481c6cd7889a002ed5ee382bc9190da6fc026e479558e4475677e9aa9e3050e2765694dfc81f56e880b96e7160c980dd98edd3dfffffffffffffffff"}}},"4Yhh":function(e,t){},"4sPJ":function(e,t){e.exports=function(e){for(var t,n=e.length;n--;){if(255!==(t=e.readUInt8(n))){t++,e.writeUInt8(t,n);break}e.writeUInt8(0,n)}}},"4tuZ":function(e,t,n){"use strict";var i,r=n("aL7J"),o=n("80kS"),s=n("tqet"),a=n("03Zz"),u=n("7g0X"),c=n("EMhq"),l=n("JVO/"),d=n("8xpx"),h=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),f=Object(l.c)("IEditorCancelService"),p=new u.d("cancellableOperation",!1);Object(d.b)(f,function(){function e(){this._tokens=new WeakMap}return e.prototype.add=function(e,t){var n,i=this._tokens.get(e);return i||(i=e.invokeWithinContext(function(e){return{key:p.bindTo(e.get(u.c)),tokens:new c.a}}),this._tokens.set(e,i)),i.key.set(!0),n=i.tokens.push(t),function(){n&&(n(),i.key.set(!i.tokens.isEmpty()),n=void 0)}},e.prototype.cancel=function(e){var t=this._tokens.get(e);if(t){var n=t.tokens.pop();n&&(n.cancel(),t.key.set(!t.tokens.isEmpty()))}},e}(),!0);var g=function(e){function t(t,n){var i=e.call(this,n)||this;return i.editor=t,i._unregister=t.invokeWithinContext(function(e){return e.get(f).add(t,i)}),i}return h(t,e),t.prototype.dispose=function(){this._unregister(),e.prototype.dispose.call(this)},t}(o.b);Object(a.g)(new(function(e){function t(){return e.call(this,{id:"editor.cancelOperation",kbOpts:{weight:100,primary:9},precondition:p})||this}return h(t,e),t.prototype.runEditorCommand=function(e,t){e.get(f).cancel(t)},t}(a.c))),n.d(t,"a",function(){return v}),n.d(t,"b",function(){return _}),n.d(t,"d",function(){return b}),n.d(t,"c",function(){return y});var m=this&&this.__extends||function(){var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(t,n)};return function(t,n){function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}}(),v=function(){function e(e,t){if(this.flags=t,0!=(1&this.flags)){var n=e.getModel();this.modelVersionId=n?r.r("{0}#{1}",n.uri.toString(),n.getVersionId()):null}else this.modelVersionId=null;0!=(4&this.flags)?this.position=e.getPosition():this.position=null,0!=(2&this.flags)?this.selection=e.getSelection():this.selection=null,0!=(8&this.flags)?(this.scrollLeft=e.getScrollLeft(),this.scrollTop=e.getScrollTop()):(this.scrollLeft=-1,this.scrollTop=-1)}return e.prototype._equals=function(t){if(!(t instanceof e))return!1;var n=t;return this.modelVersionId===n.modelVersionId&&(this.scrollLeft===n.scrollLeft&&this.scrollTop===n.scrollTop&&(!(!this.position&&n.position||this.position&&!n.position||this.position&&n.position&&!this.position.equals(n.position))&&!(!this.selection&&n.selection||this.selection&&!n.selection||this.selection&&n.selection&&!this.selection.equalsRange(n.selection))))},e.prototype.validate=function(t){return this._equals(new e(t,this.flags))},e}(),_=function(e){function t(t,n,i){var r=e.call(this,t,i)||this;return r.editor=t,r._listener=new s.b,4&n&&r._listener.add(t.onDidChangeCursorPosition(function(e){return r.cancel()})),2&n&&r._listener.add(t.onDidChangeCursorSelection(function(e){return r.cancel()})),8&n&&r._listener.add(t.onDidScrollChange(function(e){return r.cancel()})),1&n&&(r._listener.add(t.onDidChangeModel(function(e){return r.cancel()})),r._listener.add(t.onDidChangeModelContent(function(e){return r.cancel()}))),r}return m(t,e),t.prototype.dispose=function(){this._listener.dispose(),e.prototype.dispose.call(this)},t}(g),b=function(e){function t(t,n){var i=e.call(this,n)||this;return i._listener=t.onDidChangeContent(function(){return i.cancel()}),i}return m(t,e),t.prototype.dispose=function(){this._listener.dispose(),e.prototype.dispose.call(this)},t}(o.b),y=function(){function e(e,t){this._visiblePosition=e,this._visiblePositionScrollDelta=t}return e.capture=function(t){var n=null,i=0;if(0!==t.getScrollTop()){var r=t.getVisibleRanges();if(r.length>0){n=r[0].getStartPosition();var o=t.getTopForPosition(n.lineNumber,n.column);i=t.getScrollTop()-o}}return new e(n,i)},e.prototype.restore=function(e){if(this._visiblePosition){var t=e.getTopForPosition(this._visiblePosition.lineNumber,this._visiblePosition.column);e.setScrollTop(t+this._visiblePositionScrollDelta)}},e}()},"5QAX":function(e,t,n){var i=n("geuY"),r=n("X3l8").Buffer;e.exports=function(e,t){return r.from(e.toRed(i.mont(t.modulus)).redPow(new i(t.publicExponent)).fromRed().toArray())}},"5RGO":function(e,t){},"5TlO":function(e,t,n){"use strict";t.a=function(e,t){if(!e)throw new Error(t?"Assertion failed ("+t+")":"Assertion Failed")}},"5VRF":function(e,t,n){"use strict";n.d(t,"c",function(){return s}),n.d(t,"d",function(){return r}),t.f=function(e){return Array.isArray(e)?r.fromArray(e):e},n.d(t,"a",function(){return a}),n.d(t,"b",function(){return u}),n.d(t,"e",function(){return c});var i,r,o=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),s={done:!0,value:void 0};!function(e){var t={next:function(){return s}};e.empty=function(){return t},e.single=function(e){var t=!1;return{next:function(){return t?s:(t=!0,{done:!1,value:e})}}},e.fromArray=function(e,t,n){return void 0===t&&(t=0),void 0===n&&(n=e.length),{next:function(){return t>=n?s:{done:!1,value:e[t++]}}}},e.from=function(t){return t?Array.isArray(t)?e.fromArray(t):t:e.empty()},e.map=function(e,t){return{next:function(){var n=e.next();return n.done?s:{done:!1,value:t(n.value)}}}},e.filter=function(e,t){return{next:function(){for(;;){var n=e.next();if(n.done)return s;if(t(n.value))return{done:!1,value:n.value}}}}},e.forEach=function(e,t){for(var n=e.next();!n.done;n=e.next())t(n.value)},e.collect=function(e,t){void 0===t&&(t=Number.POSITIVE_INFINITY);var n=[];if(0===t)return n;for(var i=0,r=e.next();!(r.done||(n.push(r.value),++i>=t));r=e.next());return n},e.concat=function(){for(var e=[],t=0;t=e.length)return s;var t=e[n].next();return t.done?(n++,this.next()):t}}}}(r||(r={}));var a=function(){function e(e,t,n,i){void 0===t&&(t=0),void 0===n&&(n=e.length),void 0===i&&(i=t-1),this.items=e,this.start=t,this.end=n,this.index=i}return e.prototype.first=function(){return this.index=this.start,this.current()},e.prototype.next=function(){return this.index=Math.min(this.index+1,this.end),this.current()},e.prototype.current=function(){return this.index===this.start-1||this.index===this.end?null:this.items[this.index]},e}(),u=function(e){function t(t,n,i,r){return void 0===n&&(n=0),void 0===i&&(i=t.length),void 0===r&&(r=n-1),e.call(this,t,n,i,r)||this}return o(t,e),t.prototype.current=function(){return e.prototype.current.call(this)},t.prototype.previous=function(){return this.index=Math.max(this.index-1,this.start-1),this.current()},t.prototype.first=function(){return this.index=this.start,this.current()},t.prototype.last=function(){return this.index=this.end-1,this.current()},t.prototype.parent=function(){return null},t}(a),c=function(){function e(e,t){this.iterator=e,this.fn=t}return e.prototype.next=function(){return this.fn(this.iterator.next())},e}()},"5kgg":function(e,t){},"5lao":function(e,t,n){"use strict";n.d(t,"a",function(){return h}),n.d(t,"b",function(){return f});var i,r=n("ZfGv"),o=n("iXRW"),s=n("G8r4"),a=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),u=r.d?1.5:1.35;function c(e,t){if("number"==typeof e)return e;if(void 0===e)return t;var n=parseFloat(e);return isNaN(n)?t:n}function l(e,t,n){return en?n:e}function d(e,t){return"string"!=typeof e?t:e}var h=function(){function e(e){this.zoomLevel=e.zoomLevel,this.fontFamily=String(e.fontFamily),this.fontWeight=String(e.fontWeight),this.fontSize=e.fontSize,this.lineHeight=0|e.lineHeight,this.letterSpacing=e.letterSpacing}return e.createFromRawSettings=function(t,n,i){void 0===i&&(i=!1);var r=d(t.fontFamily,o.b.fontFamily),a=d(t.fontWeight,o.b.fontWeight),h=c(t.fontSize,o.b.fontSize);0===(h=l(h,0,100))?h=o.b.fontSize:h<8&&(h=8);var f=function(e,t){if("number"==typeof e)return Math.round(e);if(void 0===e)return t;var n=parseInt(e);return isNaN(n)?t:n}(t.lineHeight,0);0===(f=l(f,0,150))?f=Math.round(u*h):f<8&&(f=8);var p=c(t.letterSpacing,0);p=l(p,-5,20);var g=1+(i?0:.1*s.a.getZoomLevel());return new e({zoomLevel:n,fontFamily:r,fontWeight:a,fontSize:h*=g,lineHeight:f*=g,letterSpacing:p})},e.prototype.getId=function(){return this.zoomLevel+"-"+this.fontFamily+"-"+this.fontWeight+"-"+this.fontSize+"-"+this.lineHeight+"-"+this.letterSpacing},e.prototype.getMassagedFontFamily=function(){return/[,"']/.test(this.fontFamily)?this.fontFamily:/[+ ]/.test(this.fontFamily)?'"'+this.fontFamily+'"':this.fontFamily},e}(),f=function(e){function t(t,n){var i=e.call(this,t)||this;return i.isTrusted=n,i.isMonospace=t.isMonospace,i.typicalHalfwidthCharacterWidth=t.typicalHalfwidthCharacterWidth,i.typicalFullwidthCharacterWidth=t.typicalFullwidthCharacterWidth,i.canUseHalfwidthRightwardsArrow=t.canUseHalfwidthRightwardsArrow,i.spaceWidth=t.spaceWidth,i.maxDigitWidth=t.maxDigitWidth,i}return a(t,e),t.prototype.equals=function(e){return this.fontFamily===e.fontFamily&&this.fontWeight===e.fontWeight&&this.fontSize===e.fontSize&&this.lineHeight===e.lineHeight&&this.letterSpacing===e.letterSpacing&&this.typicalHalfwidthCharacterWidth===e.typicalHalfwidthCharacterWidth&&this.typicalFullwidthCharacterWidth===e.typicalFullwidthCharacterWidth&&this.canUseHalfwidthRightwardsArrow===e.canUseHalfwidthRightwardsArrow&&this.spaceWidth===e.spaceWidth&&this.maxDigitWidth===e.maxDigitWidth},t}(h)},"5tK6":function(e,t,n){"use strict";n.d(t,"a",function(){return m});var i,r=n("LCUL"),o=(n.n(r),n("tqet")),s=n("lAcG"),a=n("ZfGv"),u=n("KIxu"),c=n("Bug4"),l=n("b1X/"),d=n("Kp7x"),h=n("7/Cv"),f=n("Gxst"),p=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),g=!1,m=function(e){function t(t,n,i){void 0===i&&(i={});var r=e.call(this)||this;return r._state=3,r._onDidEnablementChange=r._register(new d.a),r.onDidEnablementChange=r._onDidEnablementChange.event,r._onDidStart=r._register(new d.a),r.onDidStart=r._onDidStart.event,r._onDidChange=r._register(new d.a),r.onDidChange=r._onDidChange.event,r._onDidReset=r._register(new d.a),r.onDidReset=r._onDidReset.event,r._onDidEnd=r._register(new d.a),r.onDidEnd=r._onDidEnd.event,r.linkedSash=void 0,r.orthogonalStartSashDisposables=r._register(new o.b),r.orthogonalEndSashDisposables=r._register(new o.b),r.el=Object(h.m)(t,Object(h.a)(".monaco-sash")),a.d&&Object(h.f)(r.el,"mac"),r._register(Object(f.a)(r.el,"mousedown")(r.onMouseDown,r)),r._register(Object(f.a)(r.el,"dblclick")(r.onMouseDoubleClick,r)),c.b.addTarget(r.el),r._register(Object(f.a)(r.el,c.a.Start)(r.onTouchStart,r)),s.k&&Object(h.f)(r.el,"touch"),r.setOrientation(i.orientation||0),r.hidden=!1,r.layoutProvider=n,r.orthogonalStartSash=i.orthogonalStartSash,r.orthogonalEndSash=i.orthogonalEndSash,Object(h.R)(r.el,"debug",g),r}return p(t,e),Object.defineProperty(t.prototype,"state",{get:function(){return this._state},set:function(e){this._state!==e&&(Object(h.R)(this.el,"disabled",0===e),Object(h.R)(this.el,"minimum",1===e),Object(h.R)(this.el,"maximum",2===e),this._state=e,this._onDidEnablementChange.fire(e))},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"orthogonalStartSash",{get:function(){return this._orthogonalStartSash},set:function(e){this.orthogonalStartSashDisposables.clear(),e?(this.orthogonalStartSashDisposables.add(e.onDidEnablementChange(this.onOrthogonalStartSashEnablementChange,this)),this.onOrthogonalStartSashEnablementChange(e.state)):this.onOrthogonalStartSashEnablementChange(0),this._orthogonalStartSash=e},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"orthogonalEndSash",{get:function(){return this._orthogonalEndSash},set:function(e){this.orthogonalEndSashDisposables.clear(),e?(this.orthogonalEndSashDisposables.add(e.onDidEnablementChange(this.onOrthogonalEndSashEnablementChange,this)),this.onOrthogonalEndSashEnablementChange(e.state)):this.onOrthogonalEndSashEnablementChange(0),this._orthogonalEndSash=e},enumerable:!0,configurable:!0}),t.prototype.setOrientation=function(e){this.orientation=e,1===this.orientation?(Object(h.f)(this.el,"horizontal"),Object(h.I)(this.el,"vertical")):(Object(h.I)(this.el,"horizontal"),Object(h.f)(this.el,"vertical")),this.layoutProvider&&this.layout()},t.prototype.onMouseDown=function(e){var t=this;h.c.stop(e,!1);var n=!1;if(!e.__orthogonalSashEvent){var i=this.getOrthogonalSash(e);i&&(n=!0,e.__orthogonalSashEvent=!0,i.onMouseDown(e))}if(this.linkedSash&&!e.__linkedSashEvent&&(e.__linkedSashEvent=!0,this.linkedSash.onMouseDown(e)),this.state){for(var r=Object(h.y)("iframe").concat(Object(h.y)("webview")),s=0,u=r;s=this.el.clientHeight-4)return this.orthogonalEndSash}else{if(e.offsetX<=4)return this.orthogonalStartSash;if(e.offsetX>=this.el.clientWidth-4)return this.orthogonalEndSash}},t.prototype.dispose=function(){e.prototype.dispose.call(this),this.el&&this.el.parentElement&&this.el.parentElement.removeChild(this.el),this.el=null},t}(o.a)},"5zde":function(e,t,n){n("zQR9"),n("qyJz"),e.exports=n("FeBl").Array.from},"606G":function(e,t,n){"use strict";n.d(t,"a",function(){return r});var i=n("JVO/"),r=Object(i.c)("editorWorkerService")},"67ys":function(e,t){},"6Hge":function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=n("X6iQ"),r=n("80kS"),o=n("03Zz"),s=n("artP"),a=n("vTy2"),u=n("iHM7"),c=n("/9db"),l=n("PCC9"),d=n("hK2W"),h=n("tqet"),f=n("aL7J"),p=function(){function e(){}return e.prototype.provideSelectionRanges=function(e,t){for(var n=[],i=0,r=t;i=0;u--){if(95===(d=r.charCodeAt(u))||45===d)break;if(Object(f.y)(d)&&Object(f.z)(l))break;l=d}for(u+=1;c0&&0===t.getLineFirstNonWhitespaceColumn(n.lineNumber)&&0===t.getLineLastNonWhitespaceColumn(n.lineNumber)&&e.push({range:new a.a(n.lineNumber,1,n.lineNumber,t.getLineMaxColumn(n.lineNumber))})},e}(),g=n("NjuD"),m=n("ItKl"),v=n("zxiH");t.provideSelectionRanges=k;var _,b=this&&this.__extends||(_=function(e,t){return(_=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}_(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),y=this&&this.__awaiter||function(e,t,n,i){return new(n||(n=Promise))(function(r,o){function s(e){try{u(i.next(e))}catch(e){o(e)}}function a(e){try{u(i.throw(e))}catch(e){o(e)}}function u(e){e.done?r(e.value):new n(function(t){t(e.value)}).then(s,a)}u((i=i.apply(e,t||[])).next())})},w=this&&this.__generator||function(e,t){var n,i,r,o,s={label:0,sent:function(){if(1&r[0])throw r[1];return r[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,i&&(r=2&o[0]?i.return:o[0]?i.throw||((r=i.return)&&r.call(i),0):i.next)&&!(r=r.call(i,o[1])).done)return r;switch(i=0,r&&(o=[2&o[0],r.value]),o[0]){case 0:case 1:r=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,i=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(r=(r=s.trys).length>0&&r[r.length-1])&&(6===o[0]||2===o[0])){s=0;continue}if(3===o[0]&&(!r||o[1]>r[0]&&o[1]=this.ranges.length)return this;var i=new e(n,this.ranges);return i.ranges[n].equalsRange(this.ranges[this.index])?i.mov(t):i},e}(),S=function(){function e(e){this._ignoreSelection=!1,this._editor=e}return e.get=function(t){return t.getContribution(e._id)},e.prototype.dispose=function(){Object(h.f)(this._selectionListener)},e.prototype.getId=function(){return e._id},e.prototype.run=function(e){var t=this;if(this._editor.hasModel()){var n=this._editor.getSelections(),o=this._editor.getModel();if(l.u.has(o)){var s=Promise.resolve(void 0);return this._state||(s=k(o,n.map(function(e){return e.getPosition()}),r.a.None).then(function(e){if(i.n(e)&&e.length===n.length&&t._editor.hasModel()&&i.g(t._editor.getSelections(),n,function(e,t){return e.equalsSelection(t)})){for(var r=function(t){e[t]=e[t].filter(function(e){return e.containsPosition(n[t].getStartPosition())&&e.containsPosition(n[t].getEndPosition())}),e[t].unshift(n[t])},o=0;o)?=?)";var L=u++;a[L]=a[l]+"|x|X|\\*";var O=u++;a[O]=a[c]+"|x|X|\\*";var k=u++;a[k]="[v=\\s]*("+a[O]+")(?:\\.("+a[O]+")(?:\\.("+a[O]+")(?:"+a[m]+")?"+a[b]+"?)?)?";var N=u++;a[N]="[v=\\s]*("+a[L]+")(?:\\.("+a[L]+")(?:\\.("+a[L]+")(?:"+a[v]+")?"+a[b]+"?)?)?";var E=u++;a[E]="^"+a[x]+"\\s*"+a[k]+"$";var I=u++;a[I]="^"+a[x]+"\\s*"+a[N]+"$";var D=u++;a[D]="(?:^|[^\\d])(\\d{1,16})(?:\\.(\\d{1,16}))?(?:\\.(\\d{1,16}))?(?:$|[^\\d])";var M=u++;a[M]="(?:~>?)";var T=u++;a[T]="(\\s*)"+a[M]+"\\s+",s[T]=new RegExp(a[T],"g");var P=u++;a[P]="^"+a[M]+a[k]+"$";var A=u++;a[A]="^"+a[M]+a[N]+"$";var R=u++;a[R]="(?:\\^)";var F=u++;a[F]="(\\s*)"+a[R]+"\\s+",s[F]=new RegExp(a[F],"g");var j=u++;a[j]="^"+a[R]+a[k]+"$";var W=u++;a[W]="^"+a[R]+a[N]+"$";var B=u++;a[B]="^"+a[x]+"\\s*("+C+")$|^$";var V=u++;a[V]="^"+a[x]+"\\s*("+w+")$|^$";var H=u++;a[H]="(\\s*)"+a[x]+"\\s*("+C+"|"+a[k]+")",s[H]=new RegExp(a[H],"g");var z=u++;a[z]="^\\s*("+a[k]+")\\s+-\\s+("+a[k]+")\\s*$";var U=u++;a[U]="^\\s*("+a[N]+")\\s+-\\s+("+a[N]+")\\s*$";var K=u++;a[K]="(<|>)?=?\\s*\\*";for(var q=0;qr)return null;if(!(t.loose?s[S]:s[y]).test(e))return null;try{return new Z(e,t)}catch(e){return null}}function Z(e,t){if(t&&"object"==typeof t||(t={loose:!!t,includePrerelease:!1}),e instanceof Z){if(e.loose===t.loose)return e;e=e.version}else if("string"!=typeof e)throw new TypeError("Invalid Version: "+e);if(e.length>r)throw new TypeError("version is longer than "+r+" characters");if(!(this instanceof Z))return new Z(e,t);i("SemVer",e,t),this.options=t,this.loose=!!t.loose;var n=e.trim().match(t.loose?s[S]:s[y]);if(!n)throw new TypeError("Invalid Version: "+e);if(this.raw=e,this.major=+n[1],this.minor=+n[2],this.patch=+n[3],this.major>o||this.major<0)throw new TypeError("Invalid major version");if(this.minor>o||this.minor<0)throw new TypeError("Invalid minor version");if(this.patch>o||this.patch<0)throw new TypeError("Invalid patch version");n[4]?this.prerelease=n[4].split(".").map(function(e){if(/^[0-9]+$/.test(e)){var t=+e;if(t>=0&&t=0;)"number"==typeof this.prerelease[n]&&(this.prerelease[n]++,n=-2);-1===n&&this.prerelease.push(0)}t&&(this.prerelease[0]===t?isNaN(this.prerelease[1])&&(this.prerelease=[t,0]):this.prerelease=[t,0]);break;default:throw new Error("invalid increment argument: "+e)}return this.format(),this.raw=this.version,this},t.inc=function(e,t,n,i){"string"==typeof n&&(i=n,n=void 0);try{return new Z(e,n).inc(t,i).version}catch(e){return null}},t.diff=function(e,t){if(ee(e,t))return null;var n=G(e),i=G(t),r="";if(n.prerelease.length||i.prerelease.length){r="pre";var o="prerelease"}for(var s in n)if(("major"===s||"minor"===s||"patch"===s)&&n[s]!==i[s])return r+s;return o},t.compareIdentifiers=X;var Y=/^[0-9]+$/;function X(e,t){var n=Y.test(e),i=Y.test(t);return n&&i&&(e=+e,t=+t),e===t?0:n&&!i?-1:i&&!n?1:e0}function Q(e,t,n){return $(e,t,n)<0}function ee(e,t,n){return 0===$(e,t,n)}function te(e,t,n){return 0!==$(e,t,n)}function ne(e,t,n){return $(e,t,n)>=0}function ie(e,t,n){return $(e,t,n)<=0}function re(e,t,n,i){switch(t){case"===":return"object"==typeof e&&(e=e.version),"object"==typeof n&&(n=n.version),e===n;case"!==":return"object"==typeof e&&(e=e.version),"object"==typeof n&&(n=n.version),e!==n;case"":case"=":case"==":return ee(e,n,i);case"!=":return te(e,n,i);case">":return J(e,n,i);case">=":return ne(e,n,i);case"<":return Q(e,n,i);case"<=":return ie(e,n,i);default:throw new TypeError("Invalid operator: "+t)}}function oe(e,t){if(t&&"object"==typeof t||(t={loose:!!t,includePrerelease:!1}),e instanceof oe){if(e.loose===!!t.loose)return e;e=e.value}if(!(this instanceof oe))return new oe(e,t);i("comparator",e,t),this.options=t,this.loose=!!t.loose,this.parse(e),this.semver===se?this.value="":this.value=this.operator+this.semver.version,i("comp",this)}t.rcompareIdentifiers=function(e,t){return X(t,e)},t.major=function(e,t){return new Z(e,t).major},t.minor=function(e,t){return new Z(e,t).minor},t.patch=function(e,t){return new Z(e,t).patch},t.compare=$,t.compareLoose=function(e,t){return $(e,t,!0)},t.rcompare=function(e,t,n){return $(t,e,n)},t.sort=function(e,n){return e.sort(function(e,i){return t.compare(e,i,n)})},t.rsort=function(e,n){return e.sort(function(e,i){return t.rcompare(e,i,n)})},t.gt=J,t.lt=Q,t.eq=ee,t.neq=te,t.gte=ne,t.lte=ie,t.cmp=re,t.Comparator=oe;var se={};function ae(e,t){if(t&&"object"==typeof t||(t={loose:!!t,includePrerelease:!1}),e instanceof ae)return e.loose===!!t.loose&&e.includePrerelease===!!t.includePrerelease?e:new ae(e.raw,t);if(e instanceof oe)return new ae(e.value,t);if(!(this instanceof ae))return new ae(e,t);if(this.options=t,this.loose=!!t.loose,this.includePrerelease=!!t.includePrerelease,this.raw=e,this.set=e.split(/\s*\|\|\s*/).map(function(e){return this.parseRange(e.trim())},this).filter(function(e){return e.length}),!this.set.length)throw new TypeError("Invalid SemVer Range: "+e);this.format()}function ue(e){return!e||"x"===e.toLowerCase()||"*"===e}function ce(e,t,n,i,r,o,s,a,u,c,l,d,h){return((t=ue(n)?"":ue(i)?">="+n+".0.0":ue(r)?">="+n+"."+i+".0":">="+t)+" "+(a=ue(u)?"":ue(c)?"<"+(+u+1)+".0.0":ue(l)?"<"+u+"."+(+c+1)+".0":d?"<="+u+"."+c+"."+l+"-"+d:"<="+a)).trim()}function le(e,t,n){for(var r=0;r0){var o=e[r].semver;if(o.major===t.major&&o.minor===t.minor&&o.patch===t.patch)return!0}return!1}return!0}function de(e,t,n){try{t=new ae(t,n)}catch(e){return!1}return t.test(e)}function he(e,t,n,i){var r,o,s,a,u;switch(e=new Z(e,i),t=new ae(t,i),n){case">":r=J,o=ie,s=Q,a=">",u=">=";break;case"<":r=Q,o=ne,s=J,a="<",u="<=";break;default:throw new TypeError('Must provide a hilo val of "<" or ">"')}if(de(e,t,i))return!1;for(var c=0;c=0.0.0")),l=l||e,d=d||e,r(e.semver,l.semver,i)?l=e:s(e.semver,d.semver,i)&&(d=e)}),l.operator===a||l.operator===u)return!1;if((!d.operator||d.operator===a)&&o(e,d.semver))return!1;if(d.operator===u&&s(e,d.semver))return!1}return!0}oe.prototype.parse=function(e){var t=this.options.loose?s[B]:s[V],n=e.match(t);if(!n)throw new TypeError("Invalid comparator: "+e);this.operator=n[1],"="===this.operator&&(this.operator=""),n[2]?this.semver=new Z(n[2],this.options.loose):this.semver=se},oe.prototype.toString=function(){return this.value},oe.prototype.test=function(e){return i("Comparator.test",e,this.options.loose),this.semver===se||("string"==typeof e&&(e=new Z(e,this.options)),re(e,this.operator,this.semver,this.options))},oe.prototype.intersects=function(e,t){if(!(e instanceof oe))throw new TypeError("a Comparator is required");var n;if(t&&"object"==typeof t||(t={loose:!!t,includePrerelease:!1}),""===this.operator)return n=new ae(e.value,t),de(this.value,n,t);if(""===e.operator)return n=new ae(this.value,t),de(e.semver,n,t);var i=!(">="!==this.operator&&">"!==this.operator||">="!==e.operator&&">"!==e.operator),r=!("<="!==this.operator&&"<"!==this.operator||"<="!==e.operator&&"<"!==e.operator),o=this.semver.version===e.semver.version,s=!(">="!==this.operator&&"<="!==this.operator||">="!==e.operator&&"<="!==e.operator),a=re(this.semver,"<",e.semver,t)&&(">="===this.operator||">"===this.operator)&&("<="===e.operator||"<"===e.operator),u=re(this.semver,">",e.semver,t)&&("<="===this.operator||"<"===this.operator)&&(">="===e.operator||">"===e.operator);return i||r||o&&s||a||u},t.Range=ae,ae.prototype.format=function(){return this.range=this.set.map(function(e){return e.join(" ").trim()}).join("||").trim(),this.range},ae.prototype.toString=function(){return this.range},ae.prototype.parseRange=function(e){var t=this.options.loose;e=e.trim();var n=t?s[U]:s[z];e=e.replace(n,ce),i("hyphen replace",e),e=e.replace(s[H],"$1$2$3"),i("comparator trim",e,s[H]),e=(e=(e=e.replace(s[T],"$1~")).replace(s[F],"$1^")).split(/\s+/).join(" ");var r=t?s[B]:s[V],o=e.split(" ").map(function(e){return function(e,t){return i("comp",e,t),e=function(e,t){return e.trim().split(/\s+/).map(function(e){return function(e,t){i("caret",e,t);var n=t.loose?s[W]:s[j];return e.replace(n,function(t,n,r,o,s){var a;return i("caret",e,t,n,r,o,s),ue(n)?a="":ue(r)?a=">="+n+".0.0 <"+(+n+1)+".0.0":ue(o)?a="0"===n?">="+n+"."+r+".0 <"+n+"."+(+r+1)+".0":">="+n+"."+r+".0 <"+(+n+1)+".0.0":s?(i("replaceCaret pr",s),a="0"===n?"0"===r?">="+n+"."+r+"."+o+"-"+s+" <"+n+"."+r+"."+(+o+1):">="+n+"."+r+"."+o+"-"+s+" <"+n+"."+(+r+1)+".0":">="+n+"."+r+"."+o+"-"+s+" <"+(+n+1)+".0.0"):(i("no pr"),a="0"===n?"0"===r?">="+n+"."+r+"."+o+" <"+n+"."+r+"."+(+o+1):">="+n+"."+r+"."+o+" <"+n+"."+(+r+1)+".0":">="+n+"."+r+"."+o+" <"+(+n+1)+".0.0"),i("caret return",a),a})}(e,t)}).join(" ")}(e,t),i("caret",e),e=function(e,t){return e.trim().split(/\s+/).map(function(e){return function(e,t){var n=t.loose?s[A]:s[P];return e.replace(n,function(t,n,r,o,s){var a;return i("tilde",e,t,n,r,o,s),ue(n)?a="":ue(r)?a=">="+n+".0.0 <"+(+n+1)+".0.0":ue(o)?a=">="+n+"."+r+".0 <"+n+"."+(+r+1)+".0":s?(i("replaceTilde pr",s),a=">="+n+"."+r+"."+o+"-"+s+" <"+n+"."+(+r+1)+".0"):a=">="+n+"."+r+"."+o+" <"+n+"."+(+r+1)+".0",i("tilde return",a),a})}(e,t)}).join(" ")}(e,t),i("tildes",e),e=function(e,t){return i("replaceXRanges",e,t),e.split(/\s+/).map(function(e){return function(e,t){e=e.trim();var n=t.loose?s[I]:s[E];return e.replace(n,function(t,n,r,o,s,a){i("xRange",e,t,n,r,o,s,a);var u=ue(r),c=u||ue(o),l=c||ue(s),d=l;return"="===n&&d&&(n=""),u?t=">"===n||"<"===n?"<0.0.0":"*":n&&d?(c&&(o=0),s=0,">"===n?(n=">=",c?(r=+r+1,o=0,s=0):(o=+o+1,s=0)):"<="===n&&(n="<",c?r=+r+1:o=+o+1),t=n+r+"."+o+"."+s):c?t=">="+r+".0.0 <"+(+r+1)+".0.0":l&&(t=">="+r+"."+o+".0 <"+r+"."+(+o+1)+".0"),i("xRange return",t),t})}(e,t)}).join(" ")}(e,t),i("xrange",e),e=function(e,t){return i("replaceStars",e,t),e.trim().replace(s[K],"")}(e,t),i("stars",e),e}(e,this.options)},this).join(" ").split(/\s+/);return this.options.loose&&(o=o.filter(function(e){return!!e.match(r)})),o=o.map(function(e){return new oe(e,this.options)},this)},ae.prototype.intersects=function(e,t){if(!(e instanceof ae))throw new TypeError("a Range is required");return this.set.some(function(n){return n.every(function(n){return e.set.some(function(e){return e.every(function(e){return n.intersects(e,t)})})})})},t.toComparators=function(e,t){return new ae(e,t).set.map(function(e){return e.map(function(e){return e.value}).join(" ").trim().split(" ")})},ae.prototype.test=function(e){if(!e)return!1;"string"==typeof e&&(e=new Z(e,this.options));for(var t=0;t":0===t.prerelease.length?t.patch++:t.prerelease.push(0),t.raw=t.format();case"":case">=":n&&!J(n,t)||(n=t);break;case"<":case"<=":break;default:throw new Error("Unexpected operation: "+e.operator)}})}if(n&&e.test(n))return n;return null},t.validRange=function(e,t){try{return new ae(e,t).range||"*"}catch(e){return null}},t.ltr=function(e,t,n){return he(e,t,"<",n)},t.gtr=function(e,t,n){return he(e,t,">",n)},t.outside=he,t.prerelease=function(e,t){var n=G(e,t);return n&&n.prerelease.length?n.prerelease:null},t.intersects=function(e,t,n){return e=new ae(e,n),t=new ae(t,n),e.intersects(t)},t.coerce=function(e){if(e instanceof Z)return e;if("string"!=typeof e)return null;var t=e.match(s[D]);if(null==t)return null;return G(t[1]+"."+(t[2]||"0")+"."+(t[3]||"0"))}}).call(t,n("W2nU"))},"6TMp":function(e,t,n){"use strict";n.d(t,"a",function(){return r});var i=n("JVO/"),r=Object(i.c)("modeService")},"6ZSt":function(e,t){e.exports={"aes-128-ecb":{cipher:"AES",key:128,iv:0,mode:"ECB",type:"block"},"aes-192-ecb":{cipher:"AES",key:192,iv:0,mode:"ECB",type:"block"},"aes-256-ecb":{cipher:"AES",key:256,iv:0,mode:"ECB",type:"block"},"aes-128-cbc":{cipher:"AES",key:128,iv:16,mode:"CBC",type:"block"},"aes-192-cbc":{cipher:"AES",key:192,iv:16,mode:"CBC",type:"block"},"aes-256-cbc":{cipher:"AES",key:256,iv:16,mode:"CBC",type:"block"},aes128:{cipher:"AES",key:128,iv:16,mode:"CBC",type:"block"},aes192:{cipher:"AES",key:192,iv:16,mode:"CBC",type:"block"},aes256:{cipher:"AES",key:256,iv:16,mode:"CBC",type:"block"},"aes-128-cfb":{cipher:"AES",key:128,iv:16,mode:"CFB",type:"stream"},"aes-192-cfb":{cipher:"AES",key:192,iv:16,mode:"CFB",type:"stream"},"aes-256-cfb":{cipher:"AES",key:256,iv:16,mode:"CFB",type:"stream"},"aes-128-cfb8":{cipher:"AES",key:128,iv:16,mode:"CFB8",type:"stream"},"aes-192-cfb8":{cipher:"AES",key:192,iv:16,mode:"CFB8",type:"stream"},"aes-256-cfb8":{cipher:"AES",key:256,iv:16,mode:"CFB8",type:"stream"},"aes-128-cfb1":{cipher:"AES",key:128,iv:16,mode:"CFB1",type:"stream"},"aes-192-cfb1":{cipher:"AES",key:192,iv:16,mode:"CFB1",type:"stream"},"aes-256-cfb1":{cipher:"AES",key:256,iv:16,mode:"CFB1",type:"stream"},"aes-128-ofb":{cipher:"AES",key:128,iv:16,mode:"OFB",type:"stream"},"aes-192-ofb":{cipher:"AES",key:192,iv:16,mode:"OFB",type:"stream"},"aes-256-ofb":{cipher:"AES",key:256,iv:16,mode:"OFB",type:"stream"},"aes-128-ctr":{cipher:"AES",key:128,iv:16,mode:"CTR",type:"stream"},"aes-192-ctr":{cipher:"AES",key:192,iv:16,mode:"CTR",type:"stream"},"aes-256-ctr":{cipher:"AES",key:256,iv:16,mode:"CTR",type:"stream"},"aes-128-gcm":{cipher:"AES",key:128,iv:12,mode:"GCM",type:"auth"},"aes-192-gcm":{cipher:"AES",key:192,iv:12,mode:"GCM",type:"auth"},"aes-256-gcm":{cipher:"AES",key:256,iv:12,mode:"GCM",type:"auth"}}},"6boo":function(e,t,n){"use strict";n.d(t,"b",function(){return p}),n.d(t,"f",function(){return g}),n.d(t,"c",function(){return m}),n.d(t,"d",function(){return b}),n.d(t,"e",function(){return y}),n.d(t,"a",function(){return w}),t.g=function(e){return"'"===e||'"'===e||"`"===e};var i=n("zxiH"),r=n("aL7J"),o=n("artP"),s=n("vTy2"),a=n("iHM7"),u=n("0ly5"),c=n("Fllr"),l=function(){return!0},d=function(){return!1},h=function(e){return" "===e||"\t"===e};function f(e,t,n){e.has(t)?e.get(t).push(n):e.set(t,[n])}var p=function(){function e(t,n,i){this._languageIdentifier=t;var r=i.editor;this.readOnly=r.readOnly,this.tabSize=n.tabSize,this.indentSize=n.indentSize,this.insertSpaces=n.insertSpaces,this.pageSize=Math.max(1,Math.floor(r.layoutInfo.height/r.fontInfo.lineHeight)-2),this.lineHeight=r.lineHeight,this.useTabStops=r.useTabStops,this.wordSeparators=r.wordSeparators,this.emptySelectionClipboard=r.emptySelectionClipboard,this.copyWithSyntaxHighlighting=r.copyWithSyntaxHighlighting,this.multiCursorMergeOverlapping=r.multiCursorMergeOverlapping,this.autoClosingBrackets=r.autoClosingBrackets,this.autoClosingQuotes=r.autoClosingQuotes,this.autoClosingOvertype=r.autoClosingOvertype,this.autoSurround=r.autoSurround,this.autoIndent=r.autoIndent,this.autoClosingPairsOpen2=new Map,this.autoClosingPairsClose2=new Map,this.surroundingPairs={},this._electricChars=null,this.shouldAutoCloseBefore={quote:e._getShouldAutoClose(t,this.autoClosingQuotes),bracket:e._getShouldAutoClose(t,this.autoClosingBrackets)};var o=e._getAutoClosingPairs(t);if(o)for(var s=0,a=o;s=i.length)&&r.x(i.charCodeAt(n))},e.isHighSurrogate=function(e,t,n){var i=e.getLineContent(t);return!(n<0||n>=i.length)&&r.w(i.charCodeAt(n))},e.isInsideSurrogatePair=function(e,t,n){return this.isHighSurrogate(e,t,n-2)},e.visibleColumnFromColumn=function(e,t,n){var i=e.length;i>t-1&&(i=t-1);for(var o=0,s=0;s=t)return u-ts?s:r},e.nextRenderTabStop=function(e,t){return e+t-e%t},e.nextIndentTabStop=function(e,t){return e+t-e%t},e.prevRenderTabStop=function(e,t){return e-1-(e-1)%t},e.prevIndentTabStop=function(e,t){return e-1-(e-1)%t},e}()},"6hW9":function(e,t,n){var i=n("BEbT"),r=n("X3l8").Buffer,o=n("z+8S");function s(e,t,n,s){o.call(this),this._cipher=new i.AES(t),this._prev=r.from(n),this._cache=r.allocUnsafe(0),this._secCache=r.allocUnsafe(0),this._decrypt=s,this._mode=e}n("LC74")(s,o),s.prototype._update=function(e){return this._mode.encrypt(this,e,this._decrypt)},s.prototype._final=function(){this._cipher.scrub()},e.exports=s},"6jTg":function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=n("odeJ"),r=n("zxiH"),o=n("tqet"),s=n("4tuZ"),a=n("03Zz"),u=n("PCC9"),c=n("X6iQ"),l=n("80kS"),d=n("mrx5"),h=n("jIdl"),f=function(){function e(){this.lenses=[],this._dispoables=new o.b}return e.prototype.dispose=function(){this._dispoables.dispose()},e.prototype.add=function(e,t){this._dispoables.add(e);for(var n=0,i=e.lenses;nt.symbol.range.startLineNumber?1:i.get(e.provider)i.get(t.provider)?1:e.symbol.range.startColumnt.symbol.range.startColumn?1:0}),o})}Object(a.j)("_executeCodeLensProvider",function(e,t){var n=t.resource,i=t.itemResolveCount;if(!(n instanceof d.a))throw Object(r.b)();var s=e.get(h.a).getModel(n);if(!s)throw Object(r.b)();var a=[],u=new o.b;return p(s,l.a.None).then(function(e){u.add(e);for(var t=[],n=function(e){void 0===i||Boolean(e.symbol.command)?a.push(e.symbol):i-- >0&&e.provider.resolveCodeLens&&t.push(Promise.resolve(e.provider.resolveCodeLens(s,e.symbol,l.a.None)).then(function(t){return a.push(t||e.symbol)}))},r=0,o=e.lenses;rno commands";else{for(var i=[],r=0;r"+s+"",this._commands.set(String(r),o)):a=""+s+"",i.push(a)}}var u=""===this._domNode.innerHTML||" "===this._domNode.innerHTML;this._domNode.innerHTML=i.join(" | "),this._editor.layoutContentWidget(this),u&&t&&g.f(this._domNode,"fadein")}},e.prototype.getCommand=function(e){return e.parentElement===this._domNode?this._commands.get(e.id):void 0},e.prototype.getId=function(){return this._id},e.prototype.getDomNode=function(){return this._domNode},e.prototype.setSymbolRange=function(e){if(this._editor.hasModel()){var t=e.startLineNumber,n=this._editor.getModel().getLineFirstNonWhitespaceColumn(t);this._widgetPosition={position:{lineNumber:t,column:n},preference:[1]}}},e.prototype.getPosition=function(){return this._widgetPosition||null},e.prototype.isVisible=function(){return this._domNode.hasAttribute("monaco-visible-content-widget")},e._idPool=0,e}(),x=function(){function e(){this._removeDecorations=[],this._addDecorations=[],this._addDecorationsCallbacks=[]}return e.prototype.addDecoration=function(e,t){this._addDecorations.push(e),this._addDecorationsCallbacks.push(t)},e.prototype.removeDecoration=function(e){this._removeDecorations.push(e)},e.prototype.commit=function(e){for(var t=e.deltaDecorations(this._removeDecorations,this._addDecorations),n=0,i=t.length;n a:hover { color: "+i+" !important; }")});var O=n("ItKl"),k=n("fAkY"),N=n("JVO/"),E=n("8xpx"),I=n("WTFd"),D=n("Cfmk"),M=n("dwjm"),T=this&&this.__decorate||function(e,t,n,i){var r,o=arguments.length,s=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,n):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,i);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(s=(o<3?r(s):o>3?r(t,n,s):r(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},P=this&&this.__param||function(e,t){return function(n,i){t(n,i,e)}},A=Object(N.c)("ICodeLensCache"),R=function(){return function(e,t){this.lineCount=e,this.data=t}}(),F=function(){function e(e){var t=this;this._fakeProvider=new(function(){function e(){}return e.prototype.provideCodeLenses=function(){throw new Error("not supported")},e}()),this._cache=new I.a(20,.75);Object(i.k)(function(){return e.remove("codelens/cache",1)});var n="codelens/cache2",r=e.get(n,1,"{}");this._deserialize(r),Object(M.a)(e.onWillSaveState)(function(i){i.reason===D.c.SHUTDOWN&&e.store(n,t._serialize(),1)})}return e.prototype.put=function(e,t){var n=new f;n.add({lenses:t.lenses.map(function(e){return e.symbol}),dispose:function(){}},this._fakeProvider);var i=new R(e.getLineCount(),n);this._cache.set(e.uri.toString(),i)},e.prototype.get=function(e){var t=this._cache.get(e.uri.toString());return t&&t.lineCount===e.getLineCount()?t.data:void 0},e.prototype.delete=function(e){this._cache.delete(e.uri.toString())},e.prototype._serialize=function(){var e=Object.create(null);return this._cache.forEach(function(t,n){for(var i=new Set,r=0,o=t.data.lenses;r=0;a--)(r=e[a])&&(s=(o<3?r(s):o>3?r(t,n,s):r(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},W=this&&this.__param||function(e,t){return function(n,i){t(n,i,e)}},B=function(){function e(e,t,n,i){var r=this;this._editor=e,this._commandService=t,this._notificationService=n,this._codeLensCache=i,this._globalToDispose=new o.b,this._localToDispose=new o.b,this._lenses=[],this._oldCodeLensModels=new o.b,this._modelChangeCounter=0,this._isEnabled=this._editor.getConfiguration().contribInfo.codeLens,this._globalToDispose.add(this._editor.onDidChangeModel(function(){return r._onModelChange()})),this._globalToDispose.add(this._editor.onDidChangeModelLanguage(function(){return r._onModelChange()})),this._globalToDispose.add(this._editor.onDidChangeConfiguration(function(){var e=r._isEnabled;r._isEnabled=r._editor.getConfiguration().contribInfo.codeLens,e!==r._isEnabled&&r._onModelChange()})),this._globalToDispose.add(u.b.onDidChange(this._onModelChange,this)),this._onModelChange()}return e.prototype.dispose=function(){this._localDispose(),this._globalToDispose.dispose(),this._oldCodeLensModels.dispose(),Object(o.f)(this._currentCodeLensModel)},e.prototype._localDispose=function(){this._currentFindCodeLensSymbolsPromise&&(this._currentFindCodeLensSymbolsPromise.cancel(),this._currentFindCodeLensSymbolsPromise=void 0,this._modelChangeCounter++),this._currentResolveCodeLensSymbolsPromise&&(this._currentResolveCodeLensSymbolsPromise.cancel(),this._currentResolveCodeLensSymbolsPromise=void 0),this._localToDispose.clear(),this._oldCodeLensModels.clear(),Object(o.f)(this._currentCodeLensModel)},e.prototype.getId=function(){return e.ID},e.prototype._onModelChange=function(){var e=this;this._localDispose();var t=this._editor.getModel();if(t&&this._isEnabled){var n=this._codeLensCache.get(t);if(n&&this._renderCodeLensSymbols(n),u.b.has(t)){for(var a=0,c=u.b.all(t);a0&&h.schedule()})),this._localToDispose.add(this._editor.onDidLayoutChange(function(){h.schedule()})),this._localToDispose.add(Object(o.h)(function(){if(e._editor.getModel()){var t=s.c.capture(e._editor);e._editor.changeDecorations(function(t){e._editor.changeViewZones(function(n){e._disposeAllLenses(t,n)})}),t.restore(e._editor)}else e._disposeAllLenses(void 0,void 0)})),this._localToDispose.add(this._editor.onDidChangeConfiguration(function(t){if(t.fontInfo)for(var n=0,i=e._lenses;ni||(n&&n[n.length-1].symbol.range.startLineNumber===c?n.push(u):(n=[u],r.push(n)))}var l=s.c.capture(this._editor);this._editor.changeDecorations(function(e){t._editor.changeViewZones(function(n){for(var i=new x,o=0,s=0;s=0;r--)t.sheet.deleteRule(i[r])},t.F=function(e){if("object"==typeof HTMLElement)return e instanceof HTMLElement;return e&&"object"==typeof e&&1===e.nodeType&&"string"==typeof e.nodeName},n.d(t,"d",function(){return Y}),n.d(t,"c",function(){return X}),t.O=function(e){for(var t=[],n=0;e&&e.nodeType===e.ELEMENT_NODE;n++)t[n]=e.scrollTop,e=e.parentNode;return t},t.M=function(e,t){for(var n=0;e&&e.nodeType===e.ELEMENT_NODE;n++)e.scrollTop!==t[n]&&(e.scrollTop=t[n]),e=e.parentNode},t.S=function(e){return new $(e)},t.m=function(e){for(var t=[],n=1;n=0;){if(o=s+r,(0===s||32===n.charCodeAt(s-1))&&32===n.charCodeAt(o))return this._lastStart=s,void(this._lastEnd=o+1);if(s>0&&32===n.charCodeAt(s-1)&&o===i)return this._lastStart=s-1,void(this._lastEnd=o);if(0===s&&o===i)return this._lastStart=0,void(this._lastEnd=o)}this._lastStart=-1}else this._lastStart=-1}else this._lastStart=-1},e.prototype.hasClass=function(e,t){return this._findClassName(e,t),-1!==this._lastStart},e.prototype.addClasses=function(e){for(var t=this,n=[],i=1;i0;){T.sort(F.sort),T.shift().execute()}A=!1},I=function(e,t){void 0===t&&(t=0);var n,i=new F(e,t);return M.push(i),P||(P=!0,n=R,D||(D=self.requestAnimationFrame||self.msRequestAnimationFrame||self.webkitRequestAnimationFrame||self.mozRequestAnimationFrame||self.oRequestAnimationFrame||function(e){return setTimeout(function(){return e((new Date).getTime())},0)}),D.call(self,n)),i},E=function(e,t){if(A){var n=new F(e,t);return T.push(n),n}return I(e,t)};var j=16,W=function(e,t){return t},B=function(e){function t(t,n,i,r,o){void 0===r&&(r=W),void 0===o&&(o=j);var s=e.call(this)||this,a=null,c=0,l=s._register(new u.e),d=function(){c=(new Date).getTime(),i(a),a=null};return s._register(k(t,n,function(e){a=r(a,e);var t=(new Date).getTime()-c;t>=o?(l.cancel(),d()):l.setIfNotSet(d,o-t)})),s}return g(t,e),t}(d.a);function V(e){return document.defaultView.getComputedStyle(e,null)}var H=function(){function e(){}return e.convertToPixels=function(e,t){return parseFloat(t)||0},e.getDimension=function(t,n,i){var r=V(t),o="0";return r&&(o=r.getPropertyValue?r.getPropertyValue(n):r.getAttribute(i)),e.convertToPixels(t,o)},e.getBorderLeftWidth=function(t){return e.getDimension(t,"border-left-width","borderLeftWidth")},e.getBorderRightWidth=function(t){return e.getDimension(t,"border-right-width","borderRightWidth")},e.getBorderTopWidth=function(t){return e.getDimension(t,"border-top-width","borderTopWidth")},e.getBorderBottomWidth=function(t){return e.getDimension(t,"border-bottom-width","borderBottomWidth")},e.getPaddingLeft=function(t){return e.getDimension(t,"padding-left","paddingLeft")},e.getPaddingRight=function(t){return e.getDimension(t,"padding-right","paddingRight")},e.getPaddingTop=function(t){return e.getDimension(t,"padding-top","paddingTop")},e.getPaddingBottom=function(t){return e.getDimension(t,"padding-bottom","paddingBottom")},e.getMarginLeft=function(t){return e.getDimension(t,"margin-left","marginLeft")},e.getMarginTop=function(t){return e.getDimension(t,"margin-top","marginTop")},e.getMarginRight=function(t){return e.getDimension(t,"margin-right","marginRight")},e.getMarginBottom=function(t){return e.getDimension(t,"margin-bottom","marginBottom")},e}(),z=function(){return function(e,t){this.width=e,this.height=t}}();var U=new(function(){function e(){}return Object.defineProperty(e.prototype,"scrollX",{get:function(){return"number"==typeof window.scrollX?window.scrollX:document.body.scrollLeft+document.documentElement.scrollLeft},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"scrollY",{get:function(){return"number"==typeof window.scrollY?window.scrollY:document.body.scrollTop+document.documentElement.scrollTop},enumerable:!0,configurable:!0}),e}());function K(e,t){for(;e;){if(e===t)return!0;e=e.parentNode}return!1}function q(e){void 0===e&&(e=document.getElementsByTagName("head")[0]);var t=document.createElement("style");return t.type="text/css",t.media="screen",e.appendChild(t),t}var G=null;function Z(){return G||(G=q()),G}var Y={CLICK:"click",DBLCLICK:"dblclick",MOUSE_UP:"mouseup",MOUSE_DOWN:"mousedown",MOUSE_OVER:"mouseover",MOUSE_MOVE:"mousemove",MOUSE_OUT:"mouseout",MOUSE_ENTER:"mouseenter",MOUSE_LEAVE:"mouseleave",CONTEXT_MENU:"contextmenu",WHEEL:"wheel",KEY_DOWN:"keydown",KEY_PRESS:"keypress",KEY_UP:"keyup",LOAD:"load",BEFORE_UNLOAD:"beforeunload",UNLOAD:"unload",ABORT:"abort",ERROR:"error",RESIZE:"resize",SCROLL:"scroll",FULLSCREEN_CHANGE:"fullscreenchange",WK_FULLSCREEN_CHANGE:"webkitfullscreenchange",SELECT:"select",CHANGE:"change",SUBMIT:"submit",RESET:"reset",FOCUS:"focus",FOCUS_IN:"focusin",FOCUS_OUT:"focusout",BLUR:"blur",INPUT:"input",STORAGE:"storage",DRAG_START:"dragstart",DRAG:"drag",DRAG_ENTER:"dragenter",DRAG_LEAVE:"dragleave",DRAG_OVER:"dragover",DROP:"drop",DRAG_END:"dragend",ANIMATION_START:r.m?"webkitAnimationStart":"animationstart",ANIMATION_END:r.m?"webkitAnimationEnd":"animationend",ANIMATION_ITERATION:r.m?"webkitAnimationIteration":"animationiteration"},X={stop:function(e,t){e.preventDefault?e.preventDefault():e.returnValue=!1,t&&(e.stopPropagation?e.stopPropagation():e.cancelBubble=!0)}};var $=function(e){function t(t){var n=e.call(this)||this;n._onDidFocus=n._register(new l.a),n.onDidFocus=n._onDidFocus.event,n._onDidBlur=n._register(new l.a),n.onDidBlur=n._onDidBlur.event;var i=K(document.activeElement,t),r=!1;return n._register(Object(o.a)(t,Y.FOCUS,!0)(function(){r=!1,i||(i=!0,n._onDidFocus.fire())})),n._register(Object(o.a)(t,Y.BLUR,!0)(function(){i&&(r=!0,window.setTimeout(function(){r&&(r=!1,i=!1,n._onDidBlur.fire())},0))})),n}return g(t,e),t}(d.a);var J,Q=/([\w\-]+)?(#([\w\-]+))?((.([\w\-]+))*)/;function ee(e,t,n){for(var i=[],r=3;r=0;a--)(r=e[a])&&(s=(o<3?r(s):o>3?r(t,n,s):r(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},S=this&&this.__param||function(e,t){return function(n,i){t(n,i,e)}},x=function(){function e(){}return e.prototype.select=function(e,t,n){if(0===n.length)return 0;for(var i=n[0].score[0],r=1;ru&&d.type===i[c].completion.kind&&d.insertText===i[c].completion.insertText&&(u=d.touch,a=c),i[c].completion.preselect&&-1===s)return c}return-1!==a?a:-1!==s?s:0},t.prototype.toJSON=function(){var e=[];return this._cache.forEach(function(t,n){e.push([n,t])}),e},t.prototype.fromJSON=function(e){this._cache.clear();for(var t=0,n=e;t0){this._seq=e[0][1].touch+1;for(var t=0,n=e;t=0;a--)(r=e[a])&&(s=(o<3?r(s):o>3?r(t,n,s):r(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},R=this&&this.__param||function(e,t){return function(n,i){t(n,i,e)}},F=function(){function e(t,n){this._editor=t,this._index=0,this._ckOtherSuggestions=e.OtherSuggestions.bindTo(n)}return e.prototype.dispose=function(){this.reset()},e.prototype.reset=function(){this._ckOtherSuggestions.reset(),Object(a.f)(this._listener),this._model=void 0,this._acceptNext=void 0,this._ignore=!1},e.prototype.set=function(t,n){var i=this,r=t.model,o=t.index;0!==r.items.length?e._moveIndex(!0,r,o)!==o?(this._acceptNext=n,this._model=r,this._index=o,this._listener=this._editor.onDidChangeCursorPosition(function(){i._ignore||i.reset()}),this._ckOtherSuggestions.set(!0)):this.reset():this.reset()},e._moveIndex=function(e,t,n){for(var i=n;(i=(i+t.items.length+(e?1:-1))%t.items.length)!==n&&t.items[i].completion.additionalTextEdits;);return i},e.prototype.next=function(){this._move(!0)},e.prototype.prev=function(){this._move(!1)},e.prototype._move=function(t){if(this._model)try{this._ignore=!0,this._index=e._moveIndex(t,this._model,this._index),this._acceptNext({index:this._index,item:this._model.items[this._index],model:this._model})}finally{this._ignore=!1}},e.OtherSuggestions=new T.d("hasOtherSuggestions",!1),e=A([R(1,T.c)],e)}(),j=n("Kp7x"),W=n("iHM7"),B=n("GYOr"),V=n("iXRW"),H=n("aL7J"),z=(function(){}(),function(){function e(t,n,i,r,o){void 0===o&&(o=V.a.contribInfo.suggest),this._snippetCompareFn=e._compareCompletionItems,this._items=t,this._column=n,this._wordDistance=r,this._options=o,this._refilterKind=1,this._lineContext=i,"top"===o.snippets?this._snippetCompareFn=e._compareCompletionItemsSnippetsUp:"bottom"===o.snippets&&(this._snippetCompareFn=e._compareCompletionItemsSnippetsDown)}return Object.defineProperty(e.prototype,"lineContext",{get:function(){return this._lineContext},set:function(e){this._lineContext.leadingLineContent===e.leadingLineContent&&this._lineContext.characterCountDelta===e.characterCountDelta||(this._refilterKind=this._lineContext.characterCountDelta2e3?B.d:B.e,u=0;u=d)c.score=B.a.Default;else if("string"==typeof c.completion.filterText){if(!(p=a(i,r,h,c.completion.filterText,c.filterTextLow,0,!1)))continue;0===Object(H.e)(c.completion.filterText,c.completion.label)?c.score=p:(c.score=Object(B.b)(i,r,h,c.completion.label,c.labelLow,0),c.score[0]=p[0])}else{var p;if(!(p=a(i,r,h,c.completion.label,c.labelLow,0,!1)))continue;c.score=p}}switch(c.idx=u,c.distance=this._wordDistance.distance(c.position,c.completion),s.push(c),this._stats.suggestionCount++,c.completion.kind){case 25:this._stats.snippetCount++;break;case 18:this._stats.textCount++}}this._filteredItems=s.sort(this._snippetCompareFn),this._refilterKind=0},e._compareCompletionItems=function(e,t){return e.score[0]>t.score[0]?-1:e.score[0]t.distance?1:e.idxt.idx?1:0},e._compareCompletionItemsSnippetsDown=function(t,n){if(t.completion.kind!==n.completion.kind){if(25===t.completion.kind)return 1;if(25===n.completion.kind)return-1}return e._compareCompletionItems(t,n)},e._compareCompletionItemsSnippetsUp=function(t,n){if(t.completion.kind!==n.completion.kind){if(25===t.completion.kind)return-1;if(25===n.completion.kind)return 1}return e._compareCompletionItems(t,n)},e}()),U=n("80kS"),K=n("NjuD"),q=this&&this.__extends||function(){var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(t,n)};return function(t,n){function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}}(),G=function(){function e(){}return e.create=function(t,n){if(!n.getConfiguration().contribInfo.suggest.localityBonus)return Promise.resolve(e.None);if(!n.hasModel())return Promise.resolve(e.None);var i=n.getModel(),r=n.getPosition();return t.canComputeWordRanges(i.uri)?(new K.a).provideSelectionRanges(i,[r]).then(function(s){return s&&0!==s.length&&0!==s[0].length?t.computeWordRanges(i.uri,s[0][0].range).then(function(t){return new(function(e){function i(){return null!==e&&e.apply(this,arguments)||this}return q(i,e),i.prototype.distance=function(e,i){if(!t||!r.equals(n.getPosition()))return 0;if(17===i.kind)return 2<<20;var a=i.label,u=t[a];if(Object(o.m)(u))return 2<<20;for(var c=Object(o.c)(u,l.a.fromPositions(e),l.a.compareRangesUsingStarts),d=c>=0?u[c]:u[Math.max(0,~c-1)],h=s.length,f=0,p=s[0];f0?{triggerKind:2}:{triggerKind:0},this._requestToken=new U.b;var h=this._editor.getConfiguration().contribInfo,f=new Set,p=1;switch(h.suggest.snippets){case"top":p=0;break;case"bottom":p=2;break;case"none":f.add(25)}for(var g in h.suggest.filteredTypes){var v=Object(m.A)(g,!0);void 0!==v&&!1===h.suggest.filteredTypes[g]&&f.add(v)}var _=G.create(this._editorWorker,this._editor),b=Object(P.e)(c,this._editor.getPosition(),new P.a(p,f,n),u,this._requestToken.token);Promise.all([b,_]).then(function(t){var n=t[0],s=t[1];if(Object(a.f)(r._requestToken),0!==r._state&&r._editor.hasModel()){var u=r._editor.getModel();if(Object(o.n)(i)){var c=Object(P.d)(p);n=n.concat(i).sort(c)}var d=new Z(u,r._editor.getPosition(),l,e.shy);r._completionModel=new z(n,r._context.column,{leadingLineContent:d.leadingLineContent,characterCountDelta:d.column-r._context.column},s,r._editor.getConfiguration().contribInfo.suggest);for(var h=0,f=n;hthis._context.column&&this._completionModel.incomplete.size>0&&0!==e.leadingWord.word.length){var t=this._completionModel.incomplete,n=this._completionModel.adopt(t);this.trigger({auto:2===this._state,shy:!1},!0,t,n)}else{var i=this._completionModel.lineContext,r=!1;if(this._completionModel.lineContext={leadingLineContent:e.leadingLineContent,characterCountDelta:e.column-this._context.column},0===this._completionModel.items.length){if(Z.shouldAutoTrigger(this._editor)&&this._context.leadingWord.endColumn0)&&0===e.leadingWord.word.length)return void this.cancel()}this._onDidSuggest.fire({completionModel:this._completionModel,auto:this._context.auto,shy:this._context.shy,isFrozen:r})}}else this.cancel()},e}(),X=(n("YUwp"),n("7/Cv")),$=n("SWdJ"),J=n("qecS"),Q=n("NqM+"),ee=n("3ciN"),te=n("Yqb6"),ne=n("eoic"),ie=n("L5KM"),re=n("VBCr"),oe=n("6TMp"),se=n("GsV8"),ae=n("tpa8"),ue=n("lapT"),ce=n("ZYUE"),le=n("9XyG");function de(e,t,n,i){var r=i===I.ROOT_FOLDER?["rootfolder-icon"]:i===I.FOLDER?["folder-icon"]:["file-icon"];if(n){var o;if(n.scheme===ue.b.data)o=ce.a.parseMetaData(n).get(ce.a.META_DATA_LABEL);else o=he(Object(ce.c)(n).toLowerCase());if(i===I.FOLDER)r.push(o+"-name-folder-icon");else{if(o){r.push(o+"-name-file-icon");for(var s=o.split("."),a=1;a=0;a--)(r=e[a])&&(s=(o<3?r(s):o>3?r(t,n,s):r(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},_e=this&&this.__param||function(e,t){return function(n,i){t(n,i,e)}},be=this&&this.__awaiter||function(e,t,n,i){return new(n||(n=Promise))(function(r,o){function s(e){try{u(i.next(e))}catch(e){o(e)}}function a(e){try{u(i.throw(e))}catch(e){o(e)}}function u(e){e.done?r(e.value):new n(function(t){t(e.value)}).then(s,a)}u((i=i.apply(e,t||[])).next())})},ye=this&&this.__generator||function(e,t){var n,i,r,o,s={label:0,sent:function(){if(1&r[0])throw r[1];return r[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,i&&(r=2&o[0]?i.return:o[0]?i.throw||((r=i.return)&&r.call(i),0):i.next)&&!(r=r.call(i,o[1])).done)return r;switch(i=0,r&&(o=[2&o[0],r.value]),o[0]){case 0:case 1:r=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,i=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(r=(r=s.trys).length>0&&r[r.length-1])&&(6===o[0]||2===o[0])){s=0;continue}if(3===o[0]&&(!r||o[1]>r[0]&&o[1]=0&&(c.extraClasses=(c.extraClasses||[]).concat(["deprecated"]),c.matches=[]),r.iconLabel.setLabel(s.label,void 0,c),r.typeLabel.textContent=(s.detail||"").replace(/\n.*$/m,""),ke(e)?(Object(X.Q)(r.readMore),r.readMore.onmousedown=function(e){e.stopPropagation(),e.preventDefault()},r.readMore.onclick=function(e){e.stopPropagation(),e.preventDefault(),i.widget.toggleDetails()}):(Object(X.D)(r.readMore),r.readMore.onmousedown=null,r.readMore.onclick=null)},e.prototype.disposeTemplate=function(e){e.disposables.dispose()},e=ve([_e(3,fe.a),_e(4,oe.a),_e(5,ne.c)],e)}(),Ee=function(){function e(e,t,n,i,r){var o=this;this.widget=t,this.editor=n,this.markdownRenderer=i,this.triggerKeybindingLabel=r,this.borderWidth=1,this.disposables=new a.b,this.el=Object(X.m)(e,Object(X.a)(".details")),this.disposables.add(Object(a.h)(function(){return e.removeChild(o.el)})),this.body=Object(X.a)(".body"),this.scrollbar=new J.a(this.body,{}),Object(X.m)(this.el,this.scrollbar.getDomNode()),this.disposables.add(this.scrollbar),this.header=Object(X.m)(this.body,Object(X.a)(".header")),this.close=Object(X.m)(this.header,Object(X.a)("span.close")),this.close.title=D.a("readLess","Read less...{0}",this.triggerKeybindingLabel),this.type=Object(X.m)(this.header,Object(X.a)("p.type")),this.docs=Object(X.m)(this.body,Object(X.a)("p.docs")),this.ariaLabel=null,this.configureFont(),j.b.chain(this.editor.onDidChangeConfiguration.bind(this.editor)).filter(function(e){return e.fontInfo}).on(this.configureFont,this,this.disposables),i.onDidRenderCodeBlock(function(){return o.scrollbar.scanDomNode()},this,this.disposables)}return Object.defineProperty(e.prototype,"element",{get:function(){return this.el},enumerable:!0,configurable:!0}),e.prototype.renderLoading=function(){this.type.textContent=D.a("loading","Loading..."),this.docs.textContent=""},e.prototype.renderItem=function(e,t){var n=this;this.renderDisposeable=Object(a.f)(this.renderDisposeable);var i=e.completion,r=i.documentation,o=i.detail;if(t){var s="";s+="score: "+e.score[0]+(e.word?", compared '"+(e.completion.filterText&&e.completion.filterText+" (filterText)"||e.completion.label)+"' with '"+e.word+"'":" (no prefix)")+"\n",s+="distance: "+e.distance+", see localityBonus-setting\n",s+="index: "+e.idx+", based on "+(e.completion.sortText&&'sortText: "'+e.completion.sortText+'"'||"label")+"\n",r=(new ge.a).appendCodeblock("empty",s),o="Provider: "+e.provider._debugDisplayName}if(!t&&!ke(e))return this.type.textContent="",this.docs.textContent="",Object(X.f)(this.el,"no-docs"),void(this.ariaLabel=null);if(Object(X.I)(this.el,"no-docs"),"string"==typeof r)Object(X.I)(this.docs,"markdown-docs"),this.docs.textContent=r;else{Object(X.f)(this.docs,"markdown-docs"),this.docs.innerHTML="";var u=this.markdownRenderer.render(r);this.renderDisposeable=u,this.docs.appendChild(u.element)}o?(this.type.innerText=o,Object(X.Q)(this.type)):(this.type.innerText="",Object(X.D)(this.type)),this.el.style.height=this.header.offsetHeight+this.docs.offsetHeight+2*this.borderWidth+"px",this.close.onmousedown=function(e){e.preventDefault(),e.stopPropagation()},this.close.onclick=function(e){e.preventDefault(),e.stopPropagation(),n.widget.toggleDetails()},this.body.scrollTop=0,this.scrollbar.scanDomNode(),this.ariaLabel=H.r("{0}{1}",o||"",r?"string"==typeof r?r:r.value:"")},e.prototype.getAriaLabel=function(){return this.ariaLabel},e.prototype.scrollDown=function(e){void 0===e&&(e=8),this.body.scrollTop+=e},e.prototype.scrollUp=function(e){void 0===e&&(e=8),this.body.scrollTop-=e},e.prototype.scrollTop=function(){this.body.scrollTop=0},e.prototype.scrollBottom=function(){this.body.scrollTop=this.body.scrollHeight},e.prototype.pageDown=function(){this.scrollDown(80)},e.prototype.pageUp=function(){this.scrollUp(80)},e.prototype.setBorderWidth=function(e){this.borderWidth=e},e.prototype.configureFont=function(){var e=this.editor.getConfiguration(),t=e.fontInfo.fontFamily,n=e.contribInfo.suggestFontSize||e.fontInfo.fontSize,i=e.contribInfo.suggestLineHeight||e.fontInfo.lineHeight,r=e.fontInfo.fontWeight,o=n+"px",s=i+"px";this.el.style.fontSize=o,this.el.style.fontWeight=r,this.type.style.fontFamily=t,this.close.style.height=s,this.close.style.width=s},e.prototype.dispose=function(){this.disposables.dispose(),this.renderDisposeable=Object(a.f)(this.renderDisposeable)},e}(),Ie=function(){function e(e,t,n,i,r,o,s,u,c){var l=this;this.editor=e,this.telemetryService=t,this.allowEditorOverflow=!0,this.suppressMouseDown=!0,this.state=null,this.isAuto=!1,this.loadingTimeout=a.a.None,this.currentSuggestionDetails=null,this.ignoreFocusEvents=!1,this.completionModel=null,this.showTimeout=new v.e,this.toDispose=new a.b,this.onDidSelectEmitter=new j.a,this.onDidFocusEmitter=new j.a,this.onDidHideEmitter=new j.a,this.onDidShowEmitter=new j.a,this.onDidSelect=this.onDidSelectEmitter.event,this.onDidFocus=this.onDidFocusEmitter.event,this.onDidHide=this.onDidHideEmitter.event,this.onDidShow=this.onDidShowEmitter.event,this.maxWidgetWidth=660,this.listWidth=330,this.firstFocusInCurrentList=!1,this.preferDocPositionTop=!1,this.docsPositionPreviousWidgetY=null,this.explainMode=!1,this._lastAriaAlertLabel=null;var d=o.lookupKeybinding("editor.action.triggerSuggest"),h=d?" ("+d.getLabel()+")":"",f=this.toDispose.add(new re.a(e,s,u));this.isAuto=!1,this.focusedItem=null,this.storageService=r,this.element=Object(X.a)(".editor-widget.suggest-widget"),this.toDispose.add(Object(X.h)(this.element,"click",function(e){e.target===l.element&&l.hideWidget()})),this.messageElement=Object(X.m)(this.element,Object(X.a)(".message")),this.listElement=Object(X.m)(this.element,Object(X.a)(".tree")),this.details=c.createInstance(Ee,this.element,this,this.editor,f,h);var p=function(){return Object(X.R)(l.element,"no-icons",!l.editor.getConfiguration().contribInfo.suggest.showIcons)};p();var g=c.createInstance(Ne,this,this.editor,h);this.list=new $.b(this.listElement,this,[g],{useShadows:!1,openController:{shouldOpen:function(){return!1}},mouseSupport:!1}),this.toDispose.add(Object(te.b)(this.list,i,{listInactiveFocusBackground:xe,listInactiveFocusOutline:ie.b})),this.toDispose.add(i.onThemeChange(function(e){return l.onThemeChange(e)})),this.toDispose.add(e.onDidLayoutChange(function(){return l.onEditorLayoutChange()})),this.toDispose.add(this.list.onMouseDown(function(e){return l.onListMouseDown(e)})),this.toDispose.add(this.list.onSelectionChange(function(e){return l.onListSelection(e)})),this.toDispose.add(this.list.onFocusChange(function(e){return l.onListFocus(e)})),this.toDispose.add(this.editor.onDidChangeCursorSelection(function(){return l.onCursorSelectionChanged()})),this.toDispose.add(this.editor.onDidChangeConfiguration(function(e){return e.contribInfo&&p()})),this.suggestWidgetVisible=P.b.Visible.bindTo(n),this.suggestWidgetMultipleSuggestions=P.b.MultipleSuggestions.bindTo(n),this.editor.addContentWidget(this),this.setState(0),this.onThemeChange(i.getTheme())}return e.prototype.onCursorSelectionChanged=function(){0!==this.state&&this.editor.layoutContentWidget(this)},e.prototype.onEditorLayoutChange=function(){3!==this.state&&5!==this.state||!this.expandDocsSettingFromStorage()||this.expandSideOrBelow()},e.prototype.onListMouseDown=function(e){void 0!==e.element&&void 0!==e.index&&(e.browserEvent.preventDefault(),e.browserEvent.stopPropagation(),this.select(e.element,e.index))},e.prototype.onListSelection=function(e){e.elements.length&&this.select(e.elements[0],e.indexes[0])},e.prototype.select=function(e,t){var n=this.completionModel;n&&(this.onDidSelectEmitter.fire({item:e,index:t,model:n}),this.editor.focus())},e.prototype._getSuggestionAriaAlertLabel=function(e){return this.expandDocsSettingFromStorage()?D.a("ariaCurrenttSuggestionReadDetails","Item {0}, docs: {1}",e.completion.label,this.details.getAriaLabel()):e.completion.label},e.prototype._ariaAlert=function(e){this._lastAriaAlertLabel!==e&&(this._lastAriaAlertLabel=e,this._lastAriaAlertLabel&&Object(r.a)(this._lastAriaAlertLabel,!0))},e.prototype.onThemeChange=function(e){var t=e.getColor(we);t&&(this.listElement.style.backgroundColor=t.toString(),this.details.element.style.backgroundColor=t.toString(),this.messageElement.style.backgroundColor=t.toString());var n=e.getColor(Ce);n&&(this.listElement.style.borderColor=n.toString(),this.details.element.style.borderColor=n.toString(),this.messageElement.style.borderColor=n.toString(),this.detailsBorderColor=n.toString());var i=e.getColor(ie.S);i&&(this.detailsFocusBorderColor=i.toString()),this.details.setBorderWidth("hc"===e.type?2:1)},e.prototype.onListFocus=function(e){var t=this;if(!this.ignoreFocusEvents){if(!e.elements.length)return this.currentSuggestionDetails&&(this.currentSuggestionDetails.cancel(),this.currentSuggestionDetails=null,this.focusedItem=null),void this._ariaAlert(null);if(this.completionModel){var n=e.elements[0],i=e.indexes[0];this.firstFocusInCurrentList=!this.focusedItem,n!==this.focusedItem&&(this.currentSuggestionDetails&&(this.currentSuggestionDetails.cancel(),this.currentSuggestionDetails=null),this.focusedItem=n,this.list.reveal(i),this.currentSuggestionDetails=Object(v.f)(function(e){return be(t,void 0,void 0,function(){var t,i,r=this;return ye(this,function(o){switch(o.label){case 0:return t=Object(v.g)(function(){return r.showDetails(!0)},250),e.onCancellationRequested(function(){return t.dispose()}),[4,n.resolve(e)];case 1:return i=o.sent(),t.dispose(),[2,i]}})})}),this.currentSuggestionDetails.then(function(){i>=t.list.length||n!==t.list.element(i)||(t.ignoreFocusEvents=!0,t.list.splice(i,1,[n]),t.list.setFocus([i]),t.ignoreFocusEvents=!1,t.expandDocsSettingFromStorage()?t.showDetails(!1):Object(X.I)(t.element,"docs-side"),t._ariaAlert(t._getSuggestionAriaAlertLabel(n)))}).catch(s.e)),this.onDidFocusEmitter.fire({item:n,index:i,model:this.completionModel})}}},e.prototype.setState=function(t){if(this.element){var n=this.state!==t;switch(this.state=t,Object(X.R)(this.element,"frozen",4===t),t){case 0:Object(X.D)(this.messageElement,this.details.element,this.listElement),this.hide(),this.listHeight=0,n&&this.list.splice(0,this.list.length),this.focusedItem=null;break;case 1:this.messageElement.textContent=e.LOADING_MESSAGE,Object(X.D)(this.listElement,this.details.element),Object(X.Q)(this.messageElement),Object(X.I)(this.element,"docs-side"),this.show(),this.focusedItem=null;break;case 2:this.messageElement.textContent=e.NO_SUGGESTIONS_MESSAGE,Object(X.D)(this.listElement,this.details.element),Object(X.Q)(this.messageElement),Object(X.I)(this.element,"docs-side"),this.show(),this.focusedItem=null;break;case 3:case 4:Object(X.D)(this.messageElement),Object(X.Q)(this.listElement),this.show();break;case 5:Object(X.D)(this.messageElement),Object(X.Q)(this.details.element,this.listElement),this.show(),this._ariaAlert(this.details.getAriaLabel())}}},e.prototype.showTriggered=function(e,t){var n=this;0===this.state&&(this.isAuto=!!e,this.isAuto||(this.loadingTimeout=Object(v.g)(function(){return n.setState(1)},t)))},e.prototype.showSuggestions=function(e,t,n,i){if(this.preferDocPositionTop=!1,this.docsPositionPreviousWidgetY=null,this.loadingTimeout.dispose(),this.currentSuggestionDetails&&(this.currentSuggestionDetails.cancel(),this.currentSuggestionDetails=null),this.completionModel!==e&&(this.completionModel=e),n&&2!==this.state&&0!==this.state)this.setState(4);else{var r=this.completionModel.items.length,o=0===r;if(this.suggestWidgetMultipleSuggestions.set(r>1),o)i?this.setState(0):this.setState(2),this.completionModel=null;else{if(3!==this.state){var s=this.completionModel.stats;s.wasAutomaticallyTriggered=!!i,this.telemetryService.publicLog("suggestWidget",me({},s))}this.focusedItem=null,this.list.splice(0,this.list.length,this.completionModel.items),n?this.setState(4):this.setState(3),this.list.reveal(t,0),this.list.setFocus([t]),this.detailsBorderColor&&(this.details.element.style.borderColor=this.detailsBorderColor)}}},e.prototype.selectNextPage=function(){switch(this.state){case 0:return!1;case 5:return this.details.pageDown(),!0;case 1:return!this.isAuto;default:return this.list.focusNextPage(),!0}},e.prototype.selectNext=function(){switch(this.state){case 0:return!1;case 1:return!this.isAuto;default:return this.list.focusNext(1,!0),!0}},e.prototype.selectLast=function(){switch(this.state){case 0:return!1;case 5:return this.details.scrollBottom(),!0;case 1:return!this.isAuto;default:return this.list.focusLast(),!0}},e.prototype.selectPreviousPage=function(){switch(this.state){case 0:return!1;case 5:return this.details.pageUp(),!0;case 1:return!this.isAuto;default:return this.list.focusPreviousPage(),!0}},e.prototype.selectPrevious=function(){switch(this.state){case 0:return!1;case 1:return!this.isAuto;default:return this.list.focusPrevious(1,!0),!1}},e.prototype.selectFirst=function(){switch(this.state){case 0:return!1;case 5:return this.details.scrollTop(),!0;case 1:return!this.isAuto;default:return this.list.focusFirst(),!0}},e.prototype.getFocusedItem=function(){if(0!==this.state&&2!==this.state&&1!==this.state&&this.completionModel)return{item:this.list.getFocusedElements()[0],index:this.list.getFocus()[0],model:this.completionModel}},e.prototype.toggleDetailsFocus=function(){5===this.state?(this.setState(3),this.detailsBorderColor&&(this.details.element.style.borderColor=this.detailsBorderColor)):3===this.state&&this.expandDocsSettingFromStorage()&&(this.setState(5),this.detailsFocusBorderColor&&(this.details.element.style.borderColor=this.detailsFocusBorderColor)),this.telemetryService.publicLog2("suggestWidget:toggleDetailsFocus")},e.prototype.toggleDetails=function(){if(ke(this.list.getFocusedElements()[0]))if(this.expandDocsSettingFromStorage())this.updateExpandDocsSetting(!1),Object(X.D)(this.details.element),Object(X.I)(this.element,"docs-side"),Object(X.I)(this.element,"docs-below"),this.editor.layoutContentWidget(this),this.telemetryService.publicLog2("suggestWidget:collapseDetails");else{if(3!==this.state&&5!==this.state&&4!==this.state)return;this.updateExpandDocsSetting(!0),this.showDetails(!1),this._ariaAlert(this.details.getAriaLabel()),this.telemetryService.publicLog2("suggestWidget:expandDetails")}},e.prototype.showDetails=function(e){this.expandSideOrBelow(),Object(X.Q)(this.details.element),this.details.element.style.maxHeight=this.maxWidgetHeight+"px",e?this.details.renderLoading():this.details.renderItem(this.list.getFocusedElements()[0],this.explainMode),this.listElement.style.marginTop="0px",this.editor.layoutContentWidget(this),this.adjustDocsPosition(),this.editor.focus()},e.prototype.toggleExplainMode=function(){this.list.getFocusedElements()[0]&&this.expandDocsSettingFromStorage()&&(this.explainMode=!this.explainMode,this.showDetails(!1))},e.prototype.show=function(){var e=this,t=this.updateListHeight();t!==this.listHeight&&(this.editor.layoutContentWidget(this),this.listHeight=t),this.suggestWidgetVisible.set(!0),this.showTimeout.cancelAndSet(function(){Object(X.f)(e.element,"visible"),e.onDidShowEmitter.fire(e)},100)},e.prototype.hide=function(){this.suggestWidgetVisible.reset(),this.suggestWidgetMultipleSuggestions.reset(),Object(X.I)(this.element,"visible")},e.prototype.hideWidget=function(){this.loadingTimeout.dispose(),this.setState(0),this.onDidHideEmitter.fire(this)},e.prototype.getPosition=function(){if(0===this.state)return null;var e=[2,1];return this.preferDocPositionTop&&(e=[1]),{position:this.editor.getPosition(),preference:e}},e.prototype.getDomNode=function(){return this.element},e.prototype.getId=function(){return e.ID},e.prototype.updateListHeight=function(){var e=0;if(2===this.state||1===this.state)e=this.unfocusedHeight;else{var t=this.list.contentHeight/this.unfocusedHeight,n=this.editor.getConfiguration().contribInfo.suggest.maxVisibleSuggestions;e=Math.min(t,n)*this.unfocusedHeight}return this.element.style.lineHeight=this.unfocusedHeight+"px",this.listElement.style.height=e+"px",this.list.layout(e),e},e.prototype.adjustDocsPosition=function(){if(this.editor.hasModel()){var e=this.editor.getConfiguration().fontInfo.lineHeight,t=this.editor.getScrolledVisiblePosition(this.editor.getPosition()),n=Object(X.x)(this.editor.getDomNode()),i=n.left+t.left,r=n.top+t.top+t.height,o=Object(X.x)(this.element),s=o.left,a=o.top;if(this.docsPositionPreviousWidgetY&&this.docsPositionPreviousWidgetYa&&this.details.element.offsetHeight>this.listElement.offsetHeight&&(this.listElement.style.marginTop=this.details.element.offsetHeight-this.listElement.offsetHeight+"px")}},e.prototype.expandSideOrBelow=function(){if(!ke(this.focusedItem)&&this.firstFocusInCurrentList)return Object(X.I)(this.element,"docs-side"),void Object(X.I)(this.element,"docs-below");var e=this.element.style.maxWidth.match(/(\d+)px/);!e||Number(e[1])=0;a--)(r=e[a])&&(s=(o<3?r(s):o>3?r(t,n,s):r(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},Te=this&&this.__param||function(e,t){return function(n,i){t(n,i,e)}},Pe=function(e){function t(n,i){var r=e.call(this)||this;return r._editor=n,r._enabled=!1,r._ckAtEnd=t.AtEnd.bindTo(i),r._register(r._editor.onDidChangeConfiguration(function(e){return e.contribInfo&&r._update()})),r._update(),r}return De(t,e),t.prototype.dispose=function(){e.prototype.dispose.call(this),Object(a.f)(this._selectionListener),this._ckAtEnd.reset()},t.prototype._update=function(){var e=this,t="on"===this._editor.getConfiguration().contribInfo.tabCompletion;if(this._enabled!==t)if(this._enabled=t,this._enabled){var n=function(){if(e._editor.hasModel()){var t=e._editor.getModel(),n=e._editor.getSelection(),i=t.getWordAtPosition(n.getStartPosition());i?e._ckAtEnd.set(i.endColumn===n.getStartPosition().column):e._ckAtEnd.set(!1)}else e._ckAtEnd.set(!1)};this._selectionListener=this._editor.onDidChangeCursorSelection(n),n()}else this._selectionListener&&(this._ckAtEnd.reset(),this._selectionListener.dispose(),this._selectionListener=void 0)},t.AtEnd=new T.d("atEndOfWord",!1),t=Me([Te(1,T.c)],t)}(a.a),Ae=n("606G"),Re=n("KIxu"),Fe=n("GfE5"),je=function(){function e(e,t,n){var i=this;this._disposables=new a.b,this._disposables.add(t.onDidShow(function(){return i._onItem(t.getFocusedItem())})),this._disposables.add(t.onDidFocus(this._onItem,this)),this._disposables.add(t.onDidHide(this.reset,this)),this._disposables.add(e.onWillType(function(t){if(i._active){var r=t.charCodeAt(t.length-1);i._active.acceptCharacters.has(r)&&e.getConfiguration().contribInfo.acceptSuggestionOnCommitCharacter&&n(i._active.item)}}))}return e.prototype._onItem=function(e){if(e&&Object(o.n)(e.item.completion.commitCharacters)){if(!this._active||this._active.item.item!==e.item){for(var t=new Fe.b,n=0,i=e.item.completion.commitCharacters;n0&&t.add(r.charCodeAt(0))}this._active={acceptCharacters:t,item:e}}}else this.reset()},e.prototype.reset=function(){this._active=void 0},e.prototype.dispose=function(){this._disposables.dispose()},e}();n.d(t,"SuggestController",function(){return Ke}),n.d(t,"TriggerSuggestAction",function(){return qe});var We=this&&this.__extends||function(){var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(t,n)};return function(t,n){function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}}(),Be=this&&this.__assign||function(){return(Be=Object.assign||function(e){for(var t,n=1,i=arguments.length;n=0;a--)(r=e[a])&&(s=(o<3?r(s):o>3?r(t,n,s):r(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},He=this&&this.__param||function(e,t){return function(n,i){t(n,i,e)}},ze=!1,Ue=function(){function e(e,t){if(this._model=e,this._position=t,e.getLineMaxColumn(t.lineNumber)!==t.column){var n=e.getOffsetAt(t),i=e.getPositionAt(n+1);this._marker=e.deltaDecorations([],[{range:l.a.fromPositions(t,i),options:{stickiness:1}}])}}return e.prototype.dispose=function(){this._marker&&!this._model.isDisposed()&&this._model.deltaDecorations(this._marker,[])},e.prototype.delta=function(e){if(this._model.isDisposed()||this._position.lineNumber!==e.lineNumber)return 0;if(this._marker){var t=this._model.getDecorationRange(this._marker[0]);return this._model.getOffsetAt(t.getStartPosition())-this._model.getOffsetAt(e)}return this._model.getLineMaxColumn(e.lineNumber)-e.column},e}(),Ke=function(){function e(e,t,n,i,r,o){var s=this;this._editor=e,this._memoryService=n,this._commandService=i,this._contextKeyService=r,this._instantiationService=o,this._lineSuffix=new a.d,this._toDispose=new a.b,this._model=new Y(this._editor,t),this._widget=new v.b(function(){var e=s._instantiationService.createInstance(Ie,s._editor);s._toDispose.add(e),s._toDispose.add(e.onDidSelect(function(e){return s._insertSuggestion(e,!1,!0)},s));var t=new je(s._editor,e,function(e){return s._insertSuggestion(e,!1,!0)});s._toDispose.add(t),s._toDispose.add(s._model.onDidSuggest(function(e){0===e.completionModel.items.length&&t.reset()}));var n=P.b.MakesTextEdit.bindTo(s._contextKeyService);return s._toDispose.add(e.onDidFocus(function(e){var t=e.item,i=s._editor.getPosition(),r=t.completion.range.startColumn,o=i.column,a=!0;"smart"!==s._editor.getConfiguration().contribInfo.acceptSuggestionOnEnter||2!==s._model.state||t.completion.command||t.completion.additionalTextEdits||4&t.completion.insertTextRules||o-r!==t.completion.insertText.length||(a=s._editor.getModel().getValueInRange({startLineNumber:i.lineNumber,startColumn:r,endLineNumber:i.lineNumber,endColumn:o})!==t.completion.insertText);n.set(a)})),s._toDispose.add(Object(a.h)(function(){return n.reset()})),e}),this._alternatives=new v.b(function(){return s._toDispose.add(new F(s._editor,s._contextKeyService))}),this._toDispose.add(o.createInstance(Pe,e)),this._toDispose.add(this._model.onDidTrigger(function(e){s._widget.getValue().showTriggered(e.auto,e.shy?250:50),s._lineSuffix.value=new Ue(s._editor.getModel(),e.position)})),this._toDispose.add(this._model.onDidSuggest(function(e){if(!e.shy){var t=s._memoryService.select(s._editor.getModel(),s._editor.getPosition(),e.completionModel.items);s._widget.getValue().showSuggestions(e.completionModel,t,e.isFrozen,e.auto)}})),this._toDispose.add(this._model.onDidCancel(function(e){e.retrigger||s._widget.getValue().hideWidget()})),this._toDispose.add(this._editor.onDidBlurEditorWidget(function(){ze||(s._model.cancel(),s._model.clear())}));var u=P.b.AcceptSuggestionsOnEnter.bindTo(r),c=function(){var e=s._editor.getConfiguration().contribInfo.acceptSuggestionOnEnter;u.set("on"===e||"smart"===e)};this._toDispose.add(this._editor.onDidChangeConfiguration(function(){return c()})),c()}return e.get=function(t){return t.getContribution(e.ID)},e.prototype.getId=function(){return e.ID},e.prototype.dispose=function(){this._alternatives.dispose(),this._toDispose.dispose(),this._widget.dispose(),this._model.dispose(),this._lineSuffix.dispose()},e.prototype._insertSuggestion=function(e,t,n){var i,r=this;if(!e||!e.item)return this._alternatives.getValue().reset(),this._model.cancel(),void this._model.clear();if(this._editor.hasModel()){var o=this._editor.getModel(),a=o.getAlternativeVersionId(),u=e.item,d=u.completion,p=u.position,g=this._editor.getPosition().column-p.column;n&&this._editor.pushUndoStop(),Array.isArray(d.additionalTextEdits)&&this._editor.executeEdits("suggestController.additionalTextEdits",d.additionalTextEdits.map(function(e){return c.a.replace(l.a.lift(e.range),e.text)})),this._memoryService.memorize(o,this._editor.getPosition(),e.item);var m=d.insertText;4&d.insertTextRules||(m=f.c.escape(m));var v=p.column-d.range.startColumn,_=d.range.endColumn-p.column,b=this._lineSuffix.value?this._lineSuffix.value.delta(this._editor.getPosition()):0;h.SnippetController2.get(this._editor).insert(m,{overwriteBefore:v+g,overwriteAfter:_+b,undoStopBefore:!1,undoStopAfter:!1,adjustWhitespace:!(1&d.insertTextRules)}),n&&this._editor.pushUndoStop(),d.command?d.command.id===qe.id?this._model.trigger({auto:!0,shy:!1},!0):((i=this._commandService).executeCommand.apply(i,[d.command.id].concat(d.command.arguments?d.command.arguments.slice():[])).catch(s.e).finally(function(){return r._model.clear()}),this._model.cancel()):(this._model.cancel(),this._model.clear()),t&&this._alternatives.getValue().set(e,function(e){for(;o.canUndo();){a!==o.getAlternativeVersionId()&&o.undo(),r._insertSuggestion(e,!1,!1);break}}),this._alertCompletionItem(e.item)}},e.prototype._alertCompletionItem=function(e){var t=e.completion;if(Object(o.n)(t.additionalTextEdits)){var n=D.a("arai.alert.snippet","Accepting '{0}' made {1} additional edits",t.label,t.additionalTextEdits.length);Object(r.a)(n)}},e.prototype.triggerSuggest=function(e){this._editor.hasModel()&&(this._model.trigger({auto:!1,shy:!1},!1,e),this._editor.revealLine(this._editor.getPosition().lineNumber,0),this._editor.focus())},e.prototype.triggerSuggestAndAcceptBest=function(e){var t=this;if(this._editor.hasModel()){var n=this._editor.getPosition(),i=function(){n.equals(t._editor.getPosition())&&t._commandService.executeCommand(e.fallback)};j.b.once(this._model.onDidTrigger)(function(e){var n=[];j.b.any(t._model.onDidTrigger,t._model.onDidCancel)(function(){Object(a.f)(n),i()},void 0,n),t._model.onDidSuggest(function(e){var r=e.completionModel;if(Object(a.f)(n),0!==r.items.length){var o=t._memoryService.select(t._editor.getModel(),t._editor.getPosition(),r.items),s=r.items[o];!function(e){if(4&e.completion.insertTextRules||e.completion.additionalTextEdits)return!0;var n=t._editor.getPosition(),i=e.completion.range.startColumn,r=n.column;return r-i!==e.completion.insertText.length||t._editor.getModel().getValueInRange({startLineNumber:n.lineNumber,startColumn:i,endLineNumber:n.lineNumber,endColumn:r})!==e.completion.insertText}(s)?i():(t._editor.pushUndoStop(),t._insertSuggestion({index:o,item:s,model:r},!0,!1))}else i()},void 0,n)}),this._model.trigger({auto:!1,shy:!0}),this._editor.revealLine(n.lineNumber,0),this._editor.focus()}},e.prototype.acceptSelectedSuggestion=function(e){var t=this._widget.getValue().getFocusedItem();this._insertSuggestion(t,!!e,!0)},e.prototype.acceptNextSuggestion=function(){this._alternatives.getValue().next()},e.prototype.acceptPrevSuggestion=function(){this._alternatives.getValue().prev()},e.prototype.cancelSuggestWidget=function(){this._model.cancel(),this._model.clear(),this._widget.getValue().hideWidget()},e.prototype.selectNextSuggestion=function(){this._widget.getValue().selectNext()},e.prototype.selectNextPageSuggestion=function(){this._widget.getValue().selectNextPage()},e.prototype.selectLastSuggestion=function(){this._widget.getValue().selectLast()},e.prototype.selectPrevSuggestion=function(){this._widget.getValue().selectPrevious()},e.prototype.selectPrevPageSuggestion=function(){this._widget.getValue().selectPreviousPage()},e.prototype.selectFirstSuggestion=function(){this._widget.getValue().selectFirst()},e.prototype.toggleSuggestionDetails=function(){this._widget.getValue().toggleDetails()},e.prototype.toggleExplainMode=function(){this._widget.getValue().toggleExplainMode()},e.prototype.toggleSuggestionFocus=function(){this._widget.getValue().toggleDetailsFocus()},e.ID="editor.contrib.suggestController",e=Ve([He(1,Ae.a),He(2,E),He(3,M.b),He(4,T.c),He(5,_.a)],e)}(),qe=function(e){function t(){return e.call(this,{id:t.id,label:D.a("suggest.trigger.label","Trigger Suggest"),alias:"Trigger Suggest",precondition:T.a.and(d.a.writable,d.a.hasCompletionItemProvider),kbOpts:{kbExpr:d.a.textInputFocus,primary:2058,mac:{primary:266},weight:100}})||this}return We(t,e),t.prototype.run=function(e,t){var n=Ke.get(t);n&&n.triggerSuggest()},t.id="editor.action.triggerSuggest",t}(u.b);Object(u.h)(Ke),Object(u.f)(qe);var Ge=u.c.bindToContribution(Ke.get);Object(u.g)(new Ge({id:"acceptSelectedSuggestion",precondition:P.b.Visible,handler:function(e){return e.acceptSelectedSuggestion(!0)},kbOpts:{weight:190,kbExpr:d.a.textInputFocus,primary:2}})),Object(u.g)(new Ge({id:"acceptSelectedSuggestionOnEnter",precondition:P.b.Visible,handler:function(e){return e.acceptSelectedSuggestion(!1)},kbOpts:{weight:190,kbExpr:T.a.and(d.a.textInputFocus,P.b.AcceptSuggestionsOnEnter,P.b.MakesTextEdit),primary:3}})),Object(u.g)(new Ge({id:"hideSuggestWidget",precondition:P.b.Visible,handler:function(e){return e.cancelSuggestWidget()},kbOpts:{weight:190,kbExpr:d.a.textInputFocus,primary:9,secondary:[1033]}})),Object(u.g)(new Ge({id:"selectNextSuggestion",precondition:T.a.and(P.b.Visible,P.b.MultipleSuggestions),handler:function(e){return e.selectNextSuggestion()},kbOpts:{weight:190,kbExpr:d.a.textInputFocus,primary:18,secondary:[2066],mac:{primary:18,secondary:[2066,300]}}})),Object(u.g)(new Ge({id:"selectNextPageSuggestion",precondition:T.a.and(P.b.Visible,P.b.MultipleSuggestions),handler:function(e){return e.selectNextPageSuggestion()},kbOpts:{weight:190,kbExpr:d.a.textInputFocus,primary:12,secondary:[2060]}})),Object(u.g)(new Ge({id:"selectLastSuggestion",precondition:T.a.and(P.b.Visible,P.b.MultipleSuggestions),handler:function(e){return e.selectLastSuggestion()}})),Object(u.g)(new Ge({id:"selectPrevSuggestion",precondition:T.a.and(P.b.Visible,P.b.MultipleSuggestions),handler:function(e){return e.selectPrevSuggestion()},kbOpts:{weight:190,kbExpr:d.a.textInputFocus,primary:16,secondary:[2064],mac:{primary:16,secondary:[2064,302]}}})),Object(u.g)(new Ge({id:"selectPrevPageSuggestion",precondition:T.a.and(P.b.Visible,P.b.MultipleSuggestions),handler:function(e){return e.selectPrevPageSuggestion()},kbOpts:{weight:190,kbExpr:d.a.textInputFocus,primary:11,secondary:[2059]}})),Object(u.g)(new Ge({id:"selectFirstSuggestion",precondition:T.a.and(P.b.Visible,P.b.MultipleSuggestions),handler:function(e){return e.selectFirstSuggestion()}})),Object(u.g)(new Ge({id:"toggleSuggestionDetails",precondition:P.b.Visible,handler:function(e){return e.toggleSuggestionDetails()},kbOpts:{weight:190,kbExpr:d.a.textInputFocus,primary:2058,mac:{primary:266}}})),Object(u.g)(new Ge({id:"toggleExplainMode",precondition:P.b.Visible,handler:function(e){return e.toggleExplainMode()},kbOpts:{weight:100,primary:2133}})),Object(u.g)(new Ge({id:"toggleSuggestionFocus",precondition:P.b.Visible,handler:function(e){return e.toggleSuggestionFocus()},kbOpts:{weight:190,kbExpr:d.a.textInputFocus,primary:2570,mac:{primary:778}}})),Object(u.g)(new Ge({id:"insertBestCompletion",precondition:T.a.and(T.a.equals("config.editor.tabCompletion","on"),Pe.AtEnd,P.b.Visible.toNegated(),F.OtherSuggestions.toNegated(),h.SnippetController2.InSnippetMode.toNegated()),handler:function(e,t){e.triggerSuggestAndAcceptBest(Object(Re.h)(t)?Be({fallback:"tab"},t):{fallback:"tab"})},kbOpts:{weight:190,primary:2}})),Object(u.g)(new Ge({id:"insertNextSuggestion",precondition:T.a.and(T.a.equals("config.editor.tabCompletion","on"),F.OtherSuggestions,P.b.Visible.toNegated(),h.SnippetController2.InSnippetMode.toNegated()),handler:function(e){return e.acceptNextSuggestion()},kbOpts:{weight:190,kbExpr:d.a.textInputFocus,primary:2}})),Object(u.g)(new Ge({id:"insertPrevSuggestion",precondition:T.a.and(T.a.equals("config.editor.tabCompletion","on"),F.OtherSuggestions,P.b.Visible.toNegated(),h.SnippetController2.InSnippetMode.toNegated()),handler:function(e){return e.acceptPrevSuggestion()},kbOpts:{weight:190,kbExpr:d.a.textInputFocus,primary:1026}}))},"7dSG":function(e,t,n){"use strict";(function(t,i){var r=n("ypnx");function o(e){var t=this;this.next=null,this.entry=null,this.finish=function(){!function(e,t,n){var i=e.entry;e.entry=null;for(;i;){var r=i.callback;t.pendingcb--,r(n),i=i.next}t.corkedRequestsFree?t.corkedRequestsFree.next=e:t.corkedRequestsFree=e}(t,e)}}e.exports=v;var s,a=!t.browser&&["v0.10","v0.9."].indexOf(t.version.slice(0,5))>-1?setImmediate:r.nextTick;v.WritableState=m;var u=n("jOgh");u.inherits=n("LC74");var c={deprecate:n("iP15")},l=n("UcPO"),d=n("kkc6").Buffer,h=i.Uint8Array||function(){};var f,p=n("x0Ha");function g(){}function m(e,t){s=s||n("DsFX"),e=e||{};var i=t instanceof s;this.objectMode=!!e.objectMode,i&&(this.objectMode=this.objectMode||!!e.writableObjectMode);var u=e.highWaterMark,c=e.writableHighWaterMark,l=this.objectMode?16:16384;this.highWaterMark=u||0===u?u:i&&(c||0===c)?c:l,this.highWaterMark=Math.floor(this.highWaterMark),this.finalCalled=!1,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1,this.destroyed=!1;var d=!1===e.decodeStrings;this.decodeStrings=!d,this.defaultEncoding=e.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(e){!function(e,t){var n=e._writableState,i=n.sync,o=n.writecb;if(function(e){e.writing=!1,e.writecb=null,e.length-=e.writelen,e.writelen=0}(n),t)!function(e,t,n,i,o){--t.pendingcb,n?(r.nextTick(o,i),r.nextTick(S,e,t),e._writableState.errorEmitted=!0,e.emit("error",i)):(o(i),e._writableState.errorEmitted=!0,e.emit("error",i),S(e,t))}(e,n,i,t,o);else{var s=w(n);s||n.corked||n.bufferProcessing||!n.bufferedRequest||y(e,n),i?a(b,e,n,s,o):b(e,n,s,o)}}(t,e)},this.writecb=null,this.writelen=0,this.bufferedRequest=null,this.lastBufferedRequest=null,this.pendingcb=0,this.prefinished=!1,this.errorEmitted=!1,this.bufferedRequestCount=0,this.corkedRequestsFree=new o(this)}function v(e){if(s=s||n("DsFX"),!(f.call(v,this)||this instanceof s))return new v(e);this._writableState=new m(e,this),this.writable=!0,e&&("function"==typeof e.write&&(this._write=e.write),"function"==typeof e.writev&&(this._writev=e.writev),"function"==typeof e.destroy&&(this._destroy=e.destroy),"function"==typeof e.final&&(this._final=e.final)),l.call(this)}function _(e,t,n,i,r,o,s){t.writelen=i,t.writecb=s,t.writing=!0,t.sync=!0,n?e._writev(r,t.onwrite):e._write(r,o,t.onwrite),t.sync=!1}function b(e,t,n,i){n||function(e,t){0===t.length&&t.needDrain&&(t.needDrain=!1,e.emit("drain"))}(e,t),t.pendingcb--,i(),S(e,t)}function y(e,t){t.bufferProcessing=!0;var n=t.bufferedRequest;if(e._writev&&n&&n.next){var i=t.bufferedRequestCount,r=new Array(i),s=t.corkedRequestsFree;s.entry=n;for(var a=0,u=!0;n;)r[a]=n,n.isBuf||(u=!1),n=n.next,a+=1;r.allBuffers=u,_(e,t,!0,t.length,r,"",s.finish),t.pendingcb++,t.lastBufferedRequest=null,s.next?(t.corkedRequestsFree=s.next,s.next=null):t.corkedRequestsFree=new o(t),t.bufferedRequestCount=0}else{for(;n;){var c=n.chunk,l=n.encoding,d=n.callback;if(_(e,t,!1,t.objectMode?1:c.length,c,l,d),n=n.next,t.bufferedRequestCount--,t.writing)break}null===n&&(t.lastBufferedRequest=null)}t.bufferedRequest=n,t.bufferProcessing=!1}function w(e){return e.ending&&0===e.length&&null===e.bufferedRequest&&!e.finished&&!e.writing}function C(e,t){e._final(function(n){t.pendingcb--,n&&e.emit("error",n),t.prefinished=!0,e.emit("prefinish"),S(e,t)})}function S(e,t){var n=w(t);return n&&(!function(e,t){t.prefinished||t.finalCalled||("function"==typeof e._final?(t.pendingcb++,t.finalCalled=!0,r.nextTick(C,e,t)):(t.prefinished=!0,e.emit("prefinish")))}(e,t),0===t.pendingcb&&(t.finished=!0,e.emit("finish"))),n}u.inherits(v,l),m.prototype.getBuffer=function(){for(var e=this.bufferedRequest,t=[];e;)t.push(e),e=e.next;return t},function(){try{Object.defineProperty(m.prototype,"buffer",{get:c.deprecate(function(){return this.getBuffer()},"_writableState.buffer is deprecated. Use _writableState.getBuffer instead.","DEP0003")})}catch(e){}}(),"function"==typeof Symbol&&Symbol.hasInstance&&"function"==typeof Function.prototype[Symbol.hasInstance]?(f=Function.prototype[Symbol.hasInstance],Object.defineProperty(v,Symbol.hasInstance,{value:function(e){return!!f.call(this,e)||this===v&&(e&&e._writableState instanceof m)}})):f=function(e){return e instanceof this},v.prototype.pipe=function(){this.emit("error",new Error("Cannot pipe, not readable"))},v.prototype.write=function(e,t,n){var i,o=this._writableState,s=!1,a=!o.objectMode&&(i=e,d.isBuffer(i)||i instanceof h);return a&&!d.isBuffer(e)&&(e=function(e){return d.from(e)}(e)),"function"==typeof t&&(n=t,t=null),a?t="buffer":t||(t=o.defaultEncoding),"function"!=typeof n&&(n=g),o.ended?function(e,t){var n=new Error("write after end");e.emit("error",n),r.nextTick(t,n)}(this,n):(a||function(e,t,n,i){var o=!0,s=!1;return null===n?s=new TypeError("May not write null values to stream"):"string"==typeof n||void 0===n||t.objectMode||(s=new TypeError("Invalid non-string/buffer chunk")),s&&(e.emit("error",s),r.nextTick(i,s),o=!1),o}(this,o,e,n))&&(o.pendingcb++,s=function(e,t,n,i,r,o){if(!n){var s=function(e,t,n){e.objectMode||!1===e.decodeStrings||"string"!=typeof t||(t=d.from(t,n));return t}(t,i,r);i!==s&&(n=!0,r="buffer",i=s)}var a=t.objectMode?1:i.length;t.length+=a;var u=t.length-1))throw new TypeError("Unknown encoding: "+e);return this._writableState.defaultEncoding=e,this},Object.defineProperty(v.prototype,"writableHighWaterMark",{enumerable:!1,get:function(){return this._writableState.highWaterMark}}),v.prototype._write=function(e,t,n){n(new Error("_write() is not implemented"))},v.prototype._writev=null,v.prototype.end=function(e,t,n){var i=this._writableState;"function"==typeof e?(n=e,e=null,t=null):"function"==typeof t&&(n=t,t=null),null!==e&&void 0!==e&&this.write(e,t),i.corked&&(i.corked=1,this.uncork()),i.ending||i.finished||function(e,t,n){t.ending=!0,S(e,t),n&&(t.finished?r.nextTick(n):e.once("finish",n));t.ended=!0,e.writable=!1}(this,i,n)},Object.defineProperty(v.prototype,"destroyed",{get:function(){return void 0!==this._writableState&&this._writableState.destroyed},set:function(e){this._writableState&&(this._writableState.destroyed=e)}}),v.prototype.destroy=p.destroy,v.prototype._undestroy=p.undestroy,v.prototype._destroy=function(e,t){this.end(),t(e)}}).call(t,n("W2nU"),n("DuR2"))},"7flL":function(e,t,n){var i=n("q5VG"),r=n("X3l8").Buffer,o=n("VI/i"),s=n("annC"),a=n("OMJi"),u="secret must be a string or buffer",c="key must be a string or a buffer",l="key must be a string, a buffer or an object",d="function"==typeof o.createPublicKey;function h(e){if(!r.isBuffer(e)&&"string"!=typeof e){if(!d)throw m(c);if("object"!=typeof e)throw m(c);if("string"!=typeof e.type)throw m(c);if("string"!=typeof e.asymmetricKeyType)throw m(c);if("function"!=typeof e.export)throw m(c)}}function f(e){if(!r.isBuffer(e)&&"string"!=typeof e&&"object"!=typeof e)throw m(l)}function p(e){return e.replace(/=/g,"").replace(/\+/g,"-").replace(/\//g,"_")}function g(e){var t=4-(e=e.toString()).length%4;if(4!==t)for(var n=0;n=0){var n=e.split("!=");return d.create(n[0].trim(),this._deserializeValue(n[1],t))}if(e.indexOf("==")>=0){n=e.split("==");return l.create(n[0].trim(),this._deserializeValue(n[1],t))}if(e.indexOf("=~")>=0){n=e.split("=~");return f.create(n[0].trim(),this._deserializeRegexValue(n[1],t))}return/^\!\s*/.test(e)?h.create(e.substr(1).trim()):c.create(e)},e._deserializeValue=function(e,t){if("true"===(e=e.trim()))return!0;if("false"===e)return!1;var n=/^'([^']*)'$/.exec(e);return n?n[1].trim():e},e._deserializeRegexValue=function(e,t){if(Object(r.u)(e)){if(t)throw new Error("missing regexp-value for =~-expression");return console.warn("missing regexp-value for =~-expression"),null}var n=e.indexOf("/"),i=e.lastIndexOf("/");if(n===i||n<0){if(t)throw new Error("bad regexp-value '"+e+"', missing /-enclosure");return console.warn("bad regexp-value '"+e+"', missing /-enclosure"),null}var o=e.slice(n+1,i),s="i"===e[i+1]?"i":"";try{return new RegExp(o,s)}catch(n){if(t)throw new Error("bad regexp-value '"+e+"', parse error: "+n);return console.warn("bad regexp-value '"+e+"', parse error: "+n),null}},e}();function u(e,t){var n=e.getType(),i=t.getType();if(n!==i)return n-i;switch(n){case 1:case 2:case 3:case 4:case 6:case 7:case 5:return e.cmp(t);default:throw new Error("Unknown ContextKeyExpr!")}}var c=function(){function e(e){this.key=e}return e.create=function(t){return new e(t)},e.prototype.getType=function(){return 1},e.prototype.cmp=function(e){return this.keye.key?1:0},e.prototype.equals=function(t){return t instanceof e&&this.key===t.key},e.prototype.evaluate=function(e){return!!e.getValue(this.key)},e.prototype.keys=function(){return[this.key]},e.prototype.negate=function(){return h.create(this.key)},e}(),l=function(){function e(e,t){this.key=e,this.value=t}return e.create=function(t,n){return"boolean"==typeof n?n?c.create(t):h.create(t):new e(t,n)},e.prototype.getType=function(){return 3},e.prototype.cmp=function(e){return this.keye.key?1:this.valuee.value?1:0},e.prototype.equals=function(t){return t instanceof e&&(this.key===t.key&&this.value===t.value)},e.prototype.evaluate=function(e){return e.getValue(this.key)==this.value},e.prototype.keys=function(){return[this.key]},e.prototype.negate=function(){return d.create(this.key,this.value)},e}(),d=function(){function e(e,t){this.key=e,this.value=t}return e.create=function(t,n){return"boolean"==typeof n?n?h.create(t):c.create(t):new e(t,n)},e.prototype.getType=function(){return 4},e.prototype.cmp=function(e){return this.keye.key?1:this.valuee.value?1:0},e.prototype.equals=function(t){return t instanceof e&&(this.key===t.key&&this.value===t.value)},e.prototype.evaluate=function(e){return e.getValue(this.key)!=this.value},e.prototype.keys=function(){return[this.key]},e.prototype.negate=function(){return l.create(this.key,this.value)},e}(),h=function(){function e(e){this.key=e}return e.create=function(t){return new e(t)},e.prototype.getType=function(){return 2},e.prototype.cmp=function(e){return this.keye.key?1:0},e.prototype.equals=function(t){return t instanceof e&&this.key===t.key},e.prototype.evaluate=function(e){return!e.getValue(this.key)},e.prototype.keys=function(){return[this.key]},e.prototype.negate=function(){return c.create(this.key)},e}(),f=function(){function e(e,t){this.key=e,this.regexp=t}return e.create=function(t,n){return new e(t,n)},e.prototype.getType=function(){return 6},e.prototype.cmp=function(e){if(this.keye.key)return 1;var t=this.regexp?this.regexp.source:"",n=e.regexp?e.regexp.source:"";return tn?1:0},e.prototype.equals=function(t){if(t instanceof e){var n=this.regexp?this.regexp.source:"",i=t.regexp?t.regexp.source:"";return this.key===t.key&&n===i}return!1},e.prototype.evaluate=function(e){var t=e.getValue(this.key);return!!this.regexp&&this.regexp.test(t)},e.prototype.keys=function(){return[this.key]},e.prototype.negate=function(){return p.create(this)},e}(),p=function(){function e(e){this._actual=e}return e.create=function(t){return new e(t)},e.prototype.getType=function(){return 7},e.prototype.cmp=function(e){return this._actual.cmp(e._actual)},e.prototype.equals=function(t){return t instanceof e&&this._actual.equals(t._actual)},e.prototype.evaluate=function(e){return!this._actual.evaluate(e)},e.prototype.keys=function(){return this._actual.keys()},e.prototype.negate=function(){return this._actual},e}(),g=function(){function e(e){this.expr=e}return e.create=function(t){var n=e._normalizeArr(t);if(0!==n.length)return 1===n.length?n[0]:new e(n)},e.prototype.getType=function(){return 5},e.prototype.cmp=function(e){if(this.expr.lengthe.expr.length)return 1;for(var t=0,n=this.expr.length;t1;){for(var s=t.shift(),u=t.shift(),c=[],l=0,d=o(s);l0&&(n._decorations=n._editor.deltaDecorations(n._decorations,[])),n._updateBracketsSoon.schedule()})),n}return _(t,e),t.get=function(e){return e.getContribution(t.ID)},t.prototype.getId=function(){return t.ID},t.prototype.jumpToBracket=function(){if(this._editor.hasModel()){var e=this._editor.getModel(),t=this._editor.getSelections().map(function(t){var n=t.getStartPosition(),i=e.matchBracket(n),r=null;if(i)i[0].containsPosition(n)?r=i[1].getStartPosition():i[1].containsPosition(n)&&(r=i[0].getStartPosition());else{var o=e.findNextBracket(n);o&&o.range&&(r=o.range.getStartPosition())}return r?new l.a(r.lineNumber,r.column,r.lineNumber,r.column):new l.a(n.lineNumber,n.column,n.lineNumber,n.column)});this._editor.setSelections(t),this._editor.revealRange(t[0])}},t.prototype.selectToBracket=function(){if(this._editor.hasModel()){var e=this._editor.getModel(),t=[];this._editor.getSelections().forEach(function(n){var i=n.getStartPosition(),r=e.matchBracket(i),o=null,s=null;if(!r){var a=e.findNextBracket(i);a&&a.range&&(r=e.matchBracket(a.range.getStartPosition()))}r&&(r[0].startLineNumber===r[1].startLineNumber?(o=r[1].startColumn0&&(this._editor.setSelections(t),this._editor.revealRange(t[0]))}},t.prototype._updateBrackets=function(){if(this._matchBrackets){this._recomputeBrackets();for(var e=[],n=0,i=0,r=this._lastBracketsData.length;i1&&r.sort(c.a.compare);var l=[],d=0,h=0,f=n.length;for(s=0,a=r.length;s0&&void 0!==arguments[0]&&arguments[0];var e=[].concat(r()(this.provider));return"sql"===this.lang&&e.push.apply(e,r()(this.sqlHints)),e},registerCustomHintsProvider:function(){var e=this;this.providerDisposeID=o.languages.registerCompletionItemProvider(this.lang,{provideCompletionItems:function(t,n,i){var r=t.getWordUntilPosition(n);return{suggestions:function(e,t,n){n.word;var i=[];return e.length&&(i=e.map(function(e){return{label:e.name,kind:e.type?o.languages.CompletionItemKind[e.type]:o.languages.CompletionItemKind.Function,documentation:e.documentation,insertText:(n=e.name,n),detail:e.detail||"EMQX",range:t};var n})),i}(e.getHints(r),{startLineNumber:n.lineNumber,endLineNumber:n.lineNumber,startColumn:r.startColumn,endColumn:r.endColumn},r)}},triggerCharacters:[" "]})},registerCustomHoverProvider:function(){var e=this;o.languages.register({id:this.lang}),this.hoverDisposeID=o.languages.registerHoverProvider(this.lang,{provideHover:function(t,n){if(!t.getWordAtPosition(n))return{};var i,r,o,s=t.getWordAtPosition(n).word;return{contents:(i=s,r=e.provider,o=[],r.forEach(function(e){var t=e.name;e.name.match(/\$events\//)&&(t=e.name.split("/")[1].replace('"',"")),i===t&&o.push({value:function(e){var t=e.name,n=e.default,i=e.valueType;return i&&(t=t+": "+i),n?t+", value: "+n:t}(e)},{value:e.documentation})}),o)}}})}},mounted:function(){this.initEditor()},created:function(){var e=this;this.defineTheme(),window.onresize=function(){e.editor&&e.editor.layout()},this.provider.length&&(this.registerCustomHintsProvider(),this.registerCustomHoverProvider())},beforeDestroy:function(){this.editor&&(this.editor.getModel().dispose(),this.editor.dispose(),this.editor=null),this.providerDisposeID&&this.providerDisposeID.dispose(),this.hoverDisposeID&&this.hoverDisposeID.dispose()}},c={render:function(){var e=this.$createElement;return(this._self._c||e)("div",{staticClass:"monaco-view",attrs:{id:"monaco-"+this.id}})},staticRenderFns:[]};var l=n("VU/8")(u,c,!1,function(e){n("u9OF")},null,null);t.a=l.exports},"9Io0":function(e,t,n){var i=n("X3l8").Buffer,r=n("sDkV"),o=n("7flL"),s=n("9DG0"),a=n("nOGB"),u=/^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.([a-zA-Z0-9\-_]+)?$/;function c(e){if(function(e){return"[object Object]"===Object.prototype.toString.call(e)}(e))return e;try{return JSON.parse(e)}catch(e){return}}function l(e){var t=e.split(".",1)[0];return c(i.from(t,"base64").toString("binary"))}function d(e){return e.split(".")[2]}function h(e){return u.test(e)&&!!l(e)}function f(e,t,n){if(!t){var i=new Error("Missing algorithm parameter for jws.verify");throw i.code="MISSING_ALGORITHM",i}var r=d(e=a(e)),s=function(e){return e.split(".",2).join(".")}(e);return o(t).verify(s,r,n)}function p(e,t){if(t=t||{},!h(e=a(e)))return null;var n=l(e);if(!n)return null;var r=function(e,t){t=t||"utf8";var n=e.split(".")[1];return i.from(n,"base64").toString(t)}(e);return("JWT"===n.typ||t.json)&&(r=JSON.parse(r,t.encoding)),{header:n,payload:r,signature:d(e)}}function g(e){var t=(e=e||{}).secret||e.publicKey||e.key,n=new r(t);this.readable=!0,this.algorithm=e.algorithm,this.encoding=e.encoding,this.secret=this.publicKey=this.key=n,this.signature=new r(e.signature),this.secret.once("close",function(){!this.signature.writable&&this.readable&&this.verify()}.bind(this)),this.signature.once("close",function(){!this.secret.writable&&this.readable&&this.verify()}.bind(this))}n("OMJi").inherits(g,s),g.prototype.verify=function(){try{var e=f(this.signature.buffer,this.algorithm,this.key.buffer),t=p(this.signature.buffer,this.encoding);return this.emit("done",e,t),this.emit("data",e),this.emit("end"),this.readable=!1,e}catch(e){this.readable=!1,this.emit("error",e),this.emit("close")}},g.decode=p,g.isValid=h,g.verify=f,e.exports=g},"9P96":function(e,t,n){t.publicEncrypt=n("9hYg"),t.privateDecrypt=n("fxuI"),t.privateEncrypt=function(e,n){return t.publicEncrypt(e,n,!0)},t.publicDecrypt=function(e,n){return t.privateDecrypt(e,n,!0)}},"9XyG":function(e,t,n){"use strict";n.d(t,"a",function(){return u}),n.d(t,"c",function(){return c}),n.d(t,"b",function(){return l});var i=n("hK2W"),r=n("Kp7x"),o=n("PCC9"),s=n("Fllr"),a=n("RWr8"),u=new(function(){function e(){this._onDidChangeLanguages=new r.a,this.onDidChangeLanguages=this._onDidChangeLanguages.event,this._languages=[],this._dynamicLanguages=[]}return e.prototype.registerLanguage=function(e){this._languages.push(e),this._onDidChangeLanguages.fire(void 0)},e.prototype.getLanguages=function(){return[].concat(this._languages).concat(this._dynamicLanguages)},e}());a.a.add("editor.modesRegistry",u);var c="plaintext",l=new o.p(c,1);u.registerLanguage({id:c,extensions:[".txt",".gitignore"],aliases:[i.a("plainText.alias","Plain Text"),"text"],mimetypes:["text/plain"]}),s.a.register(l,{brackets:[["(",")"],["[","]"],["{","}"]]})},"9bHL":function(e,t,n){"use strict";var i=n("TU7t"),r=n("tqet"),o=n("Bug4"),s=n("7/Cv"),a=n("Kp7x"),u=n("Gxst"),c=n("qecS"),l=n("vbff");function d(e,t){for(var n=[],i=0,r=t;i=o.range.end)){if(e.end=0;a--)(r=e[a])&&(s=(o<3?r(s):o>3?r(t,n,s):r(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},C={useShadows:!0,verticalScrollMode:1,setRowLineHeight:!0,supportDynamicHeights:!1,dnd:{getDragElements:function(e){return[e]},getDragURI:function(){return null},onDragStart:function(){},onDragOver:function(){return!1},drop:function(){}},horizontalScrolling:!1},S=function(){function e(e){this.elements=e}return e.prototype.update=function(){},e.prototype.getData=function(){return this.elements},e}(),x=function(){function e(e){this.elements=e}return e.prototype.update=function(){},e.prototype.getData=function(){return this.elements},e}(),L=function(){function e(){this.types=[],this.files=[]}return e.prototype.update=function(e){var t;if(e.types&&(t=this.types).splice.apply(t,[0,this.types.length].concat(e.types)),e.files){this.files.splice(0,this.files.length);for(var n=0;n=this.items.length?(this.rangeMap=new f,this.rangeMap.splice(0,0,v),this.items=v,d=[]):(this.rangeMap.splice(e,t,v),d=(i=this.items).splice.apply(i,[e,t].concat(v)));var _=n.length-t,b=this.getRenderRange(this.lastRenderTop,this.lastRenderHeight),y=h(g,_),w=l.a.intersect(b,y);for(c=w.start;c=-1&&en&&(this.scrollTop+=Math.min(14,Math.floor(.3*(t-n))))}},e.prototype.teardownDragAndDropScrollTopAnimation=function(){this.dragOverAnimationStopDisposable.dispose(),this.dragOverAnimationDisposable&&(this.dragOverAnimationDisposable.dispose(),this.dragOverAnimationDisposable=void 0)},e.prototype.getItemIndexFromEventTarget=function(e){for(var t=e;t instanceof HTMLElement&&t!==this.rowsContainer;){var n=t.getAttribute("data-index");if(n){var i=Number(n);if(!isNaN(i))return i}t=t.parentElement}},e.prototype.getRenderRange=function(e,t){return{start:this.rangeMap.indexAt(e),end:this.rangeMap.indexAfter(e+t-1)}},e.prototype._rerender=function(e,t){var n,i,r=this.getRenderRange(e,t);e===this.elementTop(r.start)?(n=r.start,i=0):r.end-r.start>1&&(n=r.start+1,i=this.elementTop(n)-e);for(var o=0;;){for(var s=this.getRenderRange(e,t),a=!1,u=s.start;un-h-2)throw new Error("message too long");var f=d.alloc(n-i-h-2),p=n-l-1,g=r(l),m=a(d.concat([c,f,d.alloc(1,1),t],p),s(g,p)),v=a(g,s(m,l));return new u(d.concat([d.alloc(1),v,m],n))}(p,t);else if(1===h)f=function(e,t,n){var i,o=t.length,s=e.modulus.byteLength();if(o>s-11)throw new Error("message too long");i=n?d.alloc(s-o-3,255):function(e){var t,n=d.allocUnsafe(e),i=0,o=r(2*e),s=0;for(;i=0)throw new Error("data too long for modulus")}return n?l(f,p):c(f,p)}},"9uVW":function(e,t,n){"use strict";n.d(t,"b",function(){return l}),n.d(t,"a",function(){return h}),n.d(t,"c",function(){return f});var i=n("hK2W"),r=n("Kp7x"),o=n("ZYUE"),s=n("tqet"),a=n("aL7J"),u=n("ZNRA"),c=n("vTy2"),l=function(){function e(e,t,n){this.parent=e,this._range=t,this.isProviderFirst=n,this._onRefChanged=new r.a,this.onRefChanged=this._onRefChanged.event,this.id=u.b.nextId()}return Object.defineProperty(e.prototype,"uri",{get:function(){return this.parent.uri},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"range",{get:function(){return this._range},set:function(e){this._range=e,this._onRefChanged.fire(this)},enumerable:!0,configurable:!0}),e.prototype.getAriaMessage=function(){return Object(i.a)("aria.oneReference","symbol in {0} on line {1} at column {2}",Object(o.b)(this.uri),this.range.startLineNumber,this.range.startColumn)},e}(),d=function(){function e(e){this._modelReference=e}return e.prototype.dispose=function(){Object(s.f)(this._modelReference)},e.prototype.preview=function(e,t){void 0===t&&(t=8);var n=this._modelReference.object.textEditorModel;if(n){var i=e.startLineNumber,r=e.startColumn,o=e.endLineNumber,s=e.endColumn,u=n.getWordUntilPosition({lineNumber:i,column:r-t}),l=new c.a(i,u.startColumn,i,r),d=new c.a(o,s,o,Number.MAX_VALUE),h=n.getValueInRange(l).replace(/^\s+/,a.l),f=n.getValueInRange(e);return{value:h+f+n.getValueInRange(d).replace(/\s+$/,a.l),highlight:{start:h.length,end:h.length+f.length}}}},e}(),h=function(){function e(e,t){this._parent=e,this._uri=t,this._children=[]}return Object.defineProperty(e.prototype,"id",{get:function(){return this._uri.toString()},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"parent",{get:function(){return this._parent},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"children",{get:function(){return this._children},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"uri",{get:function(){return this._uri},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"preview",{get:function(){return this._preview},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"failure",{get:function(){return this._loadFailure},enumerable:!0,configurable:!0}),e.prototype.getAriaMessage=function(){var e=this.children.length;return 1===e?Object(i.a)("aria.fileReferences.1","1 symbol in {0}, full path {1}",Object(o.b)(this.uri),this.uri.fsPath):Object(i.a)("aria.fileReferences.N","{0} symbols in {1}, full path {2}",e,Object(o.b)(this.uri),this.uri.fsPath)},e.prototype.resolve=function(e){var t=this;return this._resolved?Promise.resolve(this):Promise.resolve(e.createModelReference(this._uri).then(function(e){if(!e.object)throw e.dispose(),new Error;return t._preview=new d(e),t._resolved=!0,t},function(e){return t._children=[],t._resolved=!0,t._loadFailure=e,t}))},e.prototype.dispose=function(){this._preview&&(this._preview.dispose(),this._preview=void 0)},e}(),f=function(){function e(t){var n=this;this._disposables=new s.b,this.groups=[],this.references=[],this._onDidChangeReferenceRange=new r.a,this.onDidChangeReferenceRange=this._onDidChangeReferenceRange.event;var i,o=t[0];t.sort(e._compareReferences);for(var a=0,u=t;a0?(i=t?(i+1)%r:(i+r-1)%r,n.children[i]):(i=n.parent.groups.indexOf(n),t?(i=(i+1)%o,n.parent.groups[i].children[0]):(i=(i+o-1)%o,n.parent.groups[i].children[n.parent.groups[i].children.length-1]))},e.prototype.nearestReference=function(e,t){var n=this.references.map(function(n,i){return{idx:i,prefixLen:a.b(n.uri.toString(),e.toString()),offsetDist:100*Math.abs(n.range.startLineNumber-t.lineNumber)+Math.abs(n.range.startColumn-t.column)}}).sort(function(e,t){return e.prefixLen>t.prefixLen?-1:e.prefixLent.offsetDist?1:0})[0];if(n)return this.references[n.idx]},e.prototype.firstReference=function(){for(var e=0,t=this.references;ei?1:c.a.compareRangesUsingStarts(e.range,t.range)},e}()},"9vcT":function(e,t){},AKCZ:function(e,t,n){"use strict";n.d(t,"a",function(){return c}),n.d(t,"b",function(){return l});var i,r=n("tqet"),o=n("Kp7x"),s=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),a=this&&this.__awaiter||function(e,t,n,i){return new(n||(n=Promise))(function(r,o){function s(e){try{u(i.next(e))}catch(e){o(e)}}function a(e){try{u(i.throw(e))}catch(e){o(e)}}function u(e){e.done?r(e.value):new n(function(t){t(e.value)}).then(s,a)}u((i=i.apply(e,t||[])).next())})},u=this&&this.__generator||function(e,t){var n,i,r,o,s={label:0,sent:function(){if(1&r[0])throw r[1];return r[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,i&&(r=2&o[0]?i.return:o[0]?i.throw||((r=i.return)&&r.call(i),0):i.next)&&!(r=r.call(i,o[1])).done)return r;switch(i=0,r&&(o=[2&o[0],r.value]),o[0]){case 0:case 1:r=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,i=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(r=(r=s.trys).length>0&&r[r.length-1])&&(6===o[0]||2===o[0])){s=0;continue}if(3===o[0]&&(!r||o[1]>r[0]&&o[1]n)?t=("rmd160"===e?new u:c(e)).update(t).digest():t.length0;i--)t+=this._buffer(e,t),n+=this._flushBuffer(r,n);return t+=this._buffer(e,t),r},r.prototype.final=function(e){var t,n;return e&&(t=this.update(e)),n="encrypt"===this.type?this._finalEncrypt():this._finalDecrypt(),t?t.concat(n):n},r.prototype._pad=function(e,t){if(0===t)return!1;for(;t0?n.actionBar.push(o,{icon:!0,label:!1}):n.actionBar.isEmpty()||o&&0!==o.length||n.actionBar.clear(),e instanceof b&&e.getGroupLabel()?u.f(n.container,"has-group-label"):u.I(n.container,"has-group-label"),e instanceof b){var s=e,a=n;s.showBorder()?(u.f(a.container,"results-group-separator"),i.pickerGroupBorder&&(a.container.style.borderTopColor=i.pickerGroupBorder.toString())):(u.I(a.container,"results-group-separator"),a.container.style.borderTopColor=null);var c=s.getGroupLabel()||"";a.group&&(a.group.textContent=c,i.pickerGroupForeground&&(a.group.style.color=i.pickerGroupForeground.toString()))}if(e instanceof _){var l=e.getHighlights(),d=l[0],h=l[1],f=l[2],p=e.getIcon()?"quick-open-entry-icon "+e.getIcon():"";n.icon.className=p;var g=e.getLabelOptions()||Object.create(null);g.matches=d||[],g.title=e.getTooltip(),g.descriptionTitle=e.getDescriptionTooltip()||e.getDescription(),g.descriptionMatches=h||[],n.label.setLabel(r.m(e.getLabel()),e.getDescription(),g),n.detail.set(e.getDetail(),f),n.keybinding.set(e.getKeybinding())}},e.prototype.disposeTemplate=function(e,t){t.actionBar.dispose(),t.actionBar=null,t.container=null,t.entry=null,t.keybinding=null,t.detail=null,t.group=null,t.icon=null,t.label.dispose(),t.label=null},e}(),C=function(){function e(e,t){void 0===e&&(e=[]),void 0===t&&(t=new y),this._entries=e,this._dataSource=this,this._renderer=new w(t),this._filter=this,this._runner=this,this._accessibilityProvider=this}return Object.defineProperty(e.prototype,"entries",{get:function(){return this._entries},set:function(e){this._entries=e},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"dataSource",{get:function(){return this._dataSource},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"renderer",{get:function(){return this._renderer},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"filter",{get:function(){return this._filter},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"runner",{get:function(){return this._runner},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"accessibilityProvider",{get:function(){return this._accessibilityProvider},enumerable:!0,configurable:!0}),e.prototype.getId=function(e){return e.getId()},e.prototype.getLabel=function(e){return r.n(e.getLabel())},e.prototype.getAriaLabel=function(e){return e.getAriaLabel()?i.a("quickOpenAriaLabelEntry","{0}, picker",e.getAriaLabel()):i.a("quickOpenAriaLabel","picker")},e.prototype.isVisible=function(e){return!e.isHidden()},e.prototype.run=function(e,t,n){return e.run(t,n)},e}()},Ao9X:function(e,t,n){"use strict";n.d(t,"a",function(){return r}),n.d(t,"d",function(){return o}),n.d(t,"c",function(){return s}),n.d(t,"b",function(){return a});var i=n("iHM7"),r=function(){function e(e,t,n){void 0===n&&(n=!1),this._range=e,this._text=t,this.insertsAutoWhitespace=n}return e.prototype.getEditOperations=function(e,t){t.addTrackedEditOperation(this._range,this._text)},e.prototype.computeCursorState=function(e,t){var n=t.getInverseEditOperations()[0].range;return new i.a(n.endLineNumber,n.endColumn,n.endLineNumber,n.endColumn)},e}(),o=function(){function e(e,t,n){void 0===n&&(n=!1),this._range=e,this._text=t,this.insertsAutoWhitespace=n}return e.prototype.getEditOperations=function(e,t){t.addTrackedEditOperation(this._range,this._text)},e.prototype.computeCursorState=function(e,t){var n=t.getInverseEditOperations()[0].range;return new i.a(n.startLineNumber,n.startColumn,n.startLineNumber,n.startColumn)},e}(),s=function(){function e(e,t,n,i,r){void 0===r&&(r=!1),this._range=e,this._text=t,this._columnDeltaOffset=i,this._lineNumberDeltaOffset=n,this.insertsAutoWhitespace=r}return e.prototype.getEditOperations=function(e,t){t.addTrackedEditOperation(this._range,this._text)},e.prototype.computeCursorState=function(e,t){var n=t.getInverseEditOperations()[0].range;return new i.a(n.endLineNumber+this._lineNumberDeltaOffset,n.endColumn+this._columnDeltaOffset,n.endLineNumber+this._lineNumberDeltaOffset,n.endColumn+this._columnDeltaOffset)},e}(),a=function(){function e(e,t,n){this._range=e,this._text=t,this._initialSelection=n,this._selectionId=null}return e.prototype.getEditOperations=function(e,t){t.addEditOperation(this._range,this._text),this._selectionId=t.trackSelection(this._initialSelection)},e.prototype.computeCursorState=function(e,t){return t.getTrackedSelection(this._selectionId)},e}()},"B/Xy":function(e,t,n){"use strict";n.d(t,"a",function(){return r});var i=n("JVO/"),r=Object(i.c)("textModelService")},B6Bn:function(e,t,n){"use strict";var i=n("geuY"),r=n("lZ6o").utils,o=r.getNAF,s=r.getJSF,a=r.assert;function u(e,t){this.type=e,this.p=new i(t.p,16),this.red=t.prime?i.red(t.prime):i.mont(this.p),this.zero=new i(0).toRed(this.red),this.one=new i(1).toRed(this.red),this.two=new i(2).toRed(this.red),this.n=t.n&&new i(t.n,16),this.g=t.g&&this.pointFromJSON(t.g,t.gRed),this._wnafT1=new Array(4),this._wnafT2=new Array(4),this._wnafT3=new Array(4),this._wnafT4=new Array(4);var n=this.n&&this.p.div(this.n);!n||n.cmpn(100)>0?this.redN=null:(this._maxwellTrick=!0,this.redN=this.n.toRed(this.red))}function c(e,t){this.curve=e,this.type=t,this.precomputed=null}e.exports=u,u.prototype.point=function(){throw new Error("Not implemented")},u.prototype.validate=function(){throw new Error("Not implemented")},u.prototype._fixedNafMul=function(e,t){a(e.precomputed);var n=e._getDoubles(),i=o(t,1),r=(1<=u;t--)c=(c<<1)+i[t];s.push(c)}for(var l=this.jpoint(null,null,null),d=this.jpoint(null,null,null),h=r;h>0;h--){for(u=0;u=0;c--){for(t=0;c>=0&&0===s[c];c--)t++;if(c>=0&&t++,u=u.dblp(t),c<0)break;var l=s[c];a(0!==l),u="affine"===e.type?l>0?u.mixedAdd(r[l-1>>1]):u.mixedAdd(r[-l-1>>1].neg()):l>0?u.add(r[l-1>>1]):u.add(r[-l-1>>1].neg())}return"affine"===e.type?u.toP():u},u.prototype._wnafMulAdd=function(e,t,n,i,r){for(var a=this._wnafT1,u=this._wnafT2,c=this._wnafT3,l=0,d=0;d=1;d-=2){var f=d-1,p=d;if(1===a[f]&&1===a[p]){var g=[t[f],null,null,t[p]];0===t[f].y.cmp(t[p].y)?(g[1]=t[f].add(t[p]),g[2]=t[f].toJ().mixedAdd(t[p].neg())):0===t[f].y.cmp(t[p].y.redNeg())?(g[1]=t[f].toJ().mixedAdd(t[p]),g[2]=t[f].add(t[p].neg())):(g[1]=t[f].toJ().mixedAdd(t[p]),g[2]=t[f].toJ().mixedAdd(t[p].neg()));var m=[-3,-1,-5,-7,0,7,5,1,3],v=s(n[f],n[p]);l=Math.max(v[0].length,l),c[f]=new Array(l),c[p]=new Array(l);for(var _=0;_=0;d--){for(var S=0;d>=0;){var x=!0;for(_=0;_=0&&S++,w=w.dblp(S),d<0)break;for(_=0;_0?L=u[_][O-1>>1]:O<0&&(L=u[_][-O-1>>1].neg()),w="affine"===L.type?w.mixedAdd(L):w.add(L))}}for(d=0;d=Math.ceil((e.bitLength()+1)/t.step)},c.prototype._getDoubles=function(e,t){if(this.precomputed&&this.precomputed.doubles)return this.precomputed.doubles;for(var n=[this],i=this,r=0;r>>24]^l[p>>>16&255]^d[g>>>8&255]^h[255&m]^t[v++],s=c[p>>>24]^l[g>>>16&255]^d[m>>>8&255]^h[255&f]^t[v++],a=c[g>>>24]^l[m>>>16&255]^d[f>>>8&255]^h[255&p]^t[v++],u=c[m>>>24]^l[f>>>16&255]^d[p>>>8&255]^h[255&g]^t[v++],f=o,p=s,g=a,m=u;return o=(i[f>>>24]<<24|i[p>>>16&255]<<16|i[g>>>8&255]<<8|i[255&m])^t[v++],s=(i[p>>>24]<<24|i[g>>>16&255]<<16|i[m>>>8&255]<<8|i[255&f])^t[v++],a=(i[g>>>24]<<24|i[m>>>16&255]<<16|i[f>>>8&255]<<8|i[255&p])^t[v++],u=(i[m>>>24]<<24|i[f>>>16&255]<<16|i[p>>>8&255]<<8|i[255&g])^t[v++],[o>>>=0,s>>>=0,a>>>=0,u>>>=0]}var a=[0,1,2,4,8,16,32,64,128,27,54],u=function(){for(var e=new Array(256),t=0;t<256;t++)e[t]=t<128?t<<1:t<<1^283;for(var n=[],i=[],r=[[],[],[],[]],o=[[],[],[],[]],s=0,a=0,u=0;u<256;++u){var c=a^a<<1^a<<2^a<<3^a<<4;c=c>>>8^255&c^99,n[s]=c,i[c]=s;var l=e[s],d=e[l],h=e[d],f=257*e[c]^16843008*c;r[0][s]=f<<24|f>>>8,r[1][s]=f<<16|f>>>16,r[2][s]=f<<8|f>>>24,r[3][s]=f,f=16843009*h^65537*d^257*l^16843008*s,o[0][c]=f<<24|f>>>8,o[1][c]=f<<16|f>>>16,o[2][c]=f<<8|f>>>24,o[3][c]=f,0===s?s=a=1:(s=l^e[e[e[h^l]]],a^=e[e[a]])}return{SBOX:n,INV_SBOX:i,SUB_MIX:r,INV_SUB_MIX:o}}();function c(e){this._key=r(e),this._reset()}c.blockSize=16,c.keySize=32,c.prototype.blockSize=c.blockSize,c.prototype.keySize=c.keySize,c.prototype._reset=function(){for(var e=this._key,t=e.length,n=t+6,i=4*(n+1),r=[],o=0;o>>24,s=u.SBOX[s>>>24]<<24|u.SBOX[s>>>16&255]<<16|u.SBOX[s>>>8&255]<<8|u.SBOX[255&s],s^=a[o/t|0]<<24):t>6&&o%t==4&&(s=u.SBOX[s>>>24]<<24|u.SBOX[s>>>16&255]<<16|u.SBOX[s>>>8&255]<<8|u.SBOX[255&s]),r[o]=r[o-t]^s}for(var c=[],l=0;l>>24]]^u.INV_SUB_MIX[1][u.SBOX[h>>>16&255]]^u.INV_SUB_MIX[2][u.SBOX[h>>>8&255]]^u.INV_SUB_MIX[3][u.SBOX[255&h]]}this._nRounds=n,this._keySchedule=r,this._invKeySchedule=c},c.prototype.encryptBlockRaw=function(e){return s(e=r(e),this._keySchedule,u.SUB_MIX,u.SBOX,this._nRounds)},c.prototype.encryptBlock=function(e){var t=this.encryptBlockRaw(e),n=i.allocUnsafe(16);return n.writeUInt32BE(t[0],0),n.writeUInt32BE(t[1],4),n.writeUInt32BE(t[2],8),n.writeUInt32BE(t[3],12),n},c.prototype.decryptBlock=function(e){var t=(e=r(e))[1];e[1]=e[3],e[3]=t;var n=s(e,this._invKeySchedule,u.INV_SUB_MIX,u.INV_SBOX,this._nRounds),o=i.allocUnsafe(16);return o.writeUInt32BE(n[0],0),o.writeUInt32BE(n[3],4),o.writeUInt32BE(n[2],8),o.writeUInt32BE(n[1],12),o},c.prototype.scrub=function(){o(this._keySchedule),o(this._invKeySchedule),o(this._key)},e.exports.AES=c},BO8W:function(e,t,n){"use strict";t.utils=n("iNQt"),t.Cipher=n("AWjC"),t.DES=n("Icsf"),t.CBC=n("nyV4"),t.EDE=n("YePo")},BVsN:function(e,t,n){"use strict";var i=n("LC74"),r=n("eCz2"),o=n("LYGd"),s=n("JaR3"),a=n("z+8S");function u(e){a.call(this,"digest"),this._hash=e}i(u,a),u.prototype._update=function(e){this._hash.update(e)},u.prototype._final=function(){return this._hash.digest()},e.exports=function(e){return"md5"===(e=e.toLowerCase())?new r:"rmd160"===e||"ripemd160"===e?new o:new u(s(e))}},Bug4:function(e,t,n){"use strict";n.d(t,"a",function(){return r}),n.d(t,"b",function(){return d});var i,r,o=n("X6iQ"),s=n("tqet"),a=n("7/Cv"),u=n("2VYG"),c=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),l=this&&this.__decorate||function(e,t,n,i){var r,o=arguments.length,s=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,n):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,i);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(s=(o<3?r(s):o>3?r(t,n,s):r(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s};!function(e){e.Tap="-monaco-gesturetap",e.Change="-monaco-gesturechange",e.Start="-monaco-gesturestart",e.End="-monaco-gesturesend",e.Contextmenu="-monaco-gesturecontextmenu"}(r||(r={}));var d=function(e){function t(){var t=e.call(this)||this;return t.dispatched=!1,t.activeTouches={},t.handle=null,t.targets=[],t._register(a.h(document,"touchstart",function(e){return t.onTouchStart(e)})),t._register(a.h(document,"touchend",function(e){return t.onTouchEnd(e)})),t._register(a.h(document,"touchmove",function(e){return t.onTouchMove(e)})),t}return c(t,e),t.addTarget=function(e){t.isTouchDevice()&&(t.INSTANCE||(t.INSTANCE=new t),t.INSTANCE.targets.push(e))},t.isTouchDevice=function(){return"ontouchstart"in window||navigator.maxTouchPoints>0||window.navigator.msMaxTouchPoints>0},t.prototype.dispose=function(){this.handle&&(this.handle.dispose(),this.handle=null),e.prototype.dispose.call(this)},t.prototype.onTouchStart=function(e){var t=Date.now();this.handle&&(this.handle.dispose(),this.handle=null);for(var n=0,i=e.targetTouches.length;n=t.HOLD_DELAY&&Math.abs(l.initialPageX-o.s(l.rollingPageX))<30&&Math.abs(l.initialPageY-o.s(l.rollingPageY))<30){var h;(h=a.newGestureEvent(r.Contextmenu,l.initialTarget)).pageX=o.s(l.rollingPageX),h.pageY=o.s(l.rollingPageY),a.dispatchEvent(h)}else if(1===i){var f=o.s(l.rollingPageX),p=o.s(l.rollingPageY),g=o.s(l.rollingTimestamps)-l.rollingTimestamps[0],m=f-l.rollingPageX[0],v=p-l.rollingPageY[0],_=a.targets.filter(function(e){return l.initialTarget instanceof Node&&e.contains(l.initialTarget)});a.inertia(_,n,Math.abs(m)/g,m>0?1:-1,f,Math.abs(v)/g,v>0?1:-1,p)}a.dispatchEvent(a.newGestureEvent(r.End,l.initialTarget)),delete a.activeTouches[c.identifier]},a=this,u=0,c=e.changedTouches.length;u0&&(g=!1,f=o*i*h),u>0&&(g=!1,p=c*u*h);var m=d.newGestureEvent(r.Change);m.translationX=f,m.translationY=p,e.forEach(function(e){return e.dispatchEvent(m)}),g||d.inertia(e,a,i,o,s+f,u,c,l+p)})},t.prototype.onTouchMove=function(e){for(var t=Date.now(),n=0,i=e.changedTouches.length;n3&&(a.rollingPageX.shift(),a.rollingPageY.shift(),a.rollingTimestamps.shift()),a.rollingPageX.push(s.pageX),a.rollingPageY.push(s.pageY),a.rollingTimestamps.push(t)}else console.warn("end of an UNKNOWN touch",s)}this.dispatched&&(e.preventDefault(),e.stopPropagation(),this.dispatched=!1)},t.SCROLL_FRICTION=-.005,t.HOLD_DELAY=700,l([u.a],t,"isTouchDevice",null),t}(s.a)},Bv73:function(e,t){},BwcV:function(e,t,n){"use strict";n.d(t,"a",function(){return c});var i,r=n("GfE5"),o=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),s=function(e){function t(t){for(var n=e.call(this,0)||this,i=0,r=t.length;i=0){for(var i=[],r=0,o=this._placeholderGroups[this._placeholderGroupsIdx];r0&&this._editor.executeEdits("snippet.placeholderTransform",i)}var d=!1;!0===t&&this._placeholderGroupsIdx0&&(this._placeholderGroupsIdx-=1,d=!0);var h=this._editor.getModel().changeDecorations(function(t){for(var i=new Set,r=[],o=0,s=n._placeholderGroups[n._placeholderGroupsIdx];o0)return!0}t=t.parent}return!1},Object.defineProperty(e.prototype,"isAtFirstPlaceholder",{get:function(){return this._placeholderGroupsIdx<=0||0===this._placeholderGroups.length},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"isAtLastPlaceholder",{get:function(){return this._placeholderGroupsIdx===this._placeholderGroups.length-1},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"hasPlaceholder",{get:function(){return this._snippet.placeholders.length>0},enumerable:!0,configurable:!0}),e.prototype.computePossibleSelections=function(){for(var e=new Map,t=0,n=this._placeholderGroups;t0&&S!==d.getLineFirstNonWhitespaceColumn(F.positionLineNumber))&&e.adjustWhitespace(d,z,H),H.resolveVariables(new x([p,new k(u,j,D.length),new L(d,F),new N(d),new E,new I(h)]));var U=d.getOffsetAt(z)+y;y+=H.toString().length-d.getValueLengthInRange(V),c[j]=f.a.replace(V,H.toString()),l[j]=new P(t,H,U)}return{edits:c,snippets:l}},e.prototype.dispose=function(){Object(i.f)(this._snippets)},e.prototype._logInfo=function(){return'template="'+this._template+'", merged_templates="'+this._templateMerges.join(" -> ")+'"'},e.prototype.insert=function(){var t=this;if(this._editor.hasModel()){var n=e.createEditsAndSnippets(this._editor,this._template,this._options.overwriteBefore,this._options.overwriteAfter,!1,this._options.adjustWhitespace,this._options.clipboardText),i=n.edits,r=n.snippets;this._snippets=r,this._editor.executeEdits("snippet",i,function(e){return t._snippets[0].hasPlaceholder?t._move(!0):e.map(function(e){return a.a.fromPositions(e.range.getEndPosition())})}),this._editor.revealRange(this._editor.getSelections()[0])}},e.prototype.merge=function(t,n){var i=this;if(void 0===n&&(n=A),this._editor.hasModel()){this._templateMerges.push([this._snippets[0]._nestingLevel,this._snippets[0]._placeholderGroupsIdx,t]);var r=e.createEditsAndSnippets(this._editor,t,n.overwriteBefore,n.overwriteAfter,!0,n.adjustWhitespace,n.clipboardText),o=r.edits,s=r.snippets;this._editor.executeEdits("snippet",o,function(e){for(var t=0,n=i._snippets;t0},e}();n.d(t,"SnippetController2",function(){return V});var F=this&&this.__assign||function(){return(F=Object.assign||function(e){for(var t,n=1,i=arguments.length;n=0;a--)(r=e[a])&&(s=(o<3?r(s):o>3?r(t,n,s):r(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},W=this&&this.__param||function(e,t){return function(n,i){t(n,i,e)}},B={overwriteBefore:0,overwriteAfter:0,undoStopBefore:!0,undoStopAfter:!0,adjustWhitespace:!0,clipboardText:void 0},V=function(){function e(t,n,r){this._editor=t,this._logService=n,this._snippetListener=new i.b,this._modelVersionId=-1,this._inSnippet=e.InSnippetMode.bindTo(r),this._hasNextTabstop=e.HasNextTabstop.bindTo(r),this._hasPrevTabstop=e.HasPrevTabstop.bindTo(r)}return e.get=function(e){return e.getContribution("snippetController2")},e.prototype.dispose=function(){this._inSnippet.reset(),this._hasPrevTabstop.reset(),this._hasNextTabstop.reset(),Object(i.f)(this._session),this._snippetListener.dispose()},e.prototype.getId=function(){return"snippetController2"},e.prototype.insert=function(e,t){try{this._doInsert(e,void 0===t?B:F({},B,t))}catch(t){this.cancel(),this._logService.error(t),this._logService.error("snippet_error"),this._logService.error("insert_template=",e),this._logService.error("existing_template=",this._session?this._session._logInfo():"")}},e.prototype._doInsert=function(e,t){var n=this;this._editor.hasModel()&&(this._snippetListener.clear(),t.undoStopBefore&&this._editor.getModel().pushStackElement(),this._session?this._session.merge(e,t):(this._modelVersionId=this._editor.getModel().getAlternativeVersionId(),this._session=new R(this._editor,e,t),this._session.insert()),t.undoStopAfter&&this._editor.getModel().pushStackElement(),this._updateState(),this._snippetListener.add(this._editor.onDidChangeModelContent(function(e){return e.isFlush&&n.cancel()})),this._snippetListener.add(this._editor.onDidChangeModel(function(){return n.cancel()})),this._snippetListener.add(this._editor.onDidChangeCursorSelection(function(){return n._updateState()})))},e.prototype._updateState=function(){if(this._session&&this._editor.hasModel()){if(this._modelVersionId===this._editor.getModel().getAlternativeVersionId())return this.cancel();if(!this._session.hasPlaceholder)return this.cancel();if(this._session.isAtLastPlaceholder||!this._session.isSelectionWithinPlaceholders())return this.cancel();this._inSnippet.set(!0),this._hasPrevTabstop.set(!this._session.isAtFirstPlaceholder),this._hasNextTabstop.set(!this._session.isAtLastPlaceholder),this._handleChoice()}},e.prototype._handleChoice=function(){var e=this;if(this._session&&this._editor.hasModel()){var t=this._session.choice;if(t){if(this._currentChoice!==t){this._currentChoice=t,this._editor.setSelections(this._editor.getSelections().map(function(e){return a.a.fromPositions(e.getStartPosition())}));var n=t.options[0];Object(c.f)(this._editor,t.options.map(function(t,i){return{kind:13,label:t.value,insertText:t.value,sortText:Object(r.F)("a",i+1),range:s.a.fromPositions(e._editor.getPosition(),e._editor.getPosition().delta(0,n.value.length))}}))}}else this._currentChoice=void 0}else this._currentChoice=void 0},e.prototype.finish=function(){for(;this._inSnippet.get();)this.next()},e.prototype.cancel=function(e){void 0===e&&(e=!1),this._inSnippet.reset(),this._hasPrevTabstop.reset(),this._hasNextTabstop.reset(),this._snippetListener.clear(),Object(i.f)(this._session),this._session=void 0,this._modelVersionId=-1,e&&this._editor.setSelections([this._editor.getSelection()])},e.prototype.prev=function(){this._session&&this._session.prev(),this._updateState()},e.prototype.next=function(){this._session&&this._session.next(),this._updateState()},e.prototype.isInSnippet=function(){return Boolean(this._inSnippet.get())},e.InSnippetMode=new l.d("inSnippetMode",!1),e.HasNextTabstop=new l.d("hasNextTabstop",!1),e.HasPrevTabstop=new l.d("hasPrevTabstop",!1),e=j([W(1,d.a),W(2,l.c)],e)}();Object(o.h)(V);var H=o.c.bindToContribution(V.get);Object(o.g)(new H({id:"jumpToNextSnippetPlaceholder",precondition:l.a.and(V.InSnippetMode,V.HasNextTabstop),handler:function(e){return e.next()},kbOpts:{weight:130,kbExpr:u.a.editorTextFocus,primary:2}})),Object(o.g)(new H({id:"jumpToPrevSnippetPlaceholder",precondition:l.a.and(V.InSnippetMode,V.HasPrevTabstop),handler:function(e){return e.prev()},kbOpts:{weight:130,kbExpr:u.a.editorTextFocus,primary:1026}})),Object(o.g)(new H({id:"leaveSnippet",precondition:V.InSnippetMode,handler:function(e){return e.cancel(!0)},kbOpts:{weight:130,kbExpr:u.a.editorTextFocus,primary:9,secondary:[1033]}})),Object(o.g)(new H({id:"acceptSnippet",precondition:V.InSnippetMode,handler:function(e){return e.finish()}}))},C015:function(e,t,n){var i=n("LC74"),r=n("CzQx"),o=n("X3l8").Buffer,s=[1116352408,3609767458,1899447441,602891725,3049323471,3964484399,3921009573,2173295548,961987163,4081628472,1508970993,3053834265,2453635748,2937671579,2870763221,3664609560,3624381080,2734883394,310598401,1164996542,607225278,1323610764,1426881987,3590304994,1925078388,4068182383,2162078206,991336113,2614888103,633803317,3248222580,3479774868,3835390401,2666613458,4022224774,944711139,264347078,2341262773,604807628,2007800933,770255983,1495990901,1249150122,1856431235,1555081692,3175218132,1996064986,2198950837,2554220882,3999719339,2821834349,766784016,2952996808,2566594879,3210313671,3203337956,3336571891,1034457026,3584528711,2466948901,113926993,3758326383,338241895,168717936,666307205,1188179964,773529912,1546045734,1294757372,1522805485,1396182291,2643833823,1695183700,2343527390,1986661051,1014477480,2177026350,1206759142,2456956037,344077627,2730485921,1290863460,2820302411,3158454273,3259730800,3505952657,3345764771,106217008,3516065817,3606008344,3600352804,1432725776,4094571909,1467031594,275423344,851169720,430227734,3100823752,506948616,1363258195,659060556,3750685593,883997877,3785050280,958139571,3318307427,1322822218,3812723403,1537002063,2003034995,1747873779,3602036899,1955562222,1575990012,2024104815,1125592928,2227730452,2716904306,2361852424,442776044,2428436474,593698344,2756734187,3733110249,3204031479,2999351573,3329325298,3815920427,3391569614,3928383900,3515267271,566280711,3940187606,3454069534,4118630271,4000239992,116418474,1914138554,174292421,2731055270,289380356,3203993006,460393269,320620315,685471733,587496836,852142971,1086792851,1017036298,365543100,1126000580,2618297676,1288033470,3409855158,1501505948,4234509866,1607167915,987167468,1816402316,1246189591],a=new Array(160);function u(){this.init(),this._w=a,r.call(this,128,112)}function c(e,t,n){return n^e&(t^n)}function l(e,t,n){return e&t|n&(e|t)}function d(e,t){return(e>>>28|t<<4)^(t>>>2|e<<30)^(t>>>7|e<<25)}function h(e,t){return(e>>>14|t<<18)^(e>>>18|t<<14)^(t>>>9|e<<23)}function f(e,t){return(e>>>1|t<<31)^(e>>>8|t<<24)^e>>>7}function p(e,t){return(e>>>1|t<<31)^(e>>>8|t<<24)^(e>>>7|t<<25)}function g(e,t){return(e>>>19|t<<13)^(t>>>29|e<<3)^e>>>6}function m(e,t){return(e>>>19|t<<13)^(t>>>29|e<<3)^(e>>>6|t<<26)}function v(e,t){return e>>>0>>0?1:0}i(u,r),u.prototype.init=function(){return this._ah=1779033703,this._bh=3144134277,this._ch=1013904242,this._dh=2773480762,this._eh=1359893119,this._fh=2600822924,this._gh=528734635,this._hh=1541459225,this._al=4089235720,this._bl=2227873595,this._cl=4271175723,this._dl=1595750129,this._el=2917565137,this._fl=725511199,this._gl=4215389547,this._hl=327033209,this},u.prototype._update=function(e){for(var t=this._w,n=0|this._ah,i=0|this._bh,r=0|this._ch,o=0|this._dh,a=0|this._eh,u=0|this._fh,_=0|this._gh,b=0|this._hh,y=0|this._al,w=0|this._bl,C=0|this._cl,S=0|this._dl,x=0|this._el,L=0|this._fl,O=0|this._gl,k=0|this._hl,N=0;N<32;N+=2)t[N]=e.readInt32BE(4*N),t[N+1]=e.readInt32BE(4*N+4);for(;N<160;N+=2){var E=t[N-30],I=t[N-30+1],D=f(E,I),M=p(I,E),T=g(E=t[N-4],I=t[N-4+1]),P=m(I,E),A=t[N-14],R=t[N-14+1],F=t[N-32],j=t[N-32+1],W=M+R|0,B=D+A+v(W,M)|0;B=(B=B+T+v(W=W+P|0,P)|0)+F+v(W=W+j|0,j)|0,t[N]=B,t[N+1]=W}for(var V=0;V<160;V+=2){B=t[V],W=t[V+1];var H=l(n,i,r),z=l(y,w,C),U=d(n,y),K=d(y,n),q=h(a,x),G=h(x,a),Z=s[V],Y=s[V+1],X=c(a,u,_),$=c(x,L,O),J=k+G|0,Q=b+q+v(J,k)|0;Q=(Q=(Q=Q+X+v(J=J+$|0,$)|0)+Z+v(J=J+Y|0,Y)|0)+B+v(J=J+W|0,W)|0;var ee=K+z|0,te=U+H+v(ee,K)|0;b=_,k=O,_=u,O=L,u=a,L=x,a=o+Q+v(x=S+J|0,S)|0,o=r,S=C,r=i,C=w,i=n,w=y,n=Q+te+v(y=J+ee|0,J)|0}this._al=this._al+y|0,this._bl=this._bl+w|0,this._cl=this._cl+C|0,this._dl=this._dl+S|0,this._el=this._el+x|0,this._fl=this._fl+L|0,this._gl=this._gl+O|0,this._hl=this._hl+k|0,this._ah=this._ah+n+v(this._al,y)|0,this._bh=this._bh+i+v(this._bl,w)|0,this._ch=this._ch+r+v(this._cl,C)|0,this._dh=this._dh+o+v(this._dl,S)|0,this._eh=this._eh+a+v(this._el,x)|0,this._fh=this._fh+u+v(this._fl,L)|0,this._gh=this._gh+_+v(this._gl,O)|0,this._hh=this._hh+b+v(this._hl,k)|0},u.prototype._hash=function(){var e=o.allocUnsafe(64);function t(t,n,i){e.writeInt32BE(t,i),e.writeInt32BE(n,i+4)}return t(this._ah,this._al,0),t(this._bh,this._bl,8),t(this._ch,this._cl,16),t(this._dh,this._dl,24),t(this._eh,this._el,32),t(this._fh,this._fl,40),t(this._gh,this._gl,48),t(this._hh,this._hl,56),e},e.exports=u},C1C2:function(e,t,n){var i=n("TnCn");t.tagClass={0:"universal",1:"application",2:"context",3:"private"},t.tagClassByName=i._reverse(t.tagClass),t.tag={0:"end",1:"bool",2:"int",3:"bitstr",4:"octstr",5:"null_",6:"objid",7:"objDesc",8:"external",9:"real",10:"enum",11:"embed",12:"utf8str",13:"relativeOid",16:"seq",17:"set",18:"numstr",19:"printstr",20:"t61str",21:"videostr",22:"ia5str",23:"utctime",24:"gentime",25:"graphstr",26:"iso646str",27:"genstr",28:"unistr",29:"charstr",30:"bmpstr"},t.tagByName=i._reverse(t.tag)},C3c5:function(e,t,n){"use strict";t.e=h,n.d(t,"a",function(){return f}),n.d(t,"c",function(){return p}),n.d(t,"d",function(){return m}),n.d(t,"b",function(){return v});var i,r=n("AKCZ"),o=n("JVO/"),s=n("7g0X"),a=n("ItKl"),u=n("Kp7x"),c=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),l=this&&this.__decorate||function(e,t,n,i){var r,o=arguments.length,s=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,n):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,i);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(s=(o<3?r(s):o>3?r(t,n,s):r(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},d=this&&this.__param||function(e,t){return function(n,i){t(n,i,e)}};function h(e){return void 0!==e.command}var f=Object(o.c)("menuService"),p=new(function(){function e(){this._commands=new Map,this._menuItems=new Map,this._onDidChangeMenu=new u.a,this.onDidChangeMenu=this._onDidChangeMenu.event}return e.prototype.addCommand=function(e){var t=this;return this._commands.set(e.id,e),this._onDidChangeMenu.fire(0),{dispose:function(){t._commands.delete(e.id)&&t._onDidChangeMenu.fire(0)}}},e.prototype.getCommand=function(e){return this._commands.get(e)},e.prototype.getCommands=function(){var e=new Map;return this._commands.forEach(function(t,n){return e.set(n,t)}),e},e.prototype.appendMenuItem=function(e,t){var n=this,i=this._menuItems.get(e);return i?i.push(t):(i=[t],this._menuItems.set(e,i)),this._onDidChangeMenu.fire(e),{dispose:function(){var r=i.indexOf(t);r>=0&&(i.splice(r,1),n._onDidChangeMenu.fire(e))}}},e.prototype.getMenuItems=function(e){var t=(this._menuItems.get(e)||[]).slice(0);return 0===e&&this._appendImplicitItems(t),t},e.prototype._appendImplicitItems=function(e){for(var t=new Set,n=0,i=e.filter(function(e){return h(e)});n=0;r--){var o=e.charCodeAt(r),s=t.get(o);if(0===s){if(2===i)return this._createWord(e,i,s,r+1,this._findEndOfWord(e,t,i,r+1));i=1}else if(2===s){if(1===i)return this._createWord(e,i,s,r+1,this._findEndOfWord(e,t,i,r+1));i=2}else if(1===s&&0!==i)return this._createWord(e,i,s,r+1,this._findEndOfWord(e,t,i,r+1))}return 0!==i?this._createWord(e,i,1,0,this._findEndOfWord(e,t,i,0)):null},e._findEndOfWord=function(e,t,n,i){for(var r=e.length,o=i;o=0;r--){var o=e.charCodeAt(r),s=t.get(o);if(1===s)return r+1;if(1===n&&2===s)return r+1;if(2===n&&0===s)return r+1}return 0},e.moveWordLeft=function(t,n,i,r){var o=i.lineNumber,s=i.column,u=!1;1===s&&o>1&&(u=!0,o-=1,s=n.getLineMaxColumn(o));var c=e._findPreviousWordOnLine(t,n,new a.a(o,s));if(0===r){if(c&&!u)if(n.getLineLastNonWhitespaceColumn(o)1?new a.a(n-1,e.getLineMaxColumn(n-1)):t;for(var o=e.getLineContent(n),s=t.column-1;s>1;s--){var u=o.charCodeAt(s-2),c=o.charCodeAt(s-1);if(95!==u&&95===c)return new a.a(n,s);if(r.y(u)&&r.z(c))return new a.a(n,s);if(r.z(u)&&r.z(c)&&s+1=c.start+1&&(c=e._findNextWordOnLine(t,n,new a.a(o,c.end+1))),s=c?c.start+1:n.getLineMaxColumn(o);return new a.a(o,s)},e._moveWordPartRight=function(e,t){var n=t.lineNumber,i=e.getLineMaxColumn(n);if(t.column===i)return n1?l=1:(c--,l=n.getLineMaxColumn(c)):(h&&l<=h.end+1&&(h=e._findPreviousWordOnLine(t,n,new a.a(c,h.start+1))),h?l=h.end+1:l>1?l=1:(c--,l=n.getLineMaxColumn(c))),new u.a(c,l,s.lineNumber,s.column)},e._deleteWordPartLeft=function(t,n){if(!n.isEmpty())return n;var i=n.getPosition(),r=e._moveWordPartLeft(t,i);return new u.a(i.lineNumber,i.column,r.lineNumber,r.column)},e._findFirstNonWhitespaceChar=function(e,t){for(var n=e.length,i=t;i=p.start+1&&(p=e._findNextWordOnLine(t,n,new a.a(c,p.end+1))),p?l=p.start+1:l255)return 255;return 0|e},t.b=r,t.c=function(e){for(var t=e.length,n=new Uint32Array(t),i=0;i4294967295?4294967295:0|e}},CX1u:function(e,t,n){"use strict";t.c=function(e,t){void 0===t&&(t={});var n=r(t);return n.textContent=e,n},t.b=function(e,t){void 0===t&&(t={});var n=r(t);return function e(t,n,r){var o;if(2===n.type)o=document.createTextNode(n.content||"");else if(3===n.type)o=document.createElement("b");else if(4===n.type)o=document.createElement("i");else if(5===n.type&&r){var s=document.createElement("a");s.href="#",r.disposeables.add(i.k(s,"click",function(e){r.callback(String(n.index),e)})),o=s}else 7===n.type?o=document.createElement("br"):1===n.type&&(o=t);o&&t!==o&&t.appendChild(o),o&&Array.isArray(n.children)&&n.children.forEach(function(t){e(o,t,r)})}(n,function(e){for(var t={type:1,children:[]},n=0,i=t,r=[],a=new o(e);!a.eos();){var u=a.next(),c="\\"===u&&0!==s(a.peek());if(c&&(u=a.next()),c||0===s(u)||u!==a.peek())if("\n"===u)2===i.type&&(i=r.pop()),i.children.push({type:7});else if(2!==i.type){var l={type:2,content:u};i.children.push(l),r.push(i),i=l}else i.content+=u;else{a.advance(),2===i.type&&(i=r.pop());var d=s(u);if(i.type===d||5===i.type&&6===d)i=r.pop();else{var h={type:d,children:[]};5===d&&(h.index=n,n++),i.children.push(h),r.push(i),i=h}}}return 2===i.type&&(i=r.pop()),r.length,t}(e),t.actionHandler),n},t.a=r;var i=n("7/Cv");function r(e){var t=e.inline?"span":"div",n=document.createElement(t);return e.className&&(n.className=e.className),n}var o=function(){function e(e){this.source=e,this.index=0}return e.prototype.eos=function(){return this.index>=this.source.length},e.prototype.next=function(){var e=this.peek();return this.advance(),e},e.prototype.peek=function(){return this.source[this.index]},e.prototype.advance=function(){this.index++},e}();function s(e){switch(e){case"*":return 3;case"_":return 4;case"[":return 5;case"]":return 6;default:return 0}}},Cfmk:function(e,t,n){"use strict";n.d(t,"a",function(){return l}),n.d(t,"c",function(){return r}),n.d(t,"b",function(){return d});var i,r,o=n("JVO/"),s=n("Kp7x"),a=n("tqet"),u=n("KIxu"),c=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),l=Object(o.c)("storageService");!function(e){e[e.NONE=0]="NONE",e[e.SHUTDOWN=1]="SHUTDOWN"}(r||(r={}));var d=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t._serviceBrand=null,t._onDidChangeStorage=t._register(new s.a),t.onDidChangeStorage=t._onDidChangeStorage.event,t.onWillSaveState=s.b.None,t.globalCache=new Map,t.workspaceCache=new Map,t}return c(t,e),t.prototype.getCache=function(e){return 0===e?this.globalCache:this.workspaceCache},t.prototype.get=function(e,t,n){var i=this.getCache(t).get(e);return Object(u.k)(i)?n:i},t.prototype.getBoolean=function(e,t,n){var i=this.getCache(t).get(e);return Object(u.k)(i)?n:"true"===i},t.prototype.store=function(e,t,n){if(Object(u.k)(t))return this.remove(e,n);var i=String(t);return this.getCache(n).get(e)===i?Promise.resolve():(this.getCache(n).set(e,i),this._onDidChangeStorage.fire({scope:n,key:e}),Promise.resolve())},t.prototype.remove=function(e,t){return this.getCache(t).delete(e)?(this._onDidChangeStorage.fire({scope:t,key:e}),Promise.resolve()):Promise.resolve()},t}(a.a)},Cgw8:function(e,t,n){var i=n("X3l8").Buffer,r=n("eCz2");e.exports=function(e,t,n,o){if(i.isBuffer(e)||(e=i.from(e,"binary")),t&&(i.isBuffer(t)||(t=i.from(t,"binary")),8!==t.length))throw new RangeError("salt should be Buffer with 8 byte length");for(var s=n/8,a=i.alloc(s),u=i.alloc(o||0),c=i.alloc(0);s>0||o>0;){var l=new r;l.update(c),l.update(e),t&&l.update(t),c=l.digest();var d=0;if(s>0){var h=a.length-s;d=Math.min(s,c.length),c.copy(a,h,0,d),s-=d}if(d0){var f=u.length-o,p=Math.min(o,c.length-d);c.copy(u,f,d,d+p),o-=p}}return c.fill(0),{key:a,iv:u}}},Crnc:function(e,t,n){"use strict";n.d(t,"a",function(){return a});var i=!1,r=null;function o(e){if(!e.parent||e.parent===e)return null;try{var t=e.location,n=e.parent.location;if(t.protocol!==n.protocol||t.hostname!==n.hostname||t.port!==n.port)return i=!0,null}catch(e){return i=!0,null}return e.parent}function s(e,t){for(var n,i=e.document.getElementsByTagName("iframe"),r=0,o=i.length;r=0;a--)(r=e[a])&&(s=(o<3?r(s):o>3?r(t,n,s):r(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},m=this&&this.__param||function(e,t){return function(n,i){t(n,i,e)}},v=function(e){function t(n,i){var r=e.call(this)||this;return r.closeTimeout=3e3,r._messageWidget=r._register(new a.d),r._messageListeners=r._register(new a.b),r._editor=n,r._visible=t.MESSAGE_VISIBLE.bindTo(i),r._register(r._editor.onDidAttemptReadOnlyEdit(function(){return r._onDidAttemptReadOnlyEdit()})),r}return p(t,e),t.get=function(e){return e.getContribution(t._id)},t.prototype.getId=function(){return t._id},t.prototype.dispose=function(){e.prototype.dispose.call(this),this._visible.reset()},t.prototype.showMessage=function(e,t){var n,i=this;Object(u.a)(e),this._visible.set(!0),this._messageWidget.clear(),this._messageListeners.clear(),this._messageWidget.value=new b(this._editor,t,e),this._messageListeners.add(this._editor.onDidBlurEditorText(function(){return i.closeMessage()})),this._messageListeners.add(this._editor.onDidChangeCursorPosition(function(){return i.closeMessage()})),this._messageListeners.add(this._editor.onDidDispose(function(){return i.closeMessage()})),this._messageListeners.add(this._editor.onDidChangeModel(function(){return i.closeMessage()})),this._messageListeners.add(new s.e(function(){return i.closeMessage()},this.closeTimeout)),this._messageListeners.add(this._editor.onMouseMove(function(e){e.target.position&&(n?n.containsPosition(e.target.position)||i.closeMessage():n=new c.a(t.lineNumber-3,1,e.target.position.lineNumber+3,1))}))},t.prototype.closeMessage=function(){this._visible.reset(),this._messageListeners.clear(),this._messageWidget.value&&this._messageListeners.add(b.fadeOut(this._messageWidget.value))},t.prototype._onDidAttemptReadOnlyEdit=function(){this._editor.hasModel()&&this.showMessage(o.a("editor.readonly","Cannot edit in read-only editor"),this._editor.getPosition())},t._id="editor.contrib.messageController",t.MESSAGE_VISIBLE=new d.d("messageVisible",!1),t=g([m(1,d.c)],t)}(a.a),_=l.c.bindToContribution(v.get);Object(l.g)(new _({id:"leaveEditorMessage",precondition:v.MESSAGE_VISIBLE,handler:function(e){return e.closeMessage()},kbOpts:{weight:130,primary:9}}));var b=function(){function e(e,t,n){var i=t.lineNumber,r=t.column;this.allowEditorOverflow=!0,this.suppressMouseDown=!1,this._editor=e,this._editor.revealLinesInCenterIfOutsideViewport(i,i,0),this._position={lineNumber:i,column:r-1},this._domNode=document.createElement("div"),this._domNode.classList.add("monaco-editor-overlaymessage");var o=document.createElement("div");o.classList.add("message"),o.textContent=n,this._domNode.appendChild(o);var s=document.createElement("div");s.classList.add("anchor"),this._domNode.appendChild(s),this._editor.addContentWidget(this),this._domNode.classList.add("fadeIn")}return e.fadeOut=function(e){var t,n=function(){e.dispose(),clearTimeout(t),e.getDomNode().removeEventListener("animationend",n)};return t=setTimeout(n,110),e.getDomNode().addEventListener("animationend",n),e.getDomNode().classList.add("fadeOut"),{dispose:n}},e.prototype.dispose=function(){this._editor.removeContentWidget(this)},e.prototype.getId=function(){return"messageoverlay"},e.prototype.getDomNode=function(){return this._domNode},e.prototype.getPosition=function(){return{position:this._position,preference:[1]}},e}();Object(l.h)(v),Object(h.f)(function(e,t){var n=e.getColor(f._3);if(n){var i=e.type===h.b?2:1;t.addRule(".monaco-editor .monaco-editor-overlaymessage .anchor { border-top-color: "+n+"; }"),t.addRule(".monaco-editor .monaco-editor-overlaymessage .message { border: "+i+"px solid "+n+"; }")}var r=e.getColor(f._2);r&&t.addRule(".monaco-editor .monaco-editor-overlaymessage .message { background-color: "+r+"; }");var o=e.getColor(f._4);o&&t.addRule(".monaco-editor .monaco-editor-overlaymessage .message { color: "+o+"; }")})},CzQx:function(e,t,n){var i=n("X3l8").Buffer;function r(e,t){this._block=i.alloc(e),this._finalSize=t,this._blockSize=e,this._len=0}r.prototype.update=function(e,t){"string"==typeof e&&(t=t||"utf8",e=i.from(e,t));for(var n=this._block,r=this._blockSize,o=e.length,s=this._len,a=0;a=this._finalSize&&(this._update(this._block),this._block.fill(0));var n=8*this._len;if(n<=4294967295)this._block.writeUInt32BE(n,this._blockSize-4);else{var i=(4294967295&n)>>>0,r=(n-i)/4294967296;this._block.writeUInt32BE(r,this._blockSize-8),this._block.writeUInt32BE(i,this._blockSize-4)}this._update(this._block);var o=this._hash();return e?o.toString(e):o},r.prototype._update=function(){throw new Error("_update must be implemented by subclass")},e.exports=r},D1Va:function(e,t,n){"use strict";e.exports=o;var i=n("DsFX"),r=n("jOgh");function o(e){if(!(this instanceof o))return new o(e);i.call(this,e),this._transformState={afterTransform:function(e,t){var n=this._transformState;n.transforming=!1;var i=n.writecb;if(!i)return this.emit("error",new Error("write callback called multiple times"));n.writechunk=null,n.writecb=null,null!=t&&this.push(t),i(e);var r=this._readableState;r.reading=!1,(r.needReadable||r.length0?i-4:i,d=0;d>16&255,a[u++]=t>>8&255,a[u++]=255&t;2===s&&(t=r[e.charCodeAt(d)]<<2|r[e.charCodeAt(d+1)]>>4,a[u++]=255&t);1===s&&(t=r[e.charCodeAt(d)]<<10|r[e.charCodeAt(d+1)]<<4|r[e.charCodeAt(d+2)]>>2,a[u++]=t>>8&255,a[u++]=255&t);return a},t.fromByteArray=function(e){for(var t,n=e.length,r=n%3,o=[],s=0,a=n-r;sa?a:s+16383));1===r?(t=e[n-1],o.push(i[t>>2]+i[t<<4&63]+"==")):2===r&&(t=(e[n-2]<<8)+e[n-1],o.push(i[t>>10]+i[t>>4&63]+i[t<<2&63]+"="));return o.join("")};for(var i=[],r=[],o="undefined"!=typeof Uint8Array?Uint8Array:Array,s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",a=0,u=s.length;a0)throw new Error("Invalid string. Length must be a multiple of 4");var n=e.indexOf("=");return-1===n&&(n=t),[n,n===t?0:4-n%4]}function l(e,t,n){for(var r,o,s=[],a=t;a>18&63]+i[o>>12&63]+i[o>>6&63]+i[63&o]);return s.join("")}r["-".charCodeAt(0)]=62,r["_".charCodeAt(0)]=63},EMDP:function(e,t,n){"use strict";n.d(t,"a",function(){return c}),n.d(t,"b",function(){return l});var i,r,o=n("mrx5"),s=n("ZYUE"),a=n("JVO/"),u=n("WTFd"),c=Object(a.c)("contextService");!function(e){e.isIWorkspace=function(e){return e&&"object"==typeof e&&"string"==typeof e.id&&Array.isArray(e.folders)}}(i||(i={})),function(e){e.isIWorkspaceFolder=function(e){return e&&"object"==typeof e&&o.a.isUri(e.uri)&&"string"==typeof e.name&&"function"==typeof e.toResource}}(r||(r={}));!function(){function e(e,t,n){void 0===t&&(t=[]),void 0===n&&(n=null),this._id=e,this._configuration=n,this._foldersMap=u.c.forPaths(),this.folders=t}Object.defineProperty(e.prototype,"folders",{get:function(){return this._folders},set:function(e){this._folders=e,this.updateFoldersMap()},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"id",{get:function(){return this._id},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"configuration",{get:function(){return this._configuration},set:function(e){this._configuration=e},enumerable:!0,configurable:!0}),e.prototype.getFolder=function(e){return e&&this._foldersMap.findSubstr(e.with({scheme:e.scheme,authority:e.authority,path:e.path}).toString())||null},e.prototype.updateFoldersMap=function(){this._foldersMap=u.c.forPaths();for(var e=0,t=this.folders;e=1.5*n;return Math.round(e/n)+" "+i+(r?"s":"")}e.exports=function(e,t){t=t||{};var c=typeof e;if("string"===c&&e.length>0)return function(e){if((e=String(e)).length>100)return;var t=/^((?:\d+)?\-?\d?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(e);if(!t)return;var u=parseFloat(t[1]);switch((t[2]||"ms").toLowerCase()){case"years":case"year":case"yrs":case"yr":case"y":return u*a;case"weeks":case"week":case"w":return u*s;case"days":case"day":case"d":return u*o;case"hours":case"hour":case"hrs":case"hr":case"h":return u*r;case"minutes":case"minute":case"mins":case"min":case"m":return u*i;case"seconds":case"second":case"secs":case"sec":case"s":return u*n;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return u;default:return}}(e);if("number"===c&&!1===isNaN(e))return t.long?function(e){var t=Math.abs(e);if(t>=o)return u(e,t,o,"day");if(t>=r)return u(e,t,r,"hour");if(t>=i)return u(e,t,i,"minute");if(t>=n)return u(e,t,n,"second");return e+" ms"}(e):function(e){var t=Math.abs(e);if(t>=o)return Math.round(e/o)+"d";if(t>=r)return Math.round(e/r)+"h";if(t>=i)return Math.round(e/i)+"m";if(t>=n)return Math.round(e/n)+"s";return e+"ms"}(e);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(e))}},Eawl:function(e,t){},Eeyw:function(e,t,n){"use strict";t.a=function(e,t){var n=e.getCount(),r=e.findTokenIndexAtOffset(t),o=e.getLanguageId(r),s=r;for(;s+10&&e.getLanguageId(a-1)===o;)a--;return new i(e,o,a,s+1,e.getStartOffset(a),e.getEndOffset(s))},t.b=function(e){return 0!=(7&e)};var i=function(){function e(e,t,n,i,r,o){this._actual=e,this.languageId=t,this._firstTokenIndex=n,this._lastTokenIndex=i,this.firstCharOffset=r,this._lastCharOffset=o}return e.prototype.getLineContent=function(){return this._actual.getLineContent().substring(this.firstCharOffset,this._lastCharOffset)},e.prototype.getTokenCount=function(){return this._lastTokenIndex-this._firstTokenIndex},e.prototype.findTokenIndexAtOffset=function(e){return this._actual.findTokenIndexAtOffset(e+this.firstCharOffset)-this._firstTokenIndex},e.prototype.getStandardTokenType=function(e){return this._actual.getStandardTokenType(e+this._firstTokenIndex)},e}()},EfIu:function(e,t,n){"use strict";n.d(t,"a",function(){return i}),n.d(t,"c",function(){return r}),n.d(t,"b",function(){return o}),n.d(t,"d",function(){return s}),n.d(t,"e",function(){return a}),n.d(t,"g",function(){return u}),n.d(t,"h",function(){return c}),n.d(t,"f",function(){return l});var i,r,o,s,a,u,c,l,d=n("hK2W");!function(e){e.noSelection=d.a("noSelection","No selection"),e.singleSelectionRange=d.a("singleSelectionRange","Line {0}, Column {1} ({2} selected)"),e.singleSelection=d.a("singleSelection","Line {0}, Column {1}"),e.multiSelectionRange=d.a("multiSelectionRange","{0} selections ({1} characters selected)"),e.multiSelection=d.a("multiSelection","{0} selections"),e.emergencyConfOn=d.a("emergencyConfOn","Now changing the setting `accessibilitySupport` to 'on'."),e.openingDocs=d.a("openingDocs","Now opening the Editor Accessibility documentation page."),e.readonlyDiffEditor=d.a("readonlyDiffEditor"," in a read-only pane of a diff editor."),e.editableDiffEditor=d.a("editableDiffEditor"," in a pane of a diff editor."),e.readonlyEditor=d.a("readonlyEditor"," in a read-only code editor"),e.editableEditor=d.a("editableEditor"," in a code editor"),e.changeConfigToOnMac=d.a("changeConfigToOnMac","To configure the editor to be optimized for usage with a Screen Reader press Command+E now."),e.changeConfigToOnWinLinux=d.a("changeConfigToOnWinLinux","To configure the editor to be optimized for usage with a Screen Reader press Control+E now."),e.auto_on=d.a("auto_on","The editor is configured to be optimized for usage with a Screen Reader."),e.auto_off=d.a("auto_off","The editor is configured to never be optimized for usage with a Screen Reader, which is not the case at this time."),e.tabFocusModeOnMsg=d.a("tabFocusModeOnMsg","Pressing Tab in the current editor will move focus to the next focusable element. Toggle this behavior by pressing {0}."),e.tabFocusModeOnMsgNoKb=d.a("tabFocusModeOnMsgNoKb","Pressing Tab in the current editor will move focus to the next focusable element. The command {0} is currently not triggerable by a keybinding."),e.tabFocusModeOffMsg=d.a("tabFocusModeOffMsg","Pressing Tab in the current editor will insert the tab character. Toggle this behavior by pressing {0}."),e.tabFocusModeOffMsgNoKb=d.a("tabFocusModeOffMsgNoKb","Pressing Tab in the current editor will insert the tab character. The command {0} is currently not triggerable by a keybinding."),e.openDocMac=d.a("openDocMac","Press Command+H now to open a browser window with more information related to editor accessibility."),e.openDocWinLinux=d.a("openDocWinLinux","Press Control+H now to open a browser window with more information related to editor accessibility."),e.outroMsg=d.a("outroMsg","You can dismiss this tooltip and return to the editor by pressing Escape or Shift+Escape."),e.showAccessibilityHelpAction=d.a("showAccessibilityHelpAction","Show Accessibility Help")}(i||(i={})),function(e){e.inspectTokensAction=d.a("inspectTokens","Developer: Inspect Tokens")}(r||(r={})),function(e){e.gotoLineLabelValidLineAndColumn=d.a("gotoLineLabelValidLineAndColumn","Go to line {0} and character {1}"),e.gotoLineLabelValidLine=d.a("gotoLineLabelValidLine","Go to line {0}"),e.gotoLineLabelEmptyWithLineLimit=d.a("gotoLineLabelEmptyWithLineLimit","Type a line number between 1 and {0} to navigate to"),e.gotoLineLabelEmptyWithLineAndColumnLimit=d.a("gotoLineLabelEmptyWithLineAndColumnLimit","Type a character between 1 and {0} to navigate to"),e.gotoLineAriaLabel=d.a("gotoLineAriaLabel","Current Line: {0}. Go to line {1}."),e.gotoLineActionInput=d.a("gotoLineActionInput","Type a line number, followed by an optional colon and a character number to navigate to"),e.gotoLineActionLabel=d.a("gotoLineActionLabel","Go to Line...")}(o||(o={})),function(e){e.ariaLabelEntryWithKey=d.a("ariaLabelEntryWithKey","{0}, {1}, commands"),e.ariaLabelEntry=d.a("ariaLabelEntry","{0}, commands"),e.quickCommandActionInput=d.a("quickCommandActionInput","Type the name of an action you want to execute"),e.quickCommandActionLabel=d.a("quickCommandActionLabel","Command Palette")}(s||(s={})),function(e){e.entryAriaLabel=d.a("entryAriaLabel","{0}, symbols"),e.quickOutlineActionInput=d.a("quickOutlineActionInput","Type the name of an identifier you wish to navigate to"),e.quickOutlineActionLabel=d.a("quickOutlineActionLabel","Go to Symbol..."),e._symbols_=d.a("symbols","symbols ({0})"),e._modules_=d.a("modules","modules ({0})"),e._class_=d.a("class","classes ({0})"),e._interface_=d.a("interface","interfaces ({0})"),e._method_=d.a("method","methods ({0})"),e._function_=d.a("function","functions ({0})"),e._property_=d.a("property","properties ({0})"),e._variable_=d.a("variable","variables ({0})"),e._variable2_=d.a("variable2","variables ({0})"),e._constructor_=d.a("_constructor","constructors ({0})"),e._call_=d.a("call","calls ({0})")}(a||(a={})),function(e){e.editorViewAccessibleLabel=d.a("editorViewAccessibleLabel","Editor content"),e.accessibilityHelpMessageIE=d.a("accessibilityHelpMessageIE","Press Ctrl+F1 for Accessibility Options."),e.accessibilityHelpMessage=d.a("accessibilityHelpMessage","Press Alt+F1 for Accessibility Options.")}(u||(u={})),function(e){e.toggleHighContrast=d.a("toggleHighContrast","Toggle High Contrast Theme")}(c||(c={})),function(e){e.bulkEditServiceSummary=d.a("bulkEditServiceSummary","Made {0} edits in {1} files")}(l||(l={}))},EfRI:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),n.d(t,"DeleteWordPartLeft",function(){return d}),n.d(t,"DeleteWordPartRight",function(){return h}),n.d(t,"WordPartLeftCommand",function(){return f}),n.d(t,"CursorWordPartLeft",function(){return p}),n.d(t,"CursorWordPartLeftSelect",function(){return g}),n.d(t,"WordPartRightCommand",function(){return m}),n.d(t,"CursorWordPartRight",function(){return v}),n.d(t,"CursorWordPartRightSelect",function(){return _});var i,r=n("03Zz"),o=n("CIBl"),s=n("vTy2"),a=n("/9db"),u=n("I8T6"),c=n("ItKl"),l=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),d=function(e){function t(){return e.call(this,{whitespaceHeuristics:!0,wordNavigationType:0,id:"deleteWordPartLeft",precondition:a.a.writable,kbOpts:{kbExpr:a.a.textInputFocus,primary:0,mac:{primary:769},weight:100}})||this}return l(t,e),t.prototype._delete=function(e,t,n,i,r){var a=o.b.deleteWordPartLeft(e,t,n,i);return a||new s.a(1,1,1,1)},t}(u.DeleteWordCommand),h=function(e){function t(){return e.call(this,{whitespaceHeuristics:!0,wordNavigationType:2,id:"deleteWordPartRight",precondition:a.a.writable,kbOpts:{kbExpr:a.a.textInputFocus,primary:0,mac:{primary:788},weight:100}})||this}return l(t,e),t.prototype._delete=function(e,t,n,i,r){var a=o.b.deleteWordPartRight(e,t,n,i);if(a)return a;var u=t.getLineCount(),c=t.getLineMaxColumn(u);return new s.a(u,c,u,c)},t}(u.DeleteWordCommand),f=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return l(t,e),t.prototype._move=function(e,t,n,i){return o.b.moveWordPartLeft(e,t,n)},t}(u.MoveWordCommand),p=function(e){function t(){return e.call(this,{inSelectionMode:!1,wordNavigationType:0,id:"cursorWordPartLeft",precondition:void 0,kbOpts:{kbExpr:a.a.textInputFocus,primary:0,mac:{primary:783},weight:100}})||this}return l(t,e),t}(f);c.a.registerCommandAlias("cursorWordPartStartLeft","cursorWordPartLeft");var g=function(e){function t(){return e.call(this,{inSelectionMode:!0,wordNavigationType:0,id:"cursorWordPartLeftSelect",precondition:void 0,kbOpts:{kbExpr:a.a.textInputFocus,primary:0,mac:{primary:1807},weight:100}})||this}return l(t,e),t}(f);c.a.registerCommandAlias("cursorWordPartStartLeftSelect","cursorWordPartLeftSelect");var m=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return l(t,e),t.prototype._move=function(e,t,n,i){return o.b.moveWordPartRight(e,t,n)},t}(u.MoveWordCommand),v=function(e){function t(){return e.call(this,{inSelectionMode:!1,wordNavigationType:2,id:"cursorWordPartRight",precondition:void 0,kbOpts:{kbExpr:a.a.textInputFocus,primary:0,mac:{primary:785},weight:100}})||this}return l(t,e),t}(m),_=function(e){function t(){return e.call(this,{inSelectionMode:!0,wordNavigationType:2,id:"cursorWordPartRightSelect",precondition:void 0,kbOpts:{kbExpr:a.a.textInputFocus,primary:0,mac:{primary:1809},weight:100}})||this}return l(t,e),t}(m);Object(r.g)(new d),Object(r.g)(new h),Object(r.g)(new p),Object(r.g)(new g),Object(r.g)(new v),Object(r.g)(new _)},EuP9:function(e,t,n){"use strict";(function(e){ +/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh + * @license MIT + */ +var i=n("EKta"),r=n("ujcs"),o=n("sOR5");function s(){return u.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function a(e,t){if(s()=s())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+s().toString(16)+" bytes");return 0|e}function p(e,t){if(u.isBuffer(e))return e.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;"string"!=typeof e&&(e=""+e);var n=e.length;if(0===n)return 0;for(var i=!1;;)switch(t){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":case void 0:return B(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return V(e).length;default:if(i)return B(e).length;t=(""+t).toLowerCase(),i=!0}}function g(e,t,n){var i=e[t];e[t]=e[n],e[n]=i}function m(e,t,n,i,r){if(0===e.length)return-1;if("string"==typeof n?(i=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n=+n,isNaN(n)&&(n=r?0:e.length-1),n<0&&(n=e.length+n),n>=e.length){if(r)return-1;n=e.length-1}else if(n<0){if(!r)return-1;n=0}if("string"==typeof t&&(t=u.from(t,i)),u.isBuffer(t))return 0===t.length?-1:v(e,t,n,i,r);if("number"==typeof t)return t&=255,u.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?r?Uint8Array.prototype.indexOf.call(e,t,n):Uint8Array.prototype.lastIndexOf.call(e,t,n):v(e,[t],n,i,r);throw new TypeError("val must be string, number or Buffer")}function v(e,t,n,i,r){var o,s=1,a=e.length,u=t.length;if(void 0!==i&&("ucs2"===(i=String(i).toLowerCase())||"ucs-2"===i||"utf16le"===i||"utf-16le"===i)){if(e.length<2||t.length<2)return-1;s=2,a/=2,u/=2,n/=2}function c(e,t){return 1===s?e[t]:e.readUInt16BE(t*s)}if(r){var l=-1;for(o=n;oa&&(n=a-u),o=n;o>=0;o--){for(var d=!0,h=0;hr&&(i=r):i=r;var o=t.length;if(o%2!=0)throw new TypeError("Invalid hex string");i>o/2&&(i=o/2);for(var s=0;s>8,r=n%256,o.push(r),o.push(i);return o}(t,e.length-n),e,n,i)}function x(e,t,n){return 0===t&&n===e.length?i.fromByteArray(e):i.fromByteArray(e.slice(t,n))}function L(e,t,n){n=Math.min(e.length,n);for(var i=[],r=t;r239?4:c>223?3:c>191?2:1;if(r+d<=n)switch(d){case 1:c<128&&(l=c);break;case 2:128==(192&(o=e[r+1]))&&(u=(31&c)<<6|63&o)>127&&(l=u);break;case 3:o=e[r+1],s=e[r+2],128==(192&o)&&128==(192&s)&&(u=(15&c)<<12|(63&o)<<6|63&s)>2047&&(u<55296||u>57343)&&(l=u);break;case 4:o=e[r+1],s=e[r+2],a=e[r+3],128==(192&o)&&128==(192&s)&&128==(192&a)&&(u=(15&c)<<18|(63&o)<<12|(63&s)<<6|63&a)>65535&&u<1114112&&(l=u)}null===l?(l=65533,d=1):l>65535&&(l-=65536,i.push(l>>>10&1023|55296),l=56320|1023&l),i.push(l),r+=d}return function(e){var t=e.length;if(t<=O)return String.fromCharCode.apply(String,e);var n="",i=0;for(;ithis.length)return"";if((void 0===n||n>this.length)&&(n=this.length),n<=0)return"";if((n>>>=0)<=(t>>>=0))return"";for(e||(e="utf8");;)switch(e){case"hex":return E(this,t,n);case"utf8":case"utf-8":return L(this,t,n);case"ascii":return k(this,t,n);case"latin1":case"binary":return N(this,t,n);case"base64":return x(this,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return I(this,t,n);default:if(i)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),i=!0}}.apply(this,arguments)},u.prototype.equals=function(e){if(!u.isBuffer(e))throw new TypeError("Argument must be a Buffer");return this===e||0===u.compare(this,e)},u.prototype.inspect=function(){var e="",n=t.INSPECT_MAX_BYTES;return this.length>0&&(e=this.toString("hex",0,n).match(/.{2}/g).join(" "),this.length>n&&(e+=" ... ")),""},u.prototype.compare=function(e,t,n,i,r){if(!u.isBuffer(e))throw new TypeError("Argument must be a Buffer");if(void 0===t&&(t=0),void 0===n&&(n=e?e.length:0),void 0===i&&(i=0),void 0===r&&(r=this.length),t<0||n>e.length||i<0||r>this.length)throw new RangeError("out of range index");if(i>=r&&t>=n)return 0;if(i>=r)return-1;if(t>=n)return 1;if(t>>>=0,n>>>=0,i>>>=0,r>>>=0,this===e)return 0;for(var o=r-i,s=n-t,a=Math.min(o,s),c=this.slice(i,r),l=e.slice(t,n),d=0;dr)&&(n=r),e.length>0&&(n<0||t<0)||t>this.length)throw new RangeError("Attempt to write outside buffer bounds");i||(i="utf8");for(var o=!1;;)switch(i){case"hex":return _(this,e,t,n);case"utf8":case"utf-8":return b(this,e,t,n);case"ascii":return y(this,e,t,n);case"latin1":case"binary":return w(this,e,t,n);case"base64":return C(this,e,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return S(this,e,t,n);default:if(o)throw new TypeError("Unknown encoding: "+i);i=(""+i).toLowerCase(),o=!0}},u.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var O=4096;function k(e,t,n){var i="";n=Math.min(e.length,n);for(var r=t;ri)&&(n=i);for(var r="",o=t;on)throw new RangeError("Trying to access beyond buffer length")}function M(e,t,n,i,r,o){if(!u.isBuffer(e))throw new TypeError('"buffer" argument must be a Buffer instance');if(t>r||te.length)throw new RangeError("Index out of range")}function T(e,t,n,i){t<0&&(t=65535+t+1);for(var r=0,o=Math.min(e.length-n,2);r>>8*(i?r:1-r)}function P(e,t,n,i){t<0&&(t=4294967295+t+1);for(var r=0,o=Math.min(e.length-n,4);r>>8*(i?r:3-r)&255}function A(e,t,n,i,r,o){if(n+i>e.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function R(e,t,n,i,o){return o||A(e,0,n,4),r.write(e,t,n,i,23,4),n+4}function F(e,t,n,i,o){return o||A(e,0,n,8),r.write(e,t,n,i,52,8),n+8}u.prototype.slice=function(e,t){var n,i=this.length;if(e=~~e,t=void 0===t?i:~~t,e<0?(e+=i)<0&&(e=0):e>i&&(e=i),t<0?(t+=i)<0&&(t=0):t>i&&(t=i),t0&&(r*=256);)i+=this[e+--t]*r;return i},u.prototype.readUInt8=function(e,t){return t||D(e,1,this.length),this[e]},u.prototype.readUInt16LE=function(e,t){return t||D(e,2,this.length),this[e]|this[e+1]<<8},u.prototype.readUInt16BE=function(e,t){return t||D(e,2,this.length),this[e]<<8|this[e+1]},u.prototype.readUInt32LE=function(e,t){return t||D(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},u.prototype.readUInt32BE=function(e,t){return t||D(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},u.prototype.readIntLE=function(e,t,n){e|=0,t|=0,n||D(e,t,this.length);for(var i=this[e],r=1,o=0;++o=(r*=128)&&(i-=Math.pow(2,8*t)),i},u.prototype.readIntBE=function(e,t,n){e|=0,t|=0,n||D(e,t,this.length);for(var i=t,r=1,o=this[e+--i];i>0&&(r*=256);)o+=this[e+--i]*r;return o>=(r*=128)&&(o-=Math.pow(2,8*t)),o},u.prototype.readInt8=function(e,t){return t||D(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},u.prototype.readInt16LE=function(e,t){t||D(e,2,this.length);var n=this[e]|this[e+1]<<8;return 32768&n?4294901760|n:n},u.prototype.readInt16BE=function(e,t){t||D(e,2,this.length);var n=this[e+1]|this[e]<<8;return 32768&n?4294901760|n:n},u.prototype.readInt32LE=function(e,t){return t||D(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},u.prototype.readInt32BE=function(e,t){return t||D(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},u.prototype.readFloatLE=function(e,t){return t||D(e,4,this.length),r.read(this,e,!0,23,4)},u.prototype.readFloatBE=function(e,t){return t||D(e,4,this.length),r.read(this,e,!1,23,4)},u.prototype.readDoubleLE=function(e,t){return t||D(e,8,this.length),r.read(this,e,!0,52,8)},u.prototype.readDoubleBE=function(e,t){return t||D(e,8,this.length),r.read(this,e,!1,52,8)},u.prototype.writeUIntLE=function(e,t,n,i){(e=+e,t|=0,n|=0,i)||M(this,e,t,n,Math.pow(2,8*n)-1,0);var r=1,o=0;for(this[t]=255&e;++o=0&&(o*=256);)this[t+r]=e/o&255;return t+n},u.prototype.writeUInt8=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,1,255,0),u.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=255&e,t+1},u.prototype.writeUInt16LE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,2,65535,0),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):T(this,e,t,!0),t+2},u.prototype.writeUInt16BE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,2,65535,0),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):T(this,e,t,!1),t+2},u.prototype.writeUInt32LE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):P(this,e,t,!0),t+4},u.prototype.writeUInt32BE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):P(this,e,t,!1),t+4},u.prototype.writeIntLE=function(e,t,n,i){if(e=+e,t|=0,!i){var r=Math.pow(2,8*n-1);M(this,e,t,n,r-1,-r)}var o=0,s=1,a=0;for(this[t]=255&e;++o>0)-a&255;return t+n},u.prototype.writeIntBE=function(e,t,n,i){if(e=+e,t|=0,!i){var r=Math.pow(2,8*n-1);M(this,e,t,n,r-1,-r)}var o=n-1,s=1,a=0;for(this[t+o]=255&e;--o>=0&&(s*=256);)e<0&&0===a&&0!==this[t+o+1]&&(a=1),this[t+o]=(e/s>>0)-a&255;return t+n},u.prototype.writeInt8=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,1,127,-128),u.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),e<0&&(e=255+e+1),this[t]=255&e,t+1},u.prototype.writeInt16LE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):T(this,e,t,!0),t+2},u.prototype.writeInt16BE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):T(this,e,t,!1),t+2},u.prototype.writeInt32LE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,4,2147483647,-2147483648),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):P(this,e,t,!0),t+4},u.prototype.writeInt32BE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):P(this,e,t,!1),t+4},u.prototype.writeFloatLE=function(e,t,n){return R(this,e,t,!0,n)},u.prototype.writeFloatBE=function(e,t,n){return R(this,e,t,!1,n)},u.prototype.writeDoubleLE=function(e,t,n){return F(this,e,t,!0,n)},u.prototype.writeDoubleBE=function(e,t,n){return F(this,e,t,!1,n)},u.prototype.copy=function(e,t,n,i){if(n||(n=0),i||0===i||(i=this.length),t>=e.length&&(t=e.length),t||(t=0),i>0&&i=this.length)throw new RangeError("sourceStart out of bounds");if(i<0)throw new RangeError("sourceEnd out of bounds");i>this.length&&(i=this.length),e.length-t=0;--r)e[r+t]=this[r+n];else if(o<1e3||!u.TYPED_ARRAY_SUPPORT)for(r=0;r>>=0,n=void 0===n?this.length:n>>>0,e||(e=0),"number"==typeof e)for(o=t;o55295&&n<57344){if(!r){if(n>56319){(t-=3)>-1&&o.push(239,191,189);continue}if(s+1===i){(t-=3)>-1&&o.push(239,191,189);continue}r=n;continue}if(n<56320){(t-=3)>-1&&o.push(239,191,189),r=n;continue}n=65536+(r-55296<<10|n-56320)}else r&&(t-=3)>-1&&o.push(239,191,189);if(r=null,n<128){if((t-=1)<0)break;o.push(n)}else if(n<2048){if((t-=2)<0)break;o.push(n>>6|192,63&n|128)}else if(n<65536){if((t-=3)<0)break;o.push(n>>12|224,n>>6&63|128,63&n|128)}else{if(!(n<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;o.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return o}function V(e){return i.toByteArray(function(e){if((e=function(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}(e).replace(j,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function H(e,t,n,i){for(var r=0;r=t.length||r>=e.length);++r)t[r+n]=e[r];return r}}).call(t,n("DuR2"))},Evjx:function(e,t,n){"use strict";n.d(t,"d",function(){return u}),n.d(t,"b",function(){return l}),n.d(t,"a",function(){return d}),n.d(t,"c",function(){return v});var i,r,o=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),s=function(){function e(){this.value="",this.pos=0}return e.isDigitCharacter=function(e){return e>=48&&e<=57},e.isVariableCharacter=function(e){return 95===e||e>=97&&e<=122||e>=65&&e<=90},e.prototype.text=function(e){this.value=e,this.pos=0},e.prototype.tokenText=function(e){return this.value.substr(e.pos,e.len)},e.prototype.next=function(){if(this.pos>=this.value.length)return{type:14,pos:this.pos,len:0};var t,n=this.pos,i=0,r=this.value.charCodeAt(n);if("number"==typeof(t=e._table[r]))return this.pos+=1,{type:t,pos:n,len:1};if(e.isDigitCharacter(r)){t=8;do{i+=1,r=this.value.charCodeAt(n+i)}while(e.isDigitCharacter(r));return this.pos+=i,{type:t,pos:n,len:i}}if(e.isVariableCharacter(r)){t=9;do{r=this.value.charCodeAt(n+ ++i)}while(e.isVariableCharacter(r)||e.isDigitCharacter(r));return this.pos+=i,{type:t,pos:n,len:i}}t=10;do{i+=1,r=this.value.charCodeAt(n+i)}while(!isNaN(r)&&void 0===e._table[r]&&!e.isDigitCharacter(r)&&!e.isVariableCharacter(r));return this.pos+=i,{type:t,pos:n,len:i}},e._table=((r={})[36]=0,r[58]=1,r[44]=2,r[123]=3,r[125]=4,r[92]=5,r[47]=6,r[124]=7,r[43]=11,r[45]=12,r[63]=13,r),e}(),a=function(){function e(){this._children=[]}return e.prototype.appendChild=function(e){return e instanceof u&&this._children[this._children.length-1]instanceof u?this._children[this._children.length-1].value+=e.value:(e.parent=this,this._children.push(e)),this},e.prototype.replace=function(e,t){var n=e.parent,i=n.children.indexOf(e),r=n.children.slice(0);r.splice.apply(r,[i,1].concat(t)),n._children=r,function e(t,n){for(var i=0,r=t;it.index?1:0},Object.defineProperty(t.prototype,"isFinalTabstop",{get:function(){return 0===this.index},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"choice",{get:function(){return 1===this._children.length&&this._children[0]instanceof d?this._children[0]:void 0},enumerable:!0,configurable:!0}),t.prototype.clone=function(){var e=new t(this.index);return this.transform&&(e.transform=this.transform.clone()),e._children=this.children.map(function(e){return e.clone()}),e},t}(c),d=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.options=[],t}return o(t,e),t.prototype.appendChild=function(e){return e instanceof u&&(e.parent=this,this.options.push(e)),this},t.prototype.toString=function(){return this.options[0].value},t.prototype.len=function(){return this.options[0].len()},t.prototype.clone=function(){var e=new t;return this.options.forEach(e.appendChild,e),e},t}(a),h=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.regexp=new RegExp(""),t}return o(t,e),t.prototype.resolve=function(e){var t=this,n=!1,i=e.replace(this.regexp,function(){return n=!0,t._replace(Array.prototype.slice.call(arguments,0,-2))});return!n&&this._children.some(function(e){return e instanceof f&&Boolean(e.elseValue)})&&(i=this._replace([])),i},t.prototype._replace=function(e){for(var t="",n=0,i=this._children;n0;){var i=n.shift();if(!t(i))break;n.unshift.apply(n,i.children)}}var m=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return o(t,e),Object.defineProperty(t.prototype,"placeholderInfo",{get:function(){if(!this._placeholders){var e,t=[];this.walk(function(n){return n instanceof l&&(t.push(n),e=!e||e.index0?r.set(e.index,e.children):o.push(e)),!0});for(var a=0,u=o;a0&&t),!r.has(0)&&n&&i.appendChild(new l(0)),i},e.prototype._accept=function(e,t){if(void 0===e||this._token.type===e){var n=!t||this._scanner.tokenText(this._token);return this._token=this._scanner.next(),n}return!1},e.prototype._backTo=function(e){return this._scanner.pos=e.pos+e.len,this._token=e,!1},e.prototype._until=function(e){if(14===this._token.type)return!1;for(var t="",n=this._token.pos,i={type:14,pos:0,len:0};this._token.type!==e||5===i.type;)if(this._token.type===e&&(t+=this._scanner.value.substring(n,i.pos),n=this._token.pos),i=this._token,this._token=this._scanner.next(),14===this._token.type)return!1;return t+=this._scanner.value.substring(n,this._token.pos),this._token=this._scanner.next(),t},e.prototype._parse=function(e){return this._parseEscaped(e)||this._parseTabstopOrVariableName(e)||this._parseComplexPlaceholder(e)||this._parseComplexVariable(e)||this._parseAnything(e)},e.prototype._parseEscaped=function(e){var t;return!!(t=this._accept(5,!0))&&(t=this._accept(0,!0)||this._accept(4,!0)||this._accept(5,!0)||t,e.appendChild(new u(t)),!0)},e.prototype._parseTabstopOrVariableName=function(e){var t,n=this._token;return this._accept(0)&&(t=this._accept(9,!0)||this._accept(8,!0))?(e.appendChild(/^\d+$/.test(t)?new l(Number(t)):new p(t)),!0):this._backTo(n)},e.prototype._parseComplexPlaceholder=function(e){var t,n=this._token;if(!(this._accept(0)&&this._accept(3)&&(t=this._accept(8,!0))))return this._backTo(n);var i=new l(Number(t));if(this._accept(1))for(;;){if(this._accept(4))return e.appendChild(i),!0;if(!this._parse(i))return e.appendChild(new u("${"+t+":")),i.children.forEach(e.appendChild,e),!0}else{if(!(i.index>0&&this._accept(7)))return this._accept(6)?this._parseTransform(i)?(e.appendChild(i),!0):(this._backTo(n),!1):this._accept(4)?(e.appendChild(i),!0):this._backTo(n);for(var r=new d;;){if(this._parseChoiceElement(r)){if(this._accept(2))continue;if(this._accept(7)&&(i.appendChild(r),this._accept(4)))return e.appendChild(i),!0}return this._backTo(n),!1}}},e.prototype._parseChoiceElement=function(e){for(var t=this._token,n=[];2!==this._token.type&&7!==this._token.type;){var i=void 0;if(!(i=(i=this._accept(5,!0))?this._accept(2,!0)||this._accept(7,!0)||this._accept(5,!0)||i:this._accept(void 0,!0)))return this._backTo(t),!1;n.push(i)}return 0===n.length?(this._backTo(t),!1):(e.appendChild(new u(n.join(""))),!0)},e.prototype._parseComplexVariable=function(e){var t,n=this._token;if(!(this._accept(0)&&this._accept(3)&&(t=this._accept(9,!0))))return this._backTo(n);var i=new p(t);if(!this._accept(1))return this._accept(6)?this._parseTransform(i)?(e.appendChild(i),!0):(this._backTo(n),!1):this._accept(4)?(e.appendChild(i),!0):this._backTo(n);for(;;){if(this._accept(4))return e.appendChild(i),!0;if(!this._parse(i))return e.appendChild(new u("${"+t+":")),i.children.forEach(e.appendChild,e),!0}},e.prototype._parseTransform=function(e){for(var t=new h,n="",i="";!this._accept(6);){var r=void 0;if(r=this._accept(5,!0))n+=r=this._accept(6,!0)||r;else{if(14===this._token.type)return!1;n+=this._accept(void 0,!0)}}for(;!this._accept(6);){r=void 0;if(r=this._accept(5,!0))r=this._accept(5,!0)||this._accept(6,!0)||r,t.appendChild(new u(r));else if(!this._parseFormatString(t)&&!this._parseAnything(t))return!1}for(;!this._accept(4);){if(14===this._token.type)return!1;i+=this._accept(void 0,!0)}try{t.regexp=new RegExp(n,i)}catch(e){return!1}return e.transform=t,!0},e.prototype._parseFormatString=function(e){var t=this._token;if(!this._accept(0))return!1;var n=!1;this._accept(3)&&(n=!0);var i=this._accept(8,!0);if(!i)return this._backTo(t),!1;if(!n)return e.appendChild(new f(Number(i))),!0;if(this._accept(4))return e.appendChild(new f(Number(i))),!0;if(!this._accept(1))return this._backTo(t),!1;if(this._accept(6)){var r=this._accept(9,!0);return r&&this._accept(4)?(e.appendChild(new f(Number(i),r)),!0):(this._backTo(t),!1)}if(this._accept(11)){if(o=this._until(4))return e.appendChild(new f(Number(i),void 0,o,void 0)),!0}else if(this._accept(12)){if(s=this._until(4))return e.appendChild(new f(Number(i),void 0,void 0,s)),!0}else if(this._accept(13)){var o;if(o=this._until(1))if(s=this._until(4))return e.appendChild(new f(Number(i),void 0,o,s)),!0}else{var s;if(s=this._until(4))return e.appendChild(new f(Number(i),void 0,void 0,s)),!0}return this._backTo(t),!1},e.prototype._parseAnything=function(e){return 14!==this._token.type&&(e.appendChild(new u(this._scanner.tokenText(this._token))),this._accept(void 0),!0)},e}()},F11g:function(e,t,n){"use strict";var i=n("geuY"),r=n("HzeT"),o=n("lZ6o"),s=o.utils.assert,a=n("yMmo"),u=n("NMED");function c(e){if(!(this instanceof c))return new c(e);"string"==typeof e&&(s(o.curves.hasOwnProperty(e),"Unknown curve "+e),e=o.curves[e]),e instanceof o.curves.PresetCurve&&(e={curve:e}),this.curve=e.curve.curve,this.n=this.curve.n,this.nh=this.n.ushrn(1),this.g=this.curve.g,this.g=e.curve.g,this.g.precompute(e.curve.n.bitLength()+1),this.hash=e.hash||e.curve.hash}e.exports=c,c.prototype.keyPair=function(e){return new a(this,e)},c.prototype.keyFromPrivate=function(e,t){return a.fromPrivate(this,e,t)},c.prototype.keyFromPublic=function(e,t){return a.fromPublic(this,e,t)},c.prototype.genKeyPair=function(e){e||(e={});for(var t=new r({hash:this.hash,pers:e.pers,persEnc:e.persEnc||"utf8",entropy:e.entropy||o.rand(this.hash.hmacStrength),entropyEnc:e.entropy&&e.entropyEnc||"utf8",nonce:this.n.toArray()}),n=this.n.byteLength(),s=this.n.sub(new i(2));;){var a=new i(t.generate(n));if(!(a.cmp(s)>0))return a.iaddn(1),this.keyFromPrivate(a)}},c.prototype._truncateToN=function(e,t){var n=8*e.byteLength()-this.n.bitLength();return n>0&&(e=e.ushrn(n)),!t&&e.cmp(this.n)>=0?e.sub(this.n):e},c.prototype.sign=function(e,t,n,o){"object"==typeof n&&(o=n,n=null),o||(o={}),t=this.keyFromPrivate(t,n),e=this._truncateToN(new i(e,16));for(var s=this.n.byteLength(),a=t.getPrivate().toArray("be",s),c=e.toArray("be",s),l=new r({hash:this.hash,entropy:a,nonce:c,pers:o.pers,persEnc:o.persEnc||"utf8"}),d=this.n.sub(new i(1)),h=0;;h++){var f=o.k?o.k(h):new i(l.generate(this.n.byteLength()));if(!((f=this._truncateToN(f,!0)).cmpn(1)<=0||f.cmp(d)>=0)){var p=this.g.mul(f);if(!p.isInfinity()){var g=p.getX(),m=g.umod(this.n);if(0!==m.cmpn(0)){var v=f.invm(this.n).mul(m.mul(t.getPrivate()).iadd(e));if(0!==(v=v.umod(this.n)).cmpn(0)){var _=(p.getY().isOdd()?1:0)|(0!==g.cmp(m)?2:0);return o.canonical&&v.cmp(this.nh)>0&&(v=this.n.sub(v),_^=1),new u({r:m,s:v,recoveryParam:_})}}}}}},c.prototype.verify=function(e,t,n,r){e=this._truncateToN(new i(e,16)),n=this.keyFromPublic(n,r);var o=(t=new u(t,"hex")).r,s=t.s;if(o.cmpn(1)<0||o.cmp(this.n)>=0)return!1;if(s.cmpn(1)<0||s.cmp(this.n)>=0)return!1;var a,c=s.invm(this.n),l=c.mul(e).umod(this.n),d=c.mul(o).umod(this.n);return this.curve._maxwellTrick?!(a=this.g.jmulAdd(l,n.getPublic(),d)).isInfinity()&&a.eqXToP(o):!(a=this.g.mulAdd(l,n.getPublic(),d)).isInfinity()&&0===a.getX().umod(this.n).cmp(o)},c.prototype.recoverPubKey=function(e,t,n,r){s((3&n)===n,"The recovery param is more than two bits"),t=new u(t,r);var o=this.n,a=new i(e),c=t.r,l=t.s,d=1&n,h=n>>1;if(c.cmp(this.curve.p.umod(this.curve.n))>=0&&h)throw new Error("Unable to find sencond key candinate");c=h?this.curve.pointFromX(c.add(this.curve.n),d):this.curve.pointFromX(c,d);var f=t.r.invm(o),p=o.sub(a).mul(f).umod(o),g=l.mul(f).umod(o);return this.g.mulAdd(p,c,g)},c.prototype.getKeyRecoveryParam=function(e,t,n,i){if(null!==(t=new u(t,i)).recoveryParam)return t.recoveryParam;for(var r=0;r<4;r++){var o;try{o=this.recoverPubKey(e,t,r)}catch(e){continue}if(o.eq(n))return r}throw new Error("Unable to find valid recovery factor")}},F5mM:function(e,t){},Fllr:function(e,t,n){"use strict";var i=n("zxiH"),r=n("Kp7x"),o=n("tqet"),s=n("aL7J"),a=n("vTy2"),u=n("+jct"),c=n("+oh4"),l=n("Eeyw"),d=function(){function e(t){if(t.autoClosingPairs?this._autoClosingPairs=t.autoClosingPairs.map(function(e){return new c.b(e)}):t.brackets?this._autoClosingPairs=t.brackets.map(function(e){return new c.b({open:e[0],close:e[1]})}):this._autoClosingPairs=[],t.__electricCharacterSupport&&t.__electricCharacterSupport.docComment){var n=t.__electricCharacterSupport.docComment;this._autoClosingPairs.push(new c.b({open:n.open,close:n.close||""}))}this._autoCloseBefore="string"==typeof t.autoCloseBefore?t.autoCloseBefore:e.DEFAULT_AUTOCLOSE_BEFORE_LANGUAGE_DEFINED,this._surroundingPairs=t.surroundingPairs||this._autoClosingPairs}return e.prototype.getAutoClosingPairs=function(){return this._autoClosingPairs},e.prototype.getAutoCloseBeforeSet=function(){return this._autoCloseBefore},e.shouldAutoClosePair=function(e,t,n){if(0===t.getTokenCount())return!0;var i=t.findTokenIndexAtOffset(n-2),r=t.getStandardTokenType(i);return e.isOK(r)},e.prototype.getSurroundingPairs=function(){return this._surroundingPairs},e.DEFAULT_AUTOCLOSE_BEFORE_LANGUAGE_DEFINED=";:.,=}])> \n\t",e}(),h=n("iNUG"),f=function(){function e(e){this._richEditBrackets=e}return e.prototype.getElectricCharacters=function(){var e=[];if(this._richEditBrackets)for(var t=0,n=this._richEditBrackets.brackets.length;t0&&n.length>0)for(i=0,r=this._brackets.length;i0)for(i=0,r=this._brackets.length;i1){var r=void 0,o=-1;for(r=t-1;r>=1;r--){if(e.getLanguageIdAtPosition(r,0)!==i)return o;var s=e.getLineContent(r);if(!n.shouldIgnore(s)&&!/^\s+$/.test(s)&&""!==s)return r;o=r}}return-1},e.prototype.getInheritIndentForLine=function(e,t,n){void 0===n&&(n=!0);var i=this.getIndentRulesSupport(e.getLanguageIdentifier().id);if(!i)return null;if(t<=1)return{indentation:"",action:null};var r=this.getPrecedingValidLine(e,t,i);if(r<0)return null;if(r<1)return{indentation:"",action:null};var o=e.getLineContent(r);if(i.shouldIncrease(o)||i.shouldIndentNextLine(o))return{indentation:s.s(o),action:c.a.Indent,line:r};if(i.shouldDecrease(o))return{indentation:s.s(o),action:null,line:r};if(1===r)return{indentation:s.s(e.getLineContent(r)),action:null,line:r};var a=r-1,u=i.getIndentMetadata(e.getLineContent(a));if(!(3&u)&&4&u){for(var l=0,d=a-1;d>0;d--)if(!i.shouldIndentNextLine(e.getLineContent(d))){l=d;break}return{indentation:s.s(e.getLineContent(l+1)),action:null,line:l+1}}if(n)return{indentation:s.s(e.getLineContent(r)),action:null,line:r};for(d=r;d>0;d--){var h=e.getLineContent(d);if(i.shouldIncrease(h))return{indentation:s.s(h),action:c.a.Indent,line:d};if(i.shouldIndentNextLine(h)){l=0;for(var f=d-1;f>0;f--)if(!i.shouldIndentNextLine(e.getLineContent(d))){l=f;break}return{indentation:s.s(e.getLineContent(l+1)),action:null,line:l+1}}if(i.shouldDecrease(h))return{indentation:s.s(h),action:null,line:d}}return{indentation:s.s(e.getLineContent(1)),action:null,line:1}},e.prototype.getGoodIndentForLine=function(e,t,n,r){var o=this.getIndentRulesSupport(t);if(!o)return null;var a=this.getInheritIndentForLine(e,n),u=e.getLineContent(n);if(a){var l=a.line;if(void 0!==l){var d=this._getOnEnterSupport(t),h=null;try{d&&(h=d.onEnter("",e.getLineContent(l),""))}catch(e){Object(i.e)(e)}if(h){var f=s.s(e.getLineContent(l));return h.removeText&&(f=f.substring(0,f.length-h.removeText)),h.indentAction===c.a.Indent||h.indentAction===c.a.IndentOutdent?f=r.shiftIndent(f):h.indentAction===c.a.Outdent&&(f=r.unshiftIndent(f)),o.shouldDecrease(u)&&(f=r.unshiftIndent(f)),h.appendText&&(f+=h.appendText),s.s(f)}}return o.shouldDecrease(u)?a.action===c.a.Indent?a.indentation:r.unshiftIndent(a.indentation):a.action===c.a.Indent?r.shiftIndent(a.indentation):a.indentation}return null},e.prototype.getIndentForEnter=function(e,t,n,i){e.forceTokenization(t.startLineNumber);var r,o,a=e.getLineTokens(t.startLineNumber),u=Object(l.a)(a,t.startColumn-1),d=u.getLineContent(),h=!1;(u.firstCharOffset>0&&a.getLanguageId(0)!==u.languageId?(h=!0,r=d.substr(0,t.startColumn-1-u.firstCharOffset)):r=a.getLineContent().substring(0,t.startColumn-1),t.isEmpty())?o=d.substr(t.startColumn-1-u.firstCharOffset):o=this.getScopedLineTokens(e,t.endLineNumber,t.endColumn).getLineContent().substr(t.endColumn-1-u.firstCharOffset);var f=this.getIndentRulesSupport(u.languageId);if(!f)return null;var p=r,g=s.s(r);if(!i&&!h){var m=this.getInheritIndentForLine(e,t.startLineNumber);f.shouldDecrease(r)&&m&&(g=m.indentation,m.action!==c.a.Indent&&(g=n.unshiftIndent(g))),p=g+s.B(s.B(r," "),"\t")}var v={getLineTokens:function(t){return e.getLineTokens(t)},getLanguageIdentifier:function(){return e.getLanguageIdentifier()},getLanguageIdAtPosition:function(t,n){return e.getLanguageIdAtPosition(t,n)},getLineContent:function(n){return n===t.startLineNumber?p:e.getLineContent(n)}},_=s.s(a.getLineContent()),b=this.getInheritIndentForLine(v,t.startLineNumber+1);if(!b){var y=h?_:g;return{beforeEnter:y,afterEnter:y}}var w=h?_:b.indentation;return b.action===c.a.Indent&&(w=n.shiftIndent(w)),f.shouldDecrease(o)&&(w=n.unshiftIndent(w)),{beforeEnter:h?_:g,afterEnter:w}},e.prototype.getIndentActionForType=function(e,t,n,i){var r=this.getScopedLineTokens(e,t.startLineNumber,t.startColumn),o=this.getIndentRulesSupport(r.languageId);if(!o)return null;var s,a=r.getLineContent(),u=a.substr(0,t.startColumn-1-r.firstCharOffset);t.isEmpty()?s=a.substr(t.startColumn-1-r.firstCharOffset):s=this.getScopedLineTokens(e,t.endLineNumber,t.endColumn).getLineContent().substr(t.endColumn-1-r.firstCharOffset);if(!o.shouldDecrease(u+s)&&o.shouldDecrease(u+n+s)){var l=this.getInheritIndentForLine(e,t.startLineNumber,!1);if(!l)return null;var d=l.indentation;return l.action!==c.a.Indent&&(d=i.unshiftIndent(d)),d}return null},e.prototype.getIndentMetadata=function(e,t){var n=this.getIndentRulesSupport(e.getLanguageIdentifier().id);return n?t<1||t>e.getLineCount()?null:n.getIndentMetadata(e.getLineContent(t)):null},e.prototype._getOnEnterSupport=function(e){var t=this._getRichEditSupport(e);return t&&t.onEnter||null},e.prototype.getRawEnterActionAtPosition=function(e,t,n){var i=this.getEnterAction(e,new a.a(t,n,t,n));return i?i.enterAction:null},e.prototype.getEnterAction=function(e,t){var n=this.getIndentationAtPosition(e,t.startLineNumber,t.startColumn),r=this.getScopedLineTokens(e,t.startLineNumber,t.startColumn),o=this._getOnEnterSupport(r.languageId);if(!o)return null;var s,a=r.getLineContent(),u=a.substr(0,t.startColumn-1-r.firstCharOffset);t.isEmpty()?s=a.substr(t.startColumn-1-r.firstCharOffset):s=this.getScopedLineTokens(e,t.endLineNumber,t.endColumn).getLineContent().substr(t.endColumn-1-r.firstCharOffset);var l=t.startLineNumber,d="";if(l>1&&0===r.firstCharOffset){var h=this.getScopedLineTokens(e,l-1);h.languageId===r.languageId&&(d=h.getLineContent())}var f=null;try{f=o.onEnter(d,u,s)}catch(e){Object(i.e)(e)}return f?(f.appendText||(f.indentAction===c.a.Indent||f.indentAction===c.a.IndentOutdent?f.appendText="\t":f.appendText=""),f.removeText&&(n=n.substring(0,n.length-f.removeText)),{enterAction:f,indentation:n}):null},e.prototype.getIndentationAtPosition=function(e,t,n){var i=e.getLineContent(t),r=s.s(i);return r.length>n-1&&(r=r.substring(0,n-1)),r},e.prototype.getScopedLineTokens=function(e,t,n){e.forceTokenization(t);var i=e.getLineTokens(t),r=void 0===n?e.getLineMaxColumn(t)-1:n-1;return Object(l.a)(i,r)},e.prototype.getBracketsSupport=function(e){var t=this._getRichEditSupport(e);return t&&t.brackets||null},e}())},G7Ib:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=n("03Zz"),r=n("0Td8");Object(i.h)(r.f),Object(i.f)(r.e),Object(i.f)(r.g),Object(i.f)(r.h),Object(i.f)(r.d),Object(i.f)(r.a),Object(i.f)(r.c),Object(i.g)(new r.b)},G8r4:function(e,t,n){"use strict";n.d(t,"a",function(){return r});var i=n("Kp7x"),r=new(function(){function e(){this._zoomLevel=0,this._onDidChangeZoomLevel=new i.a,this.onDidChangeZoomLevel=this._onDidChangeZoomLevel.event}return e.prototype.getZoomLevel=function(){return this._zoomLevel},e.prototype.setZoomLevel=function(e){e=Math.min(Math.max(-5,e),20),this._zoomLevel!==e&&(this._zoomLevel=e,this._onDidChangeZoomLevel.fire(this._zoomLevel))},e}())},GUE9:function(e,t,n){(function(t,i){var r,o=n("2JY6"),s=n("35aj"),a=n("Zq1s"),u=n("X3l8").Buffer,c=t.crypto&&t.crypto.subtle,l={sha:"SHA-1","sha-1":"SHA-1",sha1:"SHA-1",sha256:"SHA-256","sha-256":"SHA-256",sha384:"SHA-384","sha-384":"SHA-384","sha-512":"SHA-512",sha512:"SHA-512"},d=[];function h(e,t,n,i,r){return c.importKey("raw",e,{name:"PBKDF2"},!1,["deriveBits"]).then(function(e){return c.deriveBits({name:"PBKDF2",salt:t,iterations:n,hash:{name:r}},e,i<<3)}).then(function(e){return u.from(e)})}e.exports=function(e,n,f,p,g,m){"function"==typeof g&&(m=g,g=void 0);var v=l[(g=g||"sha1").toLowerCase()];if(!v||"function"!=typeof t.Promise)return i.nextTick(function(){var t;try{t=a(e,n,f,p,g)}catch(e){return m(e)}m(null,t)});if(o(e,n,f,p),"function"!=typeof m)throw new Error("No callback provided to pbkdf2");u.isBuffer(e)||(e=u.from(e,s)),u.isBuffer(n)||(n=u.from(n,s)),function(e,t){e.then(function(e){i.nextTick(function(){t(null,e)})},function(e){i.nextTick(function(){t(e)})})}(function(e){if(t.process&&!t.process.browser)return Promise.resolve(!1);if(!c||!c.importKey||!c.deriveBits)return Promise.resolve(!1);if(void 0!==d[e])return d[e];var n=h(r=r||u.alloc(8),r,10,128,e).then(function(){return!0}).catch(function(){return!1});return d[e]=n,n}(v).then(function(t){return t?h(e,n,f,p,v):a(e,n,f,p,g)}),m)}}).call(t,n("DuR2"),n("W2nU"))},GV5w:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),n.d(t,"GotoLineEntry",function(){return g}),n.d(t,"GotoLineAction",function(){return m});var i,r=n("wtJh"),o=(n.n(r),n("aL7J")),s=n("Al6Q"),a=n("P1SM"),u=n("03Zz"),c=n("artP"),l=n("vTy2"),d=n("/9db"),h=n("zwZj"),f=n("EfIu"),p=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),g=function(e){function t(t,n,i){var r=e.call(this)||this;return r.editor=n,r.decorator=i,r.parseResult=r.parseInput(t),r}return p(t,e),t.prototype.parseInput=function(e){var t,n,i=e.split(",").map(function(e){return parseInt(e,10)}).filter(function(e){return!isNaN(e)});if(t=0===i.length?new c.a(-1,-1):1===i.length?new c.a(i[0],1):new c.a(i[0],i[1]),Object(a.a)(this.editor))n=this.editor.getModel();else{var r=this.editor.getModel();n=r?r.modified:null}var s=!!n&&n.validatePosition(t).equals(t);return{position:t,isValid:s,label:s?t.column&&t.column>1?o.r(f.b.gotoLineLabelValidLineAndColumn,t.lineNumber,t.column):o.r(f.b.gotoLineLabelValidLine,t.lineNumber):t.lineNumber<1||t.lineNumber>(n?n.getLineCount():0)?o.r(f.b.gotoLineLabelEmptyWithLineLimit,n?n.getLineCount():0):o.r(f.b.gotoLineLabelEmptyWithLineAndColumnLimit,n?n.getLineMaxColumn(t.lineNumber):0)}},t.prototype.getLabel=function(){return this.parseResult.label},t.prototype.getAriaLabel=function(){var e=this.editor.getPosition(),t=e?e.lineNumber:0;return o.r(f.b.gotoLineAriaLabel,t,this.parseResult.label)},t.prototype.run=function(e,t){return 1===e?this.runOpen():this.runPreview()},t.prototype.runOpen=function(){if(!this.parseResult.isValid)return!1;var e=this.toSelection();return this.editor.setSelection(e),this.editor.revealRangeInCenter(e,0),this.editor.focus(),!0},t.prototype.runPreview=function(){if(!this.parseResult.isValid)return this.decorator.clearDecorations(),!1;var e=this.toSelection();return this.editor.revealRangeInCenter(e,0),this.decorator.decorateLine(e,this.editor),!1},t.prototype.toSelection=function(){return new l.a(this.parseResult.position.lineNumber,this.parseResult.position.column,this.parseResult.position.lineNumber,this.parseResult.position.column)},t}(s.a),m=function(e){function t(){return e.call(this,f.b.gotoLineActionInput,{id:"editor.action.gotoLine",label:f.b.gotoLineActionLabel,alias:"Go to Line...",precondition:void 0,kbOpts:{kbExpr:d.a.focus,primary:2085,mac:{primary:293},weight:100}})||this}return p(t,e),t.prototype.run=function(e,t){var n=this;this._show(this.getController(t),{getModel:function(e){return new s.c([new g(e,t,n.getController(t))])},getAutoFocus:function(e){return{autoFocusFirstEntry:e.length>0}}})},t}(h.a);Object(u.f)(m)},GYOr:function(e,t,n){"use strict";n.d(t,"g",function(){return s}),t.f=function(e,t,n){void 0===n&&(n=!1);if("string"!=typeof e||"string"!=typeof t)return null;var i=b.get(e);i||(i=new RegExp(r.j(e),"i"),b.set(e,i));var o=i.exec(t);if(o)return[{start:o.index,end:o.index+o[0].length}];return n?_(e,t):v(e,t)},t.b=function(e,t,n,i,r,o){var s=I(e,t,0,i,r,0,!0);if(s)return s;for(var a=0,u=0,c=o,l=0;l=0)u+=1,a+=Math.pow(2,d),c=d+1;else if(0!==a)break}return[u,a,o]},t.c=function(e){if(void 0===e)return[];for(var t=e[1].toString(2),n=[],i=e[2];i=3)for(var c=Math.min(7,e.length-1),l=n+1;lu[0])&&(u=h))}}return u}(e,t,n,i,r,o,!0,s)};var i=n("WTFd"),r=n("aL7J");function o(){for(var e=[],t=0;t0?[{start:0,end:t.length}]:[]}.bind(void 0,!0);function a(e){return 97<=e&&e<=122}function u(e){return 65<=e&&e<=90}function c(e){return 48<=e&&e<=57}function l(e){return 32===e||9===e||10===e||13===e}var d=new Set;function h(e){return a(e)||u(e)||c(e)}function f(e,t){return 0===t.length?t=[e]:e.end===t[0].start?t[0].start=e.start:t.unshift(e),t}function p(e,t){for(var n=t;n0&&!h(e.charCodeAt(n-1)))return n}return e.length}function g(e,t,n,i){if(n===e.length)return[];if(i===t.length)return null;if(e[n]!==t[i].toLowerCase())return null;var r=null,o=i+1;for(r=g(e,t,n+1,i+1);!r&&(o=p(t,o))60)return null;var n=function(e){for(var t=0,n=0,i=0,r=0,o=0,s=0;s.2&&t<.8&&i>.6&&r<.2}(n)){if(!function(e){var t=e.upperPercent;return 0===e.lowerPercent&&t>.6}(n))return null;t=t.toLowerCase()}var i=null,r=0;for(e=e.toLowerCase();r/?".split("").forEach(function(e){return d.add(e.charCodeAt(0))});var v=o(s,m,function(e,t){var n=t.toLowerCase().indexOf(e.toLowerCase());return-1===n?null:[{start:n,end:n+e.length}]}),_=o(s,m,function(e,t){return function e(t,n,i,r){if(i===t.length)return[];if(r===n.length)return null;if(t[i]===n[r]){var o=null;return(o=e(t,n,i+1,r+1))?f({start:r,end:r+1},o):null}return e(t,n,i,r+1)}(e.toLowerCase(),t.toLowerCase(),0,0)}),b=new i.a(1e4);var y=128;function w(){for(var e=[],t=[0],n=1;n<=y;n++)t.push(-n);for(n=0;n<=y;n++){var i=t.slice(0);i[0]=-n,e.push(i)}return e}var C,S=w(),x=w(),L=w(),O=!1;function k(e,t,n,i,r){function o(e,t,n){for(void 0===n&&(n=" ");e.length=e.length)return!1;switch(e.charCodeAt(t)){case 95:case 45:case 46:case 32:case 47:case 92:case 39:case 34:case 58:case 36:return!0;default:return!1}}function E(e,t,n){return t[e]!==n[e]}function I(e,t,n,i,r,o,s){var a=e.length>y?y:e.length,u=i.length>y?y:i.length;if(!(n>=a||o>=u||a>u)&&function(e,t,n,i,r,o){for(;t1?1:f),g=S[c-1][l]+-1,m=S[c][l-1]+-1;m>=g?m>p?(S[c][l]=m,L[c][l]=4):m===p?(S[c][l]=m,L[c][l]=6):(S[c][l]=p,L[c][l]=2):g>p?(S[c][l]=g,L[c][l]=1):g===p?(S[c][l]=g,L[c][l]=3):(S[c][l]=p,L[c][l]=2)}if(O&&function(e,t,n,i){e=e.substr(t),n=n.substr(i),console.log(k(S,e,e.length,n,n.length)),console.log(k(L,e,e.length,n,n.length)),console.log(k(x,e,e.length,n,n.length))}(e,n,i,o),M=0,P=-100,A=o,R=s,function e(t,n,i,r,o){if(M>=10||i<-25)return;var s=0;for(;t>0&&n>0;){var a=x[t][n],u=L[t][n];if(4===u)n-=1,o?i-=5:0!==r&&(i-=1),o=!1,s=0;else{if(!(2&u))return;if(4&u&&e(t,n-1,0!==r?i-1:i,r,o),i+=a,t-=1,n-=1,o=!0,r+=Math.pow(2,n+A),1===a){if(s+=1,0===t&&!R)return}else i+=1+s*(a-1),s=0}}i-=n>=3?9:3*n;M+=1;i>P&&(P=i,T=r)}(c-1,l-1,a===u?1:0,0,!1),0!==M)return[P,T,o]}}function D(e,t,n,i,r,o,s){return t[n]!==o[s]?-1:s===n-i?e[n]===r[s]?7:5:!E(s,r,o)||0!==s&&E(s-1,r,o)?!N(o,s)||0!==s&&N(o,s-1)?N(o,s-1)||function(e,t){if(t<0||t>=e.length)return!1;switch(e.charCodeAt(t)){case 32:case 9:return!0;default:return!1}}(o,s-1)?5:1:5:e[n]===r[s]?7:5}!function(e){e.Default=Object.freeze([-100,0,0]),e.isDefault=function(e){return!e||-100===e[0]&&0===e[1]&&0===e[2]}}(C||(C={}));var M=0,T=0,P=0,A=0,R=!1;function F(e,t){if(!(t+1>=e.length)){var n=e[t],i=e[t+1];if(n!==i)return e.slice(0,t)+i+n+e.slice(t+2)}}},GZKt:function(e,t){},GfE5:function(e,t,n){"use strict";n.d(t,"a",function(){return r}),n.d(t,"b",function(){return o});var i=n("CQAd"),r=function(){function e(t){var n=Object(i.d)(t);this._defaultValue=n,this._asciiMap=e._createAsciiMap(n),this._map=new Map}return e._createAsciiMap=function(e){for(var t=new Uint8Array(256),n=0;n<256;n++)t[n]=e;return t},e.prototype.set=function(e,t){var n=Object(i.d)(t);e>=0&&e<256?this._asciiMap[e]=n:this._map.set(e,n)},e.prototype.get=function(e){return e>=0&&e<256?this._asciiMap[e]:this._map.get(e)||this._defaultValue},e}(),o=function(){function e(){this._actual=new r(0)}return e.prototype.add=function(e){this._actual.set(e,1)},e.prototype.has=function(e){return 1===this._actual.get(e)},e}()},GgF8:function(e,t){var n="[object String]",i=Object.prototype.toString,r=Array.isArray;e.exports=function(e){return"string"==typeof e||!r(e)&&function(e){return!!e&&"object"==typeof e}(e)&&i.call(e)==n}},GsV8:function(e,t,n){"use strict";n.d(t,"a",function(){return r}),n.d(t,"b",function(){return o});var i=n("JVO/"),r=Object(i.c)("openerService"),o=Object.freeze({_serviceBrand:void 0,registerOpener:function(){return{dispose:function(){}}},registerValidator:function(){return{dispose:function(){}}},open:function(){return Promise.resolve(!1)}})},Gu5N:function(e,t){},Gu7T:function(e,t,n){"use strict";t.__esModule=!0;var i,r=n("c/Tr"),o=(i=r)&&i.__esModule?i:{default:i};t.default=function(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);tl&&(d=l,h=e.model.getLineMaxColumn(d)),o.d.fromModelState(new o.f(new c.a(s.lineNumber,1,d,h),0,new u.a(d,h),0))}var f=t.modelState.selectionStart.getStartPosition().lineNumber;if(s.lineNumberf){l=e.viewModel.getLineCount();var p=a.lineNumber+1,g=1;return p>l&&(p=l,g=e.viewModel.getLineMaxColumn(p)),o.d.fromViewState(t.viewState.move(t.modelState.hasSelection(),p,g,0))}var m=t.modelState.selectionStart.getEndPosition();return o.d.fromModelState(t.modelState.move(t.modelState.hasSelection(),m.lineNumber,m.column,0))},e.word=function(e,t,n,i){var r=e.model.validatePosition(i);return o.d.fromModelState(a.a.word(e.config,e.model,t.modelState,n,r))},e.cancelSelection=function(e,t){if(!t.modelState.hasSelection())return new o.d(t.modelState,t.viewState);var n=t.viewState.position.lineNumber,i=t.viewState.position.column;return o.d.fromViewState(new o.f(new c.a(n,i,n,i),0,new u.a(n,i),0))},e.moveTo=function(e,t,n,i,r){var s=e.model.validatePosition(i),a=r?e.validateViewPosition(new u.a(r.lineNumber,r.column),s):e.convertModelPositionToViewPosition(s);return o.d.fromViewState(t.viewState.move(n,a.lineNumber,a.column,0))},e.move=function(e,t,n){var i=n.select,r=n.value;switch(n.direction){case 0:return 4===n.unit?this._moveHalfLineLeft(e,t,i):this._moveLeft(e,t,i,r);case 1:return 4===n.unit?this._moveHalfLineRight(e,t,i):this._moveRight(e,t,i,r);case 2:return 2===n.unit?this._moveUpByViewLines(e,t,i,r):this._moveUpByModelLines(e,t,i,r);case 3:return 2===n.unit?this._moveDownByViewLines(e,t,i,r):this._moveDownByModelLines(e,t,i,r);case 4:return this._moveToViewMinColumn(e,t,i);case 5:return this._moveToViewFirstNonWhitespaceColumn(e,t,i);case 6:return this._moveToViewCenterColumn(e,t,i);case 7:return this._moveToViewMaxColumn(e,t,i);case 8:return this._moveToViewLastNonWhitespaceColumn(e,t,i);case 9:var o=t[0],s=e.getCompletelyVisibleModelRange(),a=this._firstLineNumberInRange(e.model,s,r),u=e.model.getLineFirstNonWhitespaceColumn(a);return[this._moveToModelPosition(e,o,i,a,u)];case 11:o=t[0],s=e.getCompletelyVisibleModelRange(),a=this._lastLineNumberInRange(e.model,s,r),u=e.model.getLineFirstNonWhitespaceColumn(a);return[this._moveToModelPosition(e,o,i,a,u)];case 10:o=t[0],s=e.getCompletelyVisibleModelRange(),a=Math.round((s.startLineNumber+s.endLineNumber)/2),u=e.model.getLineFirstNonWhitespaceColumn(a);return[this._moveToModelPosition(e,o,i,a,u)];case 12:for(var c=e.getCompletelyVisibleViewRange(),l=[],d=0,h=t.length;dn.endLineNumber-1&&(r=n.endLineNumber-1),rr,d=i>o,h=io)continue;if(bi)continue;if(_1&&r--,e.columnSelect(t,n,i.fromViewLineNumber,i.fromViewVisualColumn,i.toViewLineNumber,r)},e.columnSelectRight=function(e,t,n){for(var i=0,r=Math.min(n.fromViewLineNumber,n.toViewLineNumber),o=Math.max(n.fromViewLineNumber,n.toViewLineNumber),s=r;s<=o;s++){var c=t.getLineMaxColumn(s),l=a.a.visibleColumnFromColumn2(e,t,new u.a(s,c));i=Math.max(i,l)}var d=n.toViewVisualColumn;return d1)for(var o=n.modelState?n.modelState.position:null,s=n.viewState?n.viewState.position:null,a=0,u=r.length;ar&&(i=r);var o=new c.a(i,1,i,e.context.model.getLineMaxColumn(i)),s=0;if(n.at)switch(n.at){case b.RawAtArgument.Top:s=3;break;case b.RawAtArgument.Center:s=1;break;case b.RawAtArgument.Bottom:s=4}var a=e.context.convertModelRangeToViewRange(o);e.revealRange(!1,a,s,0)},t}(k))),e.SelectAll=Object(o.g)(new(function(e){function t(){return e.call(this,{id:"selectAll",precondition:void 0})||this}return L(t,e),t.prototype.runCoreEditorCommand=function(e,t){e.context.model.pushStackElement(),e.setStates(t.source,3,[h.b.selectAll(e.context,e.getPrimaryCursor())])},t}(k))),e.SetSelection=Object(o.g)(new(function(e){function t(){return e.call(this,{id:"setSelection",precondition:void 0})||this}return L(t,e),t.prototype.runCoreEditorCommand=function(e,t){e.context.model.pushStackElement(),e.setStates(t.source,3,[a.d.fromModelSelection(t.selection)])},t}(k)))}(w||(w={})),S=C||(C={}),x=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return L(t,e),t.prototype.runEditorCommand=function(e,t,n){var i=t._getCursors();i&&this.runCoreEditingCommand(t,i,n||{})},t}(o.c),S.CoreEditingCommand=x,S.LineBreakInsert=Object(o.g)(new(function(e){function t(){return e.call(this,{id:"lineBreakInsert",precondition:g.a.writable,kbOpts:{weight:O,kbExpr:g.a.textInputFocus,primary:0,mac:{primary:301}}})||this}return L(t,e),t.prototype.runCoreEditingCommand=function(e,t,n){e.pushUndoStop(),e.executeCommands(this.id,f.a.lineBreakInsert(t.context.config,t.context.model,t.getAll().map(function(e){return e.modelState.selection})))},t}(x))),S.Outdent=Object(o.g)(new(function(e){function t(){return e.call(this,{id:"outdent",precondition:g.a.writable,kbOpts:{weight:O,kbExpr:m.a.and(g.a.editorTextFocus,g.a.tabDoesNotMoveFocus),primary:1026}})||this}return L(t,e),t.prototype.runCoreEditingCommand=function(e,t,n){e.pushUndoStop(),e.executeCommands(this.id,f.a.outdent(t.context.config,t.context.model,t.getAll().map(function(e){return e.modelState.selection}))),e.pushUndoStop()},t}(x))),S.Tab=Object(o.g)(new(function(e){function t(){return e.call(this,{id:"tab",precondition:g.a.writable,kbOpts:{weight:O,kbExpr:m.a.and(g.a.editorTextFocus,g.a.tabDoesNotMoveFocus),primary:2}})||this}return L(t,e),t.prototype.runCoreEditingCommand=function(e,t,n){e.pushUndoStop(),e.executeCommands(this.id,f.a.tab(t.context.config,t.context.model,t.getAll().map(function(e){return e.modelState.selection}))),e.pushUndoStop()},t}(x))),S.DeleteLeft=Object(o.g)(new(function(e){function t(){return e.call(this,{id:"deleteLeft",precondition:g.a.writable,kbOpts:{weight:O,kbExpr:g.a.textInputFocus,primary:1,secondary:[1025],mac:{primary:1,secondary:[1025,294,257]}}})||this}return L(t,e),t.prototype.runCoreEditingCommand=function(e,t,n){var i=d.a.deleteLeft(t.getPrevEditOperationType(),t.context.config,t.context.model,t.getAll().map(function(e){return e.modelState.selection})),r=i[0],o=i[1];r&&e.pushUndoStop(),e.executeCommands(this.id,o),t.setPrevEditOperationType(2)},t}(x))),S.DeleteRight=Object(o.g)(new(function(e){function t(){return e.call(this,{id:"deleteRight",precondition:g.a.writable,kbOpts:{weight:O,kbExpr:g.a.textInputFocus,primary:20,mac:{primary:20,secondary:[290,276]}}})||this}return L(t,e),t.prototype.runCoreEditingCommand=function(e,t,n){var i=d.a.deleteRight(t.getPrevEditOperationType(),t.context.config,t.context.model,t.getAll().map(function(e){return e.modelState.selection})),r=i[0],o=i[1];r&&e.pushUndoStop(),e.executeCommands(this.id,o),t.setPrevEditOperationType(3)},t}(x)));var E=function(e){function t(t){var n=e.call(this,t)||this;return n._editorHandler=t.editorHandler,n._inputHandler=t.inputHandler,n}return L(t,e),t.prototype.runCommand=function(e,t){var n=e.get(s.a).getFocusedCodeEditor();if(n&&n.hasTextFocus())return this._runEditorHandler(e,n,t);var i=document.activeElement;if(!(i&&["input","textarea"].indexOf(i.tagName.toLowerCase())>=0)){var r=e.get(s.a).getActiveCodeEditor();return r?(r.focus(),this._runEditorHandler(e,r,t)):void 0}document.execCommand(this._inputHandler)},t.prototype._runEditorHandler=function(e,t,n){var i=this._editorHandler;"string"==typeof i?t.trigger("keyboard",i,n):((n=n||{}).source="keyboard",i.runEditorCommand(e,t,n))},t}(o.a),I=function(e){function t(t,n,i){var r=e.call(this,{id:t,precondition:void 0,description:i})||this;return r._handlerId=n,r}return L(t,e),t.prototype.runCommand=function(e,t){var n=e.get(s.a).getFocusedCodeEditor();n&&n.trigger("keyboard",this._handlerId,t)},t}(o.a);function D(e,t){N(new I("default:"+e,e)),N(new I(e,e,t))}N(new E({editorHandler:w.SelectAll,inputHandler:"selectAll",id:"editor.action.selectAll",precondition:g.a.textInputFocus,kbOpts:{weight:O,kbExpr:null,primary:2079},menubarOpts:{menuId:22,group:"1_basic",title:i.a({key:"miSelectAll",comment:["&& denotes a mnemonic"]},"&&Select All"),order:1}})),N(new E({editorHandler:p.b.Undo,inputHandler:"undo",id:p.b.Undo,precondition:g.a.writable,kbOpts:{weight:O,kbExpr:g.a.textInputFocus,primary:2104},menubarOpts:{menuId:14,group:"1_do",title:i.a({key:"miUndo",comment:["&& denotes a mnemonic"]},"&&Undo"),order:1}})),N(new I("default:"+p.b.Undo,p.b.Undo)),N(new E({editorHandler:p.b.Redo,inputHandler:"redo",id:p.b.Redo,precondition:g.a.writable,kbOpts:{weight:O,kbExpr:g.a.textInputFocus,primary:2103,secondary:[3128],mac:{primary:3128}},menubarOpts:{menuId:14,group:"1_do",title:i.a({key:"miRedo",comment:["&& denotes a mnemonic"]},"&&Redo"),order:2}})),N(new I("default:"+p.b.Redo,p.b.Redo)),D(p.b.Type,{description:"Type",args:[{name:"args",schema:{type:"object",required:["text"],properties:{text:{type:"string"}}}}]}),D(p.b.ReplacePreviousChar),D(p.b.CompositionStart),D(p.b.CompositionEnd),D(p.b.Paste),D(p.b.Cut)},Hv4S:function(e,t){},HzeT:function(e,t,n){"use strict";var i=n("3PYz"),r=n("tpuU"),o=n("08Lv");function s(e){if(!(this instanceof s))return new s(e);this.hash=e.hash,this.predResist=!!e.predResist,this.outLen=this.hash.outSize,this.minEntropy=e.minEntropy||this.hash.hmacStrength,this._reseed=null,this.reseedInterval=null,this.K=null,this.V=null;var t=r.toArray(e.entropy,e.entropyEnc||"hex"),n=r.toArray(e.nonce,e.nonceEnc||"hex"),i=r.toArray(e.pers,e.persEnc||"hex");o(t.length>=this.minEntropy/8,"Not enough entropy. Minimum is: "+this.minEntropy+" bits"),this._init(t,n,i)}e.exports=s,s.prototype._init=function(e,t,n){var i=e.concat(t).concat(n);this.K=new Array(this.outLen/8),this.V=new Array(this.outLen/8);for(var r=0;r=this.minEntropy/8,"Not enough entropy. Minimum is: "+this.minEntropy+" bits"),this._update(e.concat(n||[])),this._reseed=1},s.prototype.generate=function(e,t,n,i){if(this._reseed>this.reseedInterval)throw new Error("Reseed is required");"string"!=typeof t&&(i=n,n=t,t=null),n&&(n=r.toArray(n,i||"hex"),this._update(n));for(var o=[];o.length=n)break;var r=e.charCodeAt(t);if(110===r||114===r||87===r)return!0}}return!1}(this.searchString):this.searchString.indexOf("\n")>=0;var t=null;try{t=i.k(this.searchString,this.isRegex,{matchCase:this.matchCase,wholeWord:!1,multiline:e,global:!0})}catch(e){return null}if(!t)return null;var n=!this.isRegex&&!e;return n&&this.searchString.toLowerCase()!==this.searchString.toUpperCase()&&(n=this.matchCase),new c(t,this.wordSeparators?Object(r.a)(this.wordSeparators):null,n?this.searchString:null)},e}();var c=function(){return function(e,t,n){this.regex=e,this.wordSeparators=t,this.simpleSearch=n}}();function l(e,t,n){if(!n)return new a.b(e,null);for(var i=[],r=0,o=t.length;r>0);t[r]>=e?i=r-1:t[r+1]>=e?(n=r,i=r):n=r+1}return n+1},e}(),h=function(){function e(){}return e.findMatches=function(e,t,n,i,r){var o=t.parseSearchRequest();return o?o.regex.multiline?this._doFindMatchesMultiline(e,n,new p(o.wordSeparators,o.regex),i,r):this._doFindMatchesLineByLine(e,n,o,i,r):[]},e._getMultilineMatchRange=function(e,t,n,i,r,o){var a,u,c=0;if(a=i?t+r+(c=i.findLineFeedCountBeforeOffset(r)):t+r,i){var l=i.findLineFeedCountBeforeOffset(r+o.length)-c;u=a+o.length+l}else u=a+o.length;var d=e.getPositionAt(a),h=e.getPositionAt(u);return new s.a(d.lineNumber,d.column,h.lineNumber,h.column)},e._doFindMatchesMultiline=function(e,t,n,i,r){var o,s=e.getOffsetAt(t.getStartPosition()),a=e.getValueInRange(t,1),u="\r\n"===e.getEOL()?new d(a):null,c=[],h=0;for(n.reset(0);o=n.next(a);)if(c[h++]=l(this._getMultilineMatchRange(e,s,a,u,o.index,o[0]),o,i),h>=r)return c;return c},e._doFindMatchesLineByLine=function(e,t,n,i,r){var o=[],s=0;if(t.startLineNumber===t.endLineNumber){var a=e.getLineContent(t.startLineNumber).substring(t.startColumn-1,t.endColumn-1);return s=this._findMatchesInLine(n,a,t.startLineNumber,t.startColumn-1,s,o,i,r),o}var u=e.getLineContent(t.startLineNumber).substring(t.startColumn-1);s=this._findMatchesInLine(n,u,t.startLineNumber,t.startColumn-1,s,o,i,r);for(var c=t.startLineNumber+1;c=c))return r;return r}var _,b=new p(e.wordSeparators,e.regex);b.reset(0);do{if((_=b.next(t))&&(o[r++]=l(new s.a(n,_.index+1+i,n,_.index+1+_[0].length+i),_,u),r>=c))return r}while(_);return r},e.findNextMatch=function(e,t,n,i){var r=t.parseSearchRequest();if(!r)return null;var o=new p(r.wordSeparators,r.regex);return r.regex.multiline?this._doFindNextMatchMultiline(e,n,o,i):this._doFindNextMatchLineByLine(e,n,o,i)},e._doFindNextMatchMultiline=function(e,t,n,i){var r=new o.a(t.lineNumber,1),a=e.getOffsetAt(r),u=e.getLineCount(),c=e.getValueInRange(new s.a(r.lineNumber,r.column,u,e.getLineMaxColumn(u)),1),h="\r\n"===e.getEOL()?new d(c):null;n.reset(t.column-1);var f=n.next(c);return f?l(this._getMultilineMatchRange(e,a,c,h,f.index,f[0]),f,i):1!==t.lineNumber||1!==t.column?this._doFindNextMatchMultiline(e,new o.a(1,1),n,i):null},e._doFindNextMatchLineByLine=function(e,t,n,i){var r=e.getLineCount(),o=t.lineNumber,s=e.getLineContent(o),a=this._findFirstMatchInLine(n,s,o,t.column,i);if(a)return a;for(var u=1;u<=r;u++){var c=(o+u-1)%r,l=e.getLineContent(c+1),d=this._findFirstMatchInLine(n,l,c+1,1,i);if(d)return d}return null},e._findFirstMatchInLine=function(e,t,n,i,r){e.reset(i-1);var o=e.next(t);return o?l(new s.a(n,o.index+1,n,o.index+1+o[0].length),o,r):null},e.findPreviousMatch=function(e,t,n,i){var r=t.parseSearchRequest();if(!r)return null;var o=new p(r.wordSeparators,r.regex);return r.regex.multiline?this._doFindPreviousMatchMultiline(e,n,o,i):this._doFindPreviousMatchLineByLine(e,n,o,i)},e._doFindPreviousMatchMultiline=function(e,t,n,i){var r=this._doFindMatchesMultiline(e,new s.a(1,1,t.lineNumber,t.column),n,i,9990);if(r.length>0)return r[r.length-1];var a=e.getLineCount();return t.lineNumber!==a||t.column!==e.getLineMaxColumn(a)?this._doFindPreviousMatchMultiline(e,new o.a(a,e.getLineMaxColumn(a)),n,i):null},e._doFindPreviousMatchLineByLine=function(e,t,n,i){var r=e.getLineCount(),o=t.lineNumber,s=e.getLineContent(o).substring(0,t.column-1),a=this._findLastMatchInLine(n,s,o,i);if(a)return a;for(var u=1;u<=r;u++){var c=(r+o-u-1)%r,l=e.getLineContent(c+1),d=this._findLastMatchInLine(n,l,c+1,i);if(d)return d}return null},e._findLastMatchInLine=function(e,t,n,i){var r,o=null;for(e.reset(0);r=e.next(t);)o=l(new s.a(n,r.index+1,n,r.index+1+r[0].length),r,i);return o},e}();function f(e,t,n,i,r){return function(e,t,n,i,r){if(0===i)return!0;var o=t.charCodeAt(i-1);if(0!==e.get(o))return!0;if(13===o||10===o)return!0;if(r>0){var s=t.charCodeAt(i);if(0!==e.get(s))return!0}return!1}(e,t,0,i,r)&&function(e,t,n,i,r){if(i+r===n)return!0;var o=t.charCodeAt(i+r);if(0!==e.get(o))return!0;if(13===o||10===o)return!0;if(r>0){var s=t.charCodeAt(i+r-1);if(0!==e.get(s))return!0}return!1}(e,t,n,i,r)}var p=function(){function e(e,t){this._wordSeparators=e,this._searchRegex=t,this._prevMatchStartIndex=-1,this._prevMatchLength=0}return e.prototype.reset=function(e){this._searchRegex.lastIndex=e,this._prevMatchStartIndex=-1,this._prevMatchLength=0},e.prototype.next=function(e){var t,n=e.length;do{if(this._prevMatchStartIndex+this._prevMatchLength===n)return null;if(!(t=this._searchRegex.exec(e)))return null;var i=t.index,r=t[0].length;if(i===this._prevMatchStartIndex&&r===this._prevMatchLength){if(0===r){this._searchRegex.lastIndex+=1;continue}return null}if(this._prevMatchStartIndex=i,this._prevMatchLength=r,!this._wordSeparators||f(this._wordSeparators,e,n,i,r))return t}while(t);return null},e}()},IG52:function(e,t,n){"use strict";n.d(t,"c",function(){return g}),n.d(t,"d",function(){return m}),n.d(t,"b",function(){return v}),n.d(t,"a",function(){return b});var i,r=n("LC7R"),o=(n.n(r),n("ZfGv")),s=n("hK2W"),a=n("tqet"),u=n("AKCZ"),c=n("7/Cv"),l=n("KIxu"),d=n("Bug4"),h=n("gzF+"),f=n("Kp7x"),p=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),g=function(e){function t(t,n,i){var r=e.call(this)||this;return r.options=i,r._context=t||r,r._action=n,n instanceof u.a&&r._register(n.onDidChange(function(e){r.element&&r.handleActionChangeEvent(e)})),r}return p(t,e),t.prototype.handleActionChangeEvent=function(e){void 0!==e.enabled&&this.updateEnabled(),void 0!==e.checked&&this.updateChecked(),void 0!==e.class&&this.updateClass(),void 0!==e.label&&(this.updateLabel(),this.updateTooltip()),void 0!==e.tooltip&&this.updateTooltip()},Object.defineProperty(t.prototype,"actionRunner",{get:function(){return this._actionRunner},set:function(e){this._actionRunner=e},enumerable:!0,configurable:!0}),t.prototype.getAction=function(){return this._action},t.prototype.isEnabled=function(){return this._action.enabled},t.prototype.setActionContext=function(e){this._context=e},t.prototype.render=function(e){var t=this;this.element=e,d.b.addTarget(e);var n=this.options&&this.options.draggable;n&&(e.draggable=!0),this._register(c.h(this.element,d.a.Tap,function(e){return t.onClick(e)})),this._register(c.h(this.element,c.d.MOUSE_DOWN,function(e){n||c.c.stop(e,!0),t._action.enabled&&0===e.button&&t.element&&c.f(t.element,"active")})),this._register(c.h(this.element,c.d.CLICK,function(e){c.c.stop(e,!0),t.options&&t.options.isMenu?t.onClick(e):o.h(function(){return t.onClick(e)})})),this._register(c.h(this.element,c.d.DBLCLICK,function(e){c.c.stop(e,!0)})),[c.d.MOUSE_UP,c.d.MOUSE_OUT].forEach(function(e){t._register(c.h(t.element,e,function(e){c.c.stop(e),c.I(t.element,"active")}))})},t.prototype.onClick=function(e){var t;c.c.stop(e,!0),l.k(this._context)?t=e:(t=this._context,l.h(t)&&(t.event=e)),this._actionRunner.run(this._action,t)},t.prototype.focus=function(){this.element&&(this.element.focus(),c.f(this.element,"focused"))},t.prototype.blur=function(){this.element&&(this.element.blur(),c.I(this.element,"focused"))},t.prototype.updateEnabled=function(){},t.prototype.updateLabel=function(){},t.prototype.updateTooltip=function(){},t.prototype.updateClass=function(){},t.prototype.updateChecked=function(){},t.prototype.dispose=function(){this.element&&(c.K(this.element),this.element=void 0),e.prototype.dispose.call(this)},t}(a.a),m=function(e){function t(n){var i=e.call(this,t.ID,n,n?"separator text":"separator")||this;return i.checked=!1,i.radio=!1,i.enabled=!1,i}return p(t,e),t.ID="vs.actions.separator",t}(u.a),v=function(e){function t(t,n,i){void 0===i&&(i={});var r=e.call(this,t,n,i)||this;return r.options=i,r.options.icon=void 0!==i.icon&&i.icon,r.options.label=void 0===i.label||i.label,r.cssClass="",r}return p(t,e),t.prototype.render=function(t){e.prototype.render.call(this,t),this.element&&(this.label=c.m(this.element,c.a("a.action-label"))),this._action.id===m.ID?this.label.setAttribute("role","presentation"):this.options.isMenu?this.label.setAttribute("role","menuitem"):this.label.setAttribute("role","button"),this.options.label&&this.options.keybinding&&this.element&&(c.m(this.element,c.a("span.keybinding")).textContent=this.options.keybinding),this.updateClass(),this.updateLabel(),this.updateTooltip(),this.updateEnabled(),this.updateChecked()},t.prototype.focus=function(){e.prototype.focus.call(this),this.label.focus()},t.prototype.updateLabel=function(){this.options.label&&(this.label.textContent=this.getAction().label)},t.prototype.updateTooltip=function(){var e=null;this.getAction().tooltip?e=this.getAction().tooltip:!this.options.label&&this.getAction().label&&this.options.icon&&(e=this.getAction().label,this.options.keybinding&&(e=s.a({key:"titleLabel",comment:["action title","action keybinding"]},"{0} ({1})",e,this.options.keybinding))),e&&(this.label.title=e)},t.prototype.updateClass=function(){this.cssClass&&c.J(this.label,this.cssClass),this.options.icon?(this.cssClass=this.getAction().class,c.f(this.label,"icon"),this.cssClass&&c.g(this.label,this.cssClass),this.updateEnabled()):c.I(this.label,"icon")},t.prototype.updateEnabled=function(){this.getAction().enabled?(this.label.removeAttribute("aria-disabled"),this.element&&c.I(this.element,"disabled"),c.I(this.label,"disabled"),this.label.tabIndex=0):(this.label.setAttribute("aria-disabled","true"),this.element&&c.f(this.element,"disabled"),c.f(this.label,"disabled"),c.L(this.label))},t.prototype.updateChecked=function(){this.getAction().checked?c.f(this.label,"checked"):c.I(this.label,"checked")},t}(g),_={orientation:0,context:null,triggerKeys:{keys:[3,10],keyDown:!1}},b=function(e){function t(t,n){void 0===n&&(n=_);var i,r,o=e.call(this)||this;switch(o._onDidBlur=o._register(new f.a),o.onDidBlur=o._onDidBlur.event,o._onDidCancel=o._register(new f.a),o.onDidCancel=o._onDidCancel.event,o._onDidRun=o._register(new f.a),o.onDidRun=o._onDidRun.event,o._onDidBeforeRun=o._register(new f.a),o.onDidBeforeRun=o._onDidBeforeRun.event,o.options=n,o._context=n.context,o.options.triggerKeys||(o.options.triggerKeys=_.triggerKeys),o.options.actionRunner?o._actionRunner=o.options.actionRunner:(o._actionRunner=new u.b,o._register(o._actionRunner)),o._register(o._actionRunner.onDidRun(function(e){return o._onDidRun.fire(e)})),o._register(o._actionRunner.onDidBeforeRun(function(e){return o._onDidBeforeRun.fire(e)})),o.viewItems=[],o.focusedItem=void 0,o.domNode=document.createElement("div"),o.domNode.className="monaco-action-bar",!1!==n.animated&&c.f(o.domNode,"animated"),o.options.orientation){case 0:i=15,r=17;break;case 1:i=17,r=15,o.domNode.className+=" reverse";break;case 2:i=16,r=18,o.domNode.className+=" vertical";break;case 3:i=18,r=16,o.domNode.className+=" vertical reverse"}return o._register(c.h(o.domNode,c.d.KEY_DOWN,function(e){var t=new h.a(e),n=!0;t.equals(i)?o.focusPrevious():t.equals(r)?o.focusNext():t.equals(9)?o.cancel():o.isTriggerKeyEvent(t)?o.options.triggerKeys&&o.options.triggerKeys.keyDown&&o.doTrigger(t):n=!1,n&&(t.preventDefault(),t.stopPropagation())})),o._register(c.h(o.domNode,c.d.KEY_UP,function(e){var t=new h.a(e);o.isTriggerKeyEvent(t)?(o.options.triggerKeys&&!o.options.triggerKeys.keyDown&&o.doTrigger(t),t.preventDefault(),t.stopPropagation()):(t.equals(2)||t.equals(1026))&&o.updateFocusedItem()})),o.focusTracker=o._register(c.S(o.domNode)),o._register(o.focusTracker.onDidBlur(function(){document.activeElement!==o.domNode&&c.E(document.activeElement,o.domNode)||(o._onDidBlur.fire(),o.focusedItem=void 0)})),o._register(o.focusTracker.onDidFocus(function(){return o.updateFocusedItem()})),o.actionsList=document.createElement("ul"),o.actionsList.className="actions-container",o.actionsList.setAttribute("role","toolbar"),o.options.ariaLabel&&o.actionsList.setAttribute("aria-label",o.options.ariaLabel),o.domNode.appendChild(o.actionsList),t.appendChild(o.domNode),o}return p(t,e),t.prototype.isTriggerKeyEvent=function(e){var t=!1;return this.options.triggerKeys&&this.options.triggerKeys.keys.forEach(function(n){t=t||e.equals(n)}),t},t.prototype.updateFocusedItem=function(){for(var e=0;e=n.actionsList.children.length?(n.actionsList.appendChild(o),n.viewItems.push(i)):(n.actionsList.insertBefore(o,n.actionsList.children[r]),n.viewItems.splice(r,0,i),r++)})},t.prototype.clear=function(){this.viewItems=Object(a.f)(this.viewItems),c.p(this.actionsList)},t.prototype.isEmpty=function(){return 0===this.viewItems.length},t.prototype.focus=function(e){var t=!1,n=void 0;void 0===e?t=!0:"number"==typeof e?n=e:"boolean"==typeof e&&(t=e),t&&void 0===this.focusedItem?(this.focusedItem=this.viewItems.length-1,this.focusNext()):(void 0!==n&&(this.focusedItem=n),this.updateFocus())},t.prototype.focusNext=function(){void 0===this.focusedItem&&(this.focusedItem=this.viewItems.length-1);var e,t=this.focusedItem;do{this.focusedItem=(this.focusedItem+1)%this.viewItems.length,e=this.viewItems[this.focusedItem]}while(this.focusedItem!==t&&!e.isEnabled());this.focusedItem!==t||e.isEnabled()||(this.focusedItem=void 0),this.updateFocus()},t.prototype.focusPrevious=function(){void 0===this.focusedItem&&(this.focusedItem=0);var e,t=this.focusedItem;do{this.focusedItem=this.focusedItem-1,this.focusedItem<0&&(this.focusedItem=this.viewItems.length-1),e=this.viewItems[this.focusedItem]}while(this.focusedItem!==t&&!e.isEnabled());this.focusedItem!==t||e.isEnabled()||(this.focusedItem=void 0),this.updateFocus(!0)},t.prototype.updateFocus=function(e){void 0===this.focusedItem&&this.actionsList.focus();for(var t=0;t>>1];n=s.r28shl(n,a),r=s.r28shl(r,a),s.pc2(n,r,e.keys,o)}},u.prototype._update=function(e,t,n,i){var r=this._desState,o=s.readUInt32BE(e,t),a=s.readUInt32BE(e,t+4);s.ip(o,a,r.tmp,0),o=r.tmp[0],a=r.tmp[1],"encrypt"===this.type?this._encrypt(r,o,a,r.tmp,0):this._decrypt(r,o,a,r.tmp,0),o=r.tmp[0],a=r.tmp[1],s.writeUInt32BE(n,o,i),s.writeUInt32BE(n,a,i+4)},u.prototype._pad=function(e,t){for(var n=e.length-t,i=t;i>>0,o=h}s.rip(a,o,i,r)},u.prototype._decrypt=function(e,t,n,i,r){for(var o=n,a=t,u=e.keys.length-2;u>=0;u-=2){var c=e.keys[u],l=e.keys[u+1];s.expand(o,e.tmp,0),c^=e.tmp[0],l^=e.tmp[1];var d=s.substitute(c,l),h=o;o=(a^s.permute(d))>>>0,a=h}s.rip(o,a,i,r)}},IrTV:function(e,t,n){"use strict";n.d(t,"a",function(){return m});var i,r=n("TU7t"),o=n("vORD"),s=n("vZcR"),a=n("ItKl"),u=n("7g0X"),c=n("JVO/"),l=n("fAkY"),d=n("eoic"),h=n("xJaW"),f=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),p=this&&this.__decorate||function(e,t,n,i){var r,o=arguments.length,s=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,n):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,i);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(s=(o<3?r(s):o>3?r(t,n,s):r(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},g=this&&this.__param||function(e,t){return function(n,i){t(n,i,e)}},m=function(e){function t(t,n,i,r,o,s,a,u,c,l){var d=e.call(this,t,i.getRawConfiguration(),{},r,o,s,a,u,c,l)||this;return d._parentEditor=i,d._overwriteOptions=n,e.prototype.updateOptions.call(d,d._overwriteOptions),d._register(i.onDidChangeConfiguration(function(e){return d._onParentConfigurationChanged(e)})),d}return f(t,e),t.prototype.getParentEditor=function(){return this._parentEditor},t.prototype._onParentConfigurationChanged=function(t){e.prototype.updateOptions.call(this,this._parentEditor.getRawConfiguration()),e.prototype.updateOptions.call(this,this._overwriteOptions)},t.prototype.updateOptions=function(t){r.g(this._overwriteOptions,t,!0),e.prototype.updateOptions.call(this,this._overwriteOptions)},t=p([g(3,c.a),g(4,o.a),g(5,a.b),g(6,u.c),g(7,d.c),g(8,l.a),g(9,h.b)],t)}(s.a)},ItKl:function(e,t,n){"use strict";n.d(t,"b",function(){return c}),n.d(t,"a",function(){return l});var i=n("tqet"),r=n("KIxu"),o=n("JVO/"),s=n("Kp7x"),a=n("EMhq"),u=n("WTFd"),c=Object(o.c)("commandService"),l=new(function(){function e(){this._commands=new Map,this._onDidRegisterCommand=new s.a,this.onDidRegisterCommand=this._onDidRegisterCommand.event}return e.prototype.registerCommand=function(e,t){var n=this;if(!e)throw new Error("invalid command");if("string"==typeof e){if(!t)throw new Error("invalid command");return this.registerCommand({id:e,handler:t})}if(e.description){for(var o=[],s=0,u=e.description.args;s0&&(f=t.apply(this,arguments)),e<=1&&(t=void 0),f}}function p(e){var t=typeof e;return!!e&&("object"==t||"function"==t)}e.exports=function(e){return f(2,e)}},"JVO/":function(e,t,n){"use strict";var i;n.d(t,"b",function(){return i}),n.d(t,"a",function(){return r}),t.c=s,t.d=function(e){return function(t,n,i){if(3!==arguments.length)throw new Error("@optional-decorator can only be used to decorate a parameter");o(e,t,i,!0)}},function(e){e.serviceIds=new Map,e.DI_TARGET="$di$target",e.DI_DEPENDENCIES="$di$dependencies",e.getServiceDependencies=function(t){return t[e.DI_DEPENDENCIES]||[]}}(i||(i={}));var r=s("instantiationService");function o(e,t,n,r){t[i.DI_TARGET]===t?t[i.DI_DEPENDENCIES].push({id:e,index:n,optional:r}):(t[i.DI_DEPENDENCIES]=[{id:e,index:n,optional:r}],t[i.DI_TARGET]=t)}function s(e){if(i.serviceIds.has(e))return i.serviceIds.get(e);var t=function(e,n,i){if(3!==arguments.length)throw new Error("@IServiceName-decorator can only be used to decorate a parameter");o(t,e,i,!1)};return t.toString=function(){return e},i.serviceIds.set(e,t),t}},JaR3:function(e,t,n){(t=e.exports=function(e){e=e.toLowerCase();var n=t[e];if(!n)throw new Error(e+" is not supported (we accept pull requests)");return new n}).sha=n("N1es"),t.sha1=n("KQ4j"),t.sha224=n("lXn8"),t.sha256=n("zvjZ"),t.sha384=n("aY2F"),t.sha512=n("C015")},JbsQ:function(e,t,n){"use strict";n.d(t,"a",function(){return r});var i=n("JVO/"),r=Object(i.c)("markerDecorationsService")},K8Am:function(e,t,n){"use strict";n.d(t,"a",function(){return o});var i=n("ZfGv"),r=i.b.performance&&"function"==typeof i.b.performance.now,o=function(){function e(e){this._highResolution=r&&e,this._startTime=this._now(),this._stopTime=-1}return e.create=function(t){return void 0===t&&(t=!0),new e(t)},e.prototype.stop=function(){this._stopTime=this._now()},e.prototype.elapsed=function(){return-1!==this._stopTime?this._stopTime-this._startTime:this._now()-this._startTime},e.prototype._now=function(){return this._highResolution?i.b.performance.now():(new Date).getTime()},e}()},KCUl:function(e,t,n){(function(t){var i=n("geuY"),r=n("lZ6o").ec,o=n("jkjm"),s=n("QDfD");function a(e,t){if(e.cmpn(0)<=0)throw new Error("invalid sig");if(e.cmp(t)>=t)throw new Error("invalid sig")}e.exports=function(e,n,u,c,l){var d=o(u);if("ec"===d.type){if("ecdsa"!==c&&"ecdsa/rsa"!==c)throw new Error("wrong public key type");return function(e,t,n){var i=s[n.data.algorithm.curve.join(".")];if(!i)throw new Error("unknown curve "+n.data.algorithm.curve.join("."));var o=new r(i),a=n.data.subjectPrivateKey.data;return o.verify(t,e,a)}(e,n,d)}if("dsa"===d.type){if("dsa"!==c)throw new Error("wrong public key type");return function(e,t,n){var r=n.data.p,s=n.data.q,u=n.data.g,c=n.data.pub_key,l=o.signature.decode(e,"der"),d=l.s,h=l.r;a(d,s),a(h,s);var f=i.mont(r),p=d.invm(s);return 0===u.toRed(f).redPow(new i(t).mul(p).mod(s)).fromRed().mul(c.toRed(f).redPow(h.mul(p).mod(s)).fromRed()).mod(r).mod(s).cmp(h)}(e,n,d)}if("rsa"!==c&&"ecdsa/rsa"!==c)throw new Error("wrong public key type");n=t.concat([l,n]);for(var h=d.modulus.byteLength(),f=[1],p=0;n.length+f.length+2>>27}function l(e){return e<<30|e>>>2}function d(e,t,n,i){return 0===e?t&n|~t&i:2===e?t&n|t&i|n&i:t^n^i}i(u,r),u.prototype.init=function(){return this._a=1732584193,this._b=4023233417,this._c=2562383102,this._d=271733878,this._e=3285377520,this},u.prototype._update=function(e){for(var t,n=this._w,i=0|this._a,r=0|this._b,o=0|this._c,a=0|this._d,u=0|this._e,h=0;h<16;++h)n[h]=e.readInt32BE(4*h);for(;h<80;++h)n[h]=(t=n[h-3]^n[h-8]^n[h-14]^n[h-16])<<1|t>>>31;for(var f=0;f<80;++f){var p=~~(f/20),g=c(i)+d(p,r,o,a)+u+n[f]+s[p]|0;u=a,a=o,o=l(r),r=i,i=g}this._a=i+this._a|0,this._b=r+this._b|0,this._c=o+this._c|0,this._d=a+this._d|0,this._e=u+this._e|0},u.prototype._hash=function(){var e=o.allocUnsafe(20);return e.writeInt32BE(0|this._a,0),e.writeInt32BE(0|this._b,4),e.writeInt32BE(0|this._c,8),e.writeInt32BE(0|this._d,12),e.writeInt32BE(0|this._e,16),e},e.exports=u},KU51:function(e,t){},KYqO:function(e,t){e.exports={name:"elliptic",version:"6.4.1",description:"EC cryptography",main:"lib/elliptic.js",files:["lib"],scripts:{jscs:"jscs benchmarks/*.js lib/*.js lib/**/*.js lib/**/**/*.js test/index.js",jshint:"jscs benchmarks/*.js lib/*.js lib/**/*.js lib/**/**/*.js test/index.js",lint:"npm run jscs && npm run jshint",unit:"istanbul test _mocha --reporter=spec test/index.js",test:"npm run lint && npm run unit",version:"grunt dist && git add dist/"},repository:{type:"git",url:"git@github.com:indutny/elliptic"},keywords:["EC","Elliptic","curve","Cryptography"],author:"Fedor Indutny ",license:"MIT",bugs:{url:"https://github.com/indutny/elliptic/issues"},homepage:"https://github.com/indutny/elliptic",devDependencies:{brfs:"^1.4.3",coveralls:"^2.11.3",grunt:"^0.4.5","grunt-browserify":"^5.0.0","grunt-cli":"^1.2.0","grunt-contrib-connect":"^1.0.0","grunt-contrib-copy":"^1.0.0","grunt-contrib-uglify":"^1.0.1","grunt-mocha-istanbul":"^3.0.1","grunt-saucelabs":"^8.6.2",istanbul:"^0.4.2",jscs:"^2.9.0",jshint:"^2.6.0",mocha:"^2.1.0"},dependencies:{"bn.js":"^4.4.0",brorand:"^1.0.1","hash.js":"^1.0.0","hmac-drbg":"^1.0.0",inherits:"^2.0.1","minimalistic-assert":"^1.0.0","minimalistic-crypto-utils":"^1.0.0"}}},"KeN/":function(e,t,n){(function(t){var i=n("BVsN"),r=n("9DG0"),o=n("LC74"),s=n("pn+s"),a=n("KCUl"),u=n("ejIc");function c(e){r.Writable.call(this);var t=u[e];if(!t)throw new Error("Unknown message digest");this._hashType=t.hash,this._hash=i(t.hash),this._tag=t.id,this._signType=t.sign}function l(e){r.Writable.call(this);var t=u[e];if(!t)throw new Error("Unknown message digest");this._hash=i(t.hash),this._tag=t.id,this._signType=t.sign}function d(e){return new c(e)}function h(e){return new l(e)}Object.keys(u).forEach(function(e){u[e].id=new t(u[e].id,"hex"),u[e.toLowerCase()]=u[e]}),o(c,r.Writable),c.prototype._write=function(e,t,n){this._hash.update(e),n()},c.prototype.update=function(e,n){return"string"==typeof e&&(e=new t(e,n)),this._hash.update(e),this},c.prototype.sign=function(e,t){this.end();var n=this._hash.digest(),i=s(n,e,this._hashType,this._signType,this._tag);return t?i.toString(t):i},o(l,r.Writable),l.prototype._write=function(e,t,n){this._hash.update(e),n()},l.prototype.update=function(e,n){return"string"==typeof e&&(e=new t(e,n)),this._hash.update(e),this},l.prototype.verify=function(e,n,i){"string"==typeof n&&(n=new t(n,i)),this.end();var r=this._hash.digest();return a(n,r,e,this._signType,this._tag)},e.exports={Sign:d,Verify:h,createSign:d,createVerify:h}}).call(t,n("EuP9").Buffer)},Kp7x:function(e,t,n){"use strict";n.d(t,"b",function(){return r}),n.d(t,"a",function(){return h}),n.d(t,"e",function(){return f}),n.d(t,"d",function(){return p}),n.d(t,"c",function(){return g}),n.d(t,"f",function(){return m});var i,r,o=n("zxiH"),s=n("dwjm"),a=n("tqet"),u=n("EMhq"),c=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)});!function(e){function t(e){return function(t,n,i){void 0===n&&(n=null);var r,o=!1;return r=e(function(e){if(!o)return r?r.dispose():o=!0,t.call(n,e)},null,i),o&&r.dispose(),r}}function n(e,t){return s(function(n,i,r){return void 0===i&&(i=null),e(function(e){return n.call(i,t(e))},null,r)})}function i(e,t){return s(function(n,i,r){return void 0===i&&(i=null),e(function(e){t(e),n.call(i,e)},null,r)})}function r(e,t){return s(function(n,i,r){return void 0===i&&(i=null),e(function(e){return t(e)&&n.call(i,e)},null,r)})}function o(e,t,i){var r=i;return n(e,function(e){return r=t(r,e)})}function s(e){var t,n=new h({onFirstListenerAdd:function(){t=e(n.fire,n)},onLastListenerRemove:function(){t.dispose()}});return n.event}function u(e){var t,n=!0;return r(e,function(e){var i=n||e!==t;return n=!1,t=e,i})}e.None=function(){return a.a.None},e.once=t,e.map=n,e.forEach=i,e.filter=r,e.signal=function(e){return e},e.any=function(){for(var e=[],t=0;t1)&&c.fire(e),u=0},n)})},onLastListenerRemove:function(){o.dispose()}});return c.event},e.stopwatch=function(e){var i=(new Date).getTime();return n(t(e),function(e){return(new Date).getTime()-i})},e.latch=u,e.buffer=function(e,t,n){void 0===t&&(t=!1),void 0===n&&(n=[]);var i=n.slice(),r=e(function(e){i?i.push(e):s.fire(e)}),o=function(){i&&i.forEach(function(e){return s.fire(e)}),i=null},s=new h({onFirstListenerAdd:function(){r||(r=e(function(e){return s.fire(e)}))},onFirstListenerDidAdd:function(){i&&(t?setTimeout(o):o())},onLastListenerRemove:function(){r&&r.dispose(),r=null}});return s.event};var c=function(){function e(e){this.event=e}return e.prototype.map=function(t){return new e(n(this.event,t))},e.prototype.forEach=function(t){return new e(i(this.event,t))},e.prototype.filter=function(t){return new e(r(this.event,t))},e.prototype.reduce=function(t,n){return new e(o(this.event,t,n))},e.prototype.latch=function(){return new e(u(this.event))},e.prototype.on=function(e,t,n){return this.event(e,t,n)},e.prototype.once=function(e,n,i){return t(this.event)(e,n,i)},e}();e.chain=function(e){return new c(e)},e.fromNodeEventEmitter=function(e,t,n){void 0===n&&(n=function(e){return e});var i=function(){for(var e=[],t=0;t0?new d(this._options&&this._options.leakWarningThreshold):void 0}return Object.defineProperty(e.prototype,"event",{get:function(){var t=this;return this._event||(this._event=function(n,i,r){t._listeners||(t._listeners=new u.a);var o=t._listeners.isEmpty();o&&t._options&&t._options.onFirstListenerAdd&&t._options.onFirstListenerAdd(t);var s,c,l=t._listeners.push(i?[n,i]:n);return o&&t._options&&t._options.onFirstListenerDidAdd&&t._options.onFirstListenerDidAdd(t),t._options&&t._options.onListenerDidAdd&&t._options.onListenerDidAdd(t,n,i),t._leakageMon&&(s=t._leakageMon.check(t._listeners.size)),c={dispose:function(){(s&&s(),c.dispose=e._noop,t._disposed)||(l(),t._options&&t._options.onLastListenerRemove&&(t._listeners&&!t._listeners.isEmpty()||t._options.onLastListenerRemove(t)))}},r instanceof a.b?r.add(c):Array.isArray(r)&&r.push(c),c}),this._event},enumerable:!0,configurable:!0}),e.prototype.fire=function(e){if(this._listeners){this._deliveryQueue||(this._deliveryQueue=new u.a);for(var t=this._listeners.iterator(),n=t.next();!n.done;n=t.next())this._deliveryQueue.push([n.value,e]);for(;this._deliveryQueue.size>0;){var i=this._deliveryQueue.shift(),r=i[0],s=i[1];try{"function"==typeof r?r.call(void 0,s):r[0].call(r[1],s)}catch(n){Object(o.e)(n)}}}},e.prototype.dispose=function(){this._listeners&&this._listeners.clear(),this._deliveryQueue&&this._deliveryQueue.clear(),this._leakageMon&&this._leakageMon.dispose(),this._disposed=!0},e._noop=function(){},e}(),f=function(e){function t(t){var n=e.call(this,t)||this;return n._isPaused=0,n._eventQueue=new u.a,n._mergeFn=t&&t.merge,n}return c(t,e),t.prototype.pause=function(){this._isPaused++},t.prototype.resume=function(){if(0!==this._isPaused&&0==--this._isPaused)if(this._mergeFn){var t=this._eventQueue.toArray();this._eventQueue.clear(),e.prototype.fire.call(this,this._mergeFn(t))}else for(;!this._isPaused&&0!==this._eventQueue.size;)e.prototype.fire.call(this,this._eventQueue.shift())},t.prototype.fire=function(t){this._listeners&&(0!==this._isPaused?this._eventQueue.push(t):e.prototype.fire.call(this,t))},t}(h),p=function(){function e(){var e=this;this.hasListeners=!1,this.events=[],this.emitter=new h({onFirstListenerAdd:function(){return e.onFirstListenerAdd()},onLastListenerRemove:function(){return e.onLastListenerRemove()}})}return Object.defineProperty(e.prototype,"event",{get:function(){return this.emitter.event},enumerable:!0,configurable:!0}),e.prototype.add=function(e){var t=this,n={event:e,listener:null};this.events.push(n),this.hasListeners&&this.hook(n);return Object(a.h)(Object(s.a)(function(){t.hasListeners&&t.unhook(n);var e=t.events.indexOf(n);t.events.splice(e,1)}))},e.prototype.onFirstListenerAdd=function(){var e=this;this.hasListeners=!0,this.events.forEach(function(t){return e.hook(t)})},e.prototype.onLastListenerRemove=function(){var e=this;this.hasListeners=!1,this.events.forEach(function(t){return e.unhook(t)})},e.prototype.hook=function(e){var t=this;e.listener=e.event(function(e){return t.emitter.fire(e)})},e.prototype.unhook=function(e){e.listener&&e.listener.dispose(),e.listener=null},e.prototype.dispose=function(){this.emitter.dispose()},e}(),g=function(){function e(){this.buffers=[]}return e.prototype.wrapEvent=function(e){var t=this;return function(n,i,r){return e(function(e){var r=t.buffers[t.buffers.length-1];r?r.push(function(){return n.call(i,e)}):n.call(i,e)},void 0,r)}},e.prototype.bufferEvents=function(e){var t=[];this.buffers.push(t);var n=e();return this.buffers.pop(),t.forEach(function(e){return e()}),n},e}(),m=function(){function e(){var e=this;this.listening=!1,this.inputEvent=r.None,this.inputEventListener=a.a.None,this.emitter=new h({onFirstListenerDidAdd:function(){e.listening=!0,e.inputEventListener=e.inputEvent(e.emitter.fire,e.emitter)},onLastListenerRemove:function(){e.listening=!1,e.inputEventListener.dispose()}}),this.event=this.emitter.event}return Object.defineProperty(e.prototype,"input",{set:function(e){this.inputEvent=e,this.listening&&(this.inputEventListener.dispose(),this.inputEventListener=e(this.emitter.fire,this.emitter))},enumerable:!0,configurable:!0}),e.prototype.dispose=function(){this.inputEventListener.dispose(),this.emitter.dispose()},e}()},Kx4b:function(e,t,n){"use strict";n.d(t,"a",function(){return a});var i=n("uNfg"),r=n("ZfGv"),o=n("ItKl"),s=n("RWr8"),a=new(function(){function e(){this._coreKeybindings=[],this._extensionKeybindings=[],this._cachedMergedKeybindings=null}return e.bindToCurrentPlatform=function(e){if(1===r.a){if(e&&e.win)return e.win}else if(2===r.a){if(e&&e.mac)return e.mac}else if(e&&e.linux)return e.linux;return e},e.prototype.registerKeybindingRule=function(t){var n=e.bindToCurrentPlatform(t);n&&n.primary&&((a=Object(i.f)(n.primary,r.a))&&this._registerDefaultKeybinding(a,t.id,void 0,t.weight,0,t.when));if(n&&Array.isArray(n.secondary))for(var o=0,s=n.secondary.length;o=21&&e<=30||(e>=31&&e<=56||(80===e||81===e||82===e||83===e||84===e||85===e||86===e||110===e||111===e||87===e||88===e||89===e||90===e||91===e||92===e))},e.prototype._assertNoCtrlAlt=function(t,n){t.ctrlKey&&t.altKey&&!t.metaKey&&e._mightProduceChar(t.keyCode)&&console.warn("Ctrl+Alt+ keybindings should not be used by default under Windows. Offender: ",t," for ",n)},e.prototype._registerDefaultKeybinding=function(e,t,n,i,o,s){1===r.a&&this._assertNoCtrlAlt(e.parts[0],t),this._coreKeybindings.push({keybinding:e,command:t,commandArgs:n,when:s,weight1:i,weight2:o}),this._cachedMergedKeybindings=null},e.prototype.getDefaultKeybindings=function(){return this._cachedMergedKeybindings||(this._cachedMergedKeybindings=[].concat(this._coreKeybindings).concat(this._extensionKeybindings),this._cachedMergedKeybindings.sort(u)),this._cachedMergedKeybindings.slice(0)},e}());function u(e,t){return e.weight1!==t.weight1?e.weight1-t.weight1:e.commandt.command?1:e.weight2-t.weight2}s.a.add("platform.keybindingsRegistry",a)},L5KM:function(e,t,n){"use strict";n.d(t,"a",function(){return c}),t._36=d,n.d(t,"T",function(){return p}),n.d(t,"R",function(){return g}),n.d(t,"S",function(){return m}),n.d(t,"e",function(){return v}),n.d(t,"b",function(){return _}),n.d(t,"_46",function(){return b}),n.d(t,"_45",function(){return y}),n.d(t,"_48",function(){return w}),n.d(t,"W",function(){return C}),n.d(t,"Y",function(){return S}),n.d(t,"X",function(){return x}),n.d(t,"V",function(){return L}),n.d(t,"U",function(){return O}),n.d(t,"_2",function(){return k}),n.d(t,"_4",function(){return N}),n.d(t,"_3",function(){return E}),n.d(t,"_5",function(){return I}),n.d(t,"_7",function(){return D}),n.d(t,"_6",function(){return M}),n.d(t,"Z",function(){return T}),n.d(t,"_1",function(){return P}),n.d(t,"_0",function(){return A}),n.d(t,"_14",function(){return j}),n.d(t,"_15",function(){return W}),n.d(t,"_8",function(){return B}),n.d(t,"_9",function(){return V}),n.d(t,"_20",function(){return H}),n.d(t,"_21",function(){return z}),n.d(t,"_19",function(){return U}),n.d(t,"_17",function(){return K}),n.d(t,"_18",function(){return q}),n.d(t,"_10",function(){return G}),n.d(t,"_16",function(){return Z}),n.d(t,"_11",function(){return Y}),n.d(t,"_13",function(){return X}),n.d(t,"_12",function(){return $}),n.d(t,"_47",function(){return J}),n.d(t,"_34",function(){return Q}),n.d(t,"_33",function(){return ee}),n.d(t,"c",function(){return te}),n.d(t,"d",function(){return ne}),n.d(t,"_37",function(){return ie}),n.d(t,"_39",function(){return re}),n.d(t,"_40",function(){return oe}),n.d(t,"_38",function(){return se}),n.d(t,"_35",function(){return ae}),n.d(t,"_23",function(){return ue}),n.d(t,"_24",function(){return ce}),n.d(t,"_22",function(){return le}),n.d(t,"_27",function(){return de}),n.d(t,"_25",function(){return he}),n.d(t,"_26",function(){return fe}),n.d(t,"_28",function(){return pe}),n.d(t,"q",function(){return ge}),n.d(t,"p",function(){return me}),n.d(t,"M",function(){return ve}),n.d(t,"L",function(){return _e}),n.d(t,"G",function(){return be}),n.d(t,"F",function(){return ye}),n.d(t,"z",function(){return we}),n.d(t,"y",function(){return Ce}),n.d(t,"o",function(){return Se}),n.d(t,"x",function(){return xe}),n.d(t,"N",function(){return Le}),n.d(t,"P",function(){return Oe}),n.d(t,"O",function(){return ke}),n.d(t,"Q",function(){return Ne}),n.d(t,"H",function(){return Ee}),n.d(t,"I",function(){return Ie}),n.d(t,"E",function(){return De}),n.d(t,"J",function(){return Me}),n.d(t,"K",function(){return Te}),n.d(t,"r",function(){return Pe}),n.d(t,"t",function(){return Ae}),n.d(t,"v",function(){return Re}),n.d(t,"s",function(){return Fe}),n.d(t,"u",function(){return je}),n.d(t,"w",function(){return We}),n.d(t,"C",function(){return Be}),n.d(t,"A",function(){return Ve}),n.d(t,"B",function(){return He}),n.d(t,"D",function(){return ze}),n.d(t,"n",function(){return Ue}),n.d(t,"g",function(){return Ke}),n.d(t,"h",function(){return qe}),n.d(t,"j",function(){return Ge}),n.d(t,"l",function(){return Ze}),n.d(t,"k",function(){return Ye}),n.d(t,"m",function(){return Xe}),n.d(t,"i",function(){return $e}),n.d(t,"_43",function(){return Je}),n.d(t,"_44",function(){return Qe}),n.d(t,"_41",function(){return et}),n.d(t,"_42",function(){return tt}),n.d(t,"_31",function(){return nt}),n.d(t,"_32",function(){return it}),n.d(t,"_29",function(){return rt}),t.f=ot,t._30=function(){for(var e=[],t=0;te.length)return!1;for(var r=0;r=65&&o<=90&&o+32===s||s>=65&&s<=90&&s+32===o))return!1}return!0},e.prototype._createOperationsForBlockComment=function(t,n,i,r,o){var s,a=t.startLineNumber,u=t.startColumn,c=t.endLineNumber,d=t.endColumn,h=r.getLineContent(a),f=r.getLineContent(c),p=h.lastIndexOf(n,u-1+n.length),g=f.indexOf(i,d-1-i.length);if(-1!==p&&-1!==g)if(a===c){h.substring(p+n.length,g).indexOf(i)>=0&&(p=-1,g=-1)}else{var m=h.substring(p+n.length),v=f.substring(0,g);(m.indexOf(i)>=0||v.indexOf(i)>=0)&&(p=-1,g=-1)}-1!==p&&-1!==g?(p+n.length0&&32===f.charCodeAt(g-1)&&(i=" "+i,g-=1),s=e._createRemoveBlockCommentOperations(new l.a(a,p+n.length+1,c,g+1),n,i)):(s=e._createAddBlockCommentOperations(t,n,i),this._usedEndToken=1===s.length?i:null);for(var _=0,b=s;_a?o-1:o}},e}(),m=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),v=function(e){function t(t,n){var i=e.call(this,n)||this;return i._type=t,i}return m(t,e),t.prototype.run=function(e,t){if(t.hasModel()){for(var n=t.getModel(),i=[],r=t.getSelections(),o=n.getOptions(),s=0,a=r;s0&&"#"===n.charAt(n.length-1)?n.substring(0,n.length-1):n)]=t,this._onDidChangeSchema.fire(e)},e.prototype.notifySchemaChanged=function(e){this._onDidChangeSchema.fire(e)},e}());i.a.add(o.JSONContribution,s)},LYGd:function(e,t,n){"use strict";var i=n("EuP9").Buffer,r=n("LC74"),o=n("yDvu"),s=new Array(16),a=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,7,4,13,1,10,6,15,3,12,0,9,5,2,14,11,8,3,10,14,4,9,15,8,1,2,7,0,6,13,11,5,12,1,9,11,10,0,8,12,4,13,3,7,15,14,5,6,2,4,0,5,9,7,12,2,10,14,1,3,8,11,6,15,13],u=[5,14,7,0,9,2,11,4,13,6,15,8,1,10,3,12,6,11,3,7,0,13,5,10,14,15,8,12,4,9,1,2,15,5,1,3,7,14,6,9,11,8,12,2,10,0,4,13,8,6,4,1,3,11,15,0,5,12,2,13,9,7,10,14,12,15,10,4,1,5,8,7,6,2,13,14,0,3,9,11],c=[11,14,15,12,5,8,7,9,11,13,14,15,6,7,9,8,7,6,8,13,11,9,7,15,7,12,15,9,11,7,13,12,11,13,6,7,14,9,13,15,14,8,13,6,5,12,7,5,11,12,14,15,14,15,9,8,9,14,5,6,8,6,5,12,9,15,5,11,6,8,13,12,5,12,13,14,11,8,5,6],l=[8,9,9,11,13,15,15,5,7,7,8,11,14,14,12,6,9,13,15,7,12,8,9,11,7,7,12,7,6,15,13,11,9,7,15,11,8,6,6,14,12,13,5,14,13,13,7,5,15,5,8,11,14,14,6,14,6,9,12,9,12,5,15,8,8,5,12,9,12,5,14,6,8,13,6,5,15,13,11,11],d=[0,1518500249,1859775393,2400959708,2840853838],h=[1352829926,1548603684,1836072691,2053994217,0];function f(){o.call(this,64),this._a=1732584193,this._b=4023233417,this._c=2562383102,this._d=271733878,this._e=3285377520}function p(e,t){return e<>>32-t}function g(e,t,n,i,r,o,s,a){return p(e+(t^n^i)+o+s|0,a)+r|0}function m(e,t,n,i,r,o,s,a){return p(e+(t&n|~t&i)+o+s|0,a)+r|0}function v(e,t,n,i,r,o,s,a){return p(e+((t|~n)^i)+o+s|0,a)+r|0}function _(e,t,n,i,r,o,s,a){return p(e+(t&i|n&~i)+o+s|0,a)+r|0}function b(e,t,n,i,r,o,s,a){return p(e+(t^(n|~i))+o+s|0,a)+r|0}r(f,o),f.prototype._update=function(){for(var e=s,t=0;t<16;++t)e[t]=this._block.readInt32LE(4*t);for(var n=0|this._a,i=0|this._b,r=0|this._c,o=0|this._d,f=0|this._e,y=0|this._a,w=0|this._b,C=0|this._c,S=0|this._d,x=0|this._e,L=0;L<80;L+=1){var O,k;L<16?(O=g(n,i,r,o,f,e[a[L]],d[0],c[L]),k=b(y,w,C,S,x,e[u[L]],h[0],l[L])):L<32?(O=m(n,i,r,o,f,e[a[L]],d[1],c[L]),k=_(y,w,C,S,x,e[u[L]],h[1],l[L])):L<48?(O=v(n,i,r,o,f,e[a[L]],d[2],c[L]),k=v(y,w,C,S,x,e[u[L]],h[2],l[L])):L<64?(O=_(n,i,r,o,f,e[a[L]],d[3],c[L]),k=m(y,w,C,S,x,e[u[L]],h[3],l[L])):(O=b(n,i,r,o,f,e[a[L]],d[4],c[L]),k=g(y,w,C,S,x,e[u[L]],h[4],l[L])),n=f,f=o,o=p(r,10),r=i,i=O,y=x,x=S,S=p(C,10),C=w,w=k}var N=this._b+r+S|0;this._b=this._c+o+x|0,this._c=this._d+f+y|0,this._d=this._e+n+w|0,this._e=this._a+i+C|0,this._a=N},f.prototype._digest=function(){this._block[this._blockOffset++]=128,this._blockOffset>56&&(this._block.fill(0,this._blockOffset,64),this._update(),this._blockOffset=0),this._block.fill(0,this._blockOffset,56),this._block.writeUInt32LE(this._length[0],56),this._block.writeUInt32LE(this._length[1],60),this._update();var e=i.alloc?i.alloc(20):new i(20);return e.writeInt32LE(this._a,0),e.writeInt32LE(this._b,4),e.writeInt32LE(this._c,8),e.writeInt32LE(this._d,12),e.writeInt32LE(this._e,16),e},e.exports=f},MOjS:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i,r=n("hK2W"),o=n("Kp7x"),s=n("tqet"),a=n("7g0X"),u=n("OHx0"),c=n("vTy2"),l=n("03Zz"),d=n("eoic"),h=n("/9db"),f=(n("OV+G"),n("7/Cv")),p=n("L5KM"),g=n("TNPA"),m=n("qecS"),v=n("1sup"),_=n("X6iQ"),b=n("fw2Z"),y=n("ZYUE"),w=n("ni2T"),C=n("Nr0y"),S=encodeURIComponent(''),L=encodeURIComponent(''),k=encodeURIComponent(''),E=encodeURIComponent(''),D=encodeURIComponent(''),T=encodeURIComponent('');function A(e,t){return"."+i.className(e).split(" ").join(".")+' { background: url("data:image/svg+xml,'+i.getSVGData(e,t)+'") center center no-repeat; height: 16px; width: 16px; }'}!function(e){e.getSVGData=function(e,t){switch(e){case C.a.Ignore:var n=t.type===d.d?g.a.fromHex("#75BEFF"):g.a.fromHex("#007ACC");return t.type===d.d?D+encodeURIComponent(n.toString())+M:T+encodeURIComponent(n.toString())+P;case C.a.Info:var i=t.type===d.d?g.a.fromHex("#007ACC"):g.a.fromHex("#75BEFF");return t.type===d.d?D+encodeURIComponent(i.toString())+M:T+encodeURIComponent(i.toString())+P;case C.a.Warning:var r=t.type===d.d?g.a.fromHex("#DDB100"):g.a.fromHex("#fc0");return t.type===d.d?k+encodeURIComponent(r.toString())+N:E+encodeURIComponent(r.toString())+I;case C.a.Error:var o=t.type===d.d?g.a.fromHex("#A1260D"):g.a.fromHex("#F48771");return t.type===d.d?S+encodeURIComponent(o.toString())+x:L+encodeURIComponent(o.toString())+O}return""},e.className=function(e){switch(e){case C.a.Ignore:return"severity-icon severity-ignore";case C.a.Info:return"severity-icon severity-info";case C.a.Warning:return"severity-icon severity-warning";case C.a.Error:return"severity-icon severity-error"}return""}}(i||(i={})),Object(d.f)(function(e,t){t.addRule(A(C.a.Error,e)),t.addRule(A(C.a.Warning,e)),t.addRule(A(C.a.Info,e)),t.addRule(A(C.a.Ignore,e))});var R,F=this&&this.__extends||(R=function(e,t){return(R=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}R(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),j=function(){function e(e,t,n){var i=this;this._lines=0,this._longestLineLength=0,this._relatedDiagnostics=new WeakMap,this._disposables=[],this._editor=t;var r=document.createElement("div");r.className="descriptioncontainer",r.setAttribute("aria-live","assertive"),r.setAttribute("role","alert"),this._messageBlock=document.createElement("div"),f.f(this._messageBlock,"message"),r.appendChild(this._messageBlock),this._relatedBlock=document.createElement("div"),r.appendChild(this._relatedBlock),this._disposables.push(f.k(this._relatedBlock,"click",function(e){e.preventDefault();var t=i._relatedDiagnostics.get(e.target);t&&n(t)})),this._scrollable=new m.b(r,{horizontal:1,vertical:1,useShadows:!1,horizontalScrollbarSize:3,verticalScrollbarSize:3}),e.appendChild(this._scrollable.getDomNode()),this._disposables.push(this._scrollable.onScroll(function(e){r.style.left="-"+e.scrollLeft+"px",r.style.top="-"+e.scrollTop+"px"})),this._disposables.push(this._scrollable)}return e.prototype.dispose=function(){Object(s.f)(this._disposables)},e.prototype.update=function(e){var t=e.source,n=e.message,i=e.relatedInformation,r=e.code,o=n.split(/\r\n|\r|\n/g);this._lines=o.length,this._longestLineLength=0;for(var s=0,a=o;s1?r.a("problems","{0} of {1} problems",n,o):r.a("change","{0} of {1} problem",n,o);this.setTitle(Object(y.b)(d.uri),h)}this._icon.className=i.className(u.c.toSeverity(this._severity)),this.editor.revealPositionInCenter(l,0)},t.prototype.updateMarker=function(e){this._container.classList.remove("stale"),this._message.update(e)},t.prototype.showStale=function(){this._container.classList.add("stale"),this._relayout()},t.prototype._doLayoutBody=function(t,n){e.prototype._doLayoutBody.call(this,t,n),this._heightInPixel=t,this._message.layout(t,n),this._container.style.height=t+"px"},t.prototype._onWidth=function(e){this._message.layout(this._heightInPixel,e)},t.prototype._relayout=function(){e.prototype._relayout.call(this,this.computeRequiredHeight())},t.prototype.computeRequiredHeight=function(){return 3+this._message.getHeightInLines()},t}(b.c),B=Object(p._30)(p.q,p.p),V=Object(p._30)(p.M,p.L),H=Object(p._30)(p.G,p.F),z=Object(p._36)("editorMarkerNavigationError.background",{dark:B,light:B,hc:B},r.a("editorMarkerNavigationError","Editor marker navigation widget error color.")),U=Object(p._36)("editorMarkerNavigationWarning.background",{dark:V,light:V,hc:V},r.a("editorMarkerNavigationWarning","Editor marker navigation widget warning color.")),K=Object(p._36)("editorMarkerNavigationInfo.background",{dark:H,light:H,hc:H},r.a("editorMarkerNavigationInfo","Editor marker navigation widget info color.")),q=Object(p._36)("editorMarkerNavigation.background",{dark:"#2D2D30",light:g.a.white,hc:"#0C141F"},r.a("editorMarkerNavigationBackground","Editor marker navigation widget background."));Object(d.f)(function(e,t){var n=e.getColor(p._46);n&&t.addRule(".monaco-editor .marker-widget a { color: "+n+"; }")});var G=n("aL7J"),Z=n("vORD"),Y=n("zxiH"),X=n("C3c5"),$=n("AKCZ"),J=n("NqM+");n.d(t,"MarkerController",function(){return oe}),n.d(t,"NextMarkerAction",function(){return ae});var Q=this&&this.__extends||function(){var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(t,n)};return function(t,n){function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}}(),ee=this&&this.__decorate||function(e,t,n,i){var r,o=arguments.length,s=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,n):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,i);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(s=(o<3?r(s):o>3?r(t,n,s):r(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},te=this&&this.__param||function(e,t){return function(n,i){t(n,i,e)}},ne=this&&this.__awaiter||function(e,t,n,i){return new(n||(n=Promise))(function(r,o){function s(e){try{u(i.next(e))}catch(e){o(e)}}function a(e){try{u(i.throw(e))}catch(e){o(e)}}function u(e){e.done?r(e.value):new n(function(t){t(e.value)}).then(s,a)}u((i=i.apply(e,t||[])).next())})},ie=this&&this.__generator||function(e,t){var n,i,r,o,s={label:0,sent:function(){if(1&r[0])throw r[1];return r[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,i&&(r=2&o[0]?i.return:o[0]?i.throw||((r=i.return)&&r.call(i),0):i.next)&&!(r=r.call(i,o[1])).done)return r;switch(i=0,r&&(o=[2&o[0],r.value]),o[0]){case 0:case 1:r=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,i=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(r=(r=s.trys).length>0&&r[r.length-1])&&(6===o[0]||2===o[0])){s=0;continue}if(3===o[0]&&(!r||o[1]>r[0]&&o[1]=0?this._markers[this._nextIdx]:void 0;this._markers=e||[],this._markers.sort(se.compareMarker),this._nextIdx=t?Math.max(-1,Object(_.c)(this._markers,t,se.compareMarker)):-1,this._onMarkerSetChanged.fire(this)},e.prototype.withoutWatchingEditorPosition=function(e){this._ignoreSelectionChange=!0;try{e()}finally{this._ignoreSelectionChange=!1}},e.prototype._initIdx=function(e){for(var t=!1,n=this._editor.getPosition(),i=0;i0?this._nextIdx=(this._nextIdx-1+this._markers.length)%this._markers.length:i=!0),n!==this._nextIdx){var r=this._markers[this._nextIdx];this._onCurrentMarkerChanged.fire(r)}return i},e.prototype.canNavigate=function(){return this._markers.length>0},e.prototype.findMarkerAtPosition=function(e){for(var t=0,n=this._markers;t=0;a--)(r=e[a])&&(s=(o<3?r(s):o>3?r(t,n,s):r(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},y=this&&this.__param||function(e,t){return function(n,i){t(n,i,e)}},w=function(e){function t(t,n,i){var r=e.call(this)||this;return r._editor=t,r._codeEditorService=n,r._configurationService=i,r._localToDispose=r._register(new c.b),r._decorationsIds=[],r._colorDatas=new Map,r._colorDecoratorIds=[],r._decorationsTypes=new Set,r._register(t.onDidChangeModel(function(e){r._isEnabled=r.isEnabled(),r.onModelChanged()})),r._register(t.onDidChangeModelLanguage(function(e){return r.onModelChanged()})),r._register(p.c.onDidChange(function(e){return r.onModelChanged()})),r._register(t.onDidChangeConfiguration(function(e){var t=r._isEnabled;r._isEnabled=r.isEnabled(),t!==r._isEnabled&&(r._isEnabled?r.onModelChanged():r.removeAllDecorations())})),r._timeoutTimer=null,r._computePromise=null,r._isEnabled=r.isEnabled(),r.onModelChanged(),r}return _(t,e),t.prototype.isEnabled=function(){var e=this._editor.getModel();if(!e)return!1;var t=e.getLanguageIdentifier(),n=this._configurationService.getValue(t.language);if(n){var i=n.colorDecorators;if(i&&void 0!==i.enable&&!i.enable)return i.enable}return this._editor.getConfiguration().contribInfo.colorDecorators},t.prototype.getId=function(){return t.ID},t.get=function(e){return e.getContribution(this.ID)},t.prototype.dispose=function(){this.stop(),this.removeAllDecorations(),e.prototype.dispose.call(this)},t.prototype.onModelChanged=function(){var e=this;if(this.stop(),this._isEnabled){var n=this._editor.getModel();n&&p.c.has(n)&&(this._localToDispose.add(this._editor.onDidChangeModelContent(function(n){e._timeoutTimer||(e._timeoutTimer=new i.e,e._timeoutTimer.cancelAndSet(function(){e._timeoutTimer=null,e.beginCompute()},t.RECOMPUTE_TIME))})),this.beginCompute())}},t.prototype.beginCompute=function(){var e=this;this._computePromise=Object(i.f)(function(t){var n=e._editor.getModel();return n?Object(g.b)(n,t):Promise.resolve([])}),this._computePromise.then(function(t){e.updateDecorations(t),e.updateColorDecorators(t),e._computePromise=null},o.e)},t.prototype.stop=function(){this._timeoutTimer&&(this._timeoutTimer.cancel(),this._timeoutTimer=null),this._computePromise&&(this._computePromise.cancel(),this._computePromise=null),this._localToDispose.clear()},t.prototype.updateDecorations=function(e){var t=this,n=e.map(function(e){return{range:{startLineNumber:e.colorInfo.range.startLineNumber,startColumn:e.colorInfo.range.startColumn,endLineNumber:e.colorInfo.range.endLineNumber,endColumn:e.colorInfo.range.endColumn},options:f.a.EMPTY}});this._decorationsIds=this._editor.deltaDecorations(this._decorationsIds,n),this._colorDatas=new Map,this._decorationsIds.forEach(function(n,i){return t._colorDatas.set(n,e[i])})},t.prototype.updateColorDecorators=function(e){for(var t=this,n=[],i={},o=0;o>>2}function l(e,t,n,i){return 0===e?t&n|~t&i:2===e?t&n|t&i|n&i:t^n^i}i(u,r),u.prototype.init=function(){return this._a=1732584193,this._b=4023233417,this._c=2562383102,this._d=271733878,this._e=3285377520,this},u.prototype._update=function(e){for(var t,n=this._w,i=0|this._a,r=0|this._b,o=0|this._c,a=0|this._d,u=0|this._e,d=0;d<16;++d)n[d]=e.readInt32BE(4*d);for(;d<80;++d)n[d]=n[d-3]^n[d-8]^n[d-14]^n[d-16];for(var h=0;h<80;++h){var f=~~(h/20),p=0|((t=i)<<5|t>>>27)+l(f,r,o,a)+u+n[h]+s[f];u=a,a=o,o=c(r),r=i,i=p}this._a=i+this._a|0,this._b=r+this._b|0,this._c=o+this._c|0,this._d=a+this._d|0,this._e=u+this._e|0},u.prototype._hash=function(){var e=o.allocUnsafe(20);return e.writeInt32BE(0|this._a,0),e.writeInt32BE(0|this._b,4),e.writeInt32BE(0|this._c,8),e.writeInt32BE(0|this._d,12),e.writeInt32BE(0|this._e,16),e},e.exports=u},NBYJ:function(e,t){},NCTB:function(e,t,n){"use strict";t.sha1=n("bMQ9"),t.sha224=n("fWB8"),t.sha256=n("Q48P"),t.sha384=n("EH7o"),t.sha512=n("8/0b")},NMED:function(e,t,n){"use strict";var i=n("geuY"),r=n("lZ6o").utils,o=r.assert;function s(e,t){if(e instanceof s)return e;this._importDER(e,t)||(o(e.r&&e.s,"Signature without r or s"),this.r=new i(e.r,16),this.s=new i(e.s,16),void 0===e.recoveryParam?this.recoveryParam=null:this.recoveryParam=e.recoveryParam)}function a(e,t){var n=e[t.place++];if(!(128&n))return n;for(var i=15&n,r=0,o=0,s=t.place;o>>3);for(e.push(128|n);--n;)e.push(t>>>(n<<3)&255);e.push(t)}}e.exports=s,s.prototype._importDER=function(e,t){e=r.toArray(e,t);var n=new function(){this.place=0};if(48!==e[n.place++])return!1;if(a(e,n)+n.place!==e.length)return!1;if(2!==e[n.place++])return!1;var o=a(e,n),s=e.slice(n.place,o+n.place);if(n.place+=o,2!==e[n.place++])return!1;var u=a(e,n);if(e.length!==u+n.place)return!1;var c=e.slice(n.place,u+n.place);return 0===s[0]&&128&s[1]&&(s=s.slice(1)),0===c[0]&&128&c[1]&&(c=c.slice(1)),this.r=new i(s),this.s=new i(c),this.recoveryParam=null,!0},s.prototype.toDER=function(e){var t=this.r.toArray(),n=this.s.toArray();for(128&t[0]&&(t=[0].concat(t)),128&n[0]&&(n=[0].concat(n)),t=u(t),n=u(n);!(n[0]||128&n[1]);)n=n.slice(1);var i=[2];c(i,t.length),(i=i.concat(t)).push(2),c(i,n.length);var o=i.concat(n),s=[48];return c(s,o.length),s=s.concat(o),r.encode(s,e)}},NjkW:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});n("WUwp");var i=n("tqet"),r=n("ZfGv"),o=n("03Zz"),s=n("artP"),a=n("vTy2"),u=n("iHM7"),c=function(){function e(e,t,n){this.selection=e,this.targetPosition=t,this.copy=n,this.targetSelection=null}return e.prototype.getEditOperations=function(e,t){var n=e.getValueInRange(this.selection);this.copy||t.addEditOperation(this.selection,null),t.addEditOperation(new a.a(this.targetPosition.lineNumber,this.targetPosition.column,this.targetPosition.lineNumber,this.targetPosition.column),n),!this.selection.containsPosition(this.targetPosition)||this.copy&&(this.selection.getEndPosition().equals(this.targetPosition)||this.selection.getStartPosition().equals(this.targetPosition))?this.copy?this.targetSelection=new u.a(this.targetPosition.lineNumber,this.targetPosition.column,this.selection.endLineNumber-this.selection.startLineNumber+this.targetPosition.lineNumber,this.selection.startLineNumber===this.selection.endLineNumber?this.targetPosition.column+this.selection.endColumn-this.selection.startColumn:this.selection.endColumn):this.targetPosition.lineNumber>this.selection.endLineNumber?this.targetSelection=new u.a(this.targetPosition.lineNumber-this.selection.endLineNumber+this.selection.startLineNumber,this.targetPosition.column,this.targetPosition.lineNumber,this.selection.startLineNumber===this.selection.endLineNumber?this.targetPosition.column+this.selection.endColumn-this.selection.startColumn:this.selection.endColumn):this.targetPosition.lineNumber0&&r[r.length-1])&&(6===o[0]||2===o[0])){s=0;continue}if(3===o[0]&&(!r||o[1]>r[0]&&o[1]=e._maxRounds){t();break}if(!r){t();break}var c=i.findNextBracket(r);if(!c){t();break}if(Date.now()-u>e._maxDuration){setTimeout(function(){return e._bracketsRightYield(t,n+1,i,r,s)});break}var l=c.close;if(c.isOpen){var d=a.has(l)?a.get(l):0;a.set(l,d+1)}else{d=a.has(l)?a.get(l):0;if(d-=1,a.set(l,Math.max(0,d)),d<0){var h=s.get(l);h||(h=new o.a,s.set(l,h)),h.push(c.range)}}r=c.range.getEndPosition()}},e._bracketsLeftYield=function(t,n,i,o,s,a){for(var u=new Map,c=Date.now();;){if(n>=e._maxRounds&&0===s.size){t();break}if(!o){t();break}var l=i.findPrevBracket(o);if(!l){t();break}if(Date.now()-c>e._maxDuration){setTimeout(function(){return e._bracketsLeftYield(t,n+1,i,o,s,a)});break}var d=l.close;if(l.isOpen){m=u.has(d)?u.get(d):0;if(m-=1,u.set(d,Math.max(0,m)),m<0){var h=s.get(d);if(h){var f=h.shift();0===h.size&&s.delete(d);var p=r.a.fromPositions(l.range.getEndPosition(),f.getStartPosition()),g=r.a.fromPositions(l.range.getStartPosition(),f.getEndPosition());a.push({range:p}),a.push({range:g}),e._addBracketLeading(i,g,a)}}}else{var m=u.has(d)?u.get(d):0;u.set(d,m+1)}o=l.range.getStartPosition()}},e._addBracketLeading=function(e,t,n){if(t.startLineNumber!==t.endLineNumber){var o=t.startLineNumber,s=e.getLineFirstNonWhitespaceColumn(o);0!==s&&s!==t.startColumn&&(n.push({range:r.a.fromPositions(new i.a(o,s),t.getEndPosition())}),n.push({range:r.a.fromPositions(new i.a(o,1),t.getEndPosition())}));var a=o-1;if(a>0){var u=e.getLineFirstNonWhitespaceColumn(a);u===t.startColumn&&u!==e.getLineLastNonWhitespaceColumn(a)&&(n.push({range:r.a.fromPositions(new i.a(a,u),t.getEndPosition())}),n.push({range:r.a.fromPositions(new i.a(a,1),t.getEndPosition())}))}}},e._maxDuration=30,e._maxRounds=2,e}()},"NqM+":function(e,t,n){"use strict";n.d(t,"a",function(){return r});var i=n("JVO/"),r=Object(i.c)("keybindingService")},Nr0y:function(e,t,n){"use strict";var i,r=n("hK2W"),o=n("aL7J");!function(e){e[e.Ignore=0]="Ignore",e[e.Info=1]="Info",e[e.Warning=2]="Warning",e[e.Error=3]="Error"}(i||(i={})),function(e){var t="error",n="warning",i="warn",s="info",a=Object.create(null);a[e.Error]=r.a("sev.error","Error"),a[e.Warning]=r.a("sev.warning","Warning"),a[e.Info]=r.a("sev.info","Info"),e.fromValue=function(r){return r?o.n(t,r)?e.Error:o.n(n,r)||o.n(i,r)?e.Warning:o.n(s,r)?e.Info:e.Ignore:e.Ignore}}(i||(i={})),t.a=i},Ny4g:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i,r,o,s,a,u,c,l,d,h,f,p,g,m,v,_,b,y,w,C,S,x,L,O,k,N,E,I,D,M,T=n("iXRW"),P=(n("tZcU"),n("80kS")),A=n("Kp7x"),R=n("uNfg"),F=n("mrx5"),j=n("artP"),W=n("vTy2"),B=n("iHM7"),V=n("c6Qy");!function(e){e[e.Unnecessary=1]="Unnecessary",e[e.Deprecated=2]="Deprecated"}(i||(i={})),function(e){e[e.Hint=1]="Hint",e[e.Info=2]="Info",e[e.Warning=4]="Warning",e[e.Error=8]="Error"}(r||(r={})),function(e){e[e.Unknown=0]="Unknown",e[e.Backspace=1]="Backspace",e[e.Tab=2]="Tab",e[e.Enter=3]="Enter",e[e.Shift=4]="Shift",e[e.Ctrl=5]="Ctrl",e[e.Alt=6]="Alt",e[e.PauseBreak=7]="PauseBreak",e[e.CapsLock=8]="CapsLock",e[e.Escape=9]="Escape",e[e.Space=10]="Space",e[e.PageUp=11]="PageUp",e[e.PageDown=12]="PageDown",e[e.End=13]="End",e[e.Home=14]="Home",e[e.LeftArrow=15]="LeftArrow",e[e.UpArrow=16]="UpArrow",e[e.RightArrow=17]="RightArrow",e[e.DownArrow=18]="DownArrow",e[e.Insert=19]="Insert",e[e.Delete=20]="Delete",e[e.KEY_0=21]="KEY_0",e[e.KEY_1=22]="KEY_1",e[e.KEY_2=23]="KEY_2",e[e.KEY_3=24]="KEY_3",e[e.KEY_4=25]="KEY_4",e[e.KEY_5=26]="KEY_5",e[e.KEY_6=27]="KEY_6",e[e.KEY_7=28]="KEY_7",e[e.KEY_8=29]="KEY_8",e[e.KEY_9=30]="KEY_9",e[e.KEY_A=31]="KEY_A",e[e.KEY_B=32]="KEY_B",e[e.KEY_C=33]="KEY_C",e[e.KEY_D=34]="KEY_D",e[e.KEY_E=35]="KEY_E",e[e.KEY_F=36]="KEY_F",e[e.KEY_G=37]="KEY_G",e[e.KEY_H=38]="KEY_H",e[e.KEY_I=39]="KEY_I",e[e.KEY_J=40]="KEY_J",e[e.KEY_K=41]="KEY_K",e[e.KEY_L=42]="KEY_L",e[e.KEY_M=43]="KEY_M",e[e.KEY_N=44]="KEY_N",e[e.KEY_O=45]="KEY_O",e[e.KEY_P=46]="KEY_P",e[e.KEY_Q=47]="KEY_Q",e[e.KEY_R=48]="KEY_R",e[e.KEY_S=49]="KEY_S",e[e.KEY_T=50]="KEY_T",e[e.KEY_U=51]="KEY_U",e[e.KEY_V=52]="KEY_V",e[e.KEY_W=53]="KEY_W",e[e.KEY_X=54]="KEY_X",e[e.KEY_Y=55]="KEY_Y",e[e.KEY_Z=56]="KEY_Z",e[e.Meta=57]="Meta",e[e.ContextMenu=58]="ContextMenu",e[e.F1=59]="F1",e[e.F2=60]="F2",e[e.F3=61]="F3",e[e.F4=62]="F4",e[e.F5=63]="F5",e[e.F6=64]="F6",e[e.F7=65]="F7",e[e.F8=66]="F8",e[e.F9=67]="F9",e[e.F10=68]="F10",e[e.F11=69]="F11",e[e.F12=70]="F12",e[e.F13=71]="F13",e[e.F14=72]="F14",e[e.F15=73]="F15",e[e.F16=74]="F16",e[e.F17=75]="F17",e[e.F18=76]="F18",e[e.F19=77]="F19",e[e.NumLock=78]="NumLock",e[e.ScrollLock=79]="ScrollLock",e[e.US_SEMICOLON=80]="US_SEMICOLON",e[e.US_EQUAL=81]="US_EQUAL",e[e.US_COMMA=82]="US_COMMA",e[e.US_MINUS=83]="US_MINUS",e[e.US_DOT=84]="US_DOT",e[e.US_SLASH=85]="US_SLASH",e[e.US_BACKTICK=86]="US_BACKTICK",e[e.US_OPEN_SQUARE_BRACKET=87]="US_OPEN_SQUARE_BRACKET",e[e.US_BACKSLASH=88]="US_BACKSLASH",e[e.US_CLOSE_SQUARE_BRACKET=89]="US_CLOSE_SQUARE_BRACKET",e[e.US_QUOTE=90]="US_QUOTE",e[e.OEM_8=91]="OEM_8",e[e.OEM_102=92]="OEM_102",e[e.NUMPAD_0=93]="NUMPAD_0",e[e.NUMPAD_1=94]="NUMPAD_1",e[e.NUMPAD_2=95]="NUMPAD_2",e[e.NUMPAD_3=96]="NUMPAD_3",e[e.NUMPAD_4=97]="NUMPAD_4",e[e.NUMPAD_5=98]="NUMPAD_5",e[e.NUMPAD_6=99]="NUMPAD_6",e[e.NUMPAD_7=100]="NUMPAD_7",e[e.NUMPAD_8=101]="NUMPAD_8",e[e.NUMPAD_9=102]="NUMPAD_9",e[e.NUMPAD_MULTIPLY=103]="NUMPAD_MULTIPLY",e[e.NUMPAD_ADD=104]="NUMPAD_ADD",e[e.NUMPAD_SEPARATOR=105]="NUMPAD_SEPARATOR",e[e.NUMPAD_SUBTRACT=106]="NUMPAD_SUBTRACT",e[e.NUMPAD_DECIMAL=107]="NUMPAD_DECIMAL",e[e.NUMPAD_DIVIDE=108]="NUMPAD_DIVIDE",e[e.KEY_IN_COMPOSITION=109]="KEY_IN_COMPOSITION",e[e.ABNT_C1=110]="ABNT_C1",e[e.ABNT_C2=111]="ABNT_C2",e[e.MAX_VALUE=112]="MAX_VALUE"}(o||(o={})),function(e){e[e.LTR=0]="LTR",e[e.RTL=1]="RTL"}(s||(s={})),function(e){e[e.Auto=1]="Auto",e[e.Hidden=2]="Hidden",e[e.Visible=3]="Visible"}(a||(a={})),function(e){e[e.Left=1]="Left",e[e.Center=2]="Center",e[e.Right=4]="Right",e[e.Full=7]="Full"}(u||(u={})),function(e){e[e.Inline=1]="Inline"}(c||(c={})),function(e){e[e.TextDefined=0]="TextDefined",e[e.LF=1]="LF",e[e.CRLF=2]="CRLF"}(l||(l={})),function(e){e[e.LF=1]="LF",e[e.CRLF=2]="CRLF"}(d||(d={})),function(e){e[e.LF=0]="LF",e[e.CRLF=1]="CRLF"}(h||(h={})),function(e){e[e.AlwaysGrowsWhenTypingAtEdges=0]="AlwaysGrowsWhenTypingAtEdges",e[e.NeverGrowsWhenTypingAtEdges=1]="NeverGrowsWhenTypingAtEdges",e[e.GrowsOnlyWhenTypingBefore=2]="GrowsOnlyWhenTypingBefore",e[e.GrowsOnlyWhenTypingAfter=3]="GrowsOnlyWhenTypingAfter"}(f||(f={})),function(e){e[e.Smooth=0]="Smooth",e[e.Immediate=1]="Immediate"}(p||(p={})),function(e){e[e.NotSet=0]="NotSet",e[e.ContentFlush=1]="ContentFlush",e[e.RecoverFromMarkers=2]="RecoverFromMarkers",e[e.Explicit=3]="Explicit",e[e.Paste=4]="Paste",e[e.Undo=5]="Undo",e[e.Redo=6]="Redo"}(g||(g={})),function(e){e[e.None=0]="None",e[e.Small=1]="Small",e[e.Large=2]="Large",e[e.SmallBlocks=3]="SmallBlocks",e[e.LargeBlocks=4]="LargeBlocks"}(m||(m={})),function(e){e[e.None=0]="None",e[e.Same=1]="Same",e[e.Indent=2]="Indent",e[e.DeepIndent=3]="DeepIndent"}(v||(v={})),function(e){e[e.Hidden=0]="Hidden",e[e.Blink=1]="Blink",e[e.Smooth=2]="Smooth",e[e.Phase=3]="Phase",e[e.Expand=4]="Expand",e[e.Solid=5]="Solid"}(_||(_={})),function(e){e[e.Line=1]="Line",e[e.Block=2]="Block",e[e.Underline=3]="Underline",e[e.LineThin=4]="LineThin",e[e.BlockOutline=5]="BlockOutline",e[e.UnderlineThin=6]="UnderlineThin"}(b||(b={})),function(e){e[e.Off=0]="Off",e[e.On=1]="On",e[e.Relative=2]="Relative",e[e.Interval=3]="Interval",e[e.Custom=4]="Custom"}(y||(y={})),function(e){e[e.EXACT=0]="EXACT",e[e.ABOVE=1]="ABOVE",e[e.BELOW=2]="BELOW"}(w||(w={})),function(e){e[e.TOP_RIGHT_CORNER=0]="TOP_RIGHT_CORNER",e[e.BOTTOM_RIGHT_CORNER=1]="BOTTOM_RIGHT_CORNER",e[e.TOP_CENTER=2]="TOP_CENTER"}(C||(C={})),function(e){e[e.UNKNOWN=0]="UNKNOWN",e[e.TEXTAREA=1]="TEXTAREA",e[e.GUTTER_GLYPH_MARGIN=2]="GUTTER_GLYPH_MARGIN",e[e.GUTTER_LINE_NUMBERS=3]="GUTTER_LINE_NUMBERS",e[e.GUTTER_LINE_DECORATIONS=4]="GUTTER_LINE_DECORATIONS",e[e.GUTTER_VIEW_ZONE=5]="GUTTER_VIEW_ZONE",e[e.CONTENT_TEXT=6]="CONTENT_TEXT",e[e.CONTENT_EMPTY=7]="CONTENT_EMPTY",e[e.CONTENT_VIEW_ZONE=8]="CONTENT_VIEW_ZONE",e[e.CONTENT_WIDGET=9]="CONTENT_WIDGET",e[e.OVERVIEW_RULER=10]="OVERVIEW_RULER",e[e.SCROLLBAR=11]="SCROLLBAR",e[e.OVERLAY_WIDGET=12]="OVERLAY_WIDGET",e[e.OUTSIDE_EDITOR=13]="OUTSIDE_EDITOR"}(S||(S={})),function(e){e[e.None=0]="None",e[e.Indent=1]="Indent",e[e.IndentOutdent=2]="IndentOutdent",e[e.Outdent=3]="Outdent"}(x||(x={})),function(e){e[e.Method=0]="Method",e[e.Function=1]="Function",e[e.Constructor=2]="Constructor",e[e.Field=3]="Field",e[e.Variable=4]="Variable",e[e.Class=5]="Class",e[e.Struct=6]="Struct",e[e.Interface=7]="Interface",e[e.Module=8]="Module",e[e.Property=9]="Property",e[e.Event=10]="Event",e[e.Operator=11]="Operator",e[e.Unit=12]="Unit",e[e.Value=13]="Value",e[e.Constant=14]="Constant",e[e.Enum=15]="Enum",e[e.EnumMember=16]="EnumMember",e[e.Keyword=17]="Keyword",e[e.Text=18]="Text",e[e.Color=19]="Color",e[e.File=20]="File",e[e.Reference=21]="Reference",e[e.Customcolor=22]="Customcolor",e[e.Folder=23]="Folder",e[e.TypeParameter=24]="TypeParameter",e[e.Snippet=25]="Snippet"}(L||(L={})),function(e){e[e.Deprecated=1]="Deprecated"}(O||(O={})),function(e){e[e.KeepWhitespace=1]="KeepWhitespace",e[e.InsertAsSnippet=4]="InsertAsSnippet"}(k||(k={})),function(e){e[e.Invoke=0]="Invoke",e[e.TriggerCharacter=1]="TriggerCharacter",e[e.TriggerForIncompleteCompletions=2]="TriggerForIncompleteCompletions"}(N||(N={})),function(e){e[e.Invoke=1]="Invoke",e[e.TriggerCharacter=2]="TriggerCharacter",e[e.ContentChange=3]="ContentChange"}(E||(E={})),function(e){e[e.Text=0]="Text",e[e.Read=1]="Read",e[e.Write=2]="Write"}(I||(I={})),function(e){e[e.File=0]="File",e[e.Module=1]="Module",e[e.Namespace=2]="Namespace",e[e.Package=3]="Package",e[e.Class=4]="Class",e[e.Method=5]="Method",e[e.Property=6]="Property",e[e.Field=7]="Field",e[e.Constructor=8]="Constructor",e[e.Enum=9]="Enum",e[e.Interface=10]="Interface",e[e.Function=11]="Function",e[e.Variable=12]="Variable",e[e.Constant=13]="Constant",e[e.String=14]="String",e[e.Number=15]="Number",e[e.Boolean=16]="Boolean",e[e.Array=17]="Array",e[e.Object=18]="Object",e[e.Key=19]="Key",e[e.Null=20]="Null",e[e.EnumMember=21]="EnumMember",e[e.Struct=22]="Struct",e[e.Event=23]="Event",e[e.Operator=24]="Operator",e[e.TypeParameter=25]="TypeParameter"}(D||(D={})),function(e){e[e.Deprecated=1]="Deprecated"}(M||(M={}));var H=function(){function e(){}return e.chord=function(e,t){return Object(R.a)(e,t)},e.CtrlCmd=2048,e.Shift=1024,e.Alt=512,e.WinCtrl=256,e}();function z(){return{editor:void 0,languages:void 0,CancellationTokenSource:P.b,Emitter:A.a,KeyCode:o,KeyMod:H,Position:j.a,Range:W.a,Selection:B.a,SelectionDirection:s,MarkerSeverity:r,MarkerTag:i,Uri:F.a,Token:V.a}}n("gvGx");var U,K=n("vORD"),q=n("7/Cv"),G=n("tqet"),Z=n("EMhq"),Y=n("+vUW"),X=n("lapT"),$=n("ZYUE"),J=n("aL7J"),Q=n("ItKl"),ee=this&&this.__extends||(U=function(e,t){return(U=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}U(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),te=this&&this.__decorate||function(e,t,n,i){var r,o=arguments.length,s=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,n):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,i);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(s=(o<3?r(s):o>3?r(t,n,s):r(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},ne=this&&this.__param||function(e,t){return function(n,i){t(n,i,e)}},ie=this&&this.__awaiter||function(e,t,n,i){return new(n||(n=Promise))(function(r,o){function s(e){try{u(i.next(e))}catch(e){o(e)}}function a(e){try{u(i.throw(e))}catch(e){o(e)}}function u(e){e.done?r(e.value):new n(function(t){t(e.value)}).then(s,a)}u((i=i.apply(e,t||[])).next())})},re=this&&this.__generator||function(e,t){var n,i,r,o,s={label:0,sent:function(){if(1&r[0])throw r[1];return r[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,i&&(r=2&o[0]?i.return:o[0]?i.throw||((r=i.return)&&r.call(i),0):i.next)&&!(r=r.call(i,o[1])).done)return r;switch(i=0,r&&(o=[2&o[0],r.value]),o[0]){case 0:case 1:r=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,i=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(r=(r=s.trys).length>0&&r[r.length-1])&&(6===o[0]||2===o[0])){s=0;continue}if(3===o[0]&&(!r||o[1]>r[0]&&o[1]=this.ranges.length&&(this.nextIdx=0)):(this.nextIdx-=1,this.nextIdx<0&&(this.nextIdx=this.ranges.length-1));var n=this.ranges[this.nextIdx];this.ignoreSelectionChange=!0;try{var i=n.range.getStartPosition();this._editor.setPosition(i),this._editor.revealPositionInCenter(i,t)}finally{this.ignoreSelectionChange=!1}}},t.prototype.canNavigate=function(){return this.ranges&&this.ranges.length>0},t.prototype.next=function(e){void 0===e&&(e=0),this._move(!0,e)},t.prototype.previous=function(e){void 0===e&&(e=0),this._move(!1,e)},t.prototype.dispose=function(){e.prototype.dispose.call(this),this.ranges=[],this.disposed=!0},t}(G.a),de=n("5lao"),he=n("33h2"),fe=n("D2uo"),pe=n("PCC9"),ge=n("jUH2"),me=n("606G"),ve=n("B/Xy"),_e=n("odeJ"),be=n("zxiH"),ye=n("ZfGv"),we=n("KIxu"),Ce=this&&this.__extends||function(){var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(t,n)};return function(t,n){function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}}(),Se="$initialize",xe=!1;function Le(e){ye.f&&(xe||(xe=!0,console.warn("Could not create web worker(s). Falling back to loading web worker code in main thread, which might cause UI freezes. Please see https://github.com/Microsoft/monaco-editor#faq")),console.warn(e.message))}var Oe=function(){function e(e){this._workerId=-1,this._handler=e,this._lastSentReq=0,this._pendingReplies=Object.create(null)}return e.prototype.setWorkerId=function(e){this._workerId=e},e.prototype.sendMessage=function(e,t){var n=this,i=String(++this._lastSentReq);return new Promise(function(r,o){n._pendingReplies[i]={resolve:r,reject:o},n._send({vsWorker:n._workerId,req:i,method:e,args:t})})},e.prototype.handleMessage=function(e){e&&e.vsWorker&&(-1!==this._workerId&&e.vsWorker!==this._workerId||this._handleMessage(e))},e.prototype._handleMessage=function(e){var t=this;if(e.seq){var n=e;if(!this._pendingReplies[n.seq])return void console.warn("Got reply to unknown seq");var i=this._pendingReplies[n.seq];if(delete this._pendingReplies[n.seq],n.err){var r=n.err;return n.err.$isError&&((r=new Error).name=n.err.name,r.message=n.err.message,r.stack=n.err.stack),void i.reject(r)}i.resolve(n.res)}else{var o=e,s=o.req;this._handler.handleMessage(o.method,o.args).then(function(e){t._send({vsWorker:t._workerId,seq:s,res:e,err:void 0})},function(e){e.detail instanceof Error&&(e.detail=Object(be.g)(e.detail)),t._send({vsWorker:t._workerId,seq:s,res:void 0,err:Object(be.g)(e)})})}},e.prototype._send=function(e){var t=[];if(e.req)for(var n=e,i=0;i1&&p>1;){if(d.charCodeAt(f-2)!==h.charCodeAt(p-2))break;f--,p--}(f>1||p>1)&&this._pushTrimWhitespaceCharChange(r,o+1,1,f,s+1,1,p);for(var g=Fe._getLastNonBlankColumn(d,1),m=Fe._getLastNonBlankColumn(h,1),v=d.length+1,_=h.length+1;gt&&(t=a),s>n&&(n=s),u>n&&(n=u)}t++,n++;var c=new qe.a(n,t,0);for(i=0,r=e.length;i=this._maxCharCode?0:this._states.get(e,t)},e}(),Ze=null;var Ye=null;var Xe=function(){function e(){}return e._createLink=function(e,t,n,i,r){var o=r-1;do{var s=t.charCodeAt(o);if(2!==e.get(s))break;o--}while(o>i);if(i>0){var a=t.charCodeAt(i-1),u=t.charCodeAt(o);(40===a&&41===u||91===a&&93===u||123===a&&125===u)&&o--}return{range:{startLineNumber:n,startColumn:i+1,endLineNumber:n,endColumn:o+2},url:t.substring(i,o+1)}},e.computeLinks=function(t,n){void 0===n&&(null===Ze&&(Ze=new Ge([[1,104,2],[1,72,2],[1,102,6],[1,70,6],[2,116,3],[2,84,3],[3,116,4],[3,84,4],[4,112,5],[4,80,5],[5,115,9],[5,83,9],[5,58,10],[6,105,7],[6,73,7],[7,108,8],[7,76,8],[8,101,9],[8,69,9],[9,58,10],[10,47,11],[11,47,12]])),n=Ze);for(var i=function(){if(null===Ye){Ye=new Ke.a(0);for(var e=0;e<" \t<>'\"、。。、,.:;?!@#$%&*‘“〈《「『【〔([{「」}])〕】』」》〉”’`~…".length;e++)Ye.set(" \t<>'\"、。。、,.:;?!@#$%&*‘“〈《「『【〔([{「」}])〕】』」》〉”’`~…".charCodeAt(e),1);for(e=0;e<".,;".length;e++)Ye.set(".,;".charCodeAt(e),2)}return Ye}(),r=[],o=1,s=t.getLineCount();o<=s;o++){for(var a=t.getLineContent(o),u=a.length,c=0,l=0,d=0,h=1,f=!1,p=!1,g=!1;c=0?((i+=n?1:-1)<0?i=e.length-1:i%=e.length,e[i]):null},e.INSTANCE=new e,e}(),Je=this&&this.__extends||function(){var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(t,n)};return function(t,n){function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}}(),Qe=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return Je(t,e),Object.defineProperty(t.prototype,"uri",{get:function(){return this._uri},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"version",{get:function(){return this._versionId},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"eol",{get:function(){return this._eol},enumerable:!0,configurable:!0}),t.prototype.getValue=function(){return this.getText()},t.prototype.getLinesContent=function(){return this._lines.slice(0)},t.prototype.getLineCount=function(){return this._lines.length},t.prototype.getLineContent=function(e){return this._lines[e-1]},t.prototype.getWordAtPosition=function(e,t){var n=Object(Ue.d)(e.column,Object(Ue.c)(t),this._lines[e.lineNumber-1],0);return n?new W.a(e.lineNumber,n.startColumn,e.lineNumber,n.endColumn):null},t.prototype.getWordUntilPosition=function(e,t){var n=this.getWordAtPosition(e,t);return n?{word:this._lines[e.lineNumber-1].substring(n.startColumn-1,e.column-1),startColumn:n.startColumn,endColumn:e.column}:{word:"",startColumn:e.column,endColumn:e.column}},t.prototype.createWordIterator=function(e){var t,n,i=this,r=0,o=0,s=[],a=function(){if(o=i._lines.length?Te.c:(n=i._lines[r],s=i._wordenize(n,e),o=0,r+=1,a())};return{next:a}},t.prototype.getLineWords=function(e,t){for(var n=this._lines[e-1],i=[],r=0,o=this._wordenize(n,t);rthis._lines.length)t=this._lines.length,n=this._lines[t-1].length+1,i=!0;else{var r=this._lines[t-1].length+1;n<1?(n=1,i=!0):n>r&&(n=r,i=!0)}return i?{lineNumber:t,column:n}:e},t}(ze),et=function(){function e(e,t){this._host=e,this._models=Object.create(null),this._foreignModuleFactory=t,this._foreignModule=null}return e.prototype.dispose=function(){this._models=Object.create(null)},e.prototype._getModel=function(e){return this._models[e]},e.prototype._getModels=function(){var e=this,t=[];return Object.keys(this._models).forEach(function(n){return t.push(e._models[n])}),t},e.prototype.acceptNewModel=function(e){this._models[e.url]=new Qe(F.a.parse(e.url),e.lines,e.EOL,e.versionId)},e.prototype.acceptModelChanged=function(e,t){this._models[e]&&this._models[e].onEvents(t)},e.prototype.acceptRemovedModel=function(e){this._models[e]&&delete this._models[e]},e.prototype.computeDiff=function(e,t,n){var i=this._getModel(e),r=this._getModel(t);if(!i||!r)return Promise.resolve(null);var o=i.getLinesContent(),s=r.getLinesContent(),a=new Ve(o,s,{shouldComputeCharChanges:!0,shouldPostProcessCharChanges:!0,shouldIgnoreTrimWhitespace:n,shouldMakePrettyDiff:!0}).computeDiff(),u=!(a.length>0)&&this._modelsAreIdentical(i,r);return Promise.resolve({identical:u,changes:a})},e.prototype._modelsAreIdentical=function(e,t){var n=e.getLineCount();if(n!==t.getLineCount())return!1;for(var i=1;i<=n;i++){if(e.getLineContent(i)!==t.getLineContent(i))return!1}return!0},e.prototype.computeMoreMinimalEdits=function(t,n){var i=this._getModel(t);if(!i)return Promise.resolve(n);for(var r=[],o=void 0,s=0,a=n=Object(De.o)(n,function(e,t){return e.range&&t.range?W.a.compareRangesUsingStarts(e.range,t.range):(e.range?0:1)-(t.range?0:1)});se._diffLimit)r.push({range:c,text:l});else for(var f=Object(Me.b)(h,l,!1),p=i.offsetAt(W.a.lift(c).getStartPosition()),g=0,m=f;g=0;a--)(r=e[a])&&(s=(o<3?r(s):o>3?r(t,n,s):r(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},ct=this&&this.__param||function(e,t){return function(n,i){t(n,i,e)}},lt=6e4,dt=3e5;function ht(e,t){var n=e.getModel(t);return!!n&&!n.isTooLargeForSyncing()}var ft=function(e){function t(t,n,i){var r=e.call(this)||this;return r._modelService=t,r._workerManager=r._register(new gt(r._modelService)),r._logService=i,r._register(pe.q.register("*",{provideLinks:function(e,t){return ht(r._modelService,e.uri)?r._workerManager.withWorker().then(function(t){return t.computeLinks(e.uri)}).then(function(e){return e&&{links:e}}):Promise.resolve({links:[]})}})),r._register(pe.d.register("*",new pt(r._workerManager,n,r._modelService))),r}return at(t,e),t.prototype.dispose=function(){e.prototype.dispose.call(this)},t.prototype.canComputeDiff=function(e,t){return ht(this._modelService,e)&&ht(this._modelService,t)},t.prototype.computeDiff=function(e,t,n){return this._workerManager.withWorker().then(function(i){return i.computeDiff(e,t,n)})},t.prototype.computeMoreMinimalEdits=function(e,t){var n=this;if(Object(De.n)(t)){if(!ht(this._modelService,e))return Promise.resolve(t);var i=st.a.create(!0),r=this._workerManager.withWorker().then(function(n){return n.computeMoreMinimalEdits(e,t)});return r.finally(function(){return n._logService.trace("FORMAT#computeMoreMinimalEdits",e.toString(!0),i.elapsed())}),r}return Promise.resolve(void 0)},t.prototype.canNavigateValueSet=function(e){return ht(this._modelService,e)},t.prototype.navigateValueSet=function(e,t,n){return this._workerManager.withWorker().then(function(i){return i.navigateValueSet(e,t,n)})},t.prototype.canComputeWordRanges=function(e){return ht(this._modelService,e)},t.prototype.computeWordRanges=function(e,t){return this._workerManager.withWorker().then(function(n){return n.computeWordRanges(e,t)})},t=ut([ct(0,tt.a),ct(1,it),ct(2,ot.a)],t)}(G.a),pt=function(){function e(e,t,n){this._debugDisplayName="wordbasedCompletions",this._workerManager=e,this._configurationService=t,this._modelService=n}return e.prototype.provideCompletionItems=function(e,t){if(this._configurationService.getValue(e.uri,t,"editor").wordBasedSuggestions&&ht(this._modelService,e.uri))return this._workerManager.withWorker().then(function(n){return n.textualSuggest(e.uri,t)})},e}(),gt=function(e){function t(t){var n=e.call(this)||this;return n._modelService=t,n._editorWorkerClient=null,n._lastWorkerUsedTime=(new Date).getTime(),n._register(new _e.c).cancelAndSet(function(){return n._checkStopIdleWorker()},Math.round(dt/2)),n._register(n._modelService.onModelRemoved(function(e){return n._checkStopEmptyWorker()})),n}return at(t,e),t.prototype.dispose=function(){this._editorWorkerClient&&(this._editorWorkerClient.dispose(),this._editorWorkerClient=null),e.prototype.dispose.call(this)},t.prototype._checkStopEmptyWorker=function(){this._editorWorkerClient&&(0===this._modelService.getModels().length&&(this._editorWorkerClient.dispose(),this._editorWorkerClient=null))},t.prototype._checkStopIdleWorker=function(){this._editorWorkerClient&&((new Date).getTime()-this._lastWorkerUsedTime>dt&&(this._editorWorkerClient.dispose(),this._editorWorkerClient=null))},t.prototype.withWorker=function(){return this._lastWorkerUsedTime=(new Date).getTime(),this._editorWorkerClient||(this._editorWorkerClient=new bt(this._modelService,"editorWorkerService")),Promise.resolve(this._editorWorkerClient)},t}(G.a),mt=function(e){function t(t,n,i){var r=e.call(this)||this;if(r._syncedModels=Object.create(null),r._syncedModelsLastUsedTime=Object.create(null),r._proxy=t,r._modelService=n,!i){var o=new _e.c;o.cancelAndSet(function(){return r._checkStopModelSync()},Math.round(lt/2)),r._register(o)}return r}return at(t,e),t.prototype.dispose=function(){for(var t in this._syncedModels)Object(G.f)(this._syncedModels[t]);this._syncedModels=Object.create(null),this._syncedModelsLastUsedTime=Object.create(null),e.prototype.dispose.call(this)},t.prototype.ensureSyncedResources=function(e){for(var t=0,n=e;tlt&&t.push(n)}for(var i=0,r=t;i'"_]/g,"-")}function Dt(e,t){return new Error(e.languageId+": "+t)}function Mt(e,t,n,i,r){var o=null;return t.replace(/\$((\$)|(#)|(\d\d?)|[sS](\d\d?)|@(\w+))/g,function(t,s,a,u,c,l,d,h,f){return Nt(a)?Nt(u)?!Nt(c)&&c0;){var i=e.tokenizer[n];if(i)return i;var r=n.lastIndexOf(".");n=r<0?null:n.substr(0,r)}return null}var Pt=function(){function e(e){this._maxCacheDepth=e,this._entries=Object.create(null)}return e.create=function(e,t){return this._INSTANCE.create(e,t)},e.prototype.create=function(e,t){if(null!==e&&e.depth>=this._maxCacheDepth)return new At(e,t);var n=At.getStackElementId(e);n.length>0&&(n+="|"),n+=t;var i=this._entries[n];return i||(i=new At(e,t),this._entries[n]=i,i)},e._INSTANCE=new e(5),e}(),At=function(){function e(e,t){this.parent=e,this.state=t,this.depth=(this.parent?this.parent.depth:0)+1}return e.getStackElementId=function(e){for(var t="";null!==e;)t.length>0&&(t+="|"),t+=e.state,e=e.parent;return t},e._equals=function(e,t){for(;null!==e&&null!==t;){if(e===t)return!0;if(e.state!==t.state)return!1;e=e.parent,t=t.parent}return null===e&&null===t},e.prototype.equals=function(t){return e._equals(this,t)},e.prototype.push=function(e){return Pt.create(this,e)},e.prototype.pop=function(){return this.parent},e.prototype.popall=function(){for(var e=this;e.parent;)e=e.parent;return e},e.prototype.switchTo=function(e){return Pt.create(this.parent,e)},e}(),Rt=function(){function e(e,t){this.modeId=e,this.state=t}return e.prototype.equals=function(e){return this.modeId===e.modeId&&this.state.equals(e.state)},e.prototype.clone=function(){return this.state.clone()===this.state?this:new e(this.modeId,this.state)},e}(),Ft=function(){function e(e){this._maxCacheDepth=e,this._entries=Object.create(null)}return e.create=function(e,t){return this._INSTANCE.create(e,t)},e.prototype.create=function(e,t){if(null!==t)return new jt(e,t);if(null!==e&&e.depth>=this._maxCacheDepth)return new jt(e,t);var n=At.getStackElementId(e),i=this._entries[n];return i||(i=new jt(e,null),this._entries[n]=i,i)},e._INSTANCE=new e(5),e}(),jt=function(){function e(e,t){this.stack=e,this.embeddedModeData=t}return e.prototype.clone=function(){return(this.embeddedModeData?this.embeddedModeData.clone():null)===this.embeddedModeData?this:Ft.create(this.stack,this.embeddedModeData)},e.prototype.equals=function(t){return t instanceof e&&(!!this.stack.equals(t.stack)&&(null===this.embeddedModeData&&null===t.embeddedModeData||null!==this.embeddedModeData&&null!==t.embeddedModeData&&this.embeddedModeData.equals(t.embeddedModeData)))},e}(),Wt=function(){function e(){this._tokens=[],this._language=null,this._lastTokenType=null,this._lastTokenLanguage=null}return e.prototype.enterMode=function(e,t){this._language=t},e.prototype.emit=function(e,t){this._lastTokenType===t&&this._lastTokenLanguage===this._language||(this._lastTokenType=t,this._lastTokenLanguage=this._language,this._tokens.push(new V.a(e,t,this._language)))},e.prototype.nestedModeTokenize=function(e,t,n){var i=t.modeId,r=t.state,o=pe.y.get(i);if(!o)return this.enterMode(n,i),this.emit(n,""),r;var s=o.tokenize(e,r,n);return this._tokens=this._tokens.concat(s.tokens),this._lastTokenType=null,this._lastTokenLanguage=null,this._language=null,s.endState},e.prototype.finalize=function(e){return new V.b(this._tokens,e)},e}(),Bt=function(){function e(e,t){this._modeService=e,this._theme=t,this._prependTokens=null,this._tokens=[],this._currentLanguageId=0,this._lastTokenMetadata=0}return e.prototype.enterMode=function(e,t){this._currentLanguageId=this._modeService.getLanguageIdentifier(t).id},e.prototype.emit=function(e,t){var n=this._theme.match(this._currentLanguageId,t);this._lastTokenMetadata!==n&&(this._lastTokenMetadata=n,this._tokens.push(e),this._tokens.push(n))},e._merge=function(e,t,n){var i=null!==e?e.length:0,r=t.length,o=null!==n?n.length:0;if(0===i&&0===r&&0===o)return new Uint32Array(0);if(0===i&&0===r)return n;if(0===r&&0===o)return e;var s=new Uint32Array(i+r+o);null!==e&&s.set(e);for(var a=0;a0&&i.nestedModeTokenize(s,t.embeddedModeData,n);var a=e.substring(r);return this._myTokenize(a,t,n+r,i)},e.prototype._safeRuleName=function(e){return e?e.name:"(unknown)"},e.prototype._myTokenize=function(e,t,n,i){i.enterMode(n,this._modeId);for(var r,o,s=e.length,a=t.embeddedModeData,u=t.stack,c=0,l=null,d=!0;d||c=s)break;d=!1;var C=this._lexer.tokenizer[g];if(!C&&!(C=Tt(this._lexer,g)))throw Dt(this._lexer,"tokenizer state is not defined: "+g);for(var S=e.substr(c),x=0,L=C;x=this._lexer.maxStack)throw Dt(this._lexer,"maximum tokenizer stack size reached: ["+u.state+","+u.parent.state+",...]");u=u.push(g)}else if("@pop"===_.next){if(u.depth<=1)throw Dt(this._lexer,"trying to pop an empty stack in rule: "+this._safeRuleName(b));u=u.pop()}else if("@popall"===_.next)u=u.popall();else{var N;if("@"===(N=Mt(this._lexer,_.next,v,m,g))[0]&&(N=N.substr(1)),!Tt(this._lexer,N))throw Dt(this._lexer,"trying to set a next state '"+N+"' that is undefined in rule: "+this._safeRuleName(b));u=u.push(N)}}_.log&&"string"==typeof _.log&&(r=this._lexer,o=this._lexer.languageId+": "+Mt(this._lexer,_.log,v,m,g),console.log(r.languageId+": "+o))}if(null===k)throw Dt(this._lexer,"lexer rule has no well-defined action in rule: "+this._safeRuleName(b));if(Array.isArray(k)){if(l&&l.groups.length>0)throw Dt(this._lexer,"groups cannot be nested: "+this._safeRuleName(b));if(m.length!==k.length+1)throw Dt(this._lexer,"matched number of groups does not match the number of actions in rule: "+this._safeRuleName(b));for(var E=0,I=1;I=0&&a()})})},e.colorizeLine=function(e,t,n,i,r){void 0===r&&(r=4);var o=xt.d.isBasicASCII(e,t),s=xt.d.containsRTL(e,o,n);return Object(St.e)(new St.c(!1,!0,e,!1,o,s,0,i,[],r,0,-1,"none",!1,!1,null)).html},e.colorizeModelLine=function(e,t,n){void 0===n&&(n=4);var i=e.getLineContent(t);e.forceTokenization(t);var r=e.getLineTokens(t).inflate();return this.colorizeLine(i,e.mightContainNonBasicASCII(),e.mightContainRTL(),r,n)},e}();function Ut(e,t,n){return new Promise(function(i,r){var o=function(){var s=function(e,t,n){for(var i=[],r=n.getInitialState(),o=0,s=e.length;o"),r=u.endState}return i.join("")}(e,t,n);if(n instanceof Vt){var a=n.getLoadStatus();if(!1===a.loaded)return void a.promise.then(o,r)}i(s)};o()})}function Kt(e,t){var n=[],i=new Uint32Array(2);i[0]=0,i[1]=16793600;for(var r=0,o=e.length;r")}return n.join("")}var qt=n("gzF+"),Gt=n("Nr0y"),Zt=n("P1SM"),Yt=n("TeKV"),Xt=n("0WPX"),$t=n("Gzpe"),Jt=n("WTFd"),Qt=n("rHGw"),en=this&&this.__extends||function(){var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(t,n)};return function(t,n){function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}}(),tn=function(){function e(e,t,n){void 0===e&&(e={}),void 0===t&&(t=[]),void 0===n&&(n=[]),this._contents=e,this._keys=t,this._overrides=n,this.isFrozen=!1}return Object.defineProperty(e.prototype,"contents",{get:function(){return this.checkAndFreeze(this._contents)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"overrides",{get:function(){return this.checkAndFreeze(this._overrides)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"keys",{get:function(){return this.checkAndFreeze(this._keys)},enumerable:!0,configurable:!0}),e.prototype.isEmpty=function(){return 0===this._keys.length&&0===Object.keys(this._contents).length&&0===this._overrides.length},e.prototype.getValue=function(e){return e?Object($t.d)(this.contents,e):this.contents},e.prototype.override=function(t){var n=this.getContentsForOverrideIdentifer(t);if(!n||"object"!=typeof n||!Object.keys(n).length)return this;for(var i={},r=0,o=De.e(Object.keys(this.contents).concat(Object.keys(n)));r5e3&&n._leaveChordMode():n._leaveChordMode()},500)},t.prototype._leaveChordMode=function(){this._currentChordStatusMessage&&(this._currentChordStatusMessage.dispose(),this._currentChordStatusMessage=null),this._currentChordChecker.cancel(),this._currentChord=null},t.prototype._dispatch=function(e,t){return this._doDispatch(this.resolveKeyboardEvent(e),t)},t.prototype._doDispatch=function(e,t){var n=this,i=!1;if(e.isChord())return console.warn("Unexpected keyboard event mapped to a chord"),!1;var r=e.getDispatchParts()[0];if(null===r)return i;var o=this._contextKeyService.getContext(t),s=this._currentChord?this._currentChord.keypress:null,a=e.getLabel(),u=this._getResolver().resolve(o,s,r);return u&&u.enterChord?(i=!0,this._enterChordMode(r,a),i):(this._currentChord&&(u&&u.commandId||(this._notificationService.status(on.a("missing.chord","The key combination ({0}, {1}) is not a command.",this._currentChord.label,a),{hideAfter:1e4}),i=!0)),this._leaveChordMode(),u&&u.commandId&&(u.bubble||(i=!0),void 0===u.commandArgs?this._commandService.executeCommand(u.commandId).then(void 0,function(e){return n._notificationService.warn(e)}):this._commandService.executeCommand(u.commandId,u.commandArgs).then(void 0,function(e){return n._notificationService.warn(e)}),this._telemetryService.publicLog2("workbenchActionExecuted",{id:u.commandId,from:"keybinding"})),i)},t.prototype.mightProducePrintableCharacter=function(e){return!e.ctrlKey&&!e.metaKey&&(e.keyCode>=31&&e.keyCode<=56||e.keyCode>=21&&e.keyCode<=30)},t}(G.a),un=n("7g0X"),cn=function(){function e(t,n){this._defaultKeybindings=t,this._defaultBoundCommands=new Map;for(var i=0,r=t.length;i=0;l--)this._isTargetedForRemoval(e[l],a,u,s,c)&&e.splice(l,1);else n.push(o)}return e.concat(n)},e.prototype._addKeyPress=function(t,n){var i=this._map.get(t);if(void 0===i)return this._map.set(t,[n]),void this._addToLookupMap(n);for(var r=i.length-1;r>=0;r--){var o=i[r];if(o.command!==n.command){var s=o.keypressParts.length>1,a=n.keypressParts.length>1;s&&a&&o.keypressParts[1]!==n.keypressParts[1]||e.whenIsEntirelyIncluded(o.when,n.when)&&this._removeFromLookupMap(o)}}i.push(n),this._addToLookupMap(n)},e.prototype._addToLookupMap=function(e){if(e.command){var t=this._lookupMap.get(e.command);void 0===t?(t=[e],this._lookupMap.set(e.command,t)):t.push(e)}},e.prototype._removeFromLookupMap=function(e){if(e.command){var t=this._lookupMap.get(e.command);if(void 0!==t)for(var n=0,i=t.length;n1&&null!==u.keypressParts[1]?{enterChord:!0,commandId:null,commandArgs:null,bubble:!1}:{enterChord:!1,commandId:u.command,commandArgs:u.commandArgs,bubble:u.bubble}:null},e.prototype._findCommand=function(t,n){for(var i=n.length-1;i>=0;i--){var r=n[i];if(e.contextMatchesRules(t,r.when))return r}return null},e.contextMatchesRules=function(e,t){return!t||t.evaluate(e)},e}(),ln=n("Kx4b"),dn=function(){return function(e,t,n,i,r){this.resolvedKeybinding=e,this.keypressParts=e?function(e){for(var t=[],n=0,i=e.length;n1},t.prototype.getParts=function(){var e=this;return this._parts.map(function(t){return e._getPart(t)})},t.prototype._getPart=function(e){return new R.d(e.ctrlKey,e.shiftKey,e.altKey,e.metaKey,this._getLabel(e),this._getAriaLabel(e))},t.prototype.getDispatchParts=function(){var e=this;return this._parts.map(function(t){return e._getDispatchPart(t)})},t}(R.c),gn=this&&this.__extends||function(){var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(t,n)};return function(t,n){function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}}(),mn=function(e){function t(t,n){return e.call(this,n,t.parts)||this}return gn(t,e),t.prototype._keyCodeToUILabel=function(e){if(2===this._os)switch(e){case 15:return"←";case 16:return"↑";case 17:return"→";case 18:return"↓"}return R.b.toString(e)},t.prototype._getLabel=function(e){return e.isDuplicateModifierCase()?"":this._keyCodeToUILabel(e.keyCode)},t.prototype._getAriaLabel=function(e){return e.isDuplicateModifierCase()?"":R.b.toString(e.keyCode)},t.prototype._getDispatchPart=function(e){return t.getDispatchStr(e)},t.getDispatchStr=function(e){if(e.isModifierKey())return null;var t="";return e.ctrlKey&&(t+="ctrl+"),e.shiftKey&&(t+="shift+"),e.altKey&&(t+="alt+"),e.metaKey&&(t+="meta+"),t+=R.b.toString(e.keyCode)},t}(pn),vn=n("fAkY"),_n=n("EMDP"),bn=n("EfIu"),yn=this&&this.__extends||function(){var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(t,n)};return function(t,n){function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}}(),wn=this&&this.__decorate||function(e,t,n,i){var r,o=arguments.length,s=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,n):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,i);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(s=(o<3?r(s):o>3?r(t,n,s):r(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},Cn=this&&this.__param||function(e,t){return function(n,i){t(n,i,e)}},Sn=function(){function e(e){this.model=e,this._onDispose=new A.a}return Object.defineProperty(e.prototype,"textEditorModel",{get:function(){return this.model},enumerable:!0,configurable:!0}),e.prototype.dispose=function(){this._onDispose.fire()},e}();var xn=function(){function e(){}return e.prototype.setEditor=function(e){this.editor=e},e.prototype.createModelReference=function(e){var t,n,i,r=this,o=null;return this.editor&&(t=this.editor,n=function(t){return r.findModel(t,e)},i=function(t){return r.findModel(t.getOriginalEditor(),e)||r.findModel(t.getModifiedEditor(),e)},o=Object(Zt.a)(t)?n(t):i(t)),o?Promise.resolve(new G.c(new Sn(o))):Promise.reject(new Error("Model not found"))},e.prototype.findModel=function(e,t){var n=e.getModel();return n&&n.uri.toString()!==t.toString()?null:n},e}(),Ln=function(){function e(){}return e.prototype.showWhile=function(e,t){return Promise.resolve(void 0)},e}(),On=function(){return function(){}}(),kn=function(){function e(){}return e.prototype.info=function(e){return this.notify({severity:Gt.a.Info,message:e})},e.prototype.warn=function(e){return this.notify({severity:Gt.a.Warning,message:e})},e.prototype.error=function(e){return this.notify({severity:Gt.a.Error,message:e})},e.prototype.notify=function(t){switch(t.severity){case Gt.a.Error:console.error(t.message);break;case Gt.a.Warning:console.warn(t.message);break;default:console.log(t.message)}return e.NO_OP},e.prototype.status=function(e,t){return G.a.None},e.NO_OP=new vn.b,e}(),Nn=function(){function e(e){this._onWillExecuteCommand=new A.a,this._onDidExecuteCommand=new A.a,this._instantiationService=e,this._dynamicCommands=Object.create(null)}return e.prototype.addCommand=function(e){var t=this,n=e.id;return this._dynamicCommands[n]=e,Object(G.h)(function(){delete t._dynamicCommands[n]})},e.prototype.executeCommand=function(e){for(var t=[],n=1;n0){var _=e[o-1];m=0===_.originalEndLineNumber?_.originalStartLineNumber+1:_.originalEndLineNumber+1,v=0===_.modifiedEndLineNumber?_.modifiedStartLineNumber+1:_.modifiedEndLineNumber+1}var b=p-3+1,y=g-3+1;if(bS)k+=O=S-k,N+=O;if(N>x)k+=O=x-N,N+=O;h[f++]=new ti(w,k,C,N),i[r++]=new ni(h)}var E=i[0].entries,I=[],D=0;for(o=1,s=i.length;od)&&(d=v),0!==_&&(0===h||_f)&&(f=b)}var y=document.createElement("div");y.className="diff-review-row";var w=document.createElement("div");w.className="diff-review-cell diff-review-summary";var C=d-l+1,S=f-h+1;w.appendChild(document.createTextNode(a+1+"/"+this._diffs.length+": @@ -"+l+","+C+" +"+h+","+S+" @@")),y.setAttribute("data-line",String(h));var x=function(e){return 0===e?on.a("no_lines","no lines"):1===e?on.a("one_line","1 line"):on.a("more_lines","{0} lines",e)},L=x(C),O=x(S);y.setAttribute("aria-label",on.a({key:"header",comment:["This is the ARIA label for a git diff header.","A git diff header looks like this: @@ -154,12 +159,39 @@.","That encodes that at original line 154 (which is now line 159), 12 lines were removed/changed with 39 lines.","Variables 0 and 1 refer to the diff index out of total number of diffs.","Variables 2 and 4 will be numbers (a line number).",'Variables 3 and 5 will be "no lines", "1 line" or "X lines", localized separately.']},"Difference {0} of {1}: original {2}, {3}, modified {4}, {5}",a+1,this._diffs.length,l,L,h,O)),y.appendChild(w),y.setAttribute("role","listitem"),c.appendChild(y);var k=h;for(p=0,g=u.length;p0&&r[r.length-1])&&(6===o[0]||2===o[0])){s=0;continue}if(3===o[0]&&(!r||o[1]>r[0]&&o[1]r.modifiedStartLineNumber?on.a("diff.clipboard.copyDeletedLinesContent.label","Copy deleted lines"):on.a("diff.clipboard.copyDeletedLinesContent.single.label","Copy deleted line"),void 0,!0,function(){return pi(a,void 0,void 0,function(){return gi(this,function(e){switch(e.label){case 0:return[4,this._clipboardService.writeText(r.originalContent.join(c)+c)];case 1:return e.sent(),[2]}})})}));var d=0,h=void 0;return r.originalEndLineNumber>r.modifiedStartLineNumber&&(h=new Yn.a("diff.clipboard.copyDeletedLineContent",on.a("diff.clipboard.copyDeletedLineContent.label","Copy deleted line ({0})",r.originalStartLineNumber),void 0,!0,function(){return pi(a,void 0,void 0,function(){return gi(this,function(e){switch(e.label){case 0:return[4,this._clipboardService.writeText(r.originalContent[d])];case 1:return e.sent(),[2]}})})}),l.push(h)),i.getConfiguration().readOnly||l.push(new Yn.a("diff.inline.revertChange",on.a("diff.inline.revertChange.label","Revert this change"),void 0,!0,function(){return pi(a,void 0,void 0,function(){var e;return gi(this,function(t){return 0===r.modifiedEndLineNumber?(e=i.getModel().getLineMaxColumn(r.modifiedStartLineNumber),i.executeEdits("diffEditor",[{range:new W.a(r.modifiedStartLineNumber,e,r.modifiedStartLineNumber,e),text:c+r.originalContent.join(c)}])):(e=i.getModel().getLineMaxColumn(r.modifiedEndLineNumber),i.executeEdits("diffEditor",[{range:new W.a(r.modifiedStartLineNumber,1,r.modifiedEndLineNumber,e),text:r.originalContent.join(c)}])),[2]})})})),a._register(q.k(a._diffActions,"mousedown",function(e){var t=q.x(a._diffActions),n=t.top,i=t.height,o=Math.floor(u/3);e.preventDefault(),a._contextMenuService.showContextMenu({getAnchor:function(){return{x:e.posx,y:n+i+o}},getActions:function(){return h&&(h.label=on.a("diff.clipboard.copyDeletedLineContent.label","Copy deleted line ({0})",r.originalStartLineNumber+d)),l},autoSelectFirstItem:!0})})),a._register(i.onMouseMove(function(e){8===e.target.type||5===e.target.type?e.target.detail.viewZoneId===a._viewZoneId?(a.visibility=!0,d=a._updateLightBulbPosition(a._marginDomNode,e.event.browserEvent.y,u)):a.visibility=!1:a.visibility=!1})),a}return fi(t,e),Object.defineProperty(t.prototype,"visibility",{get:function(){return this._visibility},set:function(e){this._visibility!==e&&(this._visibility=e,this._diffActions.style.visibility=e?"visible":"hidden")},enumerable:!0,configurable:!0}),t.prototype._updateLightBulbPosition=function(e,t,n){var i=t-q.x(e).top,r=Math.floor(i/n),o=r*n;return this._diffActions.style.top=o+"px",r},t}(G.a),vi=this&&this.__extends||function(){var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(t,n)};return function(t,n){function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}}(),_i=this&&this.__decorate||function(e,t,n,i){var r,o=arguments.length,s=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,n):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,i);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(s=(o<3?r(s):o>3?r(t,n,s):r(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},bi=this&&this.__param||function(e,t){return function(n,i){t(n,i,e)}},yi=function(){function e(e,t){this._contextMenuService=e,this._clipboardService=t,this._zones=[],this.inlineDiffMargins=[],this._zonesMap={},this._decorations=[]}return e.prototype.getForeignViewZones=function(e){var t=this;return e.filter(function(e){return!t._zonesMap[String(e.id)]})},e.prototype.clean=function(e){var t=this;this._zones.length>0&&e.changeViewZones(function(e){for(var n=0,i=t._zones.length;n0?r/n:0;return{height:Math.max(0,Math.floor(e.contentHeight*o)),top:Math.floor(t*o)}},t.prototype._createDataSource=function(){var e=this;return{getWidth:function(){return e._width},getHeight:function(){return e._height-e._reviewHeight},getContainerDomNode:function(){return e._containerDomElement},relayoutEditors:function(){e._doLayout()},getOriginalEditor:function(){return e.originalEditor},getModifiedEditor:function(){return e.modifiedEditor}}},t.prototype._setStrategy=function(e){this._strategy&&this._strategy.dispose(),this._strategy=e,e.applyColors(this._themeService.getTheme()),this._diffComputationResult&&this._updateDecorations(),this._measureDomElement(!0)},t.prototype._getLineChangeAtOrBeforeLineNumber=function(e,t){var n=this._diffComputationResult?this._diffComputationResult.changes:[];if(0===n.length||e=a?i=o+1:(i=o,r=o)}return n[i]},t.prototype._getEquivalentLineForOriginalLineNumber=function(e){var t=this._getLineChangeAtOrBeforeLineNumber(e,function(e){return e.originalStartLineNumber});if(!t)return e;var n=t.originalStartLineNumber+(t.originalEndLineNumber>0?-1:0),i=t.modifiedStartLineNumber+(t.modifiedEndLineNumber>0?-1:0),r=t.originalEndLineNumber>0?t.originalEndLineNumber-t.originalStartLineNumber+1:0,o=t.modifiedEndLineNumber>0?t.modifiedEndLineNumber-t.modifiedStartLineNumber+1:0,s=e-n;return s<=r?i+Math.min(s,o):i+o-r+s},t.prototype._getEquivalentLineForModifiedLineNumber=function(e){var t=this._getLineChangeAtOrBeforeLineNumber(e,function(e){return e.modifiedStartLineNumber});if(!t)return e;var n=t.originalStartLineNumber+(t.originalEndLineNumber>0?-1:0),i=t.modifiedStartLineNumber+(t.modifiedEndLineNumber>0?-1:0),r=t.originalEndLineNumber>0?t.originalEndLineNumber-t.originalStartLineNumber+1:0,o=t.modifiedEndLineNumber>0?t.modifiedEndLineNumber-t.modifiedStartLineNumber+1:0,s=e-i;return s<=o?n+Math.min(s,r):n+r-o+s},t.prototype.getDiffLineInformationForOriginal=function(e){return this._diffComputationResult?{equivalentLineNumber:this._getEquivalentLineForOriginalLineNumber(e)}:null},t.prototype.getDiffLineInformationForModified=function(e){return this._diffComputationResult?{equivalentLineNumber:this._getEquivalentLineForModifiedLineNumber(e)}:null},t.ONE_OVERVIEW_WIDTH=15,t.ENTIRE_DIFF_OVERVIEW_WIDTH=30,t.UPDATE_DIFF_DECORATIONS_DELAY=200,t=_i([bi(3,me.a),bi(4,un.c),bi(5,nt.a),bi(6,K.a),bi(7,Qn.c),bi(8,vn.a),bi(9,hi.a)],t)}(G.a),Si=function(e){function t(t){var n=e.call(this)||this;return n._dataSource=t,n._insertColor=null,n._removeColor=null,n}return vi(t,e),t.prototype.applyColors=function(e){var t=(e.getColor(Jn.j)||Jn.g).transparent(2),n=(e.getColor(Jn.l)||Jn.h).transparent(2),i=!t.equals(this._insertColor)||!n.equals(this._removeColor);return this._insertColor=t,this._removeColor=n,i},t.prototype.getEditorsDiffDecorations=function(e,t,n,i,r,o,s){r=r.sort(function(e,t){return e.afterLineNumber-t.afterLineNumber}),i=i.sort(function(e,t){return e.afterLineNumber-t.afterLineNumber});var a=this._getViewZones(e,i,r,o,s,n),u=this._getOriginalEditorDecorations(e,t,n,o,s),c=this._getModifiedEditorDecorations(e,t,n,o,s);return{original:{decorations:u.decorations,overviewZones:u.overviewZones,zones:a.original},modified:{decorations:c.decorations,overviewZones:c.overviewZones,zones:a.modified}}},t}(G.a),xi=function(){function e(e){this._source=e,this._index=-1,this.current=null,this.advance()}return e.prototype.advance=function(){this._index++,this._index0){var n=e[e.length-1];if(n.afterLineNumber===t.afterLineNumber&&null===n.domNode)return void(n.heightInLines+=t.heightInLines)}e.push(t)},d=new xi(this.modifiedForeignVZ),h=new xi(this.originalForeignVZ),f=0,p=this.lineChanges.length;f<=p;f++){var g=f0?-1:0),s=g.modifiedStartLineNumber+(g.modifiedEndLineNumber>0?-1:0),r=g.originalEndLineNumber>0?g.originalEndLineNumber-g.originalStartLineNumber+1:0,i=g.modifiedEndLineNumber>0?g.modifiedEndLineNumber-g.modifiedStartLineNumber+1:0,a=Math.max(g.originalStartLineNumber,g.originalEndLineNumber),u=Math.max(g.modifiedStartLineNumber,g.modifiedEndLineNumber)):(a=o+=1e7+r,u=s+=1e7+i);for(var m,v=[],_=[];d.current&&d.current.afterLineNumber<=u;){var b=void 0;b=d.current.afterLineNumber<=s?o-s+d.current.afterLineNumber:a;var y=null;g&&g.modifiedStartLineNumber<=d.current.afterLineNumber&&d.current.afterLineNumber<=g.modifiedEndLineNumber&&(y=this._createOriginalMarginDomNodeForModifiedForeignViewZoneInAddedRegion()),v.push({afterLineNumber:b,heightInLines:d.current.heightInLines,domNode:null,marginDomNode:y}),d.advance()}for(;h.current&&h.current.afterLineNumber<=a;){b=void 0;b=h.current.afterLineNumber<=o?s-o+h.current.afterLineNumber:u,_.push({afterLineNumber:b,heightInLines:h.current.heightInLines,domNode:null}),h.advance()}if(null!==g&&Mi(g))(m=this._produceOriginalFromDiff(g,r,i))&&v.push(m);if(null!==g&&Ti(g))(m=this._produceModifiedFromDiff(g,r,i))&&_.push(m);var w=0,C=0;for(v=v.sort(c),_=_.sort(c);w=x.heightInLines?(S.heightInLines-=x.heightInLines,C++):(x.heightInLines-=S.heightInLines,w++)}for(;w2*t.MINIMUM_EDITOR_WIDTH?(in-t.MINIMUM_EDITOR_WIDTH&&(i=n-t.MINIMUM_EDITOR_WIDTH)):i=r,this._sashPosition!==i&&(this._sashPosition=i,this._sash.layout()),this._sashPosition},t.prototype.onSashDragStart=function(){this._startSashPosition=this._sashPosition},t.prototype.onSashDrag=function(e){var t=this._dataSource.getWidth()-Ci.ENTIRE_DIFF_OVERVIEW_WIDTH,n=this.layout((this._startSashPosition+(e.currentX-e.startX))/t);this._sashRatio=n/t,this._dataSource.relayoutEditors()},t.prototype.onSashDragEnd=function(){this._sash.layout()},t.prototype.onSashReset=function(){this._sashRatio=.5,this._dataSource.relayoutEditors(),this._sash.layout()},t.prototype.getVerticalSashTop=function(e){return 0},t.prototype.getVerticalSashLeft=function(e){return this._sashPosition},t.prototype.getVerticalSashHeight=function(e){return this._dataSource.getHeight()},t.prototype._getViewZones=function(e,t,n,i,r){return new Ei(e,t,n).getViewZones()},t.prototype._getOriginalEditorDecorations=function(e,t,n,i,r){for(var o=String(this._removeColor),s={decorations:[],overviewZones:[]},a=i.getModel(),u=0,c=e.length;ut?{afterLineNumber:Math.max(e.originalStartLineNumber,e.originalEndLineNumber),heightInLines:n-t,domNode:null}:null},t.prototype._produceModifiedFromDiff=function(e,t,n){return t>n?{afterLineNumber:Math.max(e.modifiedStartLineNumber,e.modifiedEndLineNumber),heightInLines:t-n,domNode:null}:null},t}(Li),Ii=function(e){function t(t,n){var i=e.call(this,t)||this;return i.decorationsLeft=t.getOriginalEditor().getLayoutInfo().decorationsLeft,i._register(t.getOriginalEditor().onDidLayoutChange(function(e){i.decorationsLeft!==e.decorationsLeft&&(i.decorationsLeft=e.decorationsLeft,t.relayoutEditors())})),i}return vi(t,e),t.prototype.setEnableSplitViewResizing=function(e){},t.prototype._getViewZones=function(e,t,n,i,r,o){return new Di(e,t,n,i,r,o).getViewZones()},t.prototype._getOriginalEditorDecorations=function(e,t,n,i,r){for(var o=String(this._removeColor),s={decorations:[],overviewZones:[]},a=0,u=e.length;a'])}h+=this.modifiedEditorConfiguration.viewInfo.scrollBeyondLastColumn;var m=document.createElement("div");m.className="view-lines line-delete",m.innerHTML=a.build(),Kn.a.applyFontInfoSlow(m,this.modifiedEditorConfiguration.fontInfo);var v=document.createElement("div");return v.className="inline-deleted-margin-view-zone",v.innerHTML=u.join(""),Kn.a.applyFontInfoSlow(v,this.modifiedEditorConfiguration.fontInfo),{shouldNotShrink:!0,afterLineNumber:0===e.modifiedEndLineNumber?e.modifiedStartLineNumber:e.modifiedStartLineNumber-1,heightInLines:t,minWidthInPx:h*d,domNode:m,marginDomNode:v,diff:{originalStartLineNumber:e.originalStartLineNumber,originalEndLineNumber:e.originalEndLineNumber,modifiedStartLineNumber:e.modifiedStartLineNumber,modifiedEndLineNumber:e.modifiedEndLineNumber,originalContent:f}}},t.prototype._renderOriginalLine=function(e,t,n,i,r,o,s){var a=t.getLineTokens(r),u=a.getLineContent(),c=li.a.filter(o,r,1,u.length+1);s.appendASCIIString('
');var l=xt.d.isBasicASCII(u,t.mightContainNonBasicASCII()),d=xt.d.containsRTL(u,l,t.mightContainRTL()),h=Object(St.d)(new St.c(n.fontInfo.isMonospace&&!n.viewInfo.disableMonospaceOptimizations,n.fontInfo.canUseHalfwidthRightwardsArrow,u,!1,l,d,0,a,c,i,n.fontInfo.spaceWidth,n.viewInfo.stopRenderingLineAfter,n.viewInfo.renderWhitespace,n.viewInfo.renderControlCharacters,n.viewInfo.fontLigatures,null),s);s.appendASCIIString("
");var f=h.characterMapping.getAbsoluteOffsets();return f.length>0?f[f.length-1]:0},t}(Li);function Mi(e){return e.modifiedEndLineNumber>0}function Ti(e){return e.originalEndLineNumber>0}Object(Qn.f)(function(e,t){var n=e.getColor(Jn.j);n&&(t.addRule(".monaco-editor .line-insert, .monaco-editor .char-insert { background-color: "+n+"; }"),t.addRule(".monaco-diff-editor .line-insert, .monaco-diff-editor .char-insert { background-color: "+n+"; }"),t.addRule(".monaco-editor .inline-added-margin-view-zone { background-color: "+n+"; }"));var i=e.getColor(Jn.l);i&&(t.addRule(".monaco-editor .line-delete, .monaco-editor .char-delete { background-color: "+i+"; }"),t.addRule(".monaco-diff-editor .line-delete, .monaco-diff-editor .char-delete { background-color: "+i+"; }"),t.addRule(".monaco-editor .inline-deleted-margin-view-zone { background-color: "+i+"; }"));var r=e.getColor(Jn.k);r&&t.addRule(".monaco-editor .line-insert, .monaco-editor .char-insert { border: 1px "+("hc"===e.type?"dashed":"solid")+" "+r+"; }");var o=e.getColor(Jn.m);o&&t.addRule(".monaco-editor .line-delete, .monaco-editor .char-delete { border: 1px "+("hc"===e.type?"dashed":"solid")+" "+o+"; }");var s=e.getColor(Jn._37);s&&t.addRule(".monaco-diff-editor.side-by-side .editor.modified { box-shadow: -6px 0 5px -5px "+s+"; }");var a=e.getColor(Jn.i);a&&t.addRule(".monaco-diff-editor.side-by-side .editor.modified { border-left: 1px solid "+a+"; }")});var Pi=n("lthF"),Ai=n("sKqm"),Ri=n("C3c5"),Fi=n("NqM+"),ji=n("xJaW"),Wi=n("44YW"),Bi=this&&this.__extends||function(){var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(t,n)};return function(t,n){function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}}(),Vi=this&&this.__decorate||function(e,t,n,i){var r,o=arguments.length,s=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,n):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,i);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(s=(o<3?r(s):o>3?r(t,n,s):r(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},Hi=this&&this.__param||function(e,t){return function(n,i){t(n,i,e)}},zi=0,Ui=!1;var Ki=function(e){function t(t,n,i,r,o,s,a,u,c,l){var d=this;return(n=n||{}).ariaLabel=n.ariaLabel||bn.g.editorViewAccessibleLabel,n.ariaLabel=n.ariaLabel+";"+(Bn.j?bn.g.accessibilityHelpMessageIE:bn.g.accessibilityHelpMessage),(d=e.call(this,t,n,{},i,r,o,s,u,c,l)||this)._standaloneKeybindingService=a instanceof En?a:null,Ui||(Ui=!0,Vn.b(document.body)),d}return Bi(t,e),t.prototype.addCommand=function(e,t,n){if(!this._standaloneKeybindingService)return console.warn("Cannot add command because the editor is configured with an unrecognized KeybindingService"),null;var i="DYNAMIC_"+ ++zi,r=un.a.deserialize(n);return this._standaloneKeybindingService.addDynamicKeybinding(i,e,t,r),i},t.prototype.createContextKey=function(e,t){return this._contextKeyService.createKey(e,t)},t.prototype.addAction=function(e){var t=this;if("string"!=typeof e.id||"string"!=typeof e.label||"function"!=typeof e.run)throw new Error("Invalid action descriptor, `id`, `label` and `run` are required properties!");if(!this._standaloneKeybindingService)return console.warn("Cannot add keybinding because the editor is configured with an unrecognized KeybindingService"),G.a.None;var n=e.id,i=e.label,r=un.a.and(un.a.equals("editorId",this.getId()),un.a.deserialize(e.precondition)),o=e.keybindings,s=un.a.and(r,un.a.deserialize(e.keybindingContext)),a=e.contextMenuGroupId||null,u=e.contextMenuOrder||0,c=function(){return Promise.resolve(e.run(t))},l=new G.b,d=this.getId()+":"+n;if(l.add(Q.a.registerCommand(d,c)),a){var h={command:{id:d,title:i},when:r,group:a,order:u};l.add(Ri.c.appendMenuItem(7,h))}if(Array.isArray(o))for(var f=0,p=o;f=0}}(e);tr.push(n),n.userConfigured?ir.push(n):nr.push(n),t&&!n.userConfigured&&tr.forEach(function(e){e.mime===n.mime||e.userConfigured||(n.extension&&e.extension===n.extension&&console.warn("Overwriting extension <<"+n.extension+">> to now point to mime <<"+n.mime+">>"),n.filename&&e.filename===n.filename&&console.warn("Overwriting filename <<"+n.filename+">> to now point to mime <<"+n.mime+">>"),n.filepattern&&e.filepattern===n.filepattern&&console.warn("Overwriting filepattern <<"+n.filepattern+">> to now point to mime <<"+n.mime+">>"),n.firstline&&e.firstline===n.firstline&&console.warn("Overwriting firstline <<"+n.firstline+">> to now point to mime <<"+n.mime+">>"))})}function or(e,t){var n;if(e)switch(e.scheme){case X.b.file:n=e.fsPath;break;case X.b.data:n=$.a.parseMetaData(e).get($.a.META_DATA_LABEL);break;default:n=e.path}if(!n)return[er];n=n.toLowerCase();var i=Object($i.basename)(n),r=sr(n,i,ir);if(r)return[r,Qi];var o=sr(n,i,nr);if(o)return[o,Qi];if(t){var s=function(e){Object(J.L)(e)&&(e=e.substr(1));if(e.length>0)for(var t=tr.length-1;t>=0;t--){var n=tr[t];if(n.firstline){var i=e.match(n.firstline);if(i&&i.length>0)return n.mime}}return null}(t);if(s)return[s,Qi]}return[er]}function sr(e,t,n){for(var i=null,r=null,o=null,s=n.length-1;s>=0;s--){var a=n[s];if(t===a.filenameLowercase){i=a;break}if(a.filepattern&&(!r||a.filepattern.length>r.filepattern.length)){var u=a.filepatternOnPath?e:t;Object(Ji.a)(a.filepatternLowercase,u)&&(r=a)}a.extension&&(!o||a.extension.length>o.extension.length)&&Object(J.m)(t,a.extensionLowercase)&&(o=a)}return i?i.mime:r?r.mime:o?o.mime:null}var ar=n("9XyG"),ur=n("RWr8"),cr=this&&this.__extends||function(){var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(t,n)};return function(t,n){function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}}(),lr=Object.prototype.hasOwnProperty,dr=function(e){function t(t,n){void 0===t&&(t=!0),void 0===n&&(n=!1);var i=e.call(this)||this;return i._onDidChange=i._register(new A.a),i.onDidChange=i._onDidChange.event,i._warnOnOverwrite=n,i._nextLanguageId2=1,i._languageIdToLanguage=[],i._languageToLanguageId=Object.create(null),i._languages={},i._mimeTypesMap={},i._nameMap={},i._lowercaseNameMap={},t&&(i._initializeFromRegistry(),i._register(ar.a.onDidChangeLanguages(function(e){return i._initializeFromRegistry()}))),i}return cr(t,e),t.prototype._initializeFromRegistry=function(){this._languages={},this._mimeTypesMap={},this._nameMap={},this._lowercaseNameMap={};var e=ar.a.getLanguages();this._registerLanguages(e)},t.prototype._registerLanguages=function(e){for(var t=this,n=0,i=e;n0&&((n=e.mimetypes).push.apply(n,t.mimetypes),r=t.mimetypes[0]),r||(r="text/x-"+i,e.mimetypes.push(r)),Array.isArray(t.extensions))for(var o=0,s=t.extensions;o0){var f=t.firstLine;"^"!==f.charAt(0)&&(f="^"+f);try{var p=new RegExp(f);J.E(p)||rr({id:i,mime:r,firstline:p},this._warnOnOverwrite)}catch(e){Object(be.e)(e)}}e.aliases.push(i);var g=null;if(void 0!==t.aliases&&Array.isArray(t.aliases)&&(g=0===t.aliases.length?[null]:t.aliases),null!==g)for(var m=0,v=g;m0;if(b&&null===g[0]);else{var y=(b?g[0]:null)||i;!b&&e.name||(e.name=y)}t.configuration&&e.configurationFiles.push(t.configuration)},t.prototype.isRegisteredMode=function(e){return!!lr.call(this._mimeTypesMap,e)||lr.call(this._languages,e)},t.prototype.getModeIdForLanguageNameLowercase=function(e){return lr.call(this._lowercaseNameMap,e)?this._lowercaseNameMap[e].language:null},t.prototype.extractModeIds=function(e){var t=this;return e?e.split(",").map(function(e){return e.trim()}).map(function(e){return lr.call(t._mimeTypesMap,e)?t._mimeTypesMap[e].language:e}).filter(function(e){return lr.call(t._languages,e)}):[]},t.prototype.getLanguageIdentifier=function(e){if(e===ge.b||0===e)return ge.a;var t;if("string"==typeof e)t=e;else if(!(t=this._languageIdToLanguage[e]))return null;return lr.call(this._languages,t)?this._languages[t].identifier:null},t.prototype.getModeIdsFromFilepathOrFirstLine=function(e,t){if(!e&&!t)return[];var n=or(e,t);return this.extractModeIds(n.join(","))},t}(G.a),hr=this&&this.__extends||function(){var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(t,n)};return function(t,n){function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}}(),fr=function(e){function t(t,n){var i=e.call(this)||this;return i._onDidChange=i._register(new A.a),i.onDidChange=i._onDidChange.event,i._selector=n,i.languageIdentifier=i._selector(),i._register(t(function(){return i._evaluate()})),i}return hr(t,e),t.prototype._evaluate=function(){var e=this._selector();e.id!==this.languageIdentifier.id&&(this.languageIdentifier=e,this._onDidChange.fire(this.languageIdentifier))},t}(G.a),pr=function(){function e(e){var t=this;void 0===e&&(e=!1),this._onDidCreateMode=new A.a,this.onDidCreateMode=this._onDidCreateMode.event,this._onLanguagesMaybeChanged=new A.a,this.onLanguagesMaybeChanged=this._onLanguagesMaybeChanged.event,this._instantiatedModes={},this._registry=new dr(!0,e),this._registry.onDidChange(function(){return t._onLanguagesMaybeChanged.fire()})}return e.prototype.isRegisteredMode=function(e){return this._registry.isRegisteredMode(e)},e.prototype.getModeIdForLanguageName=function(e){return this._registry.getModeIdForLanguageNameLowercase(e)},e.prototype.getModeIdByFilepathOrFirstLine=function(e,t){var n=this._registry.getModeIdsFromFilepathOrFirstLine(e,t);return n.length>0?n[0]:null},e.prototype.getModeId=function(e){var t=this._registry.extractModeIds(e);return t.length>0?t[0]:null},e.prototype.getLanguageIdentifier=function(e){return this._registry.getLanguageIdentifier(e)},e.prototype.create=function(e){var t=this;return new fr(this.onLanguagesMaybeChanged,function(){var n=t.getModeId(e);return t._createModeAndGetLanguageIdentifier(n)})},e.prototype.createByFilepathOrFirstLine=function(e,t){var n=this;return new fr(this.onLanguagesMaybeChanged,function(){var i=n.getModeIdByFilepathOrFirstLine(e,t);return n._createModeAndGetLanguageIdentifier(i)})},e.prototype._createModeAndGetLanguageIdentifier=function(e){var t=this.getLanguageIdentifier(e||"plaintext")||ge.a;return this._getOrCreateMode(t.language),t},e.prototype.triggerMode=function(e){var t=this.getModeId(e);this._getOrCreateMode(t||"plaintext")},e.prototype._getOrCreateMode=function(e){if(!this._instantiatedModes.hasOwnProperty(e)){var t=this.getLanguageIdentifier(e)||ge.a;this._instantiatedModes[e]=new Xi(t),this._onDidCreateMode.fire(this._instantiatedModes[e])}return this._instantiatedModes[e]},e}(),gr=this&&this.__extends||function(){var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(t,n)};return function(t,n){function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}}(),mr=this&&this.__decorate||function(e,t,n,i){var r,o=arguments.length,s=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,n):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,i);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(s=(o<3?r(s):o>3?r(t,n,s):r(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},vr=this&&this.__param||function(e,t){return function(n,i){t(n,i,e)}};function _r(e){return e.toString()}var br=function(){function e(e,t,n){this._modelEventListeners=new G.b,this.model=e,this._languageSelection=null,this._languageSelectionListener=null,this._modelEventListeners.add(e.onWillDispose(function(){return t(e)})),this._modelEventListeners.add(e.onDidChangeLanguage(function(t){return n(e,t)}))}return e.prototype._disposeLanguageSelection=function(){this._languageSelectionListener&&(this._languageSelectionListener.dispose(),this._languageSelectionListener=null),this._languageSelection&&(this._languageSelection.dispose(),this._languageSelection=null)},e.prototype.dispose=function(){this._modelEventListeners.dispose(),this._disposeLanguageSelection()},e.prototype.setLanguage=function(e){var t=this;this._disposeLanguageSelection(),this._languageSelection=e,this._languageSelectionListener=this._languageSelection.onDidChange(function(){return t.model.setMode(e.languageIdentifier)}),this.model.setMode(e.languageIdentifier)},e}(),yr=ye.c||ye.d?1:2,wr=function(e){function t(t,n){var i=e.call(this)||this;return i._onModelAdded=i._register(new A.a),i.onModelAdded=i._onModelAdded.event,i._onModelRemoved=i._register(new A.a),i.onModelRemoved=i._onModelRemoved.event,i._onModelModeChanged=i._register(new A.a),i.onModelModeChanged=i._onModelModeChanged.event,i._configurationService=t,i._resourcePropertiesService=n,i._models={},i._modelCreationOptionsByLanguageAndResource=Object.create(null),i._configurationServiceSubscription=i._configurationService.onDidChangeConfiguration(function(e){return i._updateModelOptions()}),i._updateModelOptions(),i}return gr(t,e),t._readModelOptions=function(e,t){var n=T.c.tabSize;if(e.editor&&void 0!==e.editor.tabSize){var i=parseInt(e.editor.tabSize,10);isNaN(i)||(n=i),n<1&&(n=1)}var r=n;if(e.editor&&void 0!==e.editor.indentSize&&"tabSize"!==e.editor.indentSize){var o=parseInt(e.editor.indentSize,10);isNaN(o)||(r=o),r<1&&(r=1)}var s=T.c.insertSpaces;e.editor&&void 0!==e.editor.insertSpaces&&(s="false"!==e.editor.insertSpaces&&Boolean(e.editor.insertSpaces));var a=yr,u=e.eol;"\r\n"===u?a=2:"\n"===u&&(a=1);var c=T.c.trimAutoWhitespace;e.editor&&void 0!==e.editor.trimAutoWhitespace&&(c="false"!==e.editor.trimAutoWhitespace&&Boolean(e.editor.trimAutoWhitespace));var l=T.c.detectIndentation;e.editor&&void 0!==e.editor.detectIndentation&&(l="false"!==e.editor.detectIndentation&&Boolean(e.editor.detectIndentation));var d=T.c.largeFileOptimizations;return e.editor&&void 0!==e.editor.largeFileOptimizations&&(d="false"!==e.editor.largeFileOptimizations&&Boolean(e.editor.largeFileOptimizations)),{isForSimpleWidget:t,tabSize:n,indentSize:r,insertSpaces:s,detectIndentation:l,defaultEOL:a,trimAutoWhitespace:c,largeFileOptimizations:d}},t.prototype.getCreationOptions=function(e,n,i){var r=this._modelCreationOptionsByLanguageAndResource[e+n];if(!r){var o=this._configurationService.getValue("editor",{overrideIdentifier:e,resource:n}),s=this._resourcePropertiesService.getEOL(n,e);r=t._readModelOptions({editor:o,eol:s},i),this._modelCreationOptionsByLanguageAndResource[e+n]=r}return r},t.prototype._updateModelOptions=function(){var e=this._modelCreationOptionsByLanguageAndResource;this._modelCreationOptionsByLanguageAndResource=Object.create(null);for(var n=Object.keys(this._models),i=0,r=n.length;i=0;a--)(r=e[a])&&(s=(o<3?r(s):o>3?r(t,n,s):r(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},Or=this&&this.__param||function(e,t){return function(n,i){t(n,i,e)}},kr=function(e){function t(t,n){void 0===n&&(n=q.s());var i=e.call(this)||this;return i._decorationOptionProviders=new Map,i._styleSheet=n,i._themeService=t,i}return xr(t,e),t.prototype.registerDecorationType=function(e,t,n){var i=this._decorationOptionProviders.get(e);if(!i){var r={styleSheet:this._styleSheet,key:e,parentTypeKey:n,options:t||Object.create(null)};i=n?new Nr(this._themeService,r):new Er(this._themeService,r),this._decorationOptionProviders.set(e,i)}i.refCount++},t.prototype.removeDecorationType=function(e){var t=this._decorationOptionProviders.get(e);t&&(t.refCount--,t.refCount<=0&&(this._decorationOptionProviders.delete(e),t.dispose(),this.listCodeEditors().forEach(function(t){return t.removeDecorations(e)})))},t.prototype.resolveDecorationOptions=function(e,t){var n=this._decorationOptionProviders.get(e);if(!n)throw new Error("Unknown decoration type key: "+e);return n.getOptions(this,t)},t=Lr([Or(0,Qn.c)],t)}(Sr),Nr=function(){function e(e,t){this._parentTypeKey=t.parentTypeKey,this.refCount=0,this._beforeContentRules=new Dr(3,t,e),this._afterContentRules=new Dr(4,t,e)}return e.prototype.getOptions=function(e,t){var n=e.resolveDecorationOptions(this._parentTypeKey,!0);return this._beforeContentRules&&(n.beforeContentClassName=this._beforeContentRules.className),this._afterContentRules&&(n.afterContentClassName=this._afterContentRules.className),n},e.prototype.dispose=function(){this._beforeContentRules&&(this._beforeContentRules.dispose(),this._beforeContentRules=null),this._afterContentRules&&(this._afterContentRules.dispose(),this._afterContentRules=null)},e}(),Er=function(){function e(e,t){var n=this;this._disposables=new G.b,this.refCount=0;var i=function(i){var r=new Dr(i,t,e);if(n._disposables.add(r),r.hasContent)return r.className};this.className=i(0);var r,o=(r=new Dr(1,t,e),n._disposables.add(r),r.hasContent?{className:r.className,hasLetterSpacing:r.hasLetterSpacing}:null);o&&(this.inlineClassName=o.className,this.inlineClassNameAffectsLetterSpacing=o.hasLetterSpacing),this.beforeContentClassName=i(3),this.afterContentClassName=i(4),this.glyphMarginClassName=i(2);var s=t.options;this.isWholeLine=Boolean(s.isWholeLine),this.stickiness=s.rangeBehavior;var a=s.light&&s.light.overviewRulerColor||s.overviewRulerColor,u=s.dark&&s.dark.overviewRulerColor||s.overviewRulerColor;void 0===a&&void 0===u||(this.overviewRuler={color:a||u,darkColor:u||a,position:s.overviewRulerLane||fe.d.Center})}return e.prototype.getOptions=function(e,t){return t?{inlineClassName:this.inlineClassName,beforeContentClassName:this.beforeContentClassName,afterContentClassName:this.afterContentClassName,className:this.className,glyphMarginClassName:this.glyphMarginClassName,isWholeLine:this.isWholeLine,overviewRuler:this.overviewRuler,stickiness:this.stickiness}:this},e.prototype.dispose=function(){this._disposables.dispose()},e}(),Ir={color:"color:{0} !important;",opacity:"opacity:{0};",backgroundColor:"background-color:{0};",outline:"outline:{0};",outlineColor:"outline-color:{0};",outlineStyle:"outline-style:{0};",outlineWidth:"outline-width:{0};",border:"border:{0};",borderColor:"border-color:{0};",borderRadius:"border-radius:{0};",borderSpacing:"border-spacing:{0};",borderStyle:"border-style:{0};",borderWidth:"border-width:{0};",fontStyle:"font-style:{0};",fontWeight:"font-weight:{0};",textDecoration:"text-decoration:{0};",cursor:"cursor:{0};",letterSpacing:"letter-spacing:{0};",gutterIconPath:"background:{0} center center no-repeat;",gutterIconSize:"background-size:{0};",contentText:"content:'{0}';",contentIconPath:"content:{0};",margin:"margin:{0};",width:"width:{0};",height:"height:{0};"},Dr=function(){function e(e,t,n){var i=this;this._theme=n.getTheme(),this._ruleType=e,this._providerArgs=t,this._usesThemeColors=!1,this._hasContent=!1,this._hasLetterSpacing=!1;var r=Mr.getClassName(this._providerArgs.key,e);this._providerArgs.parentTypeKey&&(r=r+" "+Mr.getClassName(this._providerArgs.parentTypeKey,e)),this._className=r,this._unThemedSelector=Mr.getSelector(this._providerArgs.key,this._providerArgs.parentTypeKey,e),this._buildCSS(),this._usesThemeColors?this._themeListener=n.onThemeChange(function(e){i._theme=n.getTheme(),i._removeCSS(),i._buildCSS()}):this._themeListener=null}return e.prototype.dispose=function(){this._hasContent&&(this._removeCSS(),this._hasContent=!1),this._themeListener&&(this._themeListener.dispose(),this._themeListener=null)},Object.defineProperty(e.prototype,"hasContent",{get:function(){return this._hasContent},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"hasLetterSpacing",{get:function(){return this._hasLetterSpacing},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"className",{get:function(){return this._className},enumerable:!0,configurable:!0}),e.prototype._buildCSS=function(){var e,t,n,i=this._providerArgs.options;switch(this._ruleType){case 0:e=this.getCSSTextForModelDecorationClassName(i),t=this.getCSSTextForModelDecorationClassName(i.light),n=this.getCSSTextForModelDecorationClassName(i.dark);break;case 1:e=this.getCSSTextForModelDecorationInlineClassName(i),t=this.getCSSTextForModelDecorationInlineClassName(i.light),n=this.getCSSTextForModelDecorationInlineClassName(i.dark);break;case 2:e=this.getCSSTextForModelDecorationGlyphMarginClassName(i),t=this.getCSSTextForModelDecorationGlyphMarginClassName(i.light),n=this.getCSSTextForModelDecorationGlyphMarginClassName(i.dark);break;case 3:e=this.getCSSTextForModelDecorationContentClassName(i.before),t=this.getCSSTextForModelDecorationContentClassName(i.light&&i.light.before),n=this.getCSSTextForModelDecorationContentClassName(i.dark&&i.dark.before);break;case 4:e=this.getCSSTextForModelDecorationContentClassName(i.after),t=this.getCSSTextForModelDecorationContentClassName(i.light&&i.light.after),n=this.getCSSTextForModelDecorationContentClassName(i.dark&&i.dark.after);break;default:throw new Error("Unknown rule type: "+this._ruleType)}var r=this._providerArgs.styleSheet.sheet,o=!1;e.length>0&&(r.insertRule(this._unThemedSelector+" {"+e+"}",0),o=!0),t.length>0&&(r.insertRule(".vs"+this._unThemedSelector+" {"+t+"}",0),o=!0),n.length>0&&(r.insertRule(".vs-dark"+this._unThemedSelector+", .hc-black"+this._unThemedSelector+" {"+n+"}",0),o=!0),this._hasContent=o},e.prototype._removeCSS=function(){q.H(this._unThemedSelector,this._providerArgs.styleSheet)},e.prototype.getCSSTextForModelDecorationClassName=function(e){if(!e)return"";var t=[];return this.collectCSSText(e,["backgroundColor"],t),this.collectCSSText(e,["outline","outlineColor","outlineStyle","outlineWidth"],t),this.collectBorderSettingsCSSText(e,t),t.join("")},e.prototype.getCSSTextForModelDecorationInlineClassName=function(e){if(!e)return"";var t=[];return this.collectCSSText(e,["fontStyle","fontWeight","textDecoration","cursor","color","opacity","letterSpacing"],t),e.letterSpacing&&(this._hasLetterSpacing=!0),t.join("")},e.prototype.getCSSTextForModelDecorationContentClassName=function(e){if(!e)return"";var t=[];if(void 0!==e){if(this.collectBorderSettingsCSSText(e,t),void 0!==e.contentIconPath&&t.push(J.r(Ir.contentIconPath,q.n(F.a.revive(e.contentIconPath)))),"string"==typeof e.contentText){var n=e.contentText.match(/^.*$/m)[0].replace(/['\\]/g,"\\$&");t.push(J.r(Ir.contentText,n))}this.collectCSSText(e,["fontStyle","fontWeight","textDecoration","color","opacity","backgroundColor","margin"],t),this.collectCSSText(e,["width","height"],t)&&t.push("display:inline-block;")}return t.join("")},e.prototype.getCSSTextForModelDecorationGlyphMarginClassName=function(e){if(!e)return"";var t=[];return void 0!==e.gutterIconPath&&(t.push(J.r(Ir.gutterIconPath,q.n(F.a.revive(e.gutterIconPath)))),void 0!==e.gutterIconSize&&t.push(J.r(Ir.gutterIconSize,e.gutterIconSize))),t.join("")},e.prototype.collectBorderSettingsCSSText=function(e,t){return!!this.collectCSSText(e,["border","borderColor","borderRadius","borderSpacing","borderStyle","borderWidth"],t)&&(t.push(J.r("box-sizing: border-box;")),!0)},e.prototype.collectCSSText=function(e,t,n){for(var i=n.length,r=0,o=t;rt)return 1;return 0}(e.token,t.token);return 0!==n?n:e.index-t.index});for(var n=0,i="000000",r="ffffff";e.length>=1&&""===e[0].token;){var o=e.shift();-1!==o.fontStyle&&(n=o.fontStyle),null!==o.foreground&&(i=o.foreground),null!==o.background&&(r=o.background)}for(var s=new Wr,a=0,u=t;a>>0,this._cache.set(t,n)}return(n|e<<0)>>>0},e}(),Vr=/\b(comment|string|regex|regexp)\b/;var Hr,zr,Ur,Kr=function(){function e(e,t,n){this._fontStyle=e,this._foreground=t,this._background=n,this.metadata=(this._fontStyle<<11|this._foreground<<14|this._background<<23)>>>0}return e.prototype.clone=function(){return new e(this._fontStyle,this._foreground,this._background)},e.prototype.acceptOverwrite=function(e,t,n){-1!==e&&(this._fontStyle=e),0!==t&&(this._foreground=t),0!==n&&(this._background=n),this.metadata=(this._fontStyle<<11|this._foreground<<14|this._background<<23)>>>0},e}(),qr=function(){function e(e){this._mainRule=e,this._children=new Map}return e.prototype.match=function(e){if(""===e)return this._mainRule;var t,n,i=e.indexOf(".");-1===i?(t=e,n=""):(t=e.substring(0,i),n=e.substring(i+1));var r=this._children.get(t);return void 0!==r?r.match(n):this._mainRule},e.prototype.insert=function(t,n,i,r){if(""!==t){var o,s,a=t.indexOf(".");-1===a?(o=t,s=""):(o=t.substring(0,a),s=t.substring(a+1));var u=this._children.get(o);void 0===u&&(u=new e(this._mainRule.clone()),this._children.set(o,u)),u.insert(s,n,i,r)}else this._mainRule.acceptOverwrite(n,i,r)},e}();var Gr={base:"vs",inherit:!1,rules:[{token:"",foreground:"000000",background:"fffffe"},{token:"invalid",foreground:"cd3131"},{token:"emphasis",fontStyle:"italic"},{token:"strong",fontStyle:"bold"},{token:"variable",foreground:"001188"},{token:"variable.predefined",foreground:"4864AA"},{token:"constant",foreground:"dd0000"},{token:"comment",foreground:"008000"},{token:"number",foreground:"09885A"},{token:"number.hex",foreground:"3030c0"},{token:"regexp",foreground:"800000"},{token:"annotation",foreground:"808080"},{token:"type",foreground:"008080"},{token:"delimiter",foreground:"000000"},{token:"delimiter.html",foreground:"383838"},{token:"delimiter.xml",foreground:"0000FF"},{token:"tag",foreground:"800000"},{token:"tag.id.pug",foreground:"4F76AC"},{token:"tag.class.pug",foreground:"4F76AC"},{token:"meta.scss",foreground:"800000"},{token:"metatag",foreground:"e00000"},{token:"metatag.content.html",foreground:"FF0000"},{token:"metatag.html",foreground:"808080"},{token:"metatag.xml",foreground:"808080"},{token:"metatag.php",fontStyle:"bold"},{token:"key",foreground:"863B00"},{token:"string.key.json",foreground:"A31515"},{token:"string.value.json",foreground:"0451A5"},{token:"attribute.name",foreground:"FF0000"},{token:"attribute.value",foreground:"0451A5"},{token:"attribute.value.number",foreground:"09885A"},{token:"attribute.value.unit",foreground:"09885A"},{token:"attribute.value.html",foreground:"0000FF"},{token:"attribute.value.xml",foreground:"0000FF"},{token:"string",foreground:"A31515"},{token:"string.html",foreground:"0000FF"},{token:"string.sql",foreground:"FF0000"},{token:"string.yaml",foreground:"0451A5"},{token:"keyword",foreground:"0000FF"},{token:"keyword.json",foreground:"0451A5"},{token:"keyword.flow",foreground:"AF00DB"},{token:"keyword.flow.scss",foreground:"0000FF"},{token:"operator.scss",foreground:"666666"},{token:"operator.sql",foreground:"778899"},{token:"operator.swift",foreground:"666666"},{token:"predefined.sql",foreground:"FF00FF"}],colors:(Hr={},Hr[Jn.o]="#FFFFFE",Hr[Jn.x]="#000000",Hr[Jn.E]="#E5EBF1",Hr[$n.h]="#D3D3D3",Hr[$n.a]="#939393",Hr[Jn.J]="#ADD6FF4D",Hr)},Zr={base:"vs-dark",inherit:!1,rules:[{token:"",foreground:"D4D4D4",background:"1E1E1E"},{token:"invalid",foreground:"f44747"},{token:"emphasis",fontStyle:"italic"},{token:"strong",fontStyle:"bold"},{token:"variable",foreground:"74B0DF"},{token:"variable.predefined",foreground:"4864AA"},{token:"variable.parameter",foreground:"9CDCFE"},{token:"constant",foreground:"569CD6"},{token:"comment",foreground:"608B4E"},{token:"number",foreground:"B5CEA8"},{token:"number.hex",foreground:"5BB498"},{token:"regexp",foreground:"B46695"},{token:"annotation",foreground:"cc6666"},{token:"type",foreground:"3DC9B0"},{token:"delimiter",foreground:"DCDCDC"},{token:"delimiter.html",foreground:"808080"},{token:"delimiter.xml",foreground:"808080"},{token:"tag",foreground:"569CD6"},{token:"tag.id.pug",foreground:"4F76AC"},{token:"tag.class.pug",foreground:"4F76AC"},{token:"meta.scss",foreground:"A79873"},{token:"meta.tag",foreground:"CE9178"},{token:"metatag",foreground:"DD6A6F"},{token:"metatag.content.html",foreground:"9CDCFE"},{token:"metatag.html",foreground:"569CD6"},{token:"metatag.xml",foreground:"569CD6"},{token:"metatag.php",fontStyle:"bold"},{token:"key",foreground:"9CDCFE"},{token:"string.key.json",foreground:"9CDCFE"},{token:"string.value.json",foreground:"CE9178"},{token:"attribute.name",foreground:"9CDCFE"},{token:"attribute.value",foreground:"CE9178"},{token:"attribute.value.number.css",foreground:"B5CEA8"},{token:"attribute.value.unit.css",foreground:"B5CEA8"},{token:"attribute.value.hex.css",foreground:"D4D4D4"},{token:"string",foreground:"CE9178"},{token:"string.sql",foreground:"FF0000"},{token:"keyword",foreground:"569CD6"},{token:"keyword.flow",foreground:"C586C0"},{token:"keyword.json",foreground:"CE9178"},{token:"keyword.flow.scss",foreground:"569CD6"},{token:"operator.scss",foreground:"909090"},{token:"operator.sql",foreground:"778899"},{token:"operator.swift",foreground:"909090"},{token:"predefined.sql",foreground:"FF00FF"}],colors:(zr={},zr[Jn.o]="#1E1E1E",zr[Jn.x]="#D4D4D4",zr[Jn.E]="#3A3D41",zr[$n.h]="#404040",zr[$n.a]="#707070",zr[Jn.J]="#ADD6FF26",zr)},Yr={base:"hc-black",inherit:!1,rules:[{token:"",foreground:"FFFFFF",background:"000000"},{token:"invalid",foreground:"f44747"},{token:"emphasis",fontStyle:"italic"},{token:"strong",fontStyle:"bold"},{token:"variable",foreground:"1AEBFF"},{token:"variable.parameter",foreground:"9CDCFE"},{token:"constant",foreground:"569CD6"},{token:"comment",foreground:"608B4E"},{token:"number",foreground:"FFFFFF"},{token:"regexp",foreground:"C0C0C0"},{token:"annotation",foreground:"569CD6"},{token:"type",foreground:"3DC9B0"},{token:"delimiter",foreground:"FFFF00"},{token:"delimiter.html",foreground:"FFFF00"},{token:"tag",foreground:"569CD6"},{token:"tag.id.pug",foreground:"4F76AC"},{token:"tag.class.pug",foreground:"4F76AC"},{token:"meta",foreground:"D4D4D4"},{token:"meta.tag",foreground:"CE9178"},{token:"metatag",foreground:"569CD6"},{token:"metatag.content.html",foreground:"1AEBFF"},{token:"metatag.html",foreground:"569CD6"},{token:"metatag.xml",foreground:"569CD6"},{token:"metatag.php",fontStyle:"bold"},{token:"key",foreground:"9CDCFE"},{token:"string.key",foreground:"9CDCFE"},{token:"string.value",foreground:"CE9178"},{token:"attribute.name",foreground:"569CD6"},{token:"attribute.value",foreground:"3FF23F"},{token:"string",foreground:"CE9178"},{token:"string.sql",foreground:"FF0000"},{token:"keyword",foreground:"569CD6"},{token:"keyword.flow",foreground:"C586C0"},{token:"operator.sql",foreground:"778899"},{token:"operator.swift",foreground:"909090"},{token:"predefined.sql",foreground:"FF00FF"}],colors:(Ur={},Ur[Jn.o]="#000000",Ur[Jn.x]="#FFFFFF",Ur[$n.h]="#FFFFFF",Ur[$n.a]="#FFFFFF",Ur)},Xr="vs",$r="vs-dark",Jr="hc-black",Qr=ur.a.as(Jn.a.ColorContribution),eo=ur.a.as(Qn.a.ThemingContribution),to=function(){function e(e,t){this.themeData=t;var n=t.base;e.length>0?(this.id=n+" "+e,this.themeName=e):(this.id=n,this.themeName=n),this.colors=null,this.defaultColors=Object.create(null),this._tokenTheme=null}return Object.defineProperty(e.prototype,"base",{get:function(){return this.themeData.base},enumerable:!0,configurable:!0}),e.prototype.notifyBaseUpdated=function(){this.themeData.inherit&&(this.colors=null,this._tokenTheme=null)},e.prototype.getColors=function(){if(!this.colors){var e=new Map;for(var t in this.themeData.colors)e.set(t,Ar.a.fromHex(this.themeData.colors[t]));if(this.themeData.inherit){var n=io(this.themeData.base);for(var t in n.colors)e.has(t)||e.set(t,Ar.a.fromHex(n.colors[t]))}this.colors=e}return this.colors},e.prototype.getColor=function(e,t){var n=this.getColors().get(e);return n||(!1!==t?this.getDefault(e):void 0)},e.prototype.getDefault=function(e){var t=this.defaultColors[e];return t||(t=Qr.resolveDefaultColor(e,this),this.defaultColors[e]=t,t)},e.prototype.defines=function(e){return Object.prototype.hasOwnProperty.call(this.getColors(),e)},Object.defineProperty(e.prototype,"type",{get:function(){switch(this.base){case Xr:return"light";case Jr:return"hc";default:return"dark"}},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"tokenTheme",{get:function(){if(!this._tokenTheme){var e=[],t=[];if(this.themeData.inherit){var n=io(this.themeData.base);e=n.rules,n.encodedTokensColors&&(t=n.encodedTokensColors)}e=e.concat(this.themeData.rules),this.themeData.encodedTokensColors&&(t=this.themeData.encodedTokensColors),this._tokenTheme=Br.createFromRawTokenTheme(e,t)}return this._tokenTheme},enumerable:!0,configurable:!0}),e}();function no(e){return e===Xr||e===$r||e===Jr}function io(e){switch(e){case Xr:return Gr;case $r:return Zr;case Jr:return Yr}}function ro(e){var t=io(e);return new to(e,t)}var oo=function(){function e(){this.environment=Object.create(null),this._onThemeChange=new A.a,this._onIconThemeChange=new A.a,this._knownThemes=new Map,this._knownThemes.set(Xr,ro(Xr)),this._knownThemes.set($r,ro($r)),this._knownThemes.set(Jr,ro(Jr)),this._styleElement=q.s(),this._styleElement.className="monaco-colors",this.setTheme(Xr)}return Object.defineProperty(e.prototype,"onThemeChange",{get:function(){return this._onThemeChange.event},enumerable:!0,configurable:!0}),e.prototype.defineTheme=function(e,t){if(!/^[a-z0-9\-]+$/i.test(e))throw new Error("Illegal theme name!");if(!no(t.base)&&!no(e))throw new Error("Illegal theme base!");this._knownThemes.set(e,new to(e,t)),no(e)&&this._knownThemes.forEach(function(t){t.base===e&&t.notifyBaseUpdated()}),this._theme&&this._theme.themeName===e&&this.setTheme(e)},e.prototype.getTheme=function(){return this._theme},e.prototype.setTheme=function(e){var t,n=this;if(t=this._knownThemes.has(e)?this._knownThemes.get(e):this._knownThemes.get(Xr),this._theme===t)return t.id;this._theme=t;var i=[],r={},o={addRule:function(e){r[e]||(i.push(e),r[e]=!0)}};eo.getThemingParticipants().forEach(function(e){return e(t,o,n.environment)});var s=t.tokenTheme.getColorMap();return o.addRule(function(e){for(var t=[],n=1,i=e.length;n=0;a--)(r=e[a])&&(s=(o<3?r(s):o>3?r(t,n,s):r(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},uo=this&&this.__param||function(e,t){return function(n,i){t(n,i,e)}},co="data-keybinding-context",lo=function(){function e(e,t){this._id=e,this._parent=t,this._value=Object.create(null),this._value._contextId=e}return e.prototype.setValue=function(e,t){return this._value[e]!==t&&(this._value[e]=t,!0)},e.prototype.removeValue=function(e){return e in this._value&&(delete this._value[e],!0)},e.prototype.getValue=function(e){var t=this._value[e];return void 0===t&&this._parent?this._parent.getValue(e):t},e}(),ho=function(e){function t(){return e.call(this,-1,null)||this}return so(t,e),t.prototype.setValue=function(e,t){return!1},t.prototype.removeValue=function(e){return!1},t.prototype.getValue=function(e){},t.INSTANCE=new t,t}(lo),fo=function(e){function t(t,n,i){var r=e.call(this,t,null)||this;return r._configurationService=n,r._values=new Map,r._listener=r._configurationService.onDidChangeConfiguration(function(e){if(6===e.source){var t=Object(Jt.d)(r._values);r._values.clear(),i.fire(new mo(t))}else{for(var n=[],o=0,s=e.affectedKeys;o1){var i=n.shift();i&&(r.focusItemByElement(i.container),n.push(i)),r.mnemonics.set(t,n)}}})),ye.c&&r._register(Object(q.h)(o,q.d.KEY_DOWN,function(e){var t=new qt.a(e);t.equals(14)||t.equals(11)?(r.focusedItem=r.viewItems.length-1,r.focusNext(),q.c.stop(e,!0)):(t.equals(13)||t.equals(12))&&(r.focusedItem=0,r.focusPrevious(),q.c.stop(e,!0))})),r._register(Object(q.h)(r.domNode,q.d.MOUSE_OUT,function(e){var t=e.relatedTarget;Object(q.E)(t,r.domNode)||(r.focusedItem=void 0,r.scrollTopHold=r.menuElement.scrollTop,r.updateFocus(),e.stopPropagation())})),r._register(Object(q.h)(r.domNode,q.d.MOUSE_UP,function(e){q.c.stop(e,!0)})),r._register(Object(q.h)(r.actionsList,q.d.MOUSE_OVER,function(e){var t=e.target;if(t&&Object(q.E)(t,r.actionsList)&&t!==r.actionsList){for(;t.parentElement!==r.actionsList&&null!==t.parentElement;)t=t.parentElement;if(Object(q.C)(t,"action-item")){var n=r.focusedItem;r.scrollTopHold=r.menuElement.scrollTop,r.setFocusedItem(t),n!==r.focusedItem&&r.updateFocus()}}}));var s={parent:r};return r.mnemonics=new Map,r.push(n,{icon:!0,label:!0,isMenu:!0}),r.scrollableElement=r._register(new Zn.a(o,{alwaysConsumeMouseWheel:!0,horizontal:2,vertical:3,verticalScrollbarSize:7,handleMouseWheel:!0,useShadows:!0})),r.scrollableElement.getDomNode().style.position=null,o.style.maxHeight=Math.max(10,window.innerHeight-t.getBoundingClientRect().top-30)+"px",r.menuDisposables.add(r.scrollableElement.onScroll(function(){r._onScroll.fire()},r)),r._register(Object(q.h)(r.menuElement,q.d.SCROLL,function(e){void 0!==r.scrollTopHold&&(r.menuElement.scrollTop=r.scrollTopHold,r.scrollTopHold=void 0),r.scrollableElement.scanDomNode()})),t.appendChild(r.scrollableElement.getDomNode()),r.scrollableElement.scanDomNode(),r.viewItems.filter(function(e){return!(e instanceof No)}).forEach(function(e,t,n){e.updatePositionInSet(t+1,n.length)}),r}return wo(t,e),t.prototype.style=function(e){var t=this.getContainer(),n=e.foregroundColor?""+e.foregroundColor:null,i=e.backgroundColor?""+e.backgroundColor:null,r=e.borderColor?"2px solid "+e.borderColor:null,o=e.shadowColor?"0 2px 4px "+e.shadowColor:null;t.style.border=r,this.domNode.style.color=n,this.domNode.style.backgroundColor=i,t.style.boxShadow=o,this.viewItems&&this.viewItems.forEach(function(t){(t instanceof Oo||t instanceof No)&&t.style(e)})},t.prototype.getContainer=function(){return this.scrollableElement.getDomNode()},Object.defineProperty(t.prototype,"onScroll",{get:function(){return this._onScroll.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"scrollOffset",{get:function(){return this.menuElement.scrollTop},enumerable:!0,configurable:!0}),t.prototype.focusItemByElement=function(e){var t=this.focusedItem;this.setFocusedItem(e),t!==this.focusedItem&&this.updateFocus()},t.prototype.setFocusedItem=function(e){for(var t=0;t