diff --git a/.gitignore b/.gitignore index 2e19823c3..f59eb37a2 100644 --- a/.gitignore +++ b/.gitignore @@ -12,33 +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.*/ -.stamp +*.DS_Store +_checkouts +rebar.config.rendered +/rebar3 \ No newline at end of file diff --git a/Makefile b/Makefile index d1cd12a60..0718d4e5a 100644 --- a/Makefile +++ b/Makefile @@ -1,139 +1,62 @@ -## shallow clone for speed +REBAR_VERSION = 3.14.3-emqx-1 +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/apps/.gitkeep b/apps/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/emqx_auth_http/.gitignore b/apps/emqx_auth_http/.gitignore new file mode 100644 index 000000000..557a3a337 --- /dev/null +++ b/apps/emqx_auth_http/.gitignore @@ -0,0 +1,25 @@ +.eunit +deps +*.o +*.beam +*.plt +erl_crash.dump +ebin +rel/example_project +.concrete/DEV_MODE +.rebar +.erlang.mk/ +emqx_auth_http.d +data +ct.cover.spec +cover/ +ct.coverdata +eunit.coverdata +logs/ +erlang.mk +_build/ +rebar.lock +rebar3.crashdump +etc/emqx_auth_http.conf.rendered +.rebar3/ +*.swp 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/etc/emqx_auth_http.conf b/apps/emqx_auth_http/etc/emqx_auth_http.conf new file mode 100644 index 000000000..0df589169 --- /dev/null +++ b/apps/emqx_auth_http/etc/emqx_auth_http.conf @@ -0,0 +1,162 @@ +##-------------------------------------------------------------------- +## HTTP Auth/ACL Plugin +##-------------------------------------------------------------------- + +##-------------------------------------------------------------------- +## Authentication request. + +## HTTP URL API path for authentication request +## +## Value: URL +## +## Examples: http://127.0.0.1:8991/mqtt/auth, https://[::1]:8991/mqtt/auth +auth.http.auth_req = http://127.0.0.1:8991/mqtt/auth + +## Value: post | get +auth.http.auth_req.method = post + +## It only works when method=post +## Value: json | x-www-form-urlencoded +auth.http.auth_req.content_type = x-www-form-urlencoded + +## Variables: +## - %u: username +## - %c: clientid +## - %a: ipaddress +## - %r: protocol +## - %P: password +## - %p: sockport of server accepted +## - %C: common name of client TLS cert +## - %d: subject of client TLS cert +## +## Value: Params +auth.http.auth_req.params = clientid=%c,username=%u,password=%P + +##-------------------------------------------------------------------- +## Superuser request. + +## HTTP URL API path for Superuser request +## +## Value: URL +## +## Examples: http://127.0.0.1:8991/mqtt/superuser, https://[::1]:8991/mqtt/superuser +#auth.http.super_req = http://127.0.0.1:8991/mqtt/superuser + +## Value: post | get +#auth.http.super_req.method = post + +## It only works when method=pos +## Value: json | x-www-form-urlencoded +#auth.http.super_req.content_type = x-www-form-urlencoded + +## Variables: +## - %u: username +## - %c: clientid +## - %a: ipaddress +## - %r: protocol +## - %P: password +## - %p: sockport of server accepted +## - %C: common name of client TLS cert +## - %d: subject of client TLS cert +## +## Value: Params +#auth.http.super_req.params = clientid=%c,username=%u + +##-------------------------------------------------------------------- +## ACL request. + +## HTTP URL API path for ACL request +## +## Value: URL +## +## Examples: http://127.0.0.1:8991/mqtt/acl, https://[::1]:8991/mqtt/acl +auth.http.acl_req = http://127.0.0.1:8991/mqtt/acl + +## Value: post | get +auth.http.acl_req.method = get + +## It only works when method=post +## Value: json | x-www-form-urlencoded +auth.http.acl_req.content_type = x-www-form-urlencoded + +## Variables: +## - %A: 1 | 2, 1 = sub, 2 = pub +## - %u: username +## - %c: clientid +## - %a: ipaddress +## - %r: protocol +## - %m: mountpoint +## - %t: topic +## +## Value: Params +auth.http.acl_req.params = access=%A,username=%u,clientid=%c,ipaddr=%a,topic=%t,mountpoint=%m + +##------------------------------------------------------------------------------ +## Http Reqeust options + +## Time-out time for the http request, 0 is never timeout. +## +## Value: Duration +## -h: hour, e.g. '2h' for 2 hours +## -m: minute, e.g. '5m' for 5 minutes +## -s: second, e.g. '30s' for 30 seconds +## +## Default: 5s +## auth.http.request.timeout = 5s + +## Connection time-out time, used during the initial request +## when the client is connecting to the server +## +## Value: Duration +## +## Default is same with the timeout option +## auth.http.request.connect_timeout = 0 + +## Re-send http reuqest times +## +## Value: integer +## +## Default: 3 +auth.http.request.retry_times = 5 + +## The interval for re-sending the http request +## +## Value: Duration +## +## Default: 1s +auth.http.request.retry_interval = 1s + +## The 'Exponential Backoff' mechanism for re-sending request. The actually +## re-send time interval is `interval * backoff ^ times` +## +## Value: float +## +## Default: 2.0 +auth.http.request.retry_backoff = 2.0 + +##------------------------------------------------------------------------------ +## SSL options + +## Path to the file containing PEM-encoded CA certificates. The CA certificates +## are used during server authentication and when building the client certificate chain. +## +## Value: File +## auth.http.ssl.cacertfile = {{ platform_etc_dir }}/certs/ca.pem + +## The path to a file containing the client's certificate. +## +## Value: File +## auth.http.ssl.certfile = {{ platform_etc_dir }}/certs/client-cert.pem + +## Path to a file containing the client's private PEM-encoded key. +## +## Value: File +## auth.http.ssl.keyfile = {{ platform_etc_dir }}/certs/client-key.pem + +##-------------------------------------------------------------------- +## HTTP Request Headers +## +## Example: auth.http.header.Accept-Encoding = * +## +## Value: String +## auth.http.header.Accept = */* 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..2bbe12827 --- /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, path, headers, params, request_timeout}). + +-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..4f4289db0 --- /dev/null +++ b/apps/emqx_auth_http/priv/emqx_auth_http.schema @@ -0,0 +1,169 @@ +%%-*- 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, list_to_binary("application/" ++ atom_to_list(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, list_to_binary("application/" ++ atom_to_list(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, list_to_binary("application/" ++ atom_to_list(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.request_timeout", [ + {default, "5s"}, + {datatype, [integer, {duration, ms}]} +]}. + +{mapping, "auth.http.pool_size", "emqx_auth_http.pool_opts", [ + {default, 8}, + {datatype, integer} +]}. + +{mapping, "auth.http.request.connect_timeout", "emqx_auth_http.pool_opts", [ + {default, "5s"}, + {datatype, [integer, {duration, ms}]} +]}. + +{mapping, "auth.http.ssl.cacertfile", "emqx_auth_http.pool_opts", [ + {datatype, string} +]}. + +{mapping, "auth.http.ssl.certfile", "emqx_auth_http.pool_opts", [ + {datatype, string} +]}. + +{mapping, "auth.http.ssl.keyfile", "emqx_auth_http.pool_opts", [ + {datatype, string} +]}. + +{mapping, "auth.http.request.retry_times", "emqx_auth_http.pool_opts", [ + {default, 5}, + {datatype, integer} +]}. + +{mapping, "auth.http.request.retry_interval", "emqx_auth_http.pool_opts", [ + {default, "1s"}, + {datatype, {duration, ms}} +]}. + +{mapping, "auth.http.request.retry_backoff", "emqx_auth_http.pool_opts", [ + {default, 2.0}, + {datatype, float} +]}. + +{translation, "emqx_auth_http.pool_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 = [{pool_size, cuttlefish:conf_get("auth.http.pool_size", Conf)}, + {connect_timeout, InfinityFun(cuttlefish:conf_get("auth.http.request.connect_timeout", Conf))}, + {retry, cuttlefish:conf_get("auth.http.request.retry_times", Conf)}, + {retry_timeout, cuttlefish:conf_get("auth.http.request.retry_interval", Conf)}], + 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.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..0b1959427 --- /dev/null +++ b/apps/emqx_auth_http/rebar.config @@ -0,0 +1,30 @@ +{deps, + [{cowlib, {git, "https://github.com/ninenines/cowlib", {tag, "2.7.0"}}}, + {gun, {git, "https://github.com/emqx/gun", {tag, "1.3.4"}}}, + {gproc, {git, "https://github.com/uwiger/gproc", {tag, "0.8.0"}}} + ]}. + +{edoc_opts, [{preprocess, true}]}. +{erl_opts, [warn_unused_vars, + warn_shadow_vars, + warn_unused_import, + warn_obsolete_guard, + debug_info, + {parse_transform}]}. + +{xref_checks, [undefined_function_calls, undefined_functions, + locals_not_used, deprecated_function_calls, + warnings_as_errors, deprecated_functions]}. + +{cover_enabled, true}. +{cover_opts, [verbose]}. +{cover_export_enabled, true}. + +{profiles, + [{test, + [{deps, + [{emqx_ct_helpers, {git, "https://github.com/emqx/emqx-ct-helpers", {tag, "1.2.2"}}}, + {emqtt, {git, "https://github.com/emqx/emqtt", {tag, "v1.2.2"}}} + ]} + ]} + ]}. 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..a6f60b465 --- /dev/null +++ b/apps/emqx_auth_http/src/emqx_acl_http.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_acl_http). + +-include("emqx_auth_http.hrl"). + +-include_lib("emqx/include/emqx.hrl"). +-include_lib("emqx/include/logger.hrl"). + +-logger_header("[ACL http]"). + +-import(emqx_auth_http_cli, + [ request/6 + , 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, + pool_name := PoolName}) -> + ClientInfo1 = ClientInfo#{access => access(PubSub), topic => Topic}, + case check_acl_request(PoolName, AclReq, ClientInfo1) of + {ok, 200, <<"ignore">>} -> ok; + {ok, 200, _Body} -> {stop, allow}; + {ok, _Code, _Body} -> {stop, deny}; + {error, Error} -> + ?LOG(error, "Request ACL path ~s, error: ~p", + [AclReq#http_request.path, 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(PoolName, #http_request{path = Path, + method = Method, + headers = Headers, + params = Params, + request_timeout = RequestTimeout}, ClientInfo) -> + request(PoolName, Method, Path, Headers, feedvar(Params, ClientInfo), RequestTimeout). + +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..8b1c10111 --- /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, "4.3.0"}, % strict semver, bump manually! + {modules, []}, + {registered, [emqx_auth_http_sup]}, + {applications, [kernel,stdlib,gproc,gun,emqx]}, + {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..20026d6ee --- /dev/null +++ b/apps/emqx_auth_http/src/emqx_auth_http.erl @@ -0,0 +1,112 @@ +%%-------------------------------------------------------------------- +%% 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/include/emqx.hrl"). +-include_lib("emqx/include/logger.hrl"). +-include_lib("emqx/include/types.hrl"). + +-logger_header("[Auth http]"). + +-import(emqx_auth_http_cli, + [ request/6 + , 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, + pool_name := PoolName}) -> + case authenticate(PoolName, AuthReq, ClientInfo) of + {ok, 200, <<"ignore">>} -> + emqx_metrics:inc(?AUTH_METRICS(ignore)), ok; + {ok, 200, Body} -> + emqx_metrics:inc(?AUTH_METRICS(success)), + IsSuperuser = is_superuser(PoolName, SuperReq, ClientInfo), + {stop, AuthResult#{is_superuser => IsSuperuser, + auth_result => success, + anonymous => false, + mountpoint => mountpoint(Body, ClientInfo)}}; + {ok, Code, _Body} -> + ?LOG(error, "Deny connection from path: ~s, response http code: ~p", + [AuthReq#http_request.path, Code]), + emqx_metrics:inc(?AUTH_METRICS(failure)), + {stop, AuthResult#{auth_result => http_to_connack_error(Code), + anonymous => false}}; + {error, Error} -> + ?LOG(error, "Request auth path: ~s, error: ~p", + [AuthReq#http_request.path, 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(PoolName, #http_request{path = Path, + method = Method, + headers = Headers, + params = Params, + request_timeout = RequestTimeout}, ClientInfo) -> + request(PoolName, Method, Path, Headers, feedvar(Params, ClientInfo), RequestTimeout). + +-spec(is_superuser(atom(), maybe(#http_request{}), emqx_types:client()) -> boolean()). +is_superuser(_PoolName, undefined, _ClientInfo) -> + false; +is_superuser(PoolName, #http_request{path = Path, + method = Method, + headers = Headers, + params = Params, + request_timeout = RequestTimeout}, ClientInfo) -> + case request(PoolName, Method, Path, Headers, feedvar(Params, ClientInfo), RequestTimeout) of + {ok, 200, _Body} -> true; + {ok, _Code, _Body} -> false; + {error, Error} -> ?LOG(error, "Request superuser path ~s, error: ~p", [Path, Error]), + false + end. + +mountpoint(Body, #{mountpoint := Mountpoint}) -> + case emqx_json:safe_decode(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..1d235ca2a --- /dev/null +++ b/apps/emqx_auth_http/src/emqx_auth_http_app.erl @@ -0,0 +1,147 @@ +%%-------------------------------------------------------------------- +%% 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). + +-emqx_plugin(auth). + +-include("emqx_auth_http.hrl"). + +-export([ start/2 + , stop/1 + ]). +-export([init/1]). + +%%-------------------------------------------------------------------- +%% Application Callbacks +%%-------------------------------------------------------------------- + +start(_StartType, _StartArgs) -> + case translate_env() of + ok -> + {ok, PoolOpts} = application:get_env(?APP, pool_opts), + {ok, Sup} = emqx_http_client_sup:start_link(?APP, ssl(inet(PoolOpts))), + with_env(auth_req, fun load_auth_hook/1), + with_env(acl_req, fun load_acl_hook/1), + {ok, Sup}; + {error, Reason} -> + {error, Reason} + end. + +load_auth_hook(AuthReq) -> + ok = emqx_auth_http:register_metrics(), + SuperReq = r(application:get_env(?APP, super_req, undefined)), + Params = #{auth_req => AuthReq, + super_req => SuperReq, + pool_name => ?APP}, + emqx:hook('client.authenticate', {emqx_auth_http, check, [Params]}). + +load_acl_hook(AclReq) -> + ok = emqx_acl_http:register_metrics(), + Params = #{acl_req => AclReq, + pool_name => ?APP}, + 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}), + emqx_http_client_sup:stop_pool(?APP). + +%%-------------------------------------------------------------------- +%% 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) -> + Headers = application:get_env(?APP, headers, []), + Method = proplists:get_value(method, Config, post), + Path = proplists:get_value(path, Config), + NewHeaders = [{<<"content_type">>, proplists:get_value(content_type, Config, <<"application/x-www-form-urlencoded">>)} | Headers], + Params = proplists:get_value(params, Config), + {ok, RequestTimeout} = application:get_env(?APP, request_timeout), + #http_request{method = Method, path = Path, headers = NewHeaders, params = Params, request_timeout = RequestTimeout}. + +inet(PoolOpts) -> + case proplists:get_value(host, PoolOpts) of + Host when tuple_size(Host) =:= 8 -> + TransOpts = proplists:get_value(transport_opts, PoolOpts, []), + NewPoolOpts = proplists:delete(transport_opts, PoolOpts), + [{transport_opts, [inet6 | TransOpts]} | NewPoolOpts]; + _ -> + PoolOpts + end. + +ssl(PoolOpts) -> + case proplists:get_value(ssl, PoolOpts, []) of + [] -> + PoolOpts; + SSLOpts -> + TransOpts = proplists:get_value(transport_opts, PoolOpts, []), + NewPoolOpts = proplists:delete(transport_opts, PoolOpts), + [{transport_opts, SSLOpts ++ TransOpts}, {transport, ssl} | NewPoolOpts] + end. + +translate_env() -> + URLs = lists:foldl(fun(Name, Acc) -> + case application:get_env(?APP, Name, []) of + [] -> Acc; + Env -> + URL = proplists:get_value(url, Env), + #{host := Host0, + port := Port, + path := Path} = uri_string:parse(list_to_binary(URL)), + {ok, Host} = inet:parse_address(binary_to_list(Host0)), + [{Name, {Host, Port, binary_to_list(Path)}} | Acc] + end + end, [], [acl_req, auth_req, super_req]), + case same_host_and_port(URLs) of + true -> + [begin + {ok, Req} = application:get_env(?APP, Name), + application:set_env(?APP, Name, [{path, Path} | Req]) + end || {Name, {_, _, Path}} <- URLs], + {_, {Host, Port, _}} = lists:last(URLs), + PoolOpts = application:get_env(?APP, pool_opts, []), + application:set_env(?APP, pool_opts, [{host, Host}, {port, Port} | PoolOpts]), + ok; + false -> + {error, different_server} + end. + +same_host_and_port([_]) -> + true; +same_host_and_port([{_, {Host, Port, _}}, {_, {Host, Port, _}}]) -> + true; +same_host_and_port([{_, {Host, Port, _}}, URL = {_, {Host, Port, _}} | Rest]) -> + same_host_and_port([URL | Rest]); +same_host_and_port(_) -> + false. \ No newline at end of file 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..25fac4300 --- /dev/null +++ b/apps/emqx_auth_http/src/emqx_auth_http_cli.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_auth_http_cli). + +-include("emqx_auth_http.hrl"). + +-export([ request/6 + , feedvar/2 + , feedvar/3 + ]). + +%%-------------------------------------------------------------------- +%% HTTP Request +%%-------------------------------------------------------------------- + +request(PoolName, get, Path, Headers, Params, Timeout) -> + NewPath = Path ++ "?" ++ cow_qs:qs(bin_kw(Params)), + reply(emqx_http_client:request(get, PoolName, {NewPath, Headers}, Timeout)); + +request(PoolName, post, Path, Headers, Params, Timeout) -> + Body = case proplists:get_value(<<"content_type">>, Headers) of + <<"application/x-www-form-urlencoded">> -> + cow_qs:qs(bin_kw(Params)); + <<"application/json">> -> + emqx_json:encode(bin_kw(Params)) + end, + reply(emqx_http_client:request(post, PoolName, {Path, Headers, Body}, Timeout)). + +reply({ok, StatusCode, _Headers}) -> + {ok, StatusCode, <<>>}; +reply({ok, StatusCode, _Headers, Body}) -> + {ok, StatusCode, Body}; +reply({error, Reason}) -> + {error, Reason}. + +%% 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/src/emqx_http_client.erl b/apps/emqx_auth_http/src/emqx_http_client.erl new file mode 100644 index 000000000..e29d798de --- /dev/null +++ b/apps/emqx_auth_http/src/emqx_http_client.erl @@ -0,0 +1,256 @@ +-module(emqx_http_client). + +-behaviour(gen_server). + +-include_lib("emqx/include/logger.hrl"). + +%% APIs +-export([ start_link/3 + , request/3 + , request/4 + ]). + +%% gen_server callbacks +-export([ init/1 + , handle_call/3 + , handle_cast/2 + , handle_info/2 + , terminate/2 + , code_change/3 + ]). + +-record(state, { + pool :: ecpool:poo_name(), + id :: pos_integer(), + client :: pid() | undefined, + mref :: reference() | undefined, + host :: inet:hostname() | inet:ip_address(), + port :: inet:port_number(), + gun_opts :: proplists:proplist(), + gun_state :: down | up, + requests :: map() + }). + +%%-------------------------------------------------------------------- +%% APIs +%%-------------------------------------------------------------------- + +start_link(Pool, Id, Opts) -> + gen_server:start_link(?MODULE, [Pool, Id, Opts], []). + +request(Method, Pool, Req) -> + request(Method, Pool, Req, 5000). + +request(get, Pool, {Path, Headers}, Timeout) -> + call(pick(Pool), {get, {Path, Headers}, Timeout}, Timeout + 1000); +request(Method, Pool, {Path, Headers, Body}, Timeout) -> + call(pick(Pool), {Method, {Path, Headers, Body}, Timeout}, Timeout + 1000). + +%%-------------------------------------------------------------------- +%% gen_server callbacks +%%-------------------------------------------------------------------- + +init([Pool, Id, Opts]) -> + State = #state{pool = Pool, + id = Id, + client = undefined, + mref = undefined, + host = proplists:get_value(host, Opts), + port = proplists:get_value(port, Opts), + gun_opts = gun_opts(Opts), + gun_state = down, + requests = #{}}, + true = gproc_pool:connect_worker(Pool, {Pool, Id}), + {ok, State}. + +handle_call(Req = {_, _, _}, From, State = #state{client = undefined, gun_state = down}) -> + case open(State) of + {ok, NewState} -> + handle_call(Req, From, NewState); + {error, Reason} -> + {reply, {error, Reason}, State} + end; + +handle_call(Req = {_, _, Timeout}, From, State = #state{client = Client, mref = MRef, gun_state = down}) when is_pid(Client) -> + case gun:await_up(Client, Timeout, MRef) of + {ok, _} -> + handle_call(Req, From, State#state{gun_state = up}); + {error, timeout} -> + {reply, {error, timeout}, State}; + {error, Reason} -> + true = erlang:demonitor(MRef, [flush]), + {reply, {error, Reason}, State#state{client = undefined, mref = undefined}} + end; + +handle_call({Method, Request, Timeout}, From, State = #state{client = Client, requests = Requests, gun_state = up}) when is_pid(Client) -> + StreamRef = do_request(Client, Method, Request), + ExpirationTime = erlang:system_time(millisecond) + Timeout, + {noreply, State#state{requests = maps:put(StreamRef, {From, ExpirationTime, undefined}, Requests)}}; + +handle_call(Req, _From, State) -> + ?LOG(error, "Unexpected call: ~p", [Req]), + {reply, ignored, State}. + +handle_cast(Msg, State) -> + ?LOG(error, "Unexpected cast: ~p", [Msg]), + {noreply, State}. + +handle_info({gun_response, Client, StreamRef, IsFin, StatusCode, Headers}, State = #state{client = Client, requests = Requests}) -> + Now = erlang:system_time(millisecond), + case maps:take(StreamRef, Requests) of + error -> + ?LOG(error, "Received 'gun_response' message from unknown stream ref: ~p", [StreamRef]), + {noreply, State}; + {{_, ExpirationTime, _}, NRequests} when Now > ExpirationTime -> + gun:cancel(Client, StreamRef), + flush_stream(Client, StreamRef), + {noreply, State#state{requests = NRequests}}; + {{From, ExpirationTime, undefined}, NRequests} -> + case IsFin of + fin -> + gen_server:reply(From, {ok, StatusCode, Headers}), + {noreply, State#state{requests = NRequests}}; + nofin -> + {noreply, State#state{requests = NRequests#{StreamRef => {From, ExpirationTime, {StatusCode, Headers, <<>>}}}}} + end; + _ -> + ?LOG(error, "Received 'gun_response' message does not match the state"), + {noreply, State} + end; + +handle_info({gun_data, Client, StreamRef, IsFin, Data}, State = #state{client = Client, requests = Requests}) -> + Now = erlang:system_time(millisecond), + case maps:take(StreamRef, Requests) of + error -> + ?LOG(error, "Received 'gun_data' message from unknown stream ref: ~p", [StreamRef]), + {noreply, State}; + {{_, ExpirationTime, _}, NRequests} when Now > ExpirationTime -> + gun:cancel(Client, StreamRef), + flush_stream(Client, StreamRef), + {noreply, State#state{requests = NRequests}}; + {{From, ExpirationTime, {StatusCode, Headers, Acc}}, NRequests} -> + case IsFin of + fin -> + gen_server:reply(From, {ok, StatusCode, Headers, <>}), + {noreply, State#state{requests = NRequests}}; + nofin -> + {noreply, State#state{requests = NRequests#{StreamRef => {From, ExpirationTime, {StatusCode, Headers, <>}}}}} + end; + _ -> + ?LOG(error, "Received 'gun_data' message does not match the state"), + {noreply, State} + end; + +handle_info({gun_error, Client, StreamRef, Reason}, State = #state{client = Client, requests = Requests}) -> + Now = erlang:system_time(millisecond), + case maps:take(StreamRef, Requests) of + error -> + ?LOG(error, "Received 'gun_error' message from unknown stream ref: ~p~n", [StreamRef]), + {noreply, State}; + {{_, ExpirationTime, _}, NRequests} when Now > ExpirationTime -> + {noreply, State#state{requests = NRequests}}; + {{From, _, _}, NRequests} -> + gen_server:reply(From, {error, Reason}), + {noreply, State#state{requests = NRequests}} + end; + +handle_info({gun_up, Client, _}, State = #state{client = Client}) -> + {noreply, State#state{gun_state = up}}; + +handle_info({gun_down, Client, _, Reason, KilledStreams, _}, State = #state{client = Client, requests = Requests}) -> + Now = erlang:system_time(millisecond), + NRequests = lists:foldl(fun(StreamRef, Acc) -> + case maps:take(StreamRef, Acc) of + error -> Acc; + {{_, ExpirationTime, _}, NAcc} when Now > ExpirationTime -> + NAcc; + {{From, _, _}, NAcc} -> + gen_server:reply(From, {error, Reason}), + NAcc + end + end, Requests, KilledStreams), + {noreply, State#state{gun_state = down, requests = NRequests}}; + +handle_info({'DOWN', MRef, process, Client, Reason}, State = #state{mref = MRef, client = Client, requests = Requests}) -> + true = erlang:demonitor(MRef, [flush]), + Now = erlang:system_time(millisecond), + lists:foreach(fun({_, {_, ExpirationTime, _}}) when Now > ExpirationTime -> + ok; + ({_, {From, _, _}}) -> + gen_server:reply(From, {error, Reason}) + end, maps:to_list(Requests)), + case open(State#state{requests = #{}}) of + {ok, NewState} -> + {noreply, NewState}; + {error, Reason} -> + {noreply, State#state{mref = undefined, client = undefined}} + end; + +handle_info(Info, State) -> + ?LOG(error, "Unexpected info: ~p", [Info]), + {noreply, State}. + +terminate(_Reason, #state{pool = Pool, id = Id}) -> + gropc:disconnect_worker(Pool, {Pool, Id}), + ok. + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +%%-------------------------------------------------------------------- +%% Internal functions +%%-------------------------------------------------------------------- + +open(State = #state{host = Host, port = Port, gun_opts = GunOpts}) -> + case gun:open(Host, Port, GunOpts) of + {ok, ConnPid} when is_pid(ConnPid) -> + MRef = monitor(process, ConnPid), + {ok, State#state{mref = MRef, client = ConnPid}}; + {error, Reason} -> + {error, Reason} + end. + +gun_opts(Opts) -> + gun_opts(Opts, #{retry => 5, + retry_timeout => 1000, + connect_timeout => 5000, + protocols => [http], + http_opts => #{keepalive => infinity}}). + +gun_opts([], Acc) -> + Acc; +gun_opts([{retry, Retry} | Opts], Acc) -> + gun_opts(Opts, Acc#{retry => Retry}); +gun_opts([{retry_timeout, RetryTimeout} | Opts], Acc) -> + gun_opts(Opts, Acc#{retry_timeout => RetryTimeout}); +gun_opts([{connect_timeout, ConnectTimeout} | Opts], Acc) -> + gun_opts(Opts, Acc#{connect_timeout => ConnectTimeout}); +gun_opts([{transport, Transport} | Opts], Acc) -> + gun_opts(Opts, Acc#{transport => Transport}); +gun_opts([{transport_opts, TransportOpts} | Opts], Acc) -> + gun_opts(Opts, Acc#{transport_opts => TransportOpts}); +gun_opts([_ | Opts], Acc) -> + gun_opts(Opts, Acc). + +call(ChannPid, Msg, Timeout) -> + gen_server:call(ChannPid, Msg, Timeout). + +pick(Pool) -> + gproc_pool:pick_worker(Pool). + +do_request(Client, get, {Path, Headers}) -> + gun:get(Client, Path, Headers); +do_request(Client, post, {Path, Headers, Body}) -> + gun:post(Client, Path, Headers, Body). + +flush_stream(Client, StreamRef) -> + receive + {gun_response, Client, StreamRef, _, _, _} -> + flush_stream(Client, StreamRef); + {gun_data, Client, StreamRef, _, _} -> + flush_stream(Client, StreamRef); + {gun_error, Client, StreamRef, _} -> + flush_stream(Client, StreamRef) + after 0 -> + ok + end. \ No newline at end of file diff --git a/apps/emqx_auth_http/src/emqx_http_client_sup.erl b/apps/emqx_auth_http/src/emqx_http_client_sup.erl new file mode 100644 index 000000000..dcdd2e4c4 --- /dev/null +++ b/apps/emqx_auth_http/src/emqx_http_client_sup.erl @@ -0,0 +1,48 @@ +-module(emqx_http_client_sup). + +-behaviour(supervisor). + +-export([ start_link/2 + , init/1 + , stop_pool/1 + ]). + +start_link(Pool, Opts) -> + supervisor:start_link(?MODULE, [Pool, Opts]). + +init([Pool, Opts]) -> + PoolSize = pool_size(Opts), + ok = ensure_pool(Pool, random, [{size, PoolSize}]), + {ok, {{one_for_one, 10, 100}, [ + begin + ensure_pool_worker(Pool, {Pool, I}, I), + #{id => {Pool, I}, + start => {emqx_http_client, start_link, [Pool, I, Opts]}, + restart => transient, + shutdown => 5000, + type => worker, + modules => [emqx_http_client]} + end || I <- lists:seq(1, PoolSize)]}}. + + +ensure_pool(Pool, Type, Opts) -> + try gproc_pool:new(Pool, Type, Opts) + catch + error:exists -> ok + end. + +ensure_pool_worker(Pool, Name, Slot) -> + try gproc_pool:add_worker(Pool, Name, Slot) + catch + error:exists -> ok + end. + +pool_size(Opts) -> + Schedulers = erlang:system_info(schedulers), + proplists:get_value(pool_size, Opts, Schedulers). + +stop_pool(Name) -> + Workers = gproc_pool:defined_workers(Name), + [gproc_pool:remove_worker(Name, WokerName) || {WokerName, _, _} <- Workers], + gproc_pool:delete(Name), + ok. \ No newline at end of file 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..79c02c00c --- /dev/null +++ b/apps/emqx_auth_http/test/emqx_auth_http_SUITE.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_http_SUITE). + +-compile(export_all). +-compile(nowarn_export_all). + +-include_lib("emqx/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) -> + ServerAddr = http_server(Schema, Inet), + + AuthReq = #{method => get, + url => ServerAddr ++ "/mqtt/auth", + content_type => <<"application/x-www-form-urlencoded">>, + params => [{"clientid", "%c"}, {"username", "%u"}, {"password", "%P"}]}, + SuperReq = #{method => post, + url => ServerAddr ++ "/mqtt/superuser", + content_type => <<"application/x-www-form-urlencoded">>, + params => [{"clientid", "%c"}, {"username", "%u"}]}, + AclReq = #{method => post, + url => ServerAddr ++ "/mqtt/acl", + content_type => <<"application/json">>, + params => [{"access", "%A"}, {"username", "%u"}, {"clientid", "%c"}, {"ipaddr", "%a"}, {"topic", "%t"}, {"mountpoint", "%m"}]}, + + Schema =:= https andalso set_https_client_opts(), + + application:set_env(emqx_auth_http, auth_req, maps:to_list(AuthReq)), + application:set_env(emqx_auth_http, super_req, maps:to_list(SuperReq)), + application:set_env(emqx_auth_http, acl_req, maps:to_list(AclReq)). + +%% @private +set_https_client_opts() -> + TransportOpts = emqx_ct_helpers:client_ssl_twoway(), + {ok, PoolOpts} = application:get_env(emqx_auth_http, pool_opts), + application:set_env(emqx_auth_http, pool_opts, [{transport_opts, TransportOpts}, {transport, ssl} | PoolOpts]). + +%% @private +http_server(http, inet) -> "http://127.0.0.1:8991"; +http_server(http, inet6) -> "http://[::1]:8991"; +http_server(https, inet) -> "https://127.0.0.1:8991"; +http_server(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/.gitignore b/apps/emqx_auth_jwt/.gitignore new file mode 100644 index 000000000..62e4fbb25 --- /dev/null +++ b/apps/emqx_auth_jwt/.gitignore @@ -0,0 +1,28 @@ +.eunit +deps +*.o +*.beam +*.plt +erl_crash.dump +ebin +rel/example_project +.concrete/DEV_MODE +.rebar +.erlang.mk/ +emqx_auth_jwt.d +data/ +.DS_Store +cover/ +ct.coverdata +eunit.coverdata +logs/ +test/ct.cover.spec +emq_auth_jwt.d +erlang.mk +_build/ +rebar.lock +rebar3.crashdump +etc/emqx_auth_jwt.conf.rendered +.rebar3/ +*.swp +Mnesia.nonode@nohost/ 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/etc/emqx_auth_jwt.conf b/apps/emqx_auth_jwt/etc/emqx_auth_jwt.conf new file mode 100644 index 000000000..5a599ca23 --- /dev/null +++ b/apps/emqx_auth_jwt/etc/emqx_auth_jwt.conf @@ -0,0 +1,45 @@ +##-------------------------------------------------------------------- +## JWT Auth Plugin +##-------------------------------------------------------------------- + +## HMAC Hash Secret. +## +## Value: String +auth.jwt.secret = emqxsecret + +## RSA or ECDSA public key file. +## +## Value: File +#auth.jwt.pubkey = etc/certs/jwt_public_key.pem + +## The JWKs server address +## +## see: http://self-issued.info/docs/draft-ietf-jose-json-web-key.html +## +#auth.jwt.jwks = https://127.0.0.1:8080/jwks + +## The JWKs refresh interval +## +## Value: Duration +#auth.jwt.jwks.refresh_interval = 5m + +## From where the JWT string can be got +## +## Value: username | password +## Default: password +auth.jwt.from = password + +## 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 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..3d8de3678 --- /dev/null +++ b/apps/emqx_auth_jwt/priv/emqx_auth_jwt.schema @@ -0,0 +1,49 @@ +%%-*- mode: erlang -*- + +{mapping, "auth.jwt.secret", "emqx_auth_jwt.secret", [ + {datatype, string} +]}. + +{mapping, "auth.jwt.jwks", "emqx_auth_jwt.jwks", [ + {datatype, string} +]}. + +{mapping, "auth.jwt.jwks.refresh_interval", "emqx_auth_jwt.refresh_interval", [ + {datatype, {duration, ms}} +]}. + +{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.signature_format", "emqx_auth_jwt.jwerl_opts", [ + {default, "der"}, + {datatype, {enum, [raw, der]}} +]}. + +{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}. diff --git a/apps/emqx_auth_jwt/rebar.config b/apps/emqx_auth_jwt/rebar.config new file mode 100644 index 000000000..4164d1fed --- /dev/null +++ b/apps/emqx_auth_jwt/rebar.config @@ -0,0 +1,25 @@ +{deps, + [ + {jose, {git, "https://github.com/potatosalad/erlang-jose", {tag, "1.10.1"}}} + ]}. + +{edoc_opts, [{preprocess, true}]}. +{erl_opts, [warn_unused_vars, + warn_shadow_vars, + warn_unused_import, + warn_obsolete_guard, + debug_info, + {parse_transform}]}. + +{xref_checks, [undefined_function_calls, undefined_functions, + locals_not_used, deprecated_function_calls, + warnings_as_errors, deprecated_functions]}. +{cover_enabled, true}. +{cover_opts, [verbose]}. +{cover_export_enabled, true}. + +{profiles, + [{test, + [{deps, [{emqx_ct_helpers, {git, "http://github.com/emqx/emqx-ct-helpers", {tag, "1.2.2"}}}]} + ]} + ]}. 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..8e9d8daff --- /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, "4.3.0"}, % strict semver, bump manually! + {modules, []}, + {registered, [emqx_auth_jwt_sup]}, + {applications, [kernel,stdlib,jose,emqx]}, + {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.appup.src b/apps/emqx_auth_jwt/src/emqx_auth_jwt.appup.src new file mode 100644 index 000000000..0c7b8ebf3 --- /dev/null +++ b/apps/emqx_auth_jwt/src/emqx_auth_jwt.appup.src @@ -0,0 +1,10 @@ +%% -*-: erlang -*- + +{VSN, + [ + {<<".*">>, []} + ], + [ + {<<".*">>, []} + ] +}. 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..6be726dc9 --- /dev/null +++ b/apps/emqx_auth_jwt/src/emqx_auth_jwt.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. +%%-------------------------------------------------------------------- + +-module(emqx_auth_jwt). + +-include_lib("emqx/include/emqx.hrl"). +-include_lib("emqx/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, #{pid := Pid, + from := From, + checklists := Checklists}) -> + case maps:find(From, ClientInfo) of + error -> + ok = emqx_metrics:inc(?AUTH_METRICS(ignore)); + {ok, undefined} -> + ok = emqx_metrics:inc(?AUTH_METRICS(ignore)); + {ok, Token} -> + case emqx_auth_jwt_svr:verify(Pid, Token) of + {error, not_found} -> + ok = emqx_metrics:inc(?AUTH_METRICS(ignore)); + {error, not_token} -> + ok = emqx_metrics:inc(?AUTH_METRICS(ignore)); + {error, Reason} -> + ok = emqx_metrics:inc(?AUTH_METRICS(failure)), + {stop, AuthResult#{auth_result => Reason, anonymous => false}}; + {ok, Claims} -> + {stop, maps:merge(AuthResult, verify_claims(Checklists, Claims, ClientInfo))} + end + end. + +description() -> "Authentication with JWT". + +%%------------------------------------------------------------------------------ +%% 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..736fb28b9 --- /dev/null +++ b/apps/emqx_auth_jwt/src/emqx_auth_jwt_app.erl @@ -0,0 +1,82 @@ +%%-------------------------------------------------------------------- +%% 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). + +start(_Type, _Args) -> + {ok, Sup} = supervisor:start_link({local, ?MODULE}, ?MODULE, []), + + {ok, Pid} = start_auth_server(jwks_svr_options()), + ok = emqx_auth_jwt:register_metrics(), + + AuthEnv0 = auth_env(), + AuthEnv1 = AuthEnv0#{pid => Pid}, + + emqx:hook('client.authenticate', {emqx_auth_jwt, check, [AuthEnv1]}), + {ok, Sup, AuthEnv1}. + +stop(AuthEnv) -> + emqx:unhook('client.authenticate', {emqx_auth_jwt, check, [AuthEnv]}). + +%%-------------------------------------------------------------------- +%% Dummy supervisor +%%-------------------------------------------------------------------- + +init([]) -> + {ok, {{one_for_all, 1, 10}, []}}. + +start_auth_server(Options) -> + Spec = #{id => jwt_svr, + start => {emqx_auth_jwt_svr, start_link, [Options]}, + restart => permanent, + shutdown => brutal_kill, + type => worker, + modules => [emqx_auth_jwt_svr]}, + supervisor:start_child(?MODULE, Spec). + +%%-------------------------------------------------------------------- +%% Internal functions +%%-------------------------------------------------------------------- + +auth_env() -> + Checklists = [{atom_to_binary(K, utf8), V} + || {K, V} <- env(verify_claims, [])], + #{ from => env(from, password) + , checklists => Checklists + }. + +jwks_svr_options() -> + [{K, V} || {K, V} + <- [{secret, env(secret, undefined)}, + {pubkey, env(pubkey, undefined)}, + {jwks_addr, env(jwks, undefined)}, + {interval, env(refresh_interval, undefined)}], + V /= undefined]. + +env(Key, Default) -> + application:get_env(?APP, Key, Default). diff --git a/apps/emqx_auth_jwt/src/emqx_auth_jwt_svr.erl b/apps/emqx_auth_jwt/src/emqx_auth_jwt_svr.erl new file mode 100644 index 000000000..b347d0e0b --- /dev/null +++ b/apps/emqx_auth_jwt/src/emqx_auth_jwt_svr.erl @@ -0,0 +1,222 @@ +%%-------------------------------------------------------------------- +%% 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_svr). + +-behaviour(gen_server). + +-include_lib("emqx/include/logger.hrl"). +-include_lib("jose/include/jose_jwk.hrl"). + +-logger_header("[JWT-SVR]"). + +%% APIs +-export([start_link/1]). + +-export([verify/2]). + +%% gen_server callbacks +-export([ init/1 + , handle_call/3 + , handle_cast/2 + , handle_info/2 + , terminate/2 + , code_change/3 + ]). + +-type options() :: [option()]. +-type option() :: {secret, list()} + | {pubkey, list()} + | {jwks_addr, list()} + | {interval, pos_integer()}. + +-define(INTERVAL, 300000). + +-record(state, {static, remote, addr, tref, intv}). + +%%-------------------------------------------------------------------- +%% APIs +%%-------------------------------------------------------------------- + +-spec start_link(options()) -> gen_server:start_ret(). +start_link(Options) -> + gen_server:start_link(?MODULE, [Options], []). + +-spec verify(pid(), binary()) + -> {error, term()} + | {ok, Payload :: map()}. +verify(S, JwsCompacted) when is_binary(JwsCompacted) -> + case catch jose_jws:peek(JwsCompacted) of + {'EXIT', _} -> {error, not_token}; + _ -> gen_server:call(S, {verify, JwsCompacted}) + end. + +%%-------------------------------------------------------------------- +%% gen_server callbacks +%%-------------------------------------------------------------------- + +init([Options]) -> + ok = jose:json_module(jiffy), + {Static, Remote} = do_init_jwks(Options), + Intv = proplists:get_value(interval, Options, ?INTERVAL), + {ok, reset_timer( + #state{ + static = Static, + remote = Remote, + addr = proplists:get_value(jwks_addr, Options), + intv = Intv})}. + +%% @private +do_init_jwks(Options) -> + K2J = fun(K, F) -> + case proplists:get_value(K, Options) of + undefined -> undefined; + V -> + try F(V) of + {error, Reason} -> + ?LOG(warning, "Build ~p JWK ~p failed: {error, ~p}~n", + [K, V, Reason]), + undefined; + J -> J + catch T:R:_ -> + ?LOG(warning, "Build ~p JWK ~p failed: {~p, ~p}~n", + [K, V, T, R]), + undefined + end + end + end, + OctJwk = K2J(secret, fun(V) -> + jose_jwk:from_oct(list_to_binary(V)) + end), + PemJwk = K2J(pubkey, fun jose_jwk:from_pem_file/1), + Remote = K2J(jwks_addr, fun request_jwks/1), + {[J ||J <- [OctJwk, PemJwk], J /= undefined], Remote}. + +handle_call({verify, JwsCompacted}, _From, State) -> + handle_verify(JwsCompacted, State); + +handle_call(_Req, _From, State) -> + {reply, ok, State}. + +handle_cast(_Msg, State) -> + {noreply, State}. + +handle_info({timeout, _TRef, refresh}, State = #state{addr = Addr}) -> + NState = try + State#state{remote = request_jwks(Addr)} + catch _:_ -> + State + end, + {noreply, reset_timer(NState)}; + +handle_info(_Info, State) -> + {noreply, State}. + +terminate(_Reason, State) -> + _ = cancel_timer(State), + ok. + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +%%-------------------------------------------------------------------- +%% Internal funcs +%%-------------------------------------------------------------------- + +handle_verify(JwsCompacted, + State = #state{static = Static, remote = Remote}) -> + try + Jwks = case emqx_json:decode(jose_jws:peek_protected(JwsCompacted), [return_maps]) of + #{<<"kid">> := Kid} -> + [J || J <- Remote, maps:get(<<"kid">>, J#jose_jwk.fields, undefined) =:= Kid]; + _ -> Static + end, + case Jwks of + [] -> {reply, {error, not_found}, State}; + _ -> + {reply, do_verify(JwsCompacted, Jwks), State} + end + catch + _:_ -> + {reply, {error, invalid_signature}, State} + end. + +request_jwks(Addr) -> + case httpc:request(get, {Addr, []}, [], [{body_format, binary}]) of + {error, Reason} -> + error(Reason); + {ok, {_Code, _Headers, Body}} -> + try + JwkSet = jose_jwk:from(emqx_json:decode(Body, [return_maps])), + {_, Jwks} = JwkSet#jose_jwk.keys, Jwks + catch _:_ -> + ?LOG(error, "Invalid jwks server response: ~p~n", [Body]), + error(badarg) + end + end. + +reset_timer(State = #state{addr = undefined}) -> + State; +reset_timer(State = #state{intv = Intv}) -> + State#state{tref = erlang:start_timer(Intv, self(), refresh)}. + +cancel_timer(State = #state{tref = undefined}) -> + State; +cancel_timer(State = #state{tref = TRef}) -> + erlang:cancel_timer(TRef), + State#state{tref = undefined}. + +do_verify(_JwsCompated, []) -> + {error, invalid_signature}; +do_verify(JwsCompacted, [Jwk|More]) -> + case jose_jws:verify(Jwk, JwsCompacted) of + {true, Payload, _Jws} -> + Claims = emqx_json:decode(Payload, [return_maps]), + case check_claims(Claims) of + false -> + {error, invalid_signature}; + NClaims -> + {ok, NClaims} + end; + {false, _, _} -> + do_verify(JwsCompacted, More) + end. + +check_claims(Claims) -> + Now = os:system_time(seconds), + Checker = [{<<"exp">>, fun(ExpireTime) -> + Now < ExpireTime + end}, + {<<"iat">>, fun(IssueAt) -> + IssueAt =< Now + end}, + {<<"nbf">>, fun(NotBefore) -> + NotBefore =< Now + end} + ], + do_check_claim(Checker, Claims). + +do_check_claim([], Claims) -> + Claims; +do_check_claim([{K, F}|More], Claims) -> + case maps:take(K, Claims) of + error -> do_check_claim(More, Claims); + {V, NClaims} -> + case F(V) of + true -> do_check_claim(More, NClaims); + _ -> false + end + end. 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..12f307b2a --- /dev/null +++ b/apps/emqx_auth_jwt/test/emqx_auth_jwt_SUITE.erl @@ -0,0 +1,142 @@ +%%-------------------------------------------------------------------- +%% 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(export_all). +-compile(nowarn_export_all). + +-include_lib("emqx/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. + +sign(Payload, Alg, Key) -> + Jwk = jose_jwk:from_oct(Key), + Jwt = emqx_json:encode(Payload), + {_, Token} = jose_jws:compact(jose_jwt:sign(Jwk, #{<<"alg">> => Alg}, Jwt)), + Token. + +%%------------------------------------------------------------------------------ +%% Testcases +%%------------------------------------------------------------------------------ + +t_check_auth(_) -> + Plain = #{clientid => <<"client1">>, username => <<"plain">>, zone => external}, + Jwt = 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 = sign([{client_id, <<"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 = sign([{client_id, <<"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 = 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 = sign([{client_id, <<"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 = 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 = sign([{client_id, <<"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 = 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/.gitignore b/apps/emqx_auth_ldap/.gitignore new file mode 100644 index 000000000..eb8f0639f --- /dev/null +++ b/apps/emqx_auth_ldap/.gitignore @@ -0,0 +1,25 @@ +.eunit +deps +*.o +*.beam +*.plt +erl_crash.dump +ebin +rel/example_project +.concrete/DEV_MODE +.rebar +.erlang.mk/ +emqx_auth_ldap.d +data/ +cover/ +ct.coverdata +eunit.coverdata +logs/ +test/ct.cover.spec +.DS_Store +_build/ +rebar.lock +erlang.mk +rebar3.crashdump +.rebar3/ +etc/emqx_auth_ldap.conf.rendered 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/etc/emqx_auth_ldap.conf b/apps/emqx_auth_ldap/etc/emqx_auth_ldap.conf new file mode 100644 index 000000000..746510fb3 --- /dev/null +++ b/apps/emqx_auth_ldap/etc/emqx_auth_ldap.conf @@ -0,0 +1,78 @@ +##-------------------------------------------------------------------- +## LDAP Auth Plugin +##-------------------------------------------------------------------- + +## LDAP server list, seperated by ','. +## +## Value: String +auth.ldap.servers = 127.0.0.1 + +## LDAP server port. +## +## Value: Port +auth.ldap.port = 389 + +## LDAP pool size +## +## Value: String +auth.ldap.pool = 8 + +## LDAP Bind DN. +## +## Value: DN +auth.ldap.bind_dn = cn=root,dc=emqx,dc=io + +## LDAP Bind Password. +## +## Value: String +auth.ldap.bind_password = public + +## LDAP query timeout. +## +## Value: Number +auth.ldap.timeout = 30s + +## Device DN. +## +## Variables: +## +## Value: DN +auth.ldap.device_dn = ou=device,dc=emqx,dc=io + +## Specified ObjectClass +## +## Variables: +## +## Value: string +auth.ldap.match_objectclass = mqttUser + +## attributetype for username +## +## Variables: +## +## Value: string +auth.ldap.username.attributetype = uid + +## attributetype for password +## +## Variables: +## +## Value: string +auth.ldap.password.attributetype = userPassword + +## Whether to enable SSL. +## +## Value: true | false +auth.ldap.ssl = false + +#auth.ldap.ssl.certfile = etc/certs/cert.pem + +#auth.ldap.ssl.keyfile = etc/certs/key.pem + +#auth.ldap.ssl.cacertfile = etc/certs/cacert.pem + +#auth.ldap.ssl.verify = verify_peer + +#auth.ldap.ssl.fail_if_no_peer_cert = true + +#auth.ldap.ssl.server_name_indication = your_server_name 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..48eaf812f --- /dev/null +++ b/apps/emqx_auth_ldap/rebar.config @@ -0,0 +1,25 @@ +{deps, + [{eldap2, {git, "https://github.com/emqx/eldap2", {tag, "v0.2.2"}}} + ]}. + +{profiles, + [{test, + [{deps, [{emqx_ct_helpers, {git, "https://github.com/emqx/emqx-ct-helpers", {tag, "1.2.2"}}}]} + ]} + ]}. + +{edoc_opts, [{preprocess, true}]}. +{erl_opts, [warn_unused_vars, + warn_shadow_vars, + warn_unused_import, + warn_obsolete_guard, + debug_info, + {parse_transform}]}. + +{xref_checks, [undefined_function_calls, undefined_functions, + locals_not_used, deprecated_function_calls, + warnings_as_errors, deprecated_functions]}. +{cover_enabled, true}. +{cover_opts, [verbose]}. +{cover_export_enabled, true}. + 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..cfd51164a --- /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/include/emqx.hrl"). +-include_lib("eldap/include/eldap.hrl"). +-include_lib("emqx/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..8635c4834 --- /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, "4.3.0"}, % strict semver, bump manually! + {modules, []}, + {registered, [emqx_auth_ldap_sup]}, + {applications, [kernel,stdlib,eldap2,ecpool]}, + {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..01cbb0ecb --- /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/include/emqx.hrl"). +-include_lib("eldap/include/eldap.hrl"). +-include_lib("emqx/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..2f6e8099c --- /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/include/emqx.hrl"). +-include_lib("emqx/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..513ad79e1 --- /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/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..76f049cbc --- /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/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/.gitignore b/apps/emqx_auth_mnesia/.gitignore new file mode 100644 index 000000000..a4d9fea0a --- /dev/null +++ b/apps/emqx_auth_mnesia/.gitignore @@ -0,0 +1,26 @@ +.eunit +deps +*.o +*.beam +*.plt +erl_crash.dump +ebin +rel/example_project +.concrete/DEV_MODE +.rebar +.erlang.mk/ +emqx_auth_mnesia.d +data/ +_build/ +.DS_Store +cover/ +ct.coverdata +eunit.coverdata +logs/ +test/ct.cover.spec +rebar.lock +rebar3.crashdump +erlang.mk +.*.swp +.rebar3/ +etc/emqx_auth_mnesia.conf.rendered 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/etc/emqx_auth_mnesia.conf b/apps/emqx_auth_mnesia/etc/emqx_auth_mnesia.conf new file mode 100644 index 000000000..ff74656cb --- /dev/null +++ b/apps/emqx_auth_mnesia/etc/emqx_auth_mnesia.conf @@ -0,0 +1,30 @@ +## Password hash. +## +## Value: plain | md5 | sha | sha256 | sha512 +auth.mnesia.password_hash = sha256 + +##-------------------------------------------------------------------- +## ClientId Authentication +##-------------------------------------------------------------------- + +## Examples +##auth.client.1.clientid = id +##auth.client.1.password = passwd +##auth.client.2.clientid = dev:devid +##auth.client.2.password = passwd2 +##auth.client.3.clientid = app:appid +##auth.client.3.password = passwd3 +##auth.client.4.clientid = client~!@#$%^&*()_+ +##auth.client.4.password = passwd~!@#$%^&*()_+ + +##-------------------------------------------------------------------- +## Username Authentication +##-------------------------------------------------------------------- + +## Examples: +##auth.user.1.username = admin +##auth.user.1.password = public +##auth.user.2.username = feng@emqtt.io +##auth.user.2.password = public +##auth.user.3.username = name~!@#$%^&*()_+ +##auth.user.3.password = pwsswd~!@#$%^&*()_+ 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..034bd4f30 --- /dev/null +++ b/apps/emqx_auth_mnesia/include/emqx_auth_mnesia.hrl @@ -0,0 +1,38 @@ +-define(APP, emqx_auth_mnesia). + +-type(login():: {clientid, binary()} + | {username, binary()}). + +-record(emqx_user, { + login :: login(), + password :: binary(), + created_at :: integer() + }). + +-record(emqx_acl, { + filter:: {login() | all, emqx_topic:topic()}, + action :: pub | sub | pubsub, + access :: allow | deny, + created_at :: integer() + }). + +-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_mnesia/priv/emqx_auth_mnesia.schema b/apps/emqx_auth_mnesia/priv/emqx_auth_mnesia.schema new file mode 100644 index 000000000..87d6bf47f --- /dev/null +++ b/apps/emqx_auth_mnesia/priv/emqx_auth_mnesia.schema @@ -0,0 +1,43 @@ +%%-*- mode: erlang -*- +%% emqx_auth_mnesia config mapping + +{mapping, "auth.mnesia.password_hash", "emqx_auth_mnesia.password_hash", [ + {default, sha256}, + {datatype, {enum, [plain, md5, sha, sha256, sha512]}} +]}. + +{mapping, "auth.client.$id.clientid", "emqx_auth_mnesia.clientid_list", [ + {datatype, string} +]}. + +{mapping, "auth.client.$id.password", "emqx_auth_mnesia.clientid_list", [ + {datatype, string} +]}. + +{translation, "emqx_auth_mnesia.clientid_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}. + +{mapping, "auth.user.$id.username", "emqx_auth_mnesia.username_list", [ + {datatype, string} +]}. + +{mapping, "auth.user.$id.password", "emqx_auth_mnesia.username_list", [ + {datatype, string} +]}. + +{translation, "emqx_auth_mnesia.username_list", 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_mnesia/rebar.config b/apps/emqx_auth_mnesia/rebar.config new file mode 100644 index 000000000..4c695ec69 --- /dev/null +++ b/apps/emqx_auth_mnesia/rebar.config @@ -0,0 +1,17 @@ +{deps, + [ ]}. + +{erl_opts, [warn_unused_vars, + warn_shadow_vars, + warn_unused_import, + warn_obsolete_guard, + debug_info, + {parse_transform}]}. + +{xref_checks, [undefined_function_calls, undefined_functions, + locals_not_used, deprecated_function_calls, + warnings_as_errors, deprecated_functions]}. +{cover_enabled, true}. +{cover_opts, [verbose]}. +{cover_export_enabled, true}. + 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..c657e54a0 --- /dev/null +++ b/apps/emqx_auth_mnesia/src/emqx_acl_mnesia.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_acl_mnesia). + +-include("emqx_auth_mnesia.hrl"). + +-include_lib("stdlib/include/ms_transform.hrl"). + +-define(TABLE, emqx_acl). + +%% ACL Callbacks +-export([ init/0 + , register_metrics/0 + , check_acl/5 + , description/0 + ]). + +init() -> + ok = ekka_mnesia:create_table(emqx_acl, [ + {disc_copies, [node()]}, + {attributes, record_info(fields, emqx_acl)}, + {storage_properties, [{ets, [{read_concurrency, true}]}]}]), + ok = ekka_mnesia:copy_table(emqx_acl, disc_copies). + +-spec(register_metrics() -> ok). +register_metrics() -> + lists:foreach(fun emqx_metrics:ensure/1, ?ACL_METRICS). + +check_acl(ClientInfo = #{ clientid := Clientid }, PubSub, Topic, _NoMatchAction, _Params) -> + Username = maps:get(username, ClientInfo, undefined), + + Acls = case Username of + undefined -> + emqx_acl_mnesia_cli:lookup_acl({clientid, Clientid}) ++ + emqx_acl_mnesia_cli:lookup_acl(all); + _ -> + emqx_acl_mnesia_cli:lookup_acl({clientid, Clientid}) ++ + emqx_acl_mnesia_cli:lookup_acl({username, Username}) ++ + emqx_acl_mnesia_cli:lookup_acl(all) + end, + + case match(ClientInfo, PubSub, Topic, Acls) of + allow -> + emqx_metrics:inc(?ACL_METRICS(allow)), + {stop, allow}; + deny -> + emqx_metrics:inc(?ACL_METRICS(deny)), + {stop, deny}; + _ -> + emqx_metrics:inc(?ACL_METRICS(ignore)), + ok + end. + +description() -> "Acl with Mnesia". + +%%-------------------------------------------------------------------- +%% Internal functions +%%------------------------------------------------------------------- + +match(_ClientInfo, _PubSub, _Topic, []) -> + nomatch; +match(ClientInfo, PubSub, Topic, [ {_, ACLTopic, Action, Access, _} | Acls]) -> + case match_actions(PubSub, Action) andalso match_topic(ClientInfo, Topic, ACLTopic) of + true -> Access; + false -> match(ClientInfo, PubSub, Topic, Acls) + end. + +match_topic(ClientInfo, Topic, ACLTopic) when is_binary(Topic) -> + emqx_topic:match(Topic, feed_var(ClientInfo, ACLTopic)). + +match_actions(_, pubsub) -> true; +match_actions(subscribe, sub) -> true; +match_actions(publish, pub) -> true; +match_actions(_, _) -> false. + +feed_var(ClientInfo, Pattern) -> + feed_var(ClientInfo, emqx_topic:words(Pattern), []). +feed_var(_ClientInfo, [], Acc) -> + emqx_topic:join(lists:reverse(Acc)); +feed_var(ClientInfo = #{clientid := undefined}, [<<"%c">>|Words], Acc) -> + feed_var(ClientInfo, Words, [<<"%c">>|Acc]); +feed_var(ClientInfo = #{clientid := ClientId}, [<<"%c">>|Words], Acc) -> + feed_var(ClientInfo, Words, [ClientId |Acc]); +feed_var(ClientInfo = #{username := undefined}, [<<"%u">>|Words], Acc) -> + feed_var(ClientInfo, Words, [<<"%u">>|Acc]); +feed_var(ClientInfo = #{username := Username}, [<<"%u">>|Words], Acc) -> + feed_var(ClientInfo, Words, [Username|Acc]); +feed_var(ClientInfo, [W|Words], Acc) -> + feed_var(ClientInfo, Words, [W|Acc]). 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..8f858dfa6 --- /dev/null +++ b/apps/emqx_auth_mnesia/src/emqx_acl_mnesia_api.erl @@ -0,0 +1,237 @@ +%c%-------------------------------------------------------------------- +%% 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"). + +-include_lib("stdlib/include/ms_transform.hrl"). + +-import(proplists, [ get_value/2 + , get_value/3 + ]). + +-import(minirest, [return/1]). + +-rest_api(#{name => list_clientid, + method => 'GET', + path => "/acl/clientid", + func => list_clientid, + descr => "List available mnesia in the cluster" + }). + +-rest_api(#{name => list_username, + method => 'GET', + path => "/acl/username", + func => list_username, + descr => "List available mnesia in the cluster" + }). + +-rest_api(#{name => list_all, + method => 'GET', + path => "/acl/$all", + func => list_all, + descr => "List available mnesia in the cluster" + }). + +-rest_api(#{name => lookup_clientid, + method => 'GET', + path => "/acl/clientid/:bin:clientid", + func => lookup, + descr => "Lookup mnesia in the cluster" + }). + +-rest_api(#{name => lookup_username, + method => 'GET', + path => "/acl/username/:bin:username", + func => lookup, + descr => "Lookup mnesia in the cluster" + }). + +-rest_api(#{name => add, + method => 'POST', + path => "/acl", + func => add, + descr => "Add mnesia in the cluster" + }). + +-rest_api(#{name => delete_clientid, + method => 'DELETE', + path => "/acl/clientid/:bin:clientid/topic/:bin:topic", + func => delete, + descr => "Delete mnesia in the cluster" + }). + +-rest_api(#{name => delete_username, + method => 'DELETE', + path => "/acl/username/:bin:username/topic/:bin:topic", + func => delete, + descr => "Delete mnesia in the cluster" + }). + +-rest_api(#{name => delete_all, + method => 'DELETE', + path => "/acl/$all/topic/:bin:topic", + func => delete, + descr => "Delete mnesia in the cluster" + }). + + +-export([ list_clientid/2 + , list_username/2 + , list_all/2 + , lookup/2 + , add/2 + , delete/2 + ]). + +list_clientid(_Bindings, Params) -> + MatchSpec = ets:fun2ms( + fun({emqx_acl, {{clientid, Clientid}, Topic}, Action, Access, CreatedAt}) -> {{clientid,Clientid}, Topic, Action,Access, CreatedAt} end), + return({ok, emqx_auth_mnesia_api:paginate(emqx_acl, MatchSpec, Params, fun emqx_acl_mnesia_cli:comparing/2, fun format/1)}). + +list_username(_Bindings, Params) -> + MatchSpec = ets:fun2ms( + fun({emqx_acl, {{username, Username}, Topic}, Action, Access, CreatedAt}) -> {{username, Username}, Topic, Action,Access, CreatedAt} end), + return({ok, emqx_auth_mnesia_api:paginate(emqx_acl, MatchSpec, Params, fun emqx_acl_mnesia_cli:comparing/2, fun format/1)}). + +list_all(_Bindings, Params) -> + MatchSpec = ets:fun2ms( + fun({emqx_acl, {all, Topic}, Action, Access, CreatedAt}) -> {all, Topic, Action,Access, CreatedAt}end + ), + return({ok, emqx_auth_mnesia_api:paginate(emqx_acl, MatchSpec, Params, fun emqx_acl_mnesia_cli:comparing/2, fun format/1)}). + + +lookup(#{clientid := Clientid}, _Params) -> + return({ok, format(emqx_acl_mnesia_cli:lookup_acl({clientid, urldecode(Clientid)}))}); +lookup(#{username := Username}, _Params) -> + return({ok, format(emqx_acl_mnesia_cli:lookup_acl({username, urldecode(Username)}))}). + +add(_Bindings, Params) -> + [ P | _] = Params, + case is_list(P) of + true -> return(do_add(Params, [])); + false -> + Re = do_add(Params), + case Re of + #{result := ok} -> return({ok, Re}); + #{result := <<"ok">>} -> return({ok, Re}); + _ -> return({error, Re}) + end + end. + +do_add([ Params | ParamsN ], ReList) -> + do_add(ParamsN, [do_add(Params) | ReList]); + +do_add([], ReList) -> + {ok, ReList}. + +do_add(Params) -> + Clientid = get_value(<<"clientid">>, Params, undefined), + Username = get_value(<<"username">>, Params, undefined), + Login = case {Clientid, Username} of + {undefined, undefined} -> all; + {_, undefined} -> {clientid, urldecode(Clientid)}; + {undefined, _} -> {username, urldecode(Username)} + end, + Topic = urldecode(get_value(<<"topic">>, Params)), + Action = urldecode(get_value(<<"action">>, Params)), + Access = urldecode(get_value(<<"access">>, Params)), + Re = case validate([login, topic, action, access], [Login, Topic, Action, Access]) of + ok -> + emqx_acl_mnesia_cli:add_acl(Login, Topic, erlang:binary_to_atom(Action, utf8), erlang:binary_to_atom(Access, utf8)); + Err -> Err + end, + maps:merge(#{topic => Topic, + action => Action, + access => Access, + result => format_msg(Re) + }, case Login of + all -> #{all => '$all'}; + _ -> maps:from_list([Login]) + end). + +delete(#{clientid := Clientid, topic := Topic}, _) -> + return(emqx_acl_mnesia_cli:remove_acl({clientid, urldecode(Clientid)}, urldecode(Topic))); +delete(#{username := Username, topic := Topic}, _) -> + return(emqx_acl_mnesia_cli:remove_acl({username, urldecode(Username)}, urldecode(Topic))); +delete(#{topic := Topic}, _) -> + return(emqx_acl_mnesia_cli:remove_acl(all, urldecode(Topic))). + +%%------------------------------------------------------------------------------ +%% Interval Funcs +%%------------------------------------------------------------------------------ +format({{clientid, Clientid}, Topic, Action, Access, _CreatedAt}) -> + #{clientid => Clientid, topic => Topic, action => Action, access => Access}; +format({{username, Username}, Topic, Action, Access, _CreatedAt}) -> + #{username => Username, topic => Topic, action => Action, access => Access}; +format({all, Topic, Action, Access, _CreatedAt}) -> + #{all => '$all', topic => Topic, action => Action, access => Access}; +format(List) when is_list(List) -> + format(List, []). + +format([L | List], Relist) -> + format(List, [format(L) | Relist]); +format([], ReList) -> lists:reverse(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, all) -> + true; +do_validation(login, {clientid, V}) when is_binary(V) + andalso byte_size(V) > 0-> + true; +do_validation(login, {username, V}) when is_binary(V) + andalso byte_size(V) > 0-> + true; +do_validation(clientid, V) when is_binary(V) + andalso byte_size(V) > 0 -> + true; +do_validation(username, 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(access, V) when V =:= <<"allow">> orelse V =:= <<"deny">> -> + 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_acl_mnesia_cli.erl b/apps/emqx_auth_mnesia/src/emqx_acl_mnesia_cli.erl new file mode 100644 index 000000000..020a94542 --- /dev/null +++ b/apps/emqx_auth_mnesia/src/emqx_acl_mnesia_cli.erl @@ -0,0 +1,198 @@ +%%-------------------------------------------------------------------- +%% 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_cli). + +-include("emqx_auth_mnesia.hrl"). +-include_lib("emqx/include/logger.hrl"). +-include_lib("stdlib/include/ms_transform.hrl"). +-define(TABLE, emqx_acl). + +%% Acl APIs +-export([ add_acl/4 + , lookup_acl/1 + , all_acls/0 + , all_acls/1 + , remove_acl/2 + ]). + +-export([cli/1]). +-export([comparing/2]). +%%-------------------------------------------------------------------- +%% Acl API +%%-------------------------------------------------------------------- + +%% @doc Add Acls +-spec(add_acl(login() |all, emqx_topic:topic(), pub | sub| pubsub, allow | deny) -> ok | {error, any()}). +add_acl(Login, Topic, Action, Access) -> + Acls = #?TABLE{ + filter = {Login, Topic}, + action = Action, + access = Access, + created_at = erlang:system_time(millisecond) + }, + ret(mnesia:transaction(fun mnesia:write/1, [Acls])). + +%% @doc Lookup acl by login +-spec(lookup_acl(login() | all) -> list()). +lookup_acl(undefined) -> []; +lookup_acl(Login) -> + MatchSpec = ets:fun2ms(fun({?TABLE, {Filter, ACLTopic}, Action, Access, CreatedAt}) + when Filter =:= Login -> {Filter, ACLTopic, Action, Access, CreatedAt} end), + lists:sort(fun comparing/2, ets:select(?TABLE, MatchSpec)). + +%% @doc Remove acl +-spec(remove_acl(login() | all, emqx_topic:topic()) -> ok | {error, any()}). +remove_acl(Login, Topic) -> + ret(mnesia:transaction(fun mnesia:delete/1, [{?TABLE, {Login, Topic}}])). + +%% @doc All logins +-spec(all_acls() -> list()). +all_acls() -> + all_acls(clientid) ++ + all_acls(username) ++ + all_acls(all). + +all_acls(clientid) -> + MatchSpec = ets:fun2ms(fun({?TABLE, {{clientid, Clientid}, Topic}, Action, Access, CreatedAt}) -> {{clientid, Clientid}, Topic, Action, Access, CreatedAt} end), + lists:sort(fun comparing/2, ets:select(?TABLE, MatchSpec)); +all_acls(username) -> + MatchSpec = ets:fun2ms(fun({?TABLE, {{username, Username}, Topic}, Action, Access, CreatedAt}) -> {{username, Username}, Topic, Action, Access, CreatedAt} end), + lists:sort(fun comparing/2, ets:select(?TABLE, MatchSpec)); +all_acls(all) -> + MatchSpec = ets:fun2ms(fun({?TABLE, {all, Topic}, Action, Access, CreatedAt}) -> {all, Topic, Action, Access, CreatedAt} end), + lists:sort(fun comparing/2, ets:select(?TABLE, MatchSpec)). + +%%-------------------------------------------------------------------- +%% Internal functions +%%-------------------------------------------------------------------- + +comparing({_, _, _, _, CreatedAt1}, + {_, _, _, _, CreatedAt2}) -> + CreatedAt1 >= CreatedAt2. + +ret({atomic, ok}) -> ok; +ret({aborted, Error}) -> {error, Error}. + +validate(action, "pub") -> true; +validate(action, "sub") -> true; +validate(action, "pubsub") -> true; +validate(access, "allow") -> true; +validate(access, "deny") -> true; +validate(_, _) -> false. + +%%-------------------------------------------------------------------- +%% ACL Cli +%%-------------------------------------------------------------------- + +cli(["list"]) -> + [ begin + case Filter of + {clientid, Clientid} -> + emqx_ctl:print("Acl(clientid = ~p topic = ~p action = ~p access = ~p)~n",[Clientid, Topic, Action, Access]); + {username, Username} -> + emqx_ctl:print("Acl(username = ~p topic = ~p action = ~p access = ~p)~n",[Username, Topic, Action, Access]); + all -> + emqx_ctl:print("Acl($all topic = ~p action = ~p access = ~p)~n",[Topic, Action, Access]) + end + end || {Filter, Topic, Action, Access, _} <- all_acls()]; + +cli(["list", "clientid"]) -> + [emqx_ctl:print("Acl(clientid = ~p topic = ~p action = ~p access = ~p)~n",[Clientid, Topic, Action, Access]) + || {{clientid, Clientid}, Topic, Action, Access, _} <- all_acls(clientid) ]; + +cli(["list", "username"]) -> + [emqx_ctl:print("Acl(username = ~p topic = ~p action = ~p access = ~p)~n",[Username, Topic, Action, Access]) + || {{username, Username}, Topic, Action, Access, _} <- all_acls(username) ]; + +cli(["list", "_all"]) -> + [emqx_ctl:print("Acl($all topic = ~p action = ~p access = ~p)~n",[Topic, Action, Access]) + || {all, Topic, Action, Access, _} <- all_acls(all) ]; + +cli(["add", "clientid", Clientid, Topic, Action, Access]) -> + case validate(action, Action) andalso validate(access, Access) of + true -> + case add_acl({clientid, iolist_to_binary(Clientid)}, iolist_to_binary(Topic), list_to_existing_atom(Action), list_to_existing_atom(Access)) of + ok -> emqx_ctl:print("ok~n"); + {error, Reason} -> emqx_ctl:print("Error: ~p~n", [Reason]) + end; + _ -> + emqx_ctl:print("Error: Input is illegal~n") + end; + +cli(["add", "username", Username, Topic, Action, Access]) -> + case validate(action, Action) andalso validate(access, Access) of + true -> + case add_acl({username, iolist_to_binary(Username)}, iolist_to_binary(Topic), list_to_existing_atom(Action), list_to_existing_atom(Access)) of + ok -> emqx_ctl:print("ok~n"); + {error, Reason} -> emqx_ctl:print("Error: ~p~n", [Reason]) + end; + _ -> + emqx_ctl:print("Error: Input is illegal~n") + end; + +cli(["add", "_all", Topic, Action, Access]) -> + case validate(action, Action) andalso validate(access, Access) of + true -> + case add_acl(all, iolist_to_binary(Topic), list_to_existing_atom(Action), list_to_existing_atom(Access)) of + ok -> emqx_ctl:print("ok~n"); + {error, Reason} -> emqx_ctl:print("Error: ~p~n", [Reason]) + end; + _ -> + emqx_ctl:print("Error: Input is illegal~n") + end; + +cli(["show", "clientid", Clientid]) -> + [emqx_ctl:print("Acl(clientid = ~p topic = ~p action = ~p access = ~p)~n",[NClientid, Topic, Action, Access]) + || {{clientid, NClientid}, Topic, Action, Access, _} <- lookup_acl({clientid, iolist_to_binary(Clientid)}) ]; + +cli(["show", "username", Username]) -> + [emqx_ctl:print("Acl(username = ~p topic = ~p action = ~p access = ~p)~n",[NUsername, Topic, Action, Access]) + || {{username, NUsername}, Topic, Action, Access, _} <- lookup_acl({username, iolist_to_binary(Username)}) ]; + +cli(["del", "clientid", Clientid, Topic])-> + case remove_acl({clientid, iolist_to_binary(Clientid)}, iolist_to_binary(Topic)) of + ok -> emqx_ctl:print("ok~n"); + {error, Reason} -> emqx_ctl:print("Error: ~p~n", [Reason]) + end; + +cli(["del", "username", Username, Topic])-> + case remove_acl({username, iolist_to_binary(Username)}, iolist_to_binary(Topic)) of + ok -> emqx_ctl:print("ok~n"); + {error, Reason} -> emqx_ctl:print("Error: ~p~n", [Reason]) + end; + +cli(["del", "_all", Topic])-> + case remove_acl(all, iolist_to_binary(Topic)) of + ok -> emqx_ctl:print("ok~n"); + {error, Reason} -> emqx_ctl:print("Error: ~p~n", [Reason]) + end; + +cli(_) -> + emqx_ctl:usage([ {"acl list clientid","List clientid acls"} + , {"acl list username","List username acls"} + , {"acl list _all","List $all acls"} + , {"acl show clientid ", "Lookup clientid acl detail"} + , {"acl show username ", "Lookup username acl detail"} + , {"acl aad clientid ", "Add clientid acl"} + , {"acl add Username ", "Add username acl"} + , {"acl add _all ", "Add $all acl"} + , {"acl del clientid ", "Delete clientid acl"} + , {"acl del username ", "Delete username acl"} + , {"acl del _all, ", "Delete $all acl"} + ]). + + 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..49a330fd6 --- /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, "4.3.0"}, % strict semver, bump manually + {modules, []}, + {registered, []}, + {applications, [kernel,stdlib,mnesia,emqx]}, + {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..bb413b6d9 --- /dev/null +++ b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.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_auth_mnesia). + +-include("emqx_auth_mnesia.hrl"). + +-include_lib("emqx/include/emqx.hrl"). +-include_lib("emqx/include/logger.hrl"). +-include_lib("emqx/include/types.hrl"). + +-include_lib("stdlib/include/ms_transform.hrl"). + +-define(TABLE, emqx_user). +%% Auth callbacks +-export([ init/1 + , register_metrics/0 + , check/3 + , description/0 + ]). + +init(#{clientid_list := ClientidList, username_list := UsernameList}) -> + ok = ekka_mnesia:create_table(emqx_user, [ + {disc_copies, [node()]}, + {attributes, record_info(fields, emqx_user)}, + {storage_properties, [{ets, [{read_concurrency, true}]}]}]), + [ add_default_user({{clientid, iolist_to_binary(Clientid)}, iolist_to_binary(Password)}) + || {Clientid, Password} <- ClientidList], + [ add_default_user({{username, iolist_to_binary(Username)}, iolist_to_binary(Password)}) + || {Username, Password} <- UsernameList], + ok = ekka_mnesia:copy_table(emqx_user, disc_copies). + +%% @private +add_default_user({Login, Password}) when is_tuple(Login) -> + emqx_auth_mnesia_cli:add_user(Login, Password). + +-spec(register_metrics() -> ok). +register_metrics() -> + lists:foreach(fun emqx_metrics:ensure/1, ?AUTH_METRICS). + +check(ClientInfo = #{ clientid := Clientid + , password := NPassword + }, AuthResult, #{hash_type := HashType}) -> + Username = maps:get(username, ClientInfo, undefined), + MatchSpec = ets:fun2ms(fun({?TABLE, {clientid, X }, Password, InterTime}) when X =:= Clientid-> Password; + ({?TABLE, {username, X }, Password, InterTime}) when X =:= Username andalso X =/= undefined -> Password + end), + case ets:select(?TABLE, MatchSpec) of + [] -> + emqx_metrics:inc(?AUTH_METRICS(ignore)), + ok; + List -> + case [ Hash || <> <- lists:sort(fun emqx_auth_mnesia_cli:comparing/2, List), + Hash =:= hash(NPassword, Salt, HashType) + ] of + [] -> + ?LOG(error, "[Mnesia] Auth from mnesia failed: ~p", [ClientInfo]), + emqx_metrics:inc(?AUTH_METRICS(failure)), + {stop, AuthResult#{anonymous => false, auth_result => password_error}}; + _ -> + emqx_metrics:inc(?AUTH_METRICS(success)), + {stop, AuthResult#{anonymous => false, auth_result => success}} + end + end. + +description() -> "Authentication with Mnesia". + +hash(undefined, SaltBin, HashType) -> + hash(<<>>, SaltBin, HashType); +hash(Password, SaltBin, HashType) -> + emqx_passwd:hash(HashType, <>). 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..ee52fcf36 --- /dev/null +++ b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia_api.erl @@ -0,0 +1,319 @@ +%%-------------------------------------------------------------------- +%% 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"). +-include_lib("stdlib/include/ms_transform.hrl"). + +-define(TABLE, emqx_user). + +-import(proplists, [get_value/2]). +-import(minirest, [return/1]). +-export([paginate/5]). + +-export([ list_clientid/2 + , lookup_clientid/2 + , add_clientid/2 + , update_clientid/2 + , delete_clientid/2 + ]). + +-rest_api(#{name => list_clientid, + method => 'GET', + path => "/auth_clientid", + func => list_clientid, + descr => "List available clientid in the cluster" + }). + +-rest_api(#{name => lookup_clientid, + method => 'GET', + path => "/auth_clientid/:bin:clientid", + func => lookup_clientid, + descr => "Lookup clientid in the cluster" + }). + +-rest_api(#{name => add_clientid, + method => 'POST', + path => "/auth_clientid", + func => add_clientid, + descr => "Add clientid in the cluster" + }). + +-rest_api(#{name => update_clientid, + method => 'PUT', + path => "/auth_clientid/:bin:clientid", + func => update_clientid, + descr => "Update clientid in the cluster" + }). + +-rest_api(#{name => delete_clientid, + method => 'DELETE', + path => "/auth_clientid/:bin:clientid", + func => delete_clientid, + descr => "Delete clientid in the cluster" + }). + +-export([ list_username/2 + , lookup_username/2 + , add_username/2 + , update_username/2 + , delete_username/2 + ]). + +-rest_api(#{name => list_username, + method => 'GET', + path => "/auth_username", + func => list_username, + descr => "List available username in the cluster" + }). + +-rest_api(#{name => lookup_username, + method => 'GET', + path => "/auth_username/:bin:username", + func => lookup_username, + descr => "Lookup username in the cluster" + }). + +-rest_api(#{name => add_username, + method => 'POST', + path => "/auth_username", + func => add_username, + descr => "Add username in the cluster" + }). + +-rest_api(#{name => update_username, + method => 'PUT', + path => "/auth_username/:bin:username", + func => update_username, + descr => "Update username in the cluster" + }). + +-rest_api(#{name => delete_username, + method => 'DELETE', + path => "/auth_username/:bin:username", + func => delete_username, + descr => "Delete username in the cluster" + }). + +%%------------------------------------------------------------------------------ +%% Auth Clientid Api +%%------------------------------------------------------------------------------ + +list_clientid(_Bindings, Params) -> + MatchSpec = ets:fun2ms(fun({?TABLE, {clientid, Clientid}, Password, CreatedAt}) -> {?TABLE, {clientid, Clientid}, Password, CreatedAt} end), + return({ok, paginate(?TABLE, MatchSpec, Params, fun emqx_auth_mnesia_cli:comparing/2, fun({?TABLE, {clientid, X}, _, _}) -> #{clientid => X} end)}). + +lookup_clientid(#{clientid := Clientid}, _Params) -> + return({ok, format(emqx_auth_mnesia_cli:lookup_user({clientid, urldecode(Clientid)}))}). + +add_clientid(_Bindings, Params) -> + [ P | _] = Params, + case is_list(P) of + true -> return(do_add_clientid(Params, [])); + false -> + Re = do_add_clientid(Params), + case Re of + ok -> return(ok); + <<"ok">> -> return(ok); + _ -> return({error, format_msg(Re)}) + end + end. + +do_add_clientid([ Params | ParamsN ], ReList ) -> + Clientid = urldecode(get_value(<<"clientid">>, Params)), + do_add_clientid(ParamsN, [{Clientid, format_msg(do_add_clientid(Params))} | ReList]); + +do_add_clientid([], ReList) -> + {ok, ReList}. + +do_add_clientid(Params) -> + Clientid = urldecode(get_value(<<"clientid">>, Params)), + Password = urldecode(get_value(<<"password">>, Params)), + Login = {clientid, Clientid}, + case validate([login, password], [Login, Password]) of + ok -> + emqx_auth_mnesia_cli:add_user(Login, Password); + Err -> Err + end. + +update_clientid(#{clientid := Clientid}, Params) -> + Password = get_value(<<"password">>, Params), + case validate([password], [Password]) of + ok -> return(emqx_auth_mnesia_cli:update_user({clientid, urldecode(Clientid)}, urldecode(Password))); + Err -> return(Err) + end. + +delete_clientid(#{clientid := Clientid}, _) -> + return(emqx_auth_mnesia_cli:remove_user({clientid, urldecode(Clientid)})). + +%%------------------------------------------------------------------------------ +%% Auth Username Api +%%------------------------------------------------------------------------------ + +list_username(_Bindings, Params) -> + MatchSpec = ets:fun2ms(fun({?TABLE, {username, Username}, Password, CreatedAt}) -> {?TABLE, {username, Username}, Password, CreatedAt} end), + return({ok, paginate(?TABLE, MatchSpec, Params, fun emqx_auth_mnesia_cli:comparing/2, fun({?TABLE, {username, X}, _, _}) -> #{username => X} end)}). + +lookup_username(#{username := Username}, _Params) -> + return({ok, format(emqx_auth_mnesia_cli:lookup_user({username, urldecode(Username)}))}). + +add_username(_Bindings, Params) -> + [ P | _] = Params, + case is_list(P) of + true -> return(do_add_username(Params, [])); + false -> + case do_add_username(Params) of + ok -> return(ok); + <<"ok">> -> return(ok); + Error -> return({error, format_msg(Error)}) + end + end. + +do_add_username([ Params | ParamsN ], ReList ) -> + Username = urldecode(get_value(<<"username">>, Params)), + do_add_username(ParamsN, [{Username, format_msg(do_add_username(Params))} | ReList]); + +do_add_username([], ReList) -> + {ok, ReList}. + +do_add_username(Params) -> + Username = urldecode(get_value(<<"username">>, Params)), + Password = urldecode(get_value(<<"password">>, Params)), + Login = {username, Username}, + case validate([login, password], [Login, Password]) of + ok -> + emqx_auth_mnesia_cli:add_user(Login, Password); + Err -> Err + end. + +update_username(#{username := Username}, Params) -> + Password = get_value(<<"password">>, Params), + case validate([password], [Password]) of + ok -> return(emqx_auth_mnesia_cli:update_user({username, urldecode(Username)}, urldecode(Password))); + Err -> return(Err) + end. + +delete_username(#{username := Username}, _) -> + return(emqx_auth_mnesia_cli:remove_user({username, urldecode(Username)})). + +%%------------------------------------------------------------------------------ +%% Paging Query +%%------------------------------------------------------------------------------ + +paginate(Tables, MatchSpec, Params, ComparingFun, RowFun) -> + Qh = query_handle(Tables, MatchSpec), + Count = count(Tables, MatchSpec), + 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 <- lists:sort(ComparingFun, Rows)]}. + +query_handle(Table, MatchSpec) when is_atom(Table) -> + Options = {traverse, {select, MatchSpec}}, + qlc:q([R|| R <- ets:table(Table, Options)]); +query_handle([Table], MatchSpec) when is_atom(Table) -> + Options = {traverse, {select, MatchSpec}}, + qlc:q([R|| R <- ets:table(Table, Options)]); +query_handle(Tables, MatchSpec) -> + Options = {traverse, {select, MatchSpec}}, + qlc:append([qlc:q([E || E <- ets:table(T, Options)]) || T <- Tables]). + +count(Table, MatchSpec) when is_atom(Table) -> + [{MatchPattern, Where, _Re}] = MatchSpec, + NMatchSpec = [{MatchPattern, Where, [true]}], + ets:select_count(Table, NMatchSpec); +count([Table], MatchSpec) when is_atom(Table) -> + [{MatchPattern, Where, _Re}] = MatchSpec, + NMatchSpec = [{MatchPattern, Where, [true]}], + ets:select_count(Table, NMatchSpec); +count(Tables, MatchSpec) -> + lists:sum([count(T, MatchSpec) || 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({?TABLE, {clientid, ClientId}, Password, _InterTime}) -> + #{clientid => ClientId, + password => Password}; + +format({?TABLE, {username, Username}, Password, _InterTime}) -> + #{username => Username, + password => Password}; + +format([{?TABLE, {clientid, ClientId}, Password, _InterTime}]) -> + #{clientid => ClientId, + password => Password}; + +format([{?TABLE, {username, Username}, Password, _InterTime}]) -> + #{username => Username, + password => Password}; + +format([]) -> + #{}. + +validate([], []) -> + ok; +validate([K|Keys], [V|Values]) -> + case do_validation(K, V) of + false -> {error, K}; + true -> validate(Keys, Values) + end. + +do_validation(login, {clientid, V}) when is_binary(V) + andalso byte_size(V) > 0 -> + true; +do_validation(login, {username, 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(_, _) -> + 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..cfc9df995 --- /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(clientid, {emqx_auth_mnesia_cli, auth_clientid_cli}, []), + emqx_ctl:register_command(username, {emqx_auth_mnesia_cli, auth_username_cli}, []), + emqx_ctl:register_command(user, {emqx_auth_mnesia_cli, auth_username_cli}, []), + emqx_ctl:register_command(acl, {emqx_acl_mnesia_cli, 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(clientid), + emqx_ctl:unregister_command(username), + emqx_ctl:unregister_command(user), + emqx_ctl:unregister_command(acl), + State. + +stop(_State) -> + ok. + +load_auth_hook() -> + ClientidList = application:get_env(?APP, clientid_list, []), + UsernameList = application:get_env(?APP, username_list, []), + ok = emqx_auth_mnesia:init(#{clientid_list => ClientidList, username_list => UsernameList}), + ok = emqx_auth_mnesia:register_metrics(), + Params = #{ + hash_type => application:get_env(emqx_auth_mnesia, hash_type, sha256) + }, + 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(), + emqx:hook('client.check_acl', fun emqx_acl_mnesia:check_acl/5, [#{}]). 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..b937eb238 --- /dev/null +++ b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia_cli.erl @@ -0,0 +1,181 @@ +%%-------------------------------------------------------------------- +%% 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/include/logger.hrl"). +-include_lib("stdlib/include/ms_transform.hrl"). +-define(TABLE, emqx_user). +%% Auth APIs +-export([ add_user/2 + , update_user/2 + , remove_user/1 + , lookup_user/1 + , all_users/0 + , all_users/1 + ]). +%% Cli +-export([ auth_clientid_cli/1 + , auth_username_cli/1 + ]). + +%% Helper +-export([comparing/2]). + +%%-------------------------------------------------------------------- +%% Auth APIs +%%-------------------------------------------------------------------- + +%% @doc Add User +-spec(add_user(tuple(), binary()) -> ok | {error, any()}). +add_user(Login, Password) -> + User = #emqx_user{login = Login, password = encrypted_data(Password), created_at = erlang:system_time(millisecond)}, + 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(tuple(), binary()) -> ok | {error, any()}). +update_user(Login, NewPassword) -> + User = #emqx_user{login = Login, password = encrypted_data(NewPassword)}, + ret(mnesia:transaction(fun do_update_user/1, [User])). + +do_update_user(User = #emqx_user{login = Login}) -> + case mnesia:read(?TABLE, Login) of + [{?TABLE, Login, _, CreateAt}] -> mnesia:write(User#emqx_user{created_at = CreateAt}); + [] -> mnesia:abort(noexisted) + end. + +%% @doc Lookup user by login +-spec(lookup_user(tuple()) -> 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 -> + lists:sort(fun comparing/2, Re) + end. + +%% @doc Remove user +-spec(remove_user(tuple()) -> 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). + +all_users(clientid) -> + MatchSpec = ets:fun2ms(fun({?TABLE, {clientid, Clientid}, Password, CreatedAt}) -> {?TABLE, {clientid, Clientid}, Password, CreatedAt} end), + lists:sort(fun comparing/2, ets:select(?TABLE, MatchSpec)); + +all_users(username) -> + MatchSpec = ets:fun2ms(fun({?TABLE, {username, Username}, Password, CreatedAt}) -> {?TABLE, {username, Username}, Password, CreatedAt} end), + lists:sort(fun comparing/2, ets:select(?TABLE, MatchSpec)). + +%%-------------------------------------------------------------------- +%% Internal functions +%%-------------------------------------------------------------------- + +comparing({?TABLE, _, _, CreatedAt1}, + {?TABLE, _, _, CreatedAt2}) -> + CreatedAt1 >= CreatedAt2. + +ret({atomic, ok}) -> ok; +ret({aborted, Error}) -> {error, Error}. + +encrypted_data(Password) -> + HashType = application:get_env(emqx_auth_mnesia, 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), <>. + +%%-------------------------------------------------------------------- +%% Auth Clientid Cli +%%-------------------------------------------------------------------- + +auth_clientid_cli(["list"]) -> + [emqx_ctl:print("~s~n", [ClientId]) || {?TABLE, {clientid, ClientId}, _Password, _CreatedAt} <- all_users(clientid)]; + +auth_clientid_cli(["add", ClientId, Password]) -> + case add_user({clientid, iolist_to_binary(ClientId)}, iolist_to_binary(Password)) of + ok -> emqx_ctl:print("ok~n"); + {error, Reason} -> emqx_ctl:print("Error: ~p~n", [Reason]) + end; + +auth_clientid_cli(["update", ClientId, NewPassword]) -> + case update_user({clientid, iolist_to_binary(ClientId)}, iolist_to_binary(NewPassword)) of + ok -> emqx_ctl:print("ok~n"); + {error, Reason} -> emqx_ctl:print("Error: ~p~n", [Reason]) + end; + +auth_clientid_cli(["del", ClientId]) -> + case remove_user({clientid, iolist_to_binary(ClientId)}) of + ok -> emqx_ctl:print("ok~n"); + {error, Reason} -> emqx_ctl:print("Error: ~p~n", [Reason]) + end; + +auth_clientid_cli(_) -> + emqx_ctl:usage([{"clientid list", "List clientid auth rules"}, + {"clientid add ", "Add clientid auth rule"}, + {"clientid update ", "Update clientid auth rule"}, + {"clientid del ", "Delete clientid auth rule"}]). + +%%-------------------------------------------------------------------- +%% Auth Username Cli +%%-------------------------------------------------------------------- + +auth_username_cli(["list"]) -> + [emqx_ctl:print("~s~n", [Username]) || {?TABLE, {username, Username}, _Password, _CreatedAt}<- all_users(username)]; + +auth_username_cli(["add", Username, Password]) -> + case add_user({username, iolist_to_binary(Username)}, iolist_to_binary(Password)) of + ok -> emqx_ctl:print("ok~n"); + {error, Reason} -> emqx_ctl:print("Error: ~p~n", [Reason]) + end; + +auth_username_cli(["update", Username, NewPassword]) -> + case update_user({username, iolist_to_binary(Username)}, iolist_to_binary(NewPassword)) of + ok -> emqx_ctl:print("ok~n"); + {error, Reason} -> emqx_ctl:print("Error: ~p~n", [Reason]) + end; + +auth_username_cli(["del", Username]) -> + case remove_user({username, iolist_to_binary(Username)}) of + ok -> emqx_ctl:print("ok~n"); + {error, Reason} -> emqx_ctl:print("Error: ~p~n", [Reason]) + end; + +auth_username_cli(_) -> + emqx_ctl:usage([{"users list", "List username auth rules"}, + {"users add ", "Add username auth rule"}, + {"users update ", "Update username auth rule"}, + {"users del ", "Delete username auth rule"}]). 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..61356dd24 --- /dev/null +++ b/apps/emqx_auth_mnesia/test/emqx_acl_mnesia_SUITE.erl @@ -0,0 +1,215 @@ +%%-------------------------------------------------------------------- +%% 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_acl_mnesia_cli:all_acls()), + + ok = emqx_acl_mnesia_cli:add_acl({clientid, <<"test_clientid">>}, <<"topic/%c">>, sub, allow), + ok = emqx_acl_mnesia_cli:add_acl({clientid, <<"test_clientid">>}, <<"topic/+">>, pub, deny), + ok = emqx_acl_mnesia_cli:add_acl({username, <<"test_username">>}, <<"topic/%u">>, sub, deny), + ok = emqx_acl_mnesia_cli:add_acl({username, <<"test_username">>}, <<"topic/+">>, pub, allow), + ok = emqx_acl_mnesia_cli:add_acl(all, <<"#">>, pubsub, deny), + + ?assertEqual(2, length(emqx_acl_mnesia_cli:lookup_acl({clientid, <<"test_clientid">>}))), + ?assertEqual(2, length(emqx_acl_mnesia_cli:lookup_acl({username, <<"test_username">>}))), + ?assertEqual(1, length(emqx_acl_mnesia_cli:lookup_acl(all))), + ?assertEqual(5, length(emqx_acl_mnesia_cli:all_acls())), + + User1 = #{zone => external, clientid => <<"test_clientid">>}, + User2 = #{zone => external, clientid => <<"no_exist">>, username => <<"test_username">>}, + User3 = #{zone => external, clientid => <<"test_clientid">>, username => <<"test_username">>}, + allow = emqx_access_control:check_acl(User1, subscribe, <<"topic/test_clientid">>), + deny = emqx_access_control:check_acl(User1, publish, <<"topic/A">>), + deny = emqx_access_control:check_acl(User2, subscribe, <<"topic/test_username">>), + allow = emqx_access_control:check_acl(User2, publish, <<"topic/A">>), + allow = emqx_access_control:check_acl(User3, subscribe, <<"topic/test_clientid">>), + deny = emqx_access_control:check_acl(User3, subscribe, <<"topic/test_username">>), + deny = emqx_access_control:check_acl(User3, publish, <<"topic/A">>), + deny = emqx_access_control:check_acl(User3, subscribe, <<"topic/A/B">>), + deny = emqx_access_control:check_acl(User3, publish, <<"topic/A/B">>), + + ok = emqx_acl_mnesia_cli:remove_acl({clientid, <<"test_clientid">>}, <<"topic/%c">>), + ok = emqx_acl_mnesia_cli:remove_acl({clientid, <<"test_clientid">>}, <<"topic/+">>), + ok = emqx_acl_mnesia_cli:remove_acl({username, <<"test_username">>}, <<"topic/%u">>), + ok = emqx_acl_mnesia_cli:remove_acl({username, <<"test_username">>}, <<"topic/+">>), + ok = emqx_acl_mnesia_cli:remove_acl(all, <<"#">>), + + ?assertEqual([], emqx_acl_mnesia_cli:all_acls()). + +t_acl_cli(_Config) -> + 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(), + + ?assertEqual(0, length(emqx_acl_mnesia_cli:cli(["list"]))), + + emqx_acl_mnesia_cli:cli(["add", "clientid", "test_clientid", "topic/A", "pub", "allow"]), + ?assertMatch(["Acl(clientid = <<\"test_clientid\">> topic = <<\"topic/A\">> action = pub access = allow)\n"], emqx_acl_mnesia_cli:cli(["show", "clientid", "test_clientid"])), + ?assertMatch(["Acl(clientid = <<\"test_clientid\">> topic = <<\"topic/A\">> action = pub access = allow)\n"], emqx_acl_mnesia_cli:cli(["list", "clientid"])), + + emqx_acl_mnesia_cli:cli(["add", "username", "test_username", "topic/B", "sub", "deny"]), + ?assertMatch(["Acl(username = <<\"test_username\">> topic = <<\"topic/B\">> action = sub access = deny)\n"], emqx_acl_mnesia_cli:cli(["show", "username", "test_username"])), + ?assertMatch(["Acl(username = <<\"test_username\">> topic = <<\"topic/B\">> action = sub access = deny)\n"], emqx_acl_mnesia_cli:cli(["list", "username"])), + + emqx_acl_mnesia_cli:cli(["add", "_all", "#", "pubsub", "deny"]), + ?assertMatch(["Acl($all topic = <<\"#\">> action = pubsub access = deny)\n"], emqx_acl_mnesia_cli:cli(["list", "_all"])), + ?assertEqual(3, length(emqx_acl_mnesia_cli:cli(["list"]))), + + emqx_acl_mnesia_cli:cli(["del", "clientid", "test_clientid", "topic/A"]), + emqx_acl_mnesia_cli:cli(["del", "username", "test_username", "topic/B"]), + emqx_acl_mnesia_cli:cli(["del", "_all", "#"]), + ?assertEqual(0, length(emqx_acl_mnesia_cli:cli(["list"]))), + + meck:unload(emqx_ctl). + +t_rest_api(_Config) -> + clean_all_acls(), + + Params1 = [#{<<"clientid">> => <<"test_clientid">>, <<"topic">> => <<"topic/A">>, <<"action">> => <<"pub">>, <<"access">> => <<"allow">>}, + #{<<"clientid">> => <<"test_clientid">>, <<"topic">> => <<"topic/B">>, <<"action">> => <<"sub">>, <<"access">> => <<"allow">>}, + #{<<"clientid">> => <<"test_clientid">>, <<"topic">> => <<"topic/C">>, <<"action">> => <<"pubsub">>, <<"access">> => <<"deny">>}], + {ok, _} = request_http_rest_add([], Params1), + {ok, Re1} = request_http_rest_list(["clientid", "test_clientid"]), + ?assertMatch(3, length(get_http_data(Re1))), + {ok, _} = request_http_rest_delete(["clientid", "test_clientid", "topic", "topic/A"]), + {ok, _} = request_http_rest_delete(["clientid", "test_clientid", "topic", "topic/B"]), + {ok, _} = request_http_rest_delete(["clientid", "test_clientid", "topic", "topic/C"]), + {ok, Res1} = request_http_rest_list(["clientid"]), + ?assertMatch([], get_http_data(Res1)), + + Params2 = [#{<<"username">> => <<"test_username">>, <<"topic">> => <<"topic/A">>, <<"action">> => <<"pub">>, <<"access">> => <<"allow">>}, + #{<<"username">> => <<"test_username">>, <<"topic">> => <<"topic/B">>, <<"action">> => <<"sub">>, <<"access">> => <<"allow">>}, + #{<<"username">> => <<"test_username">>, <<"topic">> => <<"topic/C">>, <<"action">> => <<"pubsub">>, <<"access">> => <<"deny">>}], + {ok, _} = request_http_rest_add([], Params2), + {ok, Re2} = request_http_rest_list(["username", "test_username"]), + ?assertMatch(3, length(get_http_data(Re2))), + {ok, _} = request_http_rest_delete(["username", "test_username", "topic", "topic/A"]), + {ok, _} = request_http_rest_delete(["username", "test_username", "topic", "topic/B"]), + {ok, _} = request_http_rest_delete(["username", "test_username", "topic", "topic/C"]), + {ok, Res2} = request_http_rest_list(["username"]), + ?assertMatch([], get_http_data(Res2)), + + Params3 = [#{<<"topic">> => <<"topic/A">>, <<"action">> => <<"pub">>, <<"access">> => <<"allow">>}, + #{<<"topic">> => <<"topic/B">>, <<"action">> => <<"sub">>, <<"access">> => <<"allow">>}, + #{<<"topic">> => <<"topic/C">>, <<"action">> => <<"pubsub">>, <<"access">> => <<"deny">>}], + {ok, _} = request_http_rest_add([], Params3), + {ok, Re3} = request_http_rest_list(["$all"]), + ?assertMatch(3, length(get_http_data(Re3))), + {ok, _} = request_http_rest_delete(["$all", "topic", "topic/A"]), + {ok, _} = request_http_rest_delete(["$all", "topic", "topic/B"]), + {ok, _} = request_http_rest_delete(["$all", "topic", "topic/C"]), + {ok, Res3} = request_http_rest_list(["$all"]), + ?assertMatch([], get_http_data(Res3)). + +%%------------------------------------------------------------------------------ +%% Helpers +%%------------------------------------------------------------------------------ + +clean_all_acls() -> + [ mnesia:dirty_delete({emqx_acl, Login}) + || Login <- mnesia:dirty_all_keys(emqx_acl)]. + +%%-------------------------------------------------------------------- +%% HTTP Request +%%-------------------------------------------------------------------- + +request_http_rest_list(Path) -> + request_api(get, uri(Path), default_auth_header()). + +request_http_rest_lookup(Path) -> + request_api(get, uri(Path), default_auth_header()). + +request_http_rest_add(Path, Params) -> + request_api(post, uri(Path), [], default_auth_header(), Params). + +request_http_rest_delete(Path) -> + request_api(delete, uri(Path), default_auth_header()). + +uri() -> uri([]). +uri(Parts) when is_list(Parts) -> + NParts = [b2l(E) || E <- Parts], + ?HOST ++ filename:join([?BASE_PATH, ?API_VERSION, "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..0f4884247 --- /dev/null +++ b/apps/emqx_auth_mnesia/test/emqx_auth_mnesia_SUITE.erl @@ -0,0 +1,284 @@ +%%-------------------------------------------------------------------- +%% 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"). + +-define(TABLE, emqx_user). +-define(CLIENTID, <<"clientid_for_ct">>). +-define(USERNAME, <<"username_for_ct">>). +-define(PASSWORD, <<"password">>). +-define(NPASSWORD, <<"new_password">>). + +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_management(_Config) -> + clean_all_users(), + + ok = emqx_auth_mnesia_cli:add_user({username,?USERNAME}, ?PASSWORD), + {error, existed} = emqx_auth_mnesia_cli:add_user({username,?USERNAME}, ?PASSWORD), + ?assertMatch([{?TABLE, {username, ?USERNAME}, _Password, _InterTime}], emqx_auth_mnesia_cli:all_users(username)), + + ok = emqx_auth_mnesia_cli:add_user({clientid,?CLIENTID}, ?PASSWORD), + {error, existed} = emqx_auth_mnesia_cli:add_user({clientid,?CLIENTID}, ?PASSWORD), + ?assertMatch([{?TABLE, {clientid, ?CLIENTID}, _Password, _InterTime}], emqx_auth_mnesia_cli:all_users(clientid)), + + ?assertEqual(2,length(emqx_auth_mnesia_cli:all_users())), + + ok = emqx_auth_mnesia_cli:update_user({username,?USERNAME}, ?NPASSWORD), + {error,noexisted} = emqx_auth_mnesia_cli:update_user({username, <<"no_existed_user">>}, ?PASSWORD), + + ok = emqx_auth_mnesia_cli:update_user({clientid,?CLIENTID}, ?NPASSWORD), + {error,noexisted} = emqx_auth_mnesia_cli:update_user({clientid, <<"no_existed_user">>}, ?PASSWORD), + + + ?assertMatch([{?TABLE, {username, ?USERNAME}, _Password, _InterTime}], emqx_auth_mnesia_cli:lookup_user({username, ?USERNAME})), + ?assertMatch([{?TABLE, {clientid, ?CLIENTID}, _Password, _InterTime}], emqx_auth_mnesia_cli:lookup_user({clientid, ?CLIENTID})), + + User1 = #{username => ?USERNAME, + clientid => undefined, + password => ?NPASSWORD, + zone => external}, + + {ok, #{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({username,?USERNAME}), + {ok, #{auth_result := success, + anonymous := true }} = emqx_access_control:authenticate(User1), + + User2 = #{clientid => ?CLIENTID, + password => ?NPASSWORD, + zone => external}, + + {ok, #{auth_result := success, + anonymous := false}} = emqx_access_control:authenticate(User2), + + {error,password_error} = emqx_access_control:authenticate(User2#{password => <<"error_password">>}), + + ok = emqx_auth_mnesia_cli:remove_user({clientid,?CLIENTID}), + {ok, #{auth_result := success, + anonymous := true }} = emqx_access_control:authenticate(User2), + + [] = emqx_auth_mnesia_cli:all_users(). + +t_auth_clientid_cli(_) -> + clean_all_users(), + + HashType = application:get_env(emqx_auth_mnesia, password_hash, sha256), + + emqx_auth_mnesia_cli:auth_clientid_cli(["add", ?CLIENTID, ?PASSWORD]), + [{_, {clientid, ?CLIENTID}, <>, _}] = emqx_auth_mnesia_cli:lookup_user({clientid, ?CLIENTID}), + ?assertEqual(Hash, emqx_passwd:hash(HashType, <>)), + + emqx_auth_mnesia_cli:auth_clientid_cli(["update", ?CLIENTID, ?NPASSWORD]), + [{_, {clientid, ?CLIENTID}, <>, _}] = emqx_auth_mnesia_cli:lookup_user({clientid, ?CLIENTID}), + ?assertEqual(Hash1, emqx_passwd:hash(HashType, <>)), + + emqx_auth_mnesia_cli:auth_clientid_cli(["del", ?CLIENTID]), + ?assertEqual([], emqx_auth_mnesia_cli:lookup_user(?CLIENTID)), + + emqx_auth_mnesia_cli:auth_clientid_cli(["add", "user1", "pass1"]), + emqx_auth_mnesia_cli:auth_clientid_cli(["add", "user2", "pass2"]), + ?assertEqual(2, length(emqx_auth_mnesia_cli:auth_clientid_cli(["list"]))), + + emqx_auth_mnesia_cli:auth_clientid_cli(usage). + +t_auth_username_cli(_) -> + clean_all_users(), + + HashType = application:get_env(emqx_auth_mnesia, password_hash, sha256), + + emqx_auth_mnesia_cli:auth_username_cli(["add", ?USERNAME, ?PASSWORD]), + [{_, {username, ?USERNAME}, <>, _}] = emqx_auth_mnesia_cli:lookup_user({username, ?USERNAME}), + ?assertEqual(Hash, emqx_passwd:hash(HashType, <>)), + + emqx_auth_mnesia_cli:auth_username_cli(["update", ?USERNAME, ?NPASSWORD]), + [{_, {username, ?USERNAME}, <>, _}] = emqx_auth_mnesia_cli:lookup_user({username, ?USERNAME}), + ?assertEqual(Hash1, emqx_passwd:hash(HashType, <>)), + + emqx_auth_mnesia_cli:auth_username_cli(["del", ?USERNAME]), + ?assertEqual([], emqx_auth_mnesia_cli:lookup_user(?USERNAME)), + + emqx_auth_mnesia_cli:auth_username_cli(["add", "user1", "pass1"]), + emqx_auth_mnesia_cli:auth_username_cli(["add", "user2", "pass2"]), + ?assertEqual(2, length(emqx_auth_mnesia_cli:auth_username_cli(["list"]))), + + emqx_auth_mnesia_cli:auth_username_cli(usage). + + +t_clientid_rest_api(_Config) -> + clean_all_users(), + + {ok, Result1} = request_http_rest_list(["auth_clientid"]), + [] = get_http_data(Result1), + + Params1 = #{<<"clientid">> => ?CLIENTID, <<"password">> => ?PASSWORD}, + {ok, _} = request_http_rest_add(["auth_clientid"], Params1), + + Params2 = #{<<"clientid">> => ?CLIENTID, <<"password">> => ?NPASSWORD}, + {ok, _} = request_http_rest_update(["auth_clientid/" ++ binary_to_list(?CLIENTID)], Params2), + + {ok, Result2} = request_http_rest_lookup(["auth_clientid/" ++ binary_to_list(?CLIENTID)]), + ?assertMatch(#{<<"clientid">> := ?CLIENTID}, get_http_data(Result2)), + + Params3 = [ #{<<"clientid">> => ?CLIENTID, <<"password">> => ?PASSWORD} + , #{<<"clientid">> => <<"clientid1">>, <<"password">> => ?PASSWORD} + , #{<<"clientid">> => <<"clientid2">>, <<"password">> => ?PASSWORD} + ], + {ok, Result3} = request_http_rest_add(["auth_clientid"], Params3), + ?assertMatch(#{ ?CLIENTID := <<"{error,existed}">> + , <<"clientid1">> := <<"ok">> + , <<"clientid2">> := <<"ok">> + }, get_http_data(Result3)), + + {ok, Result4} = request_http_rest_list(["auth_clientid"]), + ?assertEqual(3, length(get_http_data(Result4))), + + {ok, _} = request_http_rest_delete(["auth_clientid/" ++ binary_to_list(?CLIENTID)]), + {ok, Result5} = request_http_rest_lookup(["auth_clientid/" ++ binary_to_list(?CLIENTID)]), + ?assertMatch(#{}, get_http_data(Result5)). + +t_username_rest_api(_Config) -> + clean_all_users(), + + {ok, Result1} = request_http_rest_list(["auth_username"]), + [] = get_http_data(Result1), + + Params1 = #{<<"username">> => ?USERNAME, <<"password">> => ?PASSWORD}, + {ok, _} = request_http_rest_add(["auth_username"], Params1), + + Params2 = #{<<"username">> => ?USERNAME, <<"password">> => ?NPASSWORD}, + {ok, _} = request_http_rest_update(["auth_username/" ++ binary_to_list(?USERNAME)], Params2), + + {ok, Result2} = request_http_rest_lookup(["auth_username/" ++ binary_to_list(?USERNAME)]), + ?assertMatch(#{<<"username">> := ?USERNAME}, get_http_data(Result2)), + + Params3 = [ #{<<"username">> => ?USERNAME, <<"password">> => ?PASSWORD} + , #{<<"username">> => <<"username1">>, <<"password">> => ?PASSWORD} + , #{<<"username">> => <<"username2">>, <<"password">> => ?PASSWORD} + ], + {ok, Result3} = request_http_rest_add(["auth_username"], Params3), + ?assertMatch(#{ ?USERNAME := <<"{error,existed}">> + , <<"username1">> := <<"ok">> + , <<"username2">> := <<"ok">> + }, get_http_data(Result3)), + + {ok, Result4} = request_http_rest_list(["auth_username"]), + ?assertEqual(3, length(get_http_data(Result4))), + + {ok, _} = request_http_rest_delete(["auth_username/" ++ binary_to_list(?USERNAME)]), + {ok, Result5} = request_http_rest_lookup(["auth_username/" ++ binary_to_list(?USERNAME)]), + ?assertMatch(#{}, get_http_data(Result5)). + +%%------------------------------------------------------------------------------ +%% Helpers +%%------------------------------------------------------------------------------ + +clean_all_users() -> + [ mnesia:dirty_delete({emqx_user, Login}) + || Login <- mnesia:dirty_all_keys(emqx_user)]. + +%%-------------------------------------------------------------------- +%% HTTP Request +%%-------------------------------------------------------------------- + +request_http_rest_list(Path) -> + request_api(get, uri(Path), default_auth_header()). + +request_http_rest_lookup(Path) -> + request_api(get, uri([Path]), default_auth_header()). + +request_http_rest_add(Path, Params) -> + request_api(post, uri(Path), [], default_auth_header(), Params). + +request_http_rest_update(Path, Params) -> + request_api(put, uri([Path]), [], 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 | 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/.gitignore b/apps/emqx_auth_mongo/.gitignore new file mode 100644 index 000000000..a6635ffa0 --- /dev/null +++ b/apps/emqx_auth_mongo/.gitignore @@ -0,0 +1,24 @@ +.eunit +deps +*.o +*.beam +*.plt +erl_crash.dump +ebin +rel/example_project +.concrete/DEV_MODE +.rebar +.DS_Store +.erlang.mk/ +emqx_auth_mongo.d +ct.coverdata +logs/ +test/ct.cover.spec +data/ +cover/ +eunit.coverdata +_build/ +rebar.lock +erlang.mk +etc/emqx_auth_mongo.conf.rendered +.rebar3 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/etc/emqx_auth_mongo.conf b/apps/emqx_auth_mongo/etc/emqx_auth_mongo.conf new file mode 100644 index 000000000..cf1614efa --- /dev/null +++ b/apps/emqx_auth_mongo/etc/emqx_auth_mongo.conf @@ -0,0 +1,172 @@ +##-------------------------------------------------------------------- +## MongoDB Auth/ACL Plugin +##-------------------------------------------------------------------- + +## MongoDB Topology Type. +## +## Value: single | unknown | sharded | rs +auth.mongo.type = single + +## 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 query timeout +## +## Value: Duration +## auth.mongo.query_timeout = 5s + +## Whether to enable SSL connection. +## +## Value: true | false +## auth.mongo.ssl = false + +## SSL keyfile. +## +## Value: File +## auth.mongo.ssl_opts.keyfile = + +## SSL certfile. +## +## Value: File +## auth.mongo.ssl_opts.certfile = + +## SSL cacertfile. +## +## Value: File +## auth.mongo.ssl_opts.cacertfile = + +## 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 + +## ------------------------------------------------- +## Auth Query +## ------------------------------------------------- +## 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 + +## Authentication query. +auth.mongo.auth_query.collection = mqtt_user + +## Password mainly fields +## +## Value: password | password,salt +auth.mongo.auth_query.password_field = password + +## Authentication Selector. +## +## Variables: +## - %u: username +## - %c: clientid +## - %C: common name of client TLS cert +## - %d: subject of client TLS cert +## +## auth.mongo.auth_query.selector = {Field}={Placeholder} +auth.mongo.auth_query.selector = username=%u + +## ------------------------------------------------- +## Super User Query +## ------------------------------------------------- +auth.mongo.super_query.collection = mqtt_user +auth.mongo.super_query.super_field = is_superuser +#auth.mongo.super_query.selector = username=%u, clientid=%c +auth.mongo.super_query.selector = username=%u + +## ACL Selector. +## +## Multiple selectors could be combined with '$or' +## when query acl from mongo. +## +## e.g. +## +## With following 2 selectors configured: +## +## auth.mongo.acl_query.selector.1 = username=%u +## auth.mongo.acl_query.selector.2 = username=$all +## +## And if a client connected using username 'ilyas', +## then the following mongo command will be used to +## retrieve acl entries: +## +## db.mqtt_acl.find({$or: [{username: "ilyas"}, {username: "$all"}]}); +## +## Variables: +## - %u: username +## - %c: clientid +## +## Examples: +## +## auth.mongo.acl_query.selector.1 = username=%u,clientid=%c +## auth.mongo.acl_query.selector.2 = username=$all +## auth.mongo.acl_query.selector.3 = clientid=$all +auth.mongo.acl_query.collection = mqtt_acl +auth.mongo.acl_query.selector = username=%u 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..834bff904 --- /dev/null +++ b/apps/emqx_auth_mongo/rebar.config @@ -0,0 +1,24 @@ +{deps, + [{mongodb, {git,"https://github.com/emqx/mongodb-erlang", {tag, "v3.0.7"}}} + ]}. + +{edoc_opts, [{preprocess, true}]}. +{erl_opts, [warn_unused_vars, + warn_shadow_vars, + warn_unused_import, + warn_obsolete_guard, + debug_info, + compressed, + {parse_transform} + ]}. +{overrides, [{add, [{erl_opts, [compressed]}]}]}. + +{xref_checks, [undefined_function_calls, undefined_functions, + locals_not_used, deprecated_function_calls, + warnings_as_errors, deprecated_functions + ]}. + +{cover_enabled, true}. +{cover_opts, [verbose]}. +{cover_export_enabled, true}. + 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..c0ff5f8ac --- /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/include/emqx.hrl"). +-include_lib("emqx/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..4dd78cfdf --- /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, "4.3.0"}, % strict semver, bump manually! + {modules, []}, + {registered, [emqx_auth_mongo_sup]}, + {applications, [kernel,stdlib,mongodb,ecpool,emqx]}, + {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..4880e6fb9 --- /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/include/emqx.hrl"). +-include_lib("emqx/include/logger.hrl"). +-include_lib("emqx/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..4e76026ec --- /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/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/.gitignore b/apps/emqx_auth_mysql/.gitignore new file mode 100644 index 000000000..bc6fa0f2f --- /dev/null +++ b/apps/emqx_auth_mysql/.gitignore @@ -0,0 +1,31 @@ +.eunit +deps +*.so +.iml +.idea +*.o +*.beam +*.plt +erl_crash.dump +ebin +rel/example_project +.concrete/DEV_MODE +.rebar +.erlang.mk/ +emqx_auth_mysql.d +ct.coverdata +logs/ +test/ct.cover.spec +test/*.beam +cover/ +eunit.coverdata +data +.placeholder +_build/ +rebar.lock +erlang.mk +rebar3.crashdump +etc/emqx_auth_mysql.conf.rendered +.rebar3/ +*.swp +.DS_Store 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/etc/emqx_auth_mysql.conf b/apps/emqx_auth_mysql/etc/emqx_auth_mysql.conf new file mode 100644 index 000000000..0efccce29 --- /dev/null +++ b/apps/emqx_auth_mysql/etc/emqx_auth_mysql.conf @@ -0,0 +1,116 @@ +##-------------------------------------------------------------------- +## MySQL Auth/ACL Plugin +##-------------------------------------------------------------------- + +## 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 + +## MySQL query timeout +## +## Value: Duration +## auth.mysql.query_timeout = 5s + +## 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' + +## Mysql ssl configuration. +## +## Value: on | off +auth.mysql.ssl = off + +## CA certificate. +## +## Value: File +## auth.mysql.ssl.cafile = path to your ca file + +## Client ssl certificate. +## +## Value: File +## auth.mysql.ssl.certfile = path to your clientcert file + +## Client ssl keyfile. +## +## Value: File +## auth.mysql.ssl.keyfile = path to your clientkey file 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..a02471969 --- /dev/null +++ b/apps/emqx_auth_mysql/rebar.config @@ -0,0 +1,24 @@ +{deps, + [ + {mysql, {git, "https://github.com/emqx/mysql-otp", {tag, "1.6.1"}}} + ]}. + +{edoc_opts, [{preprocess, true}]}. +{erl_opts, [warn_unused_vars, + warn_shadow_vars, + warn_unused_import, + warn_obsolete_guard, + debug_info, + compressed, + {parse_transform} + ]}. +{overrides, [{add, [{erl_opts, [compressed]}]}]}. + +{xref_checks, [undefined_function_calls, undefined_functions, + locals_not_used, deprecated_function_calls, + warnings_as_errors, deprecated_functions + ]}. + +{cover_enabled, true}. +{cover_opts, [verbose]}. +{cover_export_enabled, true}. 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..174e3cd27 --- /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/include/emqx.hrl"). +-include_lib("emqx/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..221061f03 --- /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, "4.3.0"}, % strict semver, bump manually! + {modules, []}, + {registered, [emqx_auth_mysql_sup]}, + {applications, [kernel,stdlib,mysql,ecpool]}, + {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.appup.src b/apps/emqx_auth_mysql/src/emqx_auth_mysql.appup.src new file mode 100644 index 000000000..a4c8410af --- /dev/null +++ b/apps/emqx_auth_mysql/src/emqx_auth_mysql.appup.src @@ -0,0 +1,9 @@ +%% -*-: erlang -*- +{VSN, + [ + {<<".*">>, []} + ], + [ + {<<".*">>, []} + ] +}. 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..9cd9d5a25 --- /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/include/emqx.hrl"). +-include_lib("emqx/include/logger.hrl"). +-include_lib("emqx/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..c3ee3b02a --- /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/include/emqx.hrl"). +-include_lib("emqx/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..044655ac1 --- /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/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/.gitignore b/apps/emqx_auth_pgsql/.gitignore new file mode 100644 index 000000000..672d34c0c --- /dev/null +++ b/apps/emqx_auth_pgsql/.gitignore @@ -0,0 +1,20 @@ +ebin +.rebar +.eunit +.DS_Store +.erlang.mk/ +deps/ +emqx_auth_pgsql.d +ct.coverdata +logs/ +test/ct.cover.spec +test/*.beam +data/ +.DS_Store +cover/ +eunit.coverdata +_build/ +rebar.lock +erlang.mk +*.conf.rendered +.rebar3/ 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/etc/emqx_auth_pgsql.conf b/apps/emqx_auth_pgsql/etc/emqx_auth_pgsql.conf new file mode 100644 index 000000000..3e79d96d8 --- /dev/null +++ b/apps/emqx_auth_pgsql/etc/emqx_auth_pgsql.conf @@ -0,0 +1,110 @@ +##-------------------------------------------------------------------- +## PostgreSQL Auth/ACL Plugin +##-------------------------------------------------------------------- + +## 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 +## - %C: common name of client TLS cert +## - %d: subject of client TLS cert +## +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 +## - %C: common name of client TLS cert +## - %d: subject of client TLS cert +## +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 +## +## Note: You can add the 'ORDER BY' statement to control the rules match order +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' + 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..3155bbef3 --- /dev/null +++ b/apps/emqx_auth_pgsql/rebar.config @@ -0,0 +1,21 @@ +{deps, + [{epgsql, {git, "https://github.com/epgsql/epgsql", {tag, "4.4.0"}}} + ]}. + +{erl_opts, [warn_unused_vars, + warn_shadow_vars, + warn_unused_import, + warn_obsolete_guard, + debug_info, + compressed + ]}. +{overrides, [{add, [{erl_opts, [compressed]}]}]}. + +{xref_checks, [undefined_function_calls, undefined_functions, + locals_not_used, deprecated_function_calls, + warnings_as_errors, deprecated_functions + ]}. + +{cover_enabled, true}. +{cover_opts, [verbose]}. +{cover_export_enabled, true}. 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..c1792f1e2 --- /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/include/emqx.hrl"). +-include_lib("emqx/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..b84f5e3cd --- /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, "4.3.0"}, % strict semver, bump manually! + {modules, []}, + {registered, [emqx_auth_pgsql_sup]}, + {applications, [kernel,stdlib,epgsql,ecpool,emqx]}, + {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.appup.src b/apps/emqx_auth_pgsql/src/emqx_auth_pgsql.appup.src new file mode 100644 index 000000000..a4c8410af --- /dev/null +++ b/apps/emqx_auth_pgsql/src/emqx_auth_pgsql.appup.src @@ -0,0 +1,9 @@ +%% -*-: erlang -*- +{VSN, + [ + {<<".*">>, []} + ], + [ + {<<".*">>, []} + ] +}. 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..2dee5ef50 --- /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/include/emqx.hrl"). +-include_lib("emqx/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..27d25f35b --- /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/include/emqx.hrl"). +-include_lib("emqx/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..e4aefdcd3 --- /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/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/.gitignore b/apps/emqx_auth_redis/.gitignore new file mode 100644 index 000000000..0cfec36f4 --- /dev/null +++ b/apps/emqx_auth_redis/.gitignore @@ -0,0 +1,26 @@ +.rebar/ +.eunit/ +.erlang.mk/ +emqttd_auth_redis.d +deps/ +ct.coverdata +logs/ +test/ct.cover.spec +ebin/ +*.o +*.beam +*.plt +erl_crash.dump +data +emqx_auth_redis.d +cover/ +eunit.coverdata +_build/ +rebar.lock +erlang.mk +*.conf.rendered +.rebar3/ +*.swp +rebar.lock +/.idea/ +.DS_Store 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/etc/emqx_auth_redis.conf b/apps/emqx_auth_redis/etc/emqx_auth_redis.conf new file mode 100644 index 000000000..4d6b19b15 --- /dev/null +++ b/apps/emqx_auth_redis/etc/emqx_auth_redis.conf @@ -0,0 +1,116 @@ +##-------------------------------------------------------------------- +## Redis Auth/ACL Plugin +##-------------------------------------------------------------------- +## Redis Server cluster type +## single Single redis server +## sentinel Redis cluster through sentinel +## cluster Redis through cluster +auth.redis.type = single + +## Redis server address. +## +## Value: Port | IP:Port +## +## Single Redis Server: 127.0.0.1:6379, localhost:6379 +## Redis Sentinel: 127.0.0.1:26379,127.0.0.2:26379,127.0.0.3:26379 +## Redis Cluster: 127.0.0.1:6379,127.0.0.2:6379,127.0.0.3:6379 +auth.redis.server = 127.0.0.1:6379 + +## Redis sentinel cluster name. +## +## Value: String +## 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 = + +## Redis query timeout +## +## Value: Duration +## auth.redis.query_timeout = 5s + +## 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 + +## Redis ssl configuration. +## +## Value: on | off +#auth.redis.ssl = off + +## CA certificate. +## +## Value: File +#auth.redis.cafile = path/to/your/cafile + +## Client ssl certificate. +## +## Value: File +#auth.redis.certfile = path/to/your/certfile + +## Client ssl keyfile. +## +## Value: File +#auth.redis.keyfile = path/to/your/keyfile \ No newline at end of file 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..d51b9c1b2 --- /dev/null +++ b/apps/emqx_auth_redis/priv/emqx_auth_redis.schema @@ -0,0 +1,139 @@ +%%-*- 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 +]}. + +{mapping, "auth.redis.ssl", "emqx_auth_redis.options", [ + {default, off}, + {datatype, flag} +]}. + +{mapping, "auth.redis.cafile", "emqx_auth_redis.options", [ + {default, ""}, + {datatype, string} +]}. + +{mapping, "auth.redis.certfile", "emqx_auth_redis.options", [ + {default, ""}, + {datatype, string} +]}. + +{mapping, "auth.redis.keyfile", "emqx_auth_redis.options", [ + {default, ""}, + {datatype, string} +]}. + +{translation, "emqx_auth_redis.options", fun(Conf) -> + Ssl = cuttlefish:conf_get("auth.redis.ssl", Conf, false), + case Ssl of + true -> + CA = cuttlefish:conf_get("auth.redis.cafile", Conf), + Cert = cuttlefish:conf_get("auth.redis.certfile", Conf), + Key = cuttlefish:conf_get("auth.redis.keyfile", Conf), + [{options, [{ssl_options, [{cacertfile, CA}, + {certfile, Cert}, + {keyfile, Key}]}]}]; + _ -> [{options, []}] + end +end}. + +{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..a85b22fd1 --- /dev/null +++ b/apps/emqx_auth_redis/rebar.config @@ -0,0 +1,21 @@ +{deps, + [{eredis_cluster, {git, "https://github.com/emqx/eredis_cluster", {tag, "0.6.3"}}} + ]}. + +{erl_opts, [warn_unused_vars, + warn_shadow_vars, + warn_unused_import, + warn_obsolete_guard, + debug_info, + compressed + ]}. +{overrides, [{add, [{erl_opts, [compressed]}]}]}. + +{xref_checks, [undefined_function_calls, undefined_functions, + locals_not_used, deprecated_function_calls, + warnings_as_errors, deprecated_functions + ]}. + +{cover_enabled, true}. +{cover_opts, [verbose]}. +{cover_export_enabled, true}. 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..096523487 --- /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/include/emqx.hrl"). +-include_lib("emqx/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..7fed3441c --- /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, "4.3.0"}, % strict semver, bump manually! + {modules, []}, + {registered, [emqx_auth_redis_sup]}, + {applications, [kernel,stdlib,eredis,eredis_cluster,ecpool,emqx]}, + {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.appup.src b/apps/emqx_auth_redis/src/emqx_auth_redis.appup.src new file mode 100644 index 000000000..d05d8148f --- /dev/null +++ b/apps/emqx_auth_redis/src/emqx_auth_redis.appup.src @@ -0,0 +1,10 @@ +%% -*-: erlang -*- + +{VSN, + [ + {<<".*">>, []} + ], + [ + {<<".*">>, []} + ] +}. 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..65f4d9735 --- /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/include/emqx.hrl"). +-include_lib("emqx/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..31cb67505 --- /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/include/emqx.hrl"). +-include_lib("emqx/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, 0), + get_value(password, Opts, ""), + 3000, + 5000, + get_value(options, Opts, [])) 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..83112976d --- /dev/null +++ b/apps/emqx_auth_redis/src/emqx_auth_redis_sup.erl @@ -0,0 +1,43 @@ +%%-------------------------------------------------------------------- +%% 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) -> + Options = application:get_env(?APP, options, []), + case proplists:get_value(type, Server) of + cluster -> + {ok, _} = eredis_cluster:start_pool(?APP, Server ++ Options), + []; + _ -> + [ecpool:pool_spec(?APP, ?APP, emqx_auth_redis_cli, Server ++ Options)] + 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..427806f4e --- /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/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_redis/test/emqx_auth_redis_SUITE_data/certs/ca.crt b/apps/emqx_auth_redis/test/emqx_auth_redis_SUITE_data/certs/ca.crt new file mode 100644 index 000000000..b46bef4e5 --- /dev/null +++ b/apps/emqx_auth_redis/test/emqx_auth_redis_SUITE_data/certs/ca.crt @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIE5jCCAs4CCQCc1DzEYETfKTANBgkqhkiG9w0BAQsFADA1MRMwEQYDVQQKDApS +ZWRpcyBUZXN0MR4wHAYDVQQDDBVDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMjAx +MDI5MDEzNDE2WhcNMzAxMDI3MDEzNDE2WjA1MRMwEQYDVQQKDApSZWRpcyBUZXN0 +MR4wHAYDVQQDDBVDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQC/RxC/zQ6+ThI2l+LT5tpuvljE7CPca5erahTjv1Pq +mbmHYIVlige9jvZKR/AaaHuhNRT6C4PDpD98TgrhSLSgMMFImoFMSnmFEOVave3O +y1qV9vtoHLMB9hO+t7P98KRi1sCoMdPIE/o5uEGSd4YgWbk3NllAV6me108UniWU +yZMCSEKmV9OpfQ+YfHFolESV92ajdViDbtRBjfDNwD7qb8zgigxIJvBzEnWF4RZl +4+KIiyoJ55AQ3omdEi0QwiRRRONFtB6kRSqjGS8genGnycX1ZNPRB8JeG3ESuFj9 +1WQUD0EMBXFB5agHoZjvtFwxOkUkA4XbcnpKddHGKRt4BAbm+YcizJaT7mRytGWZ +UoTrDWz8/Cc0BlwAfPEk6ogU/sLSZpdxjxwprCNB89UOI+q7ng7CYiFnxY9HHZeg +GCJxYfvpKM/eOT9mSLUug8EGITd0j2cusflO4Q243clPyRbTSSr39Pcpy8rfKApF +HkUuGIpa/qgAbez+lPlIydzpbrTgrnHvL1P6fCYTnHkcgSn8glBIKv3vh4zQd6df +JvcLv3WEka9+lyoCvJ0QH+/ITqrToyWa8g9fR3ajTlyMANesKxQejo80zCwk/0ns +SFKRIJc6vfnUJ12Vdxpmm1LeoJZnCYODNUeeksL1ahHCBGq4M8UJ+ycUM6N4ndWE +6QIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQAg0BaIi7lzrNb7xC42c+GJVrBq8Qf8 +7CBzP8SXYGUavQIYNRrtH8UgTOwaju9vOn3zoY8L59N6e+Icyt+Oh1FENcQMCZ2l +SP79iaY9A/dRV56p6NqNd3VWH+EuRGbQVatLdhJf3l5+W1z3Dum1YXmIn26acawF +GZVqLalgvLqPzPHHWEqz9RnmcvTu3w9YVb4NgbmY4byCb6mB2avt0iWQrY/fZSMe +FvRXurr0jwyIXBncqnXu97sCeccNc+fo3qZC1xxH9iXOIzrRg0ud7VGMTKcNLTTc +GqnbjNT8BC96Qp2Bs8J+JGZa3mT/usKBq2TT/3q6oKevuc23u/a5s1rztnqZgIe5 +RzfevJ79xdva6DMSq/8Yyd3I8hrs3oZKJbAce6ux01RsrCcY2O7gi4dAMoEGumxW +CS9XLchNy7QxQ+J2AKBZXd6AZjvTvloDGz/yC5EbdK/MnLz8oApK5Z8U/huEilFa +AymVWQWpmlX2KxW0nkCperlb7lcbPS+ZuH0+Zd9HOvqr9cpYMrwpF54q4vnzUQkR +Hsxoapv/FBsVoxtcOqrcxwGpYWCsV0VBnv9+1fzzZ83aK7CHDIeGVuKPyjkhHzLy +v7Ljuqg400wH0WB9pyEdK+O3F+xO3zJgf4o0JptOKOFBVVSkZWTrqlDjjbcnXBmh +dwgj2xYeigqHJA== +-----END CERTIFICATE----- diff --git a/apps/emqx_auth_redis/test/emqx_auth_redis_SUITE_data/certs/ca.key b/apps/emqx_auth_redis/test/emqx_auth_redis_SUITE_data/certs/ca.key new file mode 100644 index 000000000..b615a8c1e --- /dev/null +++ b/apps/emqx_auth_redis/test/emqx_auth_redis_SUITE_data/certs/ca.key @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIJKAIBAAKCAgEAv0cQv80Ovk4SNpfi0+babr5YxOwj3GuXq2oU479T6pm5h2CF +ZYoHvY72SkfwGmh7oTUU+guDw6Q/fE4K4Ui0oDDBSJqBTEp5hRDlWr3tzstalfb7 +aByzAfYTvrez/fCkYtbAqDHTyBP6ObhBkneGIFm5NzZZQFepntdPFJ4llMmTAkhC +plfTqX0PmHxxaJRElfdmo3VYg27UQY3wzcA+6m/M4IoMSCbwcxJ1heEWZePiiIsq +CeeQEN6JnRItEMIkUUTjRbQepEUqoxkvIHpxp8nF9WTT0QfCXhtxErhY/dVkFA9B +DAVxQeWoB6GY77RcMTpFJAOF23J6SnXRxikbeAQG5vmHIsyWk+5kcrRlmVKE6w1s +/PwnNAZcAHzxJOqIFP7C0maXcY8cKawjQfPVDiPqu54OwmIhZ8WPRx2XoBgicWH7 +6SjP3jk/Zki1LoPBBiE3dI9nLrH5TuENuN3JT8kW00kq9/T3KcvK3ygKRR5FLhiK +Wv6oAG3s/pT5SMnc6W604K5x7y9T+nwmE5x5HIEp/IJQSCr974eM0HenXyb3C791 +hJGvfpcqArydEB/vyE6q06MlmvIPX0d2o05cjADXrCsUHo6PNMwsJP9J7EhSkSCX +Or351CddlXcaZptS3qCWZwmDgzVHnpLC9WoRwgRquDPFCfsnFDOjeJ3VhOkCAwEA +AQKCAgBF1jSPUtcnNGoB9MKki40FEgpnG7CcMcxWkYy++oQxC59phhwuTo807pWN +2WYYvj0lRrQ59ypMrBNh1zyxtFH+is6HK6I5sJddtiWHVAEXl7ejOWHhSVkyRh4/ +a+MTvGDIlZAR2N9yFZkuqc+HIoyeEyREvFsp2tfbXtFIvdUK1e4Oz0NGaJqnLzoa +epUNkdTYzFN1Ksr+ceCdbq2U8bQG9HrhIIYLcewol3zBPMVoviNfpy/aHenDvvyP +lKtPixKneXdhY7osT/SZSACk4w/MKydTyVRs5WBZ67sFErmrM9YuXMNrGDGZ1bfb +0Wx9WGSwtI258G9XCB0OQqYsq6WTMaEei+z8l0iarZi1l2bz2F89J+IBYM8RqSsa +E30F8AtEG32QJUfK3F6k6N4uLx6JZduJgLyzsSh6q51ghAJ8kD1vUkEeXffCzynp +hzwRHUw5O1jNLEBdKYHpSyszlFX6qbzR1YXypzZs/aehZi5d89eBKN8X/Fnbi9a2 +Q0MqpZ5J/1hH7zadJFibNyuOCP4CNO3Hm18PjyEFRrCMbSF293kY9GoiOlQiwNAT +MqrsyLYgHPCXKXpG/R60lyHEfWKO9sOjyh+mSbv3QfNZS32Fweuo0R/vGYmkmtGn +wpn2IeSmX8ychdQrSemJjwzjUl/EUN0lGRAlHEt4ZDf52vHZ4QKCAQEA9k7b2vpU +g3S3GRCMzhl8GKZloNSbnR/ZHE8b9PVNahp0bQcZj+1yimF35p27VZR662ZBoKLy +/MLyPT+ZyynykwypcTVA5U9CABpSlyZMeezLnFlBXeHHMeoXcBZfFqHeXSsNYbhW +OStf4BGwKf7m/V0P/QL9mNsA/iq2uugC1gHoyp422YUIQQvKkBiFyMl34Zp2URsX +yIwb9aVyg2GogKDtbDPIwW89l3BCBiwalvjR6UotbXh3PQgYbsv62rTJ8AN+E+XH +eSQPnmPR6EXtX2nDuov996qlbja+JQE3SAls4EXLbrLyjSlObjcvkA59r+kZgNIY +g88hv7e9ublfqwKCAQEAxs3d9Zmjh9ByCT6jOUVnRMqw0+lVyVOs0kp7nOCb4HKM +CnupZuJQHQVQt7VhgD7FrALmYwkpt2e/WllN9bPFHRJcsw+SylOqyPil9G4DO5XZ +YPvk6PeQ/c0cbREKhsYNXqj5fWdq5pRd8rE72rK82mhdGQtAAN7NOEW5fo5tqHDK +D079SZmpcgd8Wz9luNpnZRpNhO3ccKV5yf0S1LZOZBbG9t875OVNhxlQY5wwIBXv +8ab13zcFKG21tWvLzz80vgkMIp0A9xh0XznIRnH3NnBZB80Yubg4sIaWvX7bqZ4X +EE9HGeiamw6c6Sm/Lvh/H659ri95l7C9TgAfAA7puwKCAQEAgJ/N0BzJ5ZwdwckS +vs4wL+81QzfDy9nF1zK4tsMjGjWWdxkuECs/lWQw6Q2VtqtDRYqw2uI9YiGrvrBn +7+CH/KKwGZ5ltVoebU9Rsf0eEs3FxnAV4qD1FOvaMX59SaReKulAo7dPz6sG9kxG +YqfqmITwxH+7TwePDSvhINnoITn+B1F38z+1f8JYlcc4lhIfuIChKNmtId2I/E7Z +7iIhjIp9cfPY8qrUzzCgSfjeKdjmRZ2m+3PdUNHZcIK1DWE700r/nARylqBuR5h5 +FYLu4tSokdJpXdyPZ27O/SQValkBslzAT57Da1QW0RegjuoCWMqxtsQAaVTRmvyo +50QW4QKCAQBLJFbn1MmFtRjVO7KwG/Z7fu01O7WsIg9pcLOmSRNB06nw8GrIM3Q6 +c97dgRY4RgGrEXGJL1ZwNyuRd73Kx8cSRPV6zMEb7mHYEnuPluFr7Si7ypnsIF7S +P2umIdHLvSIijFW4u5UhUCTubWUFNZfCKb4+kA0CBzSkN150Yls6Vl9ZR+7emdD9 +A61SQ/Ur2IlKIpX4T3uJrFILMbejZMDefel4OEpIKw+Rp9TFwaxDBGer/AJk+0Pc +0xLiXrsrO2WxCnRmxNcvjjO2Jn33em4JSo+sLi5RTDtJJaXmPAPE6bcn9/8U4OFH +CE/wpVHY7B4ImIhyhQk9d5Ul3U/aUsivAoIBAG8zk3CnFAnii1ENxhPtE8GCinvs +NdsluVtvUgMcA8gNzvqLHLQCoIy/b1wkqxPVsdTq1gZ7+FX9D9LzW9JxrWeEZqVV +jrUQIbls6HZei7i5x0tPwh1shOZiijgY24I6HDX9QRKZ7H7lLw0HfJI9YBI1Hl8E +naOtCuzFiaYEPfbGQACL8/UuoOZaD31JQda2EGYysGRxxJ2ZNPJIphCrwRb/nQBG +7WwCSCzu0peFNhZPVvkWHaFN73Uv/MmgFkp8RZzw9TEENB05wluCZB1TYJAOe65n +HnRWSDvWYR4lzMtq5WASFLC0WrFTiJKRCuKPljjoTptbXsJKyskW/t/+XPM= +-----END RSA PRIVATE KEY----- diff --git a/apps/emqx_auth_redis/test/emqx_auth_redis_SUITE_data/certs/ca.txt b/apps/emqx_auth_redis/test/emqx_auth_redis_SUITE_data/certs/ca.txt new file mode 100644 index 000000000..cf4e2aba5 --- /dev/null +++ b/apps/emqx_auth_redis/test/emqx_auth_redis_SUITE_data/certs/ca.txt @@ -0,0 +1 @@ +BFFAA2A065DFA6FC diff --git a/apps/emqx_auth_redis/test/emqx_auth_redis_SUITE_data/certs/redis.crt b/apps/emqx_auth_redis/test/emqx_auth_redis_SUITE_data/certs/redis.crt new file mode 100644 index 000000000..5eefadf62 --- /dev/null +++ b/apps/emqx_auth_redis/test/emqx_auth_redis_SUITE_data/certs/redis.crt @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIID1zCCAb8CCQC/+qKgZd+m/DANBgkqhkiG9w0BAQsFADA1MRMwEQYDVQQKDApS +ZWRpcyBUZXN0MR4wHAYDVQQDDBVDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMjAx +MDI5MDEzNDE2WhcNMjExMDI5MDEzNDE2WjAmMRMwEQYDVQQKDApSZWRpcyBUZXN0 +MQ8wDQYDVQQDDAZTZXJ2ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQDSs3bQ9sYi2AhFuHU75Ryk1HHSgfzA6pQAJilmJdTy0s5vyiWe1HQJaWkMcS5V +GVzGMK+c+OBqtXtDDninL3betg1YPMjSCOjPMOTC1H9K7+effwf7Iwpnw9Zro8mb +TEmMslIYhhcDedzT9Owli4QAgbgTn4l1BYuKX9CLrrKFtnr21miKu3ydViy9q7T1 +pib3eigvAyk7X2fadHFArGEttsXrD6cetPPkSF/1OLWNlqzUKXzhSyrBXzO44Kks +fwR/EpTiES9g4dNOL2wvKS/YE1fNKhiCENrNxTXQo1l0yOdm2+MeyOeHFzRuS0b/ ++uGDFOPPi04KXeO6dQ5olBCPAgMBAAEwDQYJKoZIhvcNAQELBQADggIBADn0E2vG +iQWe8/I7VbBdPhPNupVNcLvew10eIHxY2g5vSruCSVRQTgk8itVMRmDQxbb7gdDW +jnCRbxykxbLjM9iCRljnOCsIcTi7qO7JRl8niV8dtEpPOs9lZxEdNXjIV1iZoWf3 +arBbPQSyQZvTQHG6qbFnyCdMMyyXGGvEPGQDaBiKH+Ko1qeAbCi0zupChYvxmtZ8 +hSTPlMFezDT9bKoNY0pkJSELfokEPU/Pn6Lz/NVbdzmCMjVa/xmF3s31g+DGhz95 +4AyOnCr6o0aydPVVV3pB/BCezNXPUxpp53BG0w/K2f2DnKYCvGvJbqDAaJ8bG/J1 +EFSOmwobdwVxJz3KNubmo1qJ6xOl/YT7yyqPRQRM1SY8nZW+YcoJSZjOe8wJVlob +d0bOwN1C3HQwomyMWes187bEQP6Y36HuEbR1fK8yIOzGsGDKRFAFwQwMgw2M91lr +EJIP5NRD3OZRuiYDiVfVhDZDaNahrAMZUcPCgeCAwc4YG6Gp2sDtdorOl4kIJYWE +BbBZ0Jplq9+g6ciu5ChjAW8iFl0Ae5U24MxPGXnrxiRF4WWxLeZMVLXLDvlPqReD +CHII5ifyvGEt5+RhqtZC/L+HimL+5wQgOlntqhUdLb6yWRz7YW37PFMnUXU3MXe9 +uY7m73ZLluXiLojcZxU2+cx89u5FOJxrYtrj +-----END CERTIFICATE----- diff --git a/apps/emqx_auth_redis/test/emqx_auth_redis_SUITE_data/certs/redis.dh b/apps/emqx_auth_redis/test/emqx_auth_redis_SUITE_data/certs/redis.dh new file mode 100644 index 000000000..f7dd0569d --- /dev/null +++ b/apps/emqx_auth_redis/test/emqx_auth_redis_SUITE_data/certs/redis.dh @@ -0,0 +1,8 @@ +-----BEGIN DH PARAMETERS----- +MIIBCAKCAQEAo2dgOzTnLK7c8AjkiTXxdmo2MJsyzTlNXUDxLfl2hgwic6benyQ3 +9iL95wKjYg2YpMhzbwux50D+9XeVkRatf1pRi/N9H911f90MO6penzUx/dxfOepN +qoGK/T9xO8e6aFCYOoQjJaZzQYC0HixJVadZd7wRlHkZ3siNKUU5QK68KaN3JE3J +R3yZ9A7MU/TVdwZyVIyoWF2+WJMQW+qaezoqiuVKZXXzzoqbj14ZrtPRmO26vMV/ +bmMuHwPsk9dL7tKnTWEOrs6NVHIQW+RxJuRE9wGa0qqzHAzysEQ8q9QYPRvGo5y+ +XRWosl1bHG4+EmvXsCCs35bcbKToi3NFWwIBAg== +-----END DH PARAMETERS----- diff --git a/apps/emqx_auth_redis/test/emqx_auth_redis_SUITE_data/certs/redis.key b/apps/emqx_auth_redis/test/emqx_auth_redis_SUITE_data/certs/redis.key new file mode 100644 index 000000000..b76303f14 --- /dev/null +++ b/apps/emqx_auth_redis/test/emqx_auth_redis_SUITE_data/certs/redis.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpgIBAAKCAQEA0rN20PbGItgIRbh1O+UcpNRx0oH8wOqUACYpZiXU8tLOb8ol +ntR0CWlpDHEuVRlcxjCvnPjgarV7Qw54py923rYNWDzI0gjozzDkwtR/Su/nn38H ++yMKZ8PWa6PJm0xJjLJSGIYXA3nc0/TsJYuEAIG4E5+JdQWLil/Qi66yhbZ69tZo +irt8nVYsvau09aYm93ooLwMpO19n2nRxQKxhLbbF6w+nHrTz5Ehf9Ti1jZas1Cl8 +4UsqwV8zuOCpLH8EfxKU4hEvYOHTTi9sLykv2BNXzSoYghDazcU10KNZdMjnZtvj +Hsjnhxc0bktG//rhgxTjz4tOCl3junUOaJQQjwIDAQABAoIBAQCP7CJ27nm9B0/v +P+ZkeUWtmaf+IOhjZlieGXMh4SmqjDCSz8QO0BRK8YPeCdmaK27huhPa521ztm9y +CIqFuLg7vKM06KBMR+Wu0TkRlFE3ANR4cC8lbnQHGRB4CjMGL3/16UCGm+FQcIdV +CPHdW4VZS0JPtSQRmS4N4RD0uOocxqGcVbCRqnJoNp1zyXhookgHfZsC3b3cgzC7 +qvI9F1oY4Yg4b9Lw5sNi3JXWtFth8JFOPyImRcE0ngcGZK4iWjiufNKWVeTmSmVy +njMZfj8xKSpfqO3sOTbJMdrH1v5pMrAR/Ed748HheXuL15Ur9n88683hMMATZInn +YzIqNSrBAoGBAO94YBB1hN+jSKw+2FbAhuuM0gWHREmLQuaF2vjeVXL3r6YofFmf ++oJNgoOWXsv4KO2MgKDv4qrz7RohhhQpOFm5PpapSH/di7u6KsbJLYSxv/TEqQFE +NPyGywwNDIkn1wPlnX3LXp26puj2Gtn21Z0trUrpgsDM99BaTBbqTR2xAoGBAOE+ +tw0GHD/6CRPfoBIgVilS/sUJ5VJYTTKo/y6ozovCAq4bt5LkYmAOy6q8paHb58Oc +J890+LEPhelM/ZJDDz9oQFfq5LvuzgNfzDRyIhgDSpghtFrdDxQZP1X1lSdh+MFW +gx0k9h8VuIPksBsIgcmUtyCYitxLFep/0tAA/GI/AoGBAMxexEVntjWSScROgh1P +hBXlAZycO4g0ZK0OEboRLYXHos1AghePM6Ee+0LIAzE6IdvR7DjtYVoagQCrGZ19 +LE1Ojf7QjEIr1kQpdrZeHQ3BERyY9c9R4ZKeiw1G2ar4KEV4Ifeop6AfGrF4z6Oz +R80znVBwhxl6FAhp98QaxCORAoGBAInkc/nEKN09u/rvpzYRl83aol+MDFjZ+ACw +lvBApZnHnw5pp3uE13jI9gRDUv8A+iS1X2XQzULQJwHJgV7eMOJ3dxSbl4Y5zuMf +7YqZ6KdctHjoAVqzBD0gq7Z7DuG6R6hMxx27d/VVvcz43preHV6D7YxF9pSgXv1d +XXi7ccbPAoGBAIeLzCYd+JGufHwbq7oNvSyXJjGMjsAQuErUQ0xXwo7VAyOere2P +Dwk67wq6vsmn38EAs7IkXDgIoTD9z69DNtcjr/3fARYfmDSWyHscRwyUaJ15WQcZ +TCXAPf70Vf0KGBpRkgD+Qnq+lMZ3dr1uINGdalI4AWsXje0dPKpd+W8U +-----END RSA PRIVATE KEY----- diff --git a/apps/emqx_bridge_mqtt/.gitignore b/apps/emqx_bridge_mqtt/.gitignore new file mode 100644 index 000000000..bf9523be5 --- /dev/null +++ b/apps/emqx_bridge_mqtt/.gitignore @@ -0,0 +1,21 @@ +.eunit +deps +*.o +*.beam +*.plt +erl_crash.dump +ebin/*.beam +rel +_build +.concrete/DEV_MODE +.rebar +.erlang.mk +data +ebin +emqx_bridge_mqtt.d +*.rendered +.rebar3/ +*.coverdata +rebar.lock +.DS_Store +Mnesia.*/ \ No newline at end of file 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/etc/emqx_bridge_mqtt.conf b/apps/emqx_bridge_mqtt/etc/emqx_bridge_mqtt.conf new file mode 100644 index 000000000..93f0f5579 --- /dev/null +++ b/apps/emqx_bridge_mqtt/etc/emqx_bridge_mqtt.conf @@ -0,0 +1,172 @@ +##==================================================================== +## Configuration for EMQ X MQTT Broker Bridge +##==================================================================== + +##-------------------------------------------------------------------- +## Bridges to aws +##-------------------------------------------------------------------- + +## Bridge address: node name for local bridge, host:port for remote. +## +## Value: String +## Example: emqx@127.0.0.1, 127.0.0.1:1883 +bridge.mqtt.aws.address = 127.0.0.1:1883 + +## Protocol version of the bridge. +## +## Value: Enum +## - mqttv5 +## - mqttv4 +## - mqttv3 +bridge.mqtt.aws.proto_ver = mqttv4 + +## Start type of the bridge. +## +## Value: enum +## manual +## auto +bridge.mqtt.aws.start_type = manual + +## Whether to enable bridge mode for mqtt bridge +## +## This option is prepared for the mqtt broker which does not +## support bridge_mode such as the mqtt-plugin of the rabbitmq +## +## Value: boolean +#bridge.mqtt.aws.bridge_mode = false + +## The ClientId of a remote bridge. +## +## Placeholders: +## ${node}: Node name +## +## Value: String +bridge.mqtt.aws.clientid = bridge_aws + +## The Clean start flag of a remote bridge. +## +## Value: boolean +## Default: true +## +## NOTE: Some IoT platforms require clean_start +## must be set to 'true' +bridge.mqtt.aws.clean_start = true + +## The username for a remote bridge. +## +## Value: String +bridge.mqtt.aws.username = user + +## The password for a remote bridge. +## +## Value: String +bridge.mqtt.aws.password = passwd + +## Topics that need to be forward to AWS IoTHUB +## +## Value: String +## Example: topic1/#,topic2/# +bridge.mqtt.aws.forwards = topic1/#,topic2/# + +## Forward messages to the mountpoint of an AWS IoTHUB +## +## Value: String +bridge.mqtt.aws.forward_mountpoint = bridge/aws/${node}/ + +## Need to subscribe to AWS topics +## +## Value: String +## bridge.mqtt.aws.subscription.1.topic = cmd/topic1 + +## Need to subscribe to AWS topics QoS. +## +## Value: Number +## bridge.mqtt.aws.subscription.1.qos = 1 + +## A mountpoint that receives messages from AWS IoTHUB +## +## Value: String +## bridge.mqtt.aws.receive_mountpoint = receive/aws/ + + +## Bribge to remote server via SSL. +## +## Value: on | off +bridge.mqtt.aws.ssl = off + +## PEM-encoded CA certificates of the bridge. +## +## Value: File +bridge.mqtt.aws.cacertfile = {{ platform_etc_dir }}/certs/cacert.pem + +## Client SSL Certfile of the bridge. +## +## Value: File +bridge.mqtt.aws.certfile = {{ platform_etc_dir }}/certs/client-cert.pem + +## Client SSL Keyfile of the bridge. +## +## Value: File +bridge.mqtt.aws.keyfile = {{ platform_etc_dir }}/certs/client-key.pem + +## SSL Ciphers used by the bridge. +## +## Value: String +bridge.mqtt.aws.ciphers = 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 + +## Ciphers for TLS PSK. +## Note that 'bridge.${BridgeName}.ciphers' and 'bridge.${BridgeName}.psk_ciphers' cannot +## be configured at the same time. +## See 'https://tools.ietf.org/html/rfc4279#section-2'. +#bridge.mqtt.aws.psk_ciphers = PSK-AES128-CBC-SHA,PSK-AES256-CBC-SHA,PSK-3DES-EDE-CBC-SHA,PSK-RC4-SHA + +## Ping interval of a down bridge. +## +## Value: Duration +## Default: 10 seconds +bridge.mqtt.aws.keepalive = 60s + +## TLS versions used by the bridge. +## +## Value: String +bridge.mqtt.aws.tls_versions = tlsv1.2,tlsv1.1,tlsv1 + +## Bridge reconnect time. +## +## Value: Duration +## Default: 30 seconds +bridge.mqtt.aws.reconnect_interval = 30s + +## Retry interval for bridge QoS1 message delivering. +## +## Value: Duration +bridge.mqtt.aws.retry_interval = 20s + +## Publish messages in batches, only RPC Bridge supports +## +## Value: Integer +## default: 32 +bridge.mqtt.aws.batch_size = 32 + +## Inflight size. +## +## Value: Integer +bridge.mqtt.aws.max_inflight_size = 32 + +## Base directory for replayq to store messages on disk +## If this config entry is missing or set to undefined, +## replayq works in a mem-only manner. +## +## Value: String +bridge.mqtt.aws.queue.replayq_dir = {{ platform_data_dir }}/replayq/emqx_aws_bridge/ + +## Replayq segment size +## +## Value: Bytesize +bridge.mqtt.aws.queue.replayq_seg_bytes = 10MB + +## Replayq max total size +## +## Value: Bytesize +bridge.mqtt.aws.queue.max_total_size = 5GB + 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..37ac5b034 --- /dev/null +++ b/apps/emqx_bridge_mqtt/rebar.config @@ -0,0 +1,19 @@ +{deps, []}. +{edoc_opts, [{preprocess, true}]}. +{erl_opts, [warn_unused_vars, + warn_shadow_vars, + warn_unused_import, + warn_obsolete_guard, + debug_info]}. + +{xref_checks, [undefined_function_calls, undefined_functions, + locals_not_used, deprecated_function_calls, + warnings_as_errors, deprecated_functions]}. +{cover_enabled, true}. +{cover_opts, [verbose]}. +{cover_export_enabled, true}. + +{shell, [ + % {config, "config/sys.config"}, + {apps, [emqx, emqx_bridge_mqtt]} +]}. 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..5086ca574 --- /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/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..df7d47571 --- /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, "4.3.0"}, % strict semver, bump manually! + {modules, []}, + {registered, []}, + {applications, [kernel,stdlib,replayq,emqtt,emqx]}, + {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.appup.src b/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt.appup.src new file mode 100644 index 000000000..f6d128b08 --- /dev/null +++ b/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt.appup.src @@ -0,0 +1,10 @@ +%% -*-: erlang -*- + +{VSN, + [ + {<<".*">>, []} + ], + [ + {<<"*.">>, []} + ] +}. 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..19c0c5711 --- /dev/null +++ b/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt.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. +%%-------------------------------------------------------------------- + +%% @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 + ]). + +%% callbacks for emqtt +-export([ handle_puback/2 + , handle_publish/2 + , handle_disconnected/2 + ]). + +-include_lib("emqx/include/logger.hrl"). +-include_lib("emqx/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(#{packet_id := PktId, reason_code := RC}, Parent) + when RC =:= ?RC_SUCCESS; + RC =:= ?RC_NO_MATCHING_SUBSCRIBERS -> + Parent ! {batch_ack, PktId}, ok; +handle_puback(#{packet_id := PktId, reason_code := RC}, _Parent) -> + ?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(Reason, Parent) -> + Parent ! {disconnected, self(), Reason}. + +make_hdlr(Parent, Mountpoint) -> + #{puback => {fun ?MODULE:handle_puback/2, [Parent]}, + publish => {fun ?MODULE:handle_publish/2, [Mountpoint]}, + disconnected => {fun ?MODULE:handle_disconnected/2, [Parent]} + }. + +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..7708521e8 --- /dev/null +++ b/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt_actions.erl @@ -0,0 +1,784 @@ +%%-------------------------------------------------------------------- +%% 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/include/emqx.hrl"). +-include_lib("emqx/include/logger.hrl"). +-include_lib("emqx_rule_engine/include/rule_actions.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 + , on_action_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 JSON 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(ActId, Opts = #{<<"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, + Opts. + +on_action_data_to_mqtt_broker(Msg, _Env = + #{id := Id, clientid := From, flags := Flags, + topic := Topic, timestamp := TimeStamp, qos := QoS, + ?BINDING_KEYS := #{ + 'ActId' := ActId, + 'PoolName' := PoolName, + 'TopicTks' := TopicTks, + 'PayloadTks' := PayloadTks + }}) -> + 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), + emqx_rule_metrics:inc_actions_success(ActId). + +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..92d8e4083 --- /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/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..20600282e --- /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/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..768cd3258 --- /dev/null +++ b/apps/emqx_bridge_mqtt/src/emqx_bridge_worker.erl @@ -0,0 +1,596 @@ +%%-------------------------------------------------------------------- +%% 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 `connection' 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 + ]). + +%% Internal +-export([msg_marshaller/1]). + +-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/include/logger.hrl"). +-include_lib("emqx/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), + ConnectCfg = get_conn_cfg(Config), + self() ! idle, + {ok, idle, State#{connect_module => ConnectModule, + connect_cfg => ConnectCfg, + 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 ?MODULE: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_module := ConnectModule, + connect_cfg := ConnectCfg, + name := Name} = State) -> + ok = subscribe_local_topics(Forwards, Name), + case emqx_bridge_connect:start(ConnectModule, ConnectCfg#{subscriptions => 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..392fa8e17 --- /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/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..7cbf0987c --- /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/include/emqx_mqtt.hrl"). +-include_lib("emqx/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..1d2ed1b82 --- /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/include/emqx.hrl"). +-include_lib("emqx/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/.gitignore b/apps/emqx_coap/.gitignore new file mode 100644 index 000000000..67eaa0145 --- /dev/null +++ b/apps/emqx_coap/.gitignore @@ -0,0 +1,25 @@ +deps/ +ebin/ +_rel/ +.erlang.mk/ +*.d +*.o +*.exe +data/ +*.iml +.idea/ +logs/ +*.beam +emqx_coap.d +intergration_test/emqx-rel/ +intergration_test/libcoap/ +intergration_test/case*.txt +.DS_Store +_build/ +rebar.lock +rebar3.crashdump +*.swp +erlang.mk +.rebar3/ +etc/emqx_coap.conf.rendered +.tags* 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/etc/emqx_coap.conf b/apps/emqx_coap/etc/emqx_coap.conf new file mode 100644 index 000000000..0590a348e --- /dev/null +++ b/apps/emqx_coap/etc/emqx_coap.conf @@ -0,0 +1,82 @@ +##-------------------------------------------------------------------- +## CoAP Gateway +##-------------------------------------------------------------------- + +## The IP and UDP port that CoAP bind with. +## +## Default: 0.0.0.0:5683 +## +## Examples: +## coap.bind.udp.x = 0.0.0.0:5683 | :::5683 | 127.0.0.1:5683 | ::1:5683 +## +coap.bind.udp.1 = 0.0.0.0:5683 +##coap.bind.udp.2 = 0.0.0.0:6683 + +## Whether to enable statistics for CoAP clients. +## +## Value: on | off +coap.enable_stats = off + + +##------------------------------------------------------------------------------ +## DTLS options + +## The DTLS port that CoAP is listening on. +## +## Default: 0.0.0.0:5684 +## +## Examples: +## coap.bind.dtls.x = 0.0.0.0:5684 | :::5684 | 127.0.0.1:5684 | ::1:5684 +## +coap.bind.dtls.1 = 0.0.0.0:5684 +##coap.bind.dtls.2 = 0.0.0.0:6684 + +## 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 + +## 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 + +## 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 + +## This is the single most important configuration option of an Erlang SSL +## application. Ciphers (and their ordering) define the way the client and +## server encrypt information over the wire, from the initial Diffie-Helman +## key exchange, the session key encryption ## algorithm and the message +## digest algorithm. Selecting a good cipher suite is critical for the +## application’s data security, confidentiality and performance. +## +## The cipher list above offers: +## +## A good balance between compatibility with older browsers. +## It can get stricter for Machine-To-Machine scenarios. +## Perfect Forward Secrecy. +## No old/insecure encryption and HMAC algorithms +## +## Most of it was copied from Mozilla’s Server Side TLS article +## +## Value: Ciphers +coap.dtls.ciphers = 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 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/Makefile b/apps/emqx_coap/intergration_test/Makefile new file mode 100644 index 000000000..12a2081dd --- /dev/null +++ b/apps/emqx_coap/intergration_test/Makefile @@ -0,0 +1,129 @@ +.PHONY: clean, clean_result, start_broker stop_broker case1 case2 case3 + +RELX_CONF = emqx-rel/relx.config +LIBCOAP_GIT = libcoap/README.md + +all: clean_result $(RELX_CONF) $(LIBCOAP_GIT) start_broker clean_result case1 case2 case3 case4 stop_broker + @echo " " + @echo " test complete" + @echo " " + +clean_result: + -rm -f case*.txt + + +start_broker: + -rm -f emqx-rel/_rel/emqx/log/* + -emqx-rel/_rel/emqx/bin/emqx stop + sleep 1 + emqx-rel/_rel/emqx/bin/emqx start + sleep 1 + emqx-rel/_rel/emqx/bin/emqx_ctl plugins load emqx_coap + +stop_broker: + -emqx-rel/_rel/emqx/bin/emqx stop + +case1: + libcoap/examples/coap-client -m get -s 5 "coap://127.0.0.1/mqtt/topic1?c=client1&u=tom&p=secret" > case1_output.txt & + sleep 1 + libcoap/examples/coap-client -m put -e w123G45 "coap://127.0.0.1/mqtt/topic1?c=client2&u=mike&p=pw12" + sleep 6 + python check_result.py case1 case1_output.txt==w123G45 + +case2: + # subscribe to topic="x/y" + libcoap/examples/coap-client -m get -s 5 "coap://127.0.0.1/mqtt/x%2Fy?c=client3&u=tom&p=secret" > case2_output1.txt & + # subscribe to topic="+/z" + libcoap/examples/coap-client -m get -s 5 "coap://127.0.0.1/mqtt/%2B%2Fz?c=client4&u=mike&p=pw12" > case2_output2.txt & + sleep 1 + # publish to topic="x/y" + libcoap/examples/coap-client -m put -e big9wolf "coap://127.0.0.1/mqtt/x%2Fy?c=client5&u=sun&p=pw3" + # publish to topic="p/z" + libcoap/examples/coap-client -m put -e black2ant "coap://127.0.0.1/mqtt/p%2Fz?c=client5&u=sun&p=pw3" + sleep 6 + python check_result.py case2 case2_output1.txt==big9wolf case2_output1.txt!=black2ant case2_output2.txt!=big9wolf case2_output2.txt==black2ant + +case3: + libcoap/examples/coap-client -m get -T tk12 -s 5 "coap://127.0.0.1/mqtt/a%2Fb?c=client3&u=tom&p=secret" > case3_output1.txt & + libcoap/examples/coap-client -m get -T tk34 -s 5 "coap://127.0.0.1/mqtt/c%2Fd?c=client3&u=tom&p=secret" > case3_output2.txt & + sleep 1 + libcoap/examples/coap-client -m put -e big9wolf "coap://127.0.0.1/mqtt/c%2Fd?c=client5&u=sun&p=pw3" + libcoap/examples/coap-client -m put -e black2ant "coap://127.0.0.1/mqtt/a%2Fb?c=client5&u=sun&p=pw3" + sleep 6 + python check_result.py case3 case3_output1.txt==black2ant case3_output2.txt==big9wolf case3_output2.txt!=black2ant + + + +case4: + # reload emqx_coap, does it work as expected? + sleep 1 + emqx-rel/_rel/emqx/bin/emqx_ctl plugins unload emqx_coap + sleep 1 + emqx-rel/_rel/emqx/bin/emqx_ctl plugins load emqx_coap + sleep 1 + libcoap/examples/coap-client -m get -s 5 "coap://127.0.0.1/mqtt/topic1?c=client1&u=tom&p=secret" > case4_output.txt & + sleep 1 + libcoap/examples/coap-client -m put -e w6J3G45 "coap://127.0.0.1/mqtt/topic1?c=client2&u=mike&p=pw12" + sleep 6 + python check_result.py case4 case4_output.txt==w6J3G45 + + + + +$(RELX_CONF): + git clone https://github.com/emqx/emqx-rel.git + git clone https://github.com/emqx/emq-coap.git + @echo "update emq-coap with this development code" + mv emq-coap emqx_coap + -rm -rf emqx_coap/etc + -rm -rf emqx_coap/include + -rm -rf emqx_coap/priv + -rm -rf emqx_coap/src + -rm -rf emqx_coap/Makefile + cp -rf ../etc emqx_coap/ + cp -rf ../include emqx_coap/ + cp -rf ../priv emqx_coap/ + cp -rf ../src emqx_coap/ + cp -rf ../Makefile emqx_coap/Makefile + -mkdir emqx-rel/deps + mv emqx_coap emqx-rel/deps/ + @echo "start building ..." + make -C emqx-rel -f Makefile + + +coap: $(LIBCOAP_GIT) + @echo "make coap" + +$(LIBCOAP_GIT): + git clone -b v4.1.2 http://github.com/obgm/libcoap + cd libcoap && ./autogen.sh && ./configure --enable-documentation=no --enable-tests=no + make -C libcoap -f Makefile + +r: rebuild_emq + # r short for rebuild_emq + @echo " rebuild complete " + +rebuild_emq: + -emqx-rel/_rel/emqx/bin/emqx stop + -rm -rf emqx-rel/deps/emqx_coap/etc + -rm -rf emqx-rel/deps/emqx_coap/include + -rm -rf emqx-rel/deps/emqx_coap/priv + -rm -rf emqx-rel/deps/emqx_coap/src + -rm -rf emqx-rel/deps/emqx_coap/Makefile + cp -rf ../etc emqx-rel/deps/emqx_coap/ + cp -rf ../include emqx-rel/deps/emqx_coap/ + cp -rf ../priv emqx-rel/deps/emqx_coap/ + cp -rf ../src emqx-rel/deps/emqx_coap/ + cp -rf ../Makefile emqx-rel/deps/emqx_coap/Makefile + make -C emqx-rel -f Makefile + +clean: clean_result + -rm -f client/*.exe + -rm -f client/*.o + -rm -rf emqx-rel + -rm -rf libcoap + +lazy: clean_result start_broker case2 stop_broker + # custom your command here + @echo "you are so lazy" + 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..dd1ad613e --- /dev/null +++ b/apps/emqx_coap/rebar.config @@ -0,0 +1,28 @@ +{deps, + [ + {gen_coap, {git, "https://github.com/emqx/gen_coap", {tag, "v0.3.0"}}} + ]}. + +{edoc_opts, [{preprocess, true}]}. +{erl_opts, [warn_unused_vars, + warn_shadow_vars, + warn_unused_import, + warn_obsolete_guard, + debug_info, + {parse_transform}]}. + +{xref_checks, [undefined_function_calls, undefined_functions, + locals_not_used, deprecated_function_calls, + warnings_as_errors, deprecated_functions]}. +{cover_enabled, true}. +{cover_opts, [verbose]}. +{cover_export_enabled, true}. + +{profiles, + [{test, + [{deps, + [{er_coap_client, {git, "https://github.com/emqx/er_coap_client", {tag, "v1.0"}}}, + {emqx_ct_helpers, {git, "https://github.com/emqx/emqx-ct-helpers", {tag, "1.2.2"}}} + ]} + ]} + ]}. 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..1ba1789d7 --- /dev/null +++ b/apps/emqx_coap/src/emqx_coap.app.src @@ -0,0 +1,14 @@ +{application, emqx_coap, + [{description, "EMQ X CoAP Gateway"}, + {vsn, "4.3.0"}, % strict semver, bump manually! + {modules, []}, + {registered, []}, + {applications, [kernel,stdlib,gen_coap,emqx]}, + {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..4c508c272 --- /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/include/emqx.hrl"). +-include_lib("emqx/include/emqx_mqtt.hrl"). +-include_lib("emqx/include/logger.hrl"). +-include_lib("emqx/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..09d291bf5 --- /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/include/emqx.hrl"). +-include_lib("emqx/include/emqx_mqtt.hrl"). +-include_lib("emqx/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..30e9d2623 --- /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/include/emqx.hrl"). +-include_lib("emqx/include/emqx_mqtt.hrl"). +-include_lib("emqx/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..369bf2787 --- /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/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..e11788a04 --- /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/include/emqx.hrl"). +-include_lib("emqx/include/logger.hrl"). +-include_lib("emqx/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..0d571fac3 --- /dev/null +++ b/apps/emqx_coap/src/emqx_coap_server.erl @@ -0,0 +1,106 @@ +%%-------------------------------------------------------------------- +%% 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 + ]). + +-export([ start_listener/1 + , start_listener/3 + , stop_listener/1 + , stop_listener/2 + ]). + +%%-------------------------------------------------------------------- +%% 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..866e2e203 --- /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/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..0a1cc3860 --- /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/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/.gitignore b/apps/emqx_dashboard/.gitignore new file mode 100644 index 000000000..d19e1b7d5 --- /dev/null +++ b/apps/emqx_dashboard/.gitignore @@ -0,0 +1,25 @@ +.eunit +deps +*.o +*.beam +*.plt +erl_crash.dump +ebin +rel/example_project +.concrete/DEV_MODE +.rebar +.erlang.mk/ +ct.coverdata +logs/ +test/ct.cover.spec +data/ +.DS_Store +emqx_dashboard.d +cover/ +eunit.coverdata +.DS_Store +erlang.mk +rebar.lock +_build/ +*.conf.rendered +.rebar3/ 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/etc/emqx_dashboard.conf b/apps/emqx_dashboard/etc/emqx_dashboard.conf new file mode 100644 index 000000000..7c2125b4c --- /dev/null +++ b/apps/emqx_dashboard/etc/emqx_dashboard.conf @@ -0,0 +1,129 @@ +##-------------------------------------------------------------------- +## EMQ X Dashboard +##-------------------------------------------------------------------- + +## Default user's login name. +## +## Value: String +dashboard.default_user.login = admin + +## Default user's password. +## +## Value: String +dashboard.default_user.password = public + +##-------------------------------------------------------------------- +## HTTP Listener + +## The port that the Dashboard HTTP listener will bind. +## +## Value: Port +## +## Examples: 18083 +dashboard.listener.http = 18083 + +## The acceptor pool for external Dashboard HTTP listener. +## +## Value: Number +dashboard.listener.http.acceptors = 4 + +## Maximum number of concurrent Dashboard HTTP connections. +## +## Value: Number +dashboard.listener.http.max_clients = 512 + +## Set up the socket for IPv6. +## +## Value: false | true +dashboard.listener.http.inet6 = false + +## Listen on IPv4 and IPv6 (false) or only on IPv6 (true). Use with inet6. +## +## Value: false | true +dashboard.listener.http.ipv6_v6only = false + +##-------------------------------------------------------------------- +## HTTPS Listener + +## The port that the Dashboard HTTPS listener will bind. +## +## Value: Port +## +## Examples: 18084 +## dashboard.listener.https = 18084 + +## The acceptor pool for external Dashboard HTTPS listener. +## +## Value: Number +## dashboard.listener.https.acceptors = 2 + +## Maximum number of concurrent Dashboard HTTPS connections. +## +## Value: Number +## dashboard.listener.https.max_clients = 512 + +## Set up the socket for IPv6. +## +## Value: false | true +## dashboard.listener.https.inet6 = false + +## Listen on IPv4 and IPv6 (false) or only on IPv6 (true). Use with inet6. +## +## Value: false | true +## dashboard.listener.https.ipv6_v6only = false + +## Path to the file containing the user's private PEM-encoded key. +## +## Value: File +## dashboard.listener.https.keyfile = etc/certs/key.pem + +## Path to a file containing the user certificate. +## +## Value: File +## dashboard.listener.https.certfile = etc/certs/cert.pem + +## Path to the file containing PEM-encoded CA certificates. +## +## Value: File +## dashboard.listener.https.cacertfile = etc/certs/cacert.pem + +## See: 'listener.ssl..dhfile' in emq.conf +## +## Value: File +## dashboard.listener.https.dhfile = {{ platform_etc_dir }}/certs/dh-params.pem + +## See: 'listener.ssl..vefify' in emq.conf +## +## Value: vefify_peer | verify_none +## dashboard.listener.https.verify = verify_peer + +## See: 'listener.ssl..fail_if_no_peer_cert' in emq.conf +## +## Value: false | true +## dashboard.listener.https.fail_if_no_peer_cert = true + +## TLS versions only to protect from POODLE attack. +## +## Value: String, seperated by ',' +## dashboard.listener.https.tls_versions = tlsv1.2,tlsv1.1,tlsv1 + +## See: 'listener.ssl..ciphers' in emq.conf +## +## Value: Ciphers +## dashboard.listener.https.ciphers = 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 + +## See: 'listener.ssl..secure_renegotiate' in emq.conf +## +## Value: on | off +## dashboard.listener.https.secure_renegotiate = off + +## See: 'listener.ssl..reuse_sessions' in emq.conf +## +## Value: on | off +## dashboard.listener.https.reuse_sessions = on + +## See: 'listener.ssl..honor_cipher_order' in emq.conf +## +## Value: on | off +## dashboard.listener.https.honor_cipher_order = on + 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