diff --git a/apps/.gitkeep b/apps/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/apps/emqx_auth_http/.github/workflows/run_test_cases.yaml b/apps/emqx_auth_http/.github/workflows/run_test_cases.yaml deleted file mode 100644 index 7a17028e7..000000000 --- a/apps/emqx_auth_http/.github/workflows/run_test_cases.yaml +++ /dev/null @@ -1,26 +0,0 @@ -name: Run test cases - -on: [push, pull_request] - -jobs: - run_test_cases: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - name: run test cases - run: | - docker network create --driver bridge --ipv6 --subnet fd15:555::/64 tests_emqx_bridge - docker run -i \ - --network tests_emqx_bridge \ - -v $(pwd):/emqx_auth_http \ - erlang:22.3 \ - bash -c "make -C /emqx_auth_http xref - make -C /emqx_auth_http eunit - make -C /emqx_auth_http ct - make -C /emqx_auth_http cover" - - uses: actions/upload-artifact@v1 - if: failure() - with: - name: logs - path: _build/test/logs diff --git a/apps/emqx_auth_http/src/emqx_auth_http.app.src.script b/apps/emqx_auth_http/src/emqx_auth_http.app.src.script deleted file mode 100644 index 0e14ff23f..000000000 --- a/apps/emqx_auth_http/src/emqx_auth_http.app.src.script +++ /dev/null @@ -1,24 +0,0 @@ -%%-*- mode: erlang -*- -%% .app.src.script - -RemoveLeadingV = - fun(Tag) -> - case re:run(Tag, "^[v|e]?[0-9]\.[0-9]\.([0-9]|(rc|beta|alpha)\.[0-9])", [{capture, none}]) of - nomatch -> - re:replace(Tag, "/", "-", [{return ,list}]); - _ -> - %% if it is a version number prefixed by 'v' or 'e', then remove it - re:replace(Tag, "[v|e]", "", [{return ,list}]) - end - end, - -case os:getenv("EMQX_DEPS_DEFAULT_VSN") of - false -> CONFIG; % env var not defined - [] -> CONFIG; % env var set to empty string - Tag -> - [begin - AppConf0 = lists:keystore(vsn, 1, AppConf, {vsn, RemoveLeadingV(Tag)}), - {application, App, AppConf0} - end || Conf = {application, App, AppConf} <- CONFIG] -end. - diff --git a/apps/emqx_auth_jwt/.github/workflows/run_test_cases.yaml b/apps/emqx_auth_jwt/.github/workflows/run_test_cases.yaml deleted file mode 100644 index b8e722570..000000000 --- a/apps/emqx_auth_jwt/.github/workflows/run_test_cases.yaml +++ /dev/null @@ -1,29 +0,0 @@ -name: Run test cases - -on: [push, pull_request] - -jobs: - run_test_cases: - runs-on: ubuntu-latest - - container: - image: erlang:22.1 - - steps: - - uses: actions/checkout@v1 - - name: run test cases - run: | - make xref - make eunit - make ct - make cover - - uses: actions/upload-artifact@v1 - if: always() - with: - name: logs - path: _build/test/logs - - uses: actions/upload-artifact@v1 - with: - name: cover - path: _build/test/cover - diff --git a/apps/emqx_auth_jwt/src/emqx_auth_jwt.app.src.script b/apps/emqx_auth_jwt/src/emqx_auth_jwt.app.src.script deleted file mode 100644 index 0e14ff23f..000000000 --- a/apps/emqx_auth_jwt/src/emqx_auth_jwt.app.src.script +++ /dev/null @@ -1,24 +0,0 @@ -%%-*- mode: erlang -*- -%% .app.src.script - -RemoveLeadingV = - fun(Tag) -> - case re:run(Tag, "^[v|e]?[0-9]\.[0-9]\.([0-9]|(rc|beta|alpha)\.[0-9])", [{capture, none}]) of - nomatch -> - re:replace(Tag, "/", "-", [{return ,list}]); - _ -> - %% if it is a version number prefixed by 'v' or 'e', then remove it - re:replace(Tag, "[v|e]", "", [{return ,list}]) - end - end, - -case os:getenv("EMQX_DEPS_DEFAULT_VSN") of - false -> CONFIG; % env var not defined - [] -> CONFIG; % env var set to empty string - Tag -> - [begin - AppConf0 = lists:keystore(vsn, 1, AppConf, {vsn, RemoveLeadingV(Tag)}), - {application, App, AppConf0} - end || Conf = {application, App, AppConf} <- CONFIG] -end. - diff --git a/apps/emqx_auth_ldap/.ci/docker-compose.yml b/apps/emqx_auth_ldap/.ci/docker-compose.yml deleted file mode 100644 index bba9b711f..000000000 --- a/apps/emqx_auth_ldap/.ci/docker-compose.yml +++ /dev/null @@ -1,26 +0,0 @@ -version: '3' - -services: - erlang: - image: erlang:22.1 - volumes: - - ../:/emqx_auth_ldap - networks: - - emqx_bridge - depends_on: - - ldap_server - tty: true - - ldap_server: - build: ./emqx-ldap - image: emqx-ldap:1.0 - restart: always - ports: - - 389:389 - - 636:636 - networks: - - emqx_bridge - -networks: - emqx_bridge: - driver: bridge diff --git a/apps/emqx_auth_ldap/.ci/emqx-ldap/Dockerfile b/apps/emqx_auth_ldap/.ci/emqx-ldap/Dockerfile deleted file mode 100644 index 0a01572c4..000000000 --- a/apps/emqx_auth_ldap/.ci/emqx-ldap/Dockerfile +++ /dev/null @@ -1,26 +0,0 @@ -FROM buildpack-deps:stretch - -ENV VERSION=2.4.50 - -RUN apt-get update && apt-get install -y groff groff-base -RUN wget ftp://ftp.openldap.org/pub/OpenLDAP/openldap-release/openldap-${VERSION}.tgz \ - && gunzip -c openldap-${VERSION}.tgz | tar xvfB - \ - && cd openldap-${VERSION} \ - && ./configure && make depend && make && make install \ - && cd .. && rm -rf openldap-${VERSION} - -COPY ./slapd.conf /usr/local/etc/openldap/slapd.conf -COPY ./emqx.io.ldif /usr/local/etc/openldap/schema/emqx.io.ldif -COPY ./emqx.schema /usr/local/etc/openldap/schema/emqx.schema -COPY ./*.pem /usr/local/etc/openldap/ - -RUN mkdir -p /usr/local/etc/openldap/data \ - && slapadd -l /usr/local/etc/openldap/schema/emqx.io.ldif -f /usr/local/etc/openldap/slapd.conf - -WORKDIR /usr/local/etc/openldap - -EXPOSE 389 636 - -ENTRYPOINT ["/usr/local/libexec/slapd", "-h", "ldap:/// ldaps:///", "-d", "3", "-f", "/usr/local/etc/openldap/slapd.conf"] - -CMD [] diff --git a/apps/emqx_auth_ldap/.ci/emqx-ldap/slapd.conf b/apps/emqx_auth_ldap/.ci/emqx-ldap/slapd.conf deleted file mode 100644 index d6ba20caa..000000000 --- a/apps/emqx_auth_ldap/.ci/emqx-ldap/slapd.conf +++ /dev/null @@ -1,16 +0,0 @@ -include /usr/local/etc/openldap/schema/core.schema -include /usr/local/etc/openldap/schema/cosine.schema -include /usr/local/etc/openldap/schema/inetorgperson.schema -include /usr/local/etc/openldap/schema/ppolicy.schema -include /usr/local/etc/openldap/schema/emqx.schema - -TLSCACertificateFile /usr/local/etc/openldap/cacert.pem -TLSCertificateFile /usr/local/etc/openldap/cert.pem -TLSCertificateKeyFile /usr/local/etc/openldap/key.pem - -database bdb -suffix "dc=emqx,dc=io" -rootdn "cn=root,dc=emqx,dc=io" -rootpw {SSHA}eoF7NhNrejVYYyGHqnt+MdKNBh4r1w3W - -directory /usr/local/etc/openldap/data diff --git a/apps/emqx_auth_ldap/.github/workflows/run_test_cases.yaml b/apps/emqx_auth_ldap/.github/workflows/run_test_cases.yaml deleted file mode 100644 index dd6978406..000000000 --- a/apps/emqx_auth_ldap/.github/workflows/run_test_cases.yaml +++ /dev/null @@ -1,49 +0,0 @@ -name: Run test cases - -on: [push, pull_request] - -jobs: - run_test_cases: - runs-on: ubuntu-latest - - strategy: - matrix: - network_type: - - ipv4 - - ipv6 - - steps: - - name: install docker-compose - run: | - sudo curl -L "https://github.com/docker/compose/releases/download/1.25.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose - sudo chmod +x /usr/local/bin/docker-compose - - uses: actions/checkout@v1 - - name: prepare - env: - NETWORK_TYPE: ${{ matrix.network_type }} - run: | - set -e -x -u - cp ./emqx.io.ldif ./emqx.schema ./.ci/emqx-ldap - cp ./test/certs/* ./.ci/emqx-ldap - docker-compose -f ./.ci/docker-compose.yml -p tests build - if [ "$NETWORK_TYPE" = "ipv6" ];then docker network create --driver bridge --ipv6 --subnet fd15:555::/64 tests_emqx_bridge --attachable; fi - docker-compose -f ./.ci/docker-compose.yml -p tests up -d - if [ "$NETWORK_TYPE" != "ipv6" ];then - docker exec -i tests_erlang_1 sh -c "sed -i '/auth.ldap.servers/c auth.ldap.servers = ldap_server' ./emqx_auth_ldap/etc/emqx_auth_ldap.conf" - else - ipv6_address=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.GlobalIPv6Address}}{{end}}' $(docker ps -a -f name=tests_ldap_server_1 -q)) - docker exec -i $(docker ps -a -f name=tests_erlang_1 -q) sh -c "sed -i '/auth.ldap.servers/c auth.ldap.servers = $ipv6_address' /emqx_auth_ldap/etc/emqx_auth_ldap.conf" - fi - - name: run test cases - run: | - set -e -x -u - docker exec -i tests_erlang_1 sh -c "make -C /emqx_auth_ldap xref" - docker exec -i tests_erlang_1 sh -c "make -C /emqx_auth_ldap eunit" - docker exec -i tests_erlang_1 sh -c "make -C /emqx_auth_ldap ct" - docker exec -i tests_erlang_1 sh -c "make -C /emqx_auth_ldap cover" - - uses: actions/upload-artifact@v1 - if: failure() - with: - name: logs_${{ matrix.network_type }} - path: _build/test/logs - diff --git a/apps/emqx_auth_ldap/src/emqx_auth_ldap.app.src.script b/apps/emqx_auth_ldap/src/emqx_auth_ldap.app.src.script deleted file mode 100644 index 0e14ff23f..000000000 --- a/apps/emqx_auth_ldap/src/emqx_auth_ldap.app.src.script +++ /dev/null @@ -1,24 +0,0 @@ -%%-*- mode: erlang -*- -%% .app.src.script - -RemoveLeadingV = - fun(Tag) -> - case re:run(Tag, "^[v|e]?[0-9]\.[0-9]\.([0-9]|(rc|beta|alpha)\.[0-9])", [{capture, none}]) of - nomatch -> - re:replace(Tag, "/", "-", [{return ,list}]); - _ -> - %% if it is a version number prefixed by 'v' or 'e', then remove it - re:replace(Tag, "[v|e]", "", [{return ,list}]) - end - end, - -case os:getenv("EMQX_DEPS_DEFAULT_VSN") of - false -> CONFIG; % env var not defined - [] -> CONFIG; % env var set to empty string - Tag -> - [begin - AppConf0 = lists:keystore(vsn, 1, AppConf, {vsn, RemoveLeadingV(Tag)}), - {application, App, AppConf0} - end || Conf = {application, App, AppConf} <- CONFIG] -end. - diff --git a/apps/emqx_auth_mnesia/.github/workflows/run_test_cases.yaml b/apps/emqx_auth_mnesia/.github/workflows/run_test_cases.yaml deleted file mode 100644 index 31efc5f92..000000000 --- a/apps/emqx_auth_mnesia/.github/workflows/run_test_cases.yaml +++ /dev/null @@ -1,29 +0,0 @@ -name: Run test cases - -on: [push, pull_request] - -jobs: - run_test_cases: - runs-on: ubuntu-latest - - container: - image: erlang:22.1 - - steps: - - uses: actions/checkout@v1 - - name: run test cases - run: | - make xref - make eunit - make ct - make cover - - uses: actions/upload-artifact@v1 - if: always() - with: - name: logs - path: _build/test/logs - - uses: actions/upload-artifact@v1 - with: - name: cover - path: _build/test/cover - diff --git a/apps/emqx_auth_mnesia/etc/emqx_auth_mnesia.conf b/apps/emqx_auth_mnesia/etc/emqx_auth_mnesia.conf index 5782ed459..ff74656cb 100644 --- a/apps/emqx_auth_mnesia/etc/emqx_auth_mnesia.conf +++ b/apps/emqx_auth_mnesia/etc/emqx_auth_mnesia.conf @@ -1,20 +1,30 @@ -## Examples: -##auth.mnesia.1.login = admin -##auth.mnesia.1.password = public -##auth.mnesia.1.is_superuser = true -##auth.mnesia.2.login = feng@emqtt.io -##auth.mnesia.2.password = public -##auth.mnesia.2.is_superuser = false -##auth.mnesia.3.login = name~!@#$%^&*()_+ -##auth.mnesia.3.password = pwsswd~!@#$%^&*()_+ -##auth.mnesia.3.is_superuser = false - ## Password hash. ## -## Value: plain | md5 | sha | sha256 +## Value: plain | md5 | sha | sha256 | sha512 auth.mnesia.password_hash = sha256 -## Auth as username or auth as clientid. -## -## Value: username | clientid -auth.mnesia.as = username +##-------------------------------------------------------------------- +## 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 index 31557ea63..034bd4f30 100644 --- a/apps/emqx_auth_mnesia/include/emqx_auth_mnesia.hrl +++ b/apps/emqx_auth_mnesia/include/emqx_auth_mnesia.hrl @@ -1,17 +1,20 @@ -define(APP, emqx_auth_mnesia). +-type(login():: {clientid, binary()} + | {username, binary()}). + -record(emqx_user, { - login, - password, - is_superuser - }). + login :: login(), + password :: binary(), + created_at :: integer() + }). -record(emqx_acl, { - login, - topic, - action, - allow - }). + filter:: {login() | all, emqx_topic:topic()}, + action :: pub | sub | pubsub, + access :: allow | deny, + created_at :: integer() + }). -record(auth_metrics, { success = 'client.auth.success', @@ -32,4 +35,4 @@ -define(AUTH_METRICS(K), ?METRICS(auth_metrics, K)). -define(ACL_METRICS, ?METRICS(acl_metrics)). --define(ACL_METRICS(K), ?METRICS(acl_metrics, K)). \ No newline at end of file +-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 index 34333b145..87d6bf47f 100644 --- a/apps/emqx_auth_mnesia/priv/emqx_auth_mnesia.schema +++ b/apps/emqx_auth_mnesia/priv/emqx_auth_mnesia.schema @@ -1,34 +1,42 @@ %%-*- mode: erlang -*- %% emqx_auth_mnesia config mapping -{mapping, "auth.mnesia.as", "emqx_auth_mnesia.as", [ - {default, username}, - {datatype, {enum, [username, clientid]}} -]}. - {mapping, "auth.mnesia.password_hash", "emqx_auth_mnesia.password_hash", [ {default, sha256}, - {datatype, {enum, [plain, md5, sha, sha256]}} + {datatype, {enum, [plain, md5, sha, sha256, sha512]}} ]}. -{mapping, "auth.mnesia.$id.login", "emqx_auth_mnesia.userlist", [ +{mapping, "auth.client.$id.clientid", "emqx_auth_mnesia.clientid_list", [ {datatype, string} ]}. -{mapping, "auth.mnesia.$id.password", "emqx_auth_mnesia.userlist", [ +{mapping, "auth.client.$id.password", "emqx_auth_mnesia.clientid_list", [ {datatype, string} ]}. -{mapping, "auth.mnesia.$id.is_superuser", "emqx_auth_mnesia.userlist", [ - {default, false}, - {datatype, {enum, [false, true]}} -]}. - -{translation, "emqx_auth_mnesia.userlist", fun(Conf) -> - Userlist = cuttlefish_variable:filter_by_prefix("auth.mnesia", Conf), +{translation, "emqx_auth_mnesia.clientid_list", fun(Conf) -> + ClientList = cuttlefish_variable:filter_by_prefix("auth.client", Conf), lists:foldl( - fun({["auth", "mnesia", Id, "login"], Username}, AccIn) -> - [{Username, cuttlefish:conf_get("auth.mnesia." ++ Id ++ ".password", Conf), cuttlefish:conf_get("auth.mnesia." ++ Id ++ ".is_superuser", Conf)} | AccIn]; + 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) diff --git a/apps/emqx_auth_mnesia/rebar.config b/apps/emqx_auth_mnesia/rebar.config index f319eb80d..8ad5b9c60 100644 --- a/apps/emqx_auth_mnesia/rebar.config +++ b/apps/emqx_auth_mnesia/rebar.config @@ -2,7 +2,7 @@ {deps, [{emqx_passwd, {git, "https://github.com/emqx/emqx-passwd.git", {tag, "v1.1.1"}}}, - {minirest, {git, "https://github.com/emqx/minirest.git", {tag, "0.3.1"}}} + {minirest, {git, "https://github.com/emqx/minirest.git", {tag, "0.3.2"}}} ]}. {profiles, diff --git a/apps/emqx_auth_mnesia/src/emqx_acl_mnesia.erl b/apps/emqx_auth_mnesia/src/emqx_acl_mnesia.erl index 63a357979..c657e54a0 100644 --- a/apps/emqx_auth_mnesia/src/emqx_acl_mnesia.erl +++ b/apps/emqx_auth_mnesia/src/emqx_acl_mnesia.erl @@ -18,6 +18,10 @@ -include("emqx_auth_mnesia.hrl"). +-include_lib("stdlib/include/ms_transform.hrl"). + +-define(TABLE, emqx_acl). + %% ACL Callbacks -export([ init/0 , register_metrics/0 @@ -27,22 +31,38 @@ init() -> ok = ekka_mnesia:create_table(emqx_acl, [ - {type, bag}, {disc_copies, [node()]}, {attributes, record_info(fields, emqx_acl)}, {storage_properties, [{ets, [{read_concurrency, true}]}]}]), - ok = ekka_mnesia:copy_table(emqx_user, disc_copies). + 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, PubSub, Topic, NoMatchAction, #{key_as := As}) -> - Login = maps:get(As, ClientInfo), - case do_check_acl(Login, PubSub, Topic, NoMatchAction) of - ok -> emqx_metrics:inc(?ACL_METRICS(ignore)), ok; - {stop, allow} -> emqx_metrics:inc(?ACL_METRICS(allow)), {stop, allow}; - {stop, deny} -> emqx_metrics:inc(?ACL_METRICS(deny)), {stop, deny} +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". @@ -51,33 +71,33 @@ description() -> "Acl with Mnesia". %% Internal functions %%------------------------------------------------------------------- -do_check_acl(Login, PubSub, Topic, _NoMatchAction) -> - case match(PubSub, Topic, emqx_auth_mnesia_cli:lookup_acl(Login)) of - allow -> {stop, allow}; - deny -> {stop, deny}; - _ -> - case match(PubSub, Topic, emqx_auth_mnesia_cli:lookup_acl(<<"$all">>)) of - allow -> {stop, allow}; - deny -> {stop, deny}; - _ -> ok - end - end. - -match(_PubSub, _Topic, []) -> +match(_ClientInfo, _PubSub, _Topic, []) -> nomatch; -match(PubSub, Topic, [ #emqx_acl{topic = ACLTopic, action = Action, allow = Allow} | UserAcl]) -> - case match_actions(PubSub, Action) andalso match_topic(Topic, ACLTopic) of - true -> case Allow of - true -> allow; - _ -> deny - end; - false -> match(PubSub, Topic, UserAcl) +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(Topic, ACLTopic) when is_binary(Topic) -> - emqx_topic:match(Topic, ACLTopic). +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(_, 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 index 3891b7ffd..8f858dfa6 100644 --- a/apps/emqx_auth_mnesia/src/emqx_acl_mnesia_api.erl +++ b/apps/emqx_auth_mnesia/src/emqx_acl_mnesia_api.erl @@ -1,4 +1,4 @@ -%%-------------------------------------------------------------------- +%c%-------------------------------------------------------------------- %% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,94 +18,174 @@ -include("emqx_auth_mnesia.hrl"). --import(proplists, [get_value/2]). +-include_lib("stdlib/include/ms_transform.hrl"). + +-import(proplists, [ get_value/2 + , get_value/3 + ]). -import(minirest, [return/1]). --rest_api(#{name => list_emqx_acl, +-rest_api(#{name => list_clientid, method => 'GET', - path => "/mqtt_acl", - func => list, + path => "/acl/clientid", + func => list_clientid, descr => "List available mnesia in the cluster" }). --rest_api(#{name => lookup_emqx_acl, +-rest_api(#{name => list_username, method => 'GET', - path => "/mqtt_acl/:bin:login", + 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 => add_emqx_acl, +-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 => "/mqtt_acl", + path => "/acl", func => add, descr => "Add mnesia in the cluster" }). --rest_api(#{name => delete_emqx_acl, +-rest_api(#{name => delete_clientid, method => 'DELETE', - path => "/mqtt_acl/:bin:login/:bin:topic", + path => "/acl/clientid/:bin:clientid/topic/:bin:topic", func => delete, descr => "Delete mnesia in the cluster" }). --export([ list/2 +-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(_Bindings, Params) -> - return({ok, emqx_auth_mnesia_api:paginate(emqx_acl, Params, fun format/1)}). +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)}). -lookup(#{login := Login}, _Params) -> - return({ok, format(emqx_auth_mnesia_cli:lookup_acl(urldecode(Login)))}). +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(add_acl(Params, [])); - false -> return(add_acl([Params], [])) + 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. -add_acl([ Params | ParamsN ], ReList ) -> - Login = urldecode(get_value(<<"login">>, Params)), - Topic = urldecode(get_value(<<"topic">>, Params)), - Action = urldecode(get_value(<<"action">>, Params)), - Allow = get_value(<<"allow">>, Params), - Re = case validate([login, topic, action, allow], [Login, Topic, Action, Allow]) of - ok -> - emqx_auth_mnesia_cli:add_acl(Login, Topic, Action, Allow); - Err -> Err - end, - add_acl(ParamsN, [{Login, format_msg(Re)} | ReList]); - -add_acl([], ReList) -> +do_add([ Params | ParamsN ], ReList) -> + do_add(ParamsN, [do_add(Params) | ReList]); + +do_add([], ReList) -> {ok, ReList}. -delete(#{login := Login, topic := Topic}, _) -> - return(emqx_auth_mnesia_cli:remove_acl(urldecode(Login), urldecode(Topic))). +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(#emqx_acl{login = Login, topic = Topic, action = Action, allow = Allow}) -> - #{login => Login, topic => Topic, action => Action, allow => Allow }; - -format([]) -> - #{}; - -format([#emqx_acl{login = Login, topic = Topic, action = Action, allow = Allow}]) -> - format(#emqx_acl{login = Login, topic = Topic, action = Action, allow = Allow}); - -format([ #emqx_acl{login = _Key, topic = _Topic, action = _Action, allow = _Allow}| _] = List) -> +format({{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([#emqx_acl{login = Login, topic = Topic, action = Action, allow = Allow} | List], ReList) -> - format(List, [ format(#emqx_acl{login = Login, topic = Topic, action = Action, allow = Allow}) | ReList]); -format([], ReList) -> ReList. + +format([L | List], Relist) -> + format(List, [format(L) | Relist]); +format([], ReList) -> lists:reverse(ReList). validate([], []) -> ok; @@ -114,8 +194,18 @@ validate([K|Keys], [V|Values]) -> false -> {error, K}; true -> validate(Keys, Values) end. - -do_validation(login, V) when is_binary(V) +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) @@ -126,7 +216,7 @@ do_validation(action, V) when is_binary(V) -> true -> true; false -> false end; -do_validation(allow, V) when is_boolean(V) -> +do_validation(access, V) when V =:= <<"allow">> orelse V =:= <<"deny">> -> true; do_validation(_, _) -> false. @@ -145,4 +235,3 @@ urldecode(S) -> 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.script b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.app.src.script deleted file mode 100644 index 0e14ff23f..000000000 --- a/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.app.src.script +++ /dev/null @@ -1,24 +0,0 @@ -%%-*- mode: erlang -*- -%% .app.src.script - -RemoveLeadingV = - fun(Tag) -> - case re:run(Tag, "^[v|e]?[0-9]\.[0-9]\.([0-9]|(rc|beta|alpha)\.[0-9])", [{capture, none}]) of - nomatch -> - re:replace(Tag, "/", "-", [{return ,list}]); - _ -> - %% if it is a version number prefixed by 'v' or 'e', then remove it - re:replace(Tag, "[v|e]", "", [{return ,list}]) - end - end, - -case os:getenv("EMQX_DEPS_DEFAULT_VSN") of - false -> CONFIG; % env var not defined - [] -> CONFIG; % env var set to empty string - Tag -> - [begin - AppConf0 = lists:keystore(vsn, 1, AppConf, {vsn, RemoveLeadingV(Tag)}), - {application, App, AppConf0} - end || Conf = {application, App, AppConf} <- CONFIG] -end. - diff --git a/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.erl b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.erl index 4dec64570..bb413b6d9 100644 --- a/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.erl +++ b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.erl @@ -22,6 +22,9 @@ -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 @@ -29,48 +32,53 @@ , description/0 ]). -init(DefaultUsers) -> +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}]}]}]), - ok = lists:foreach(fun add_default_user/1, DefaultUsers), + [ 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, IsSuperuser}) -> - emqx_auth_mnesia_cli:add_user(iolist_to_binary(Login), iolist_to_binary(Password), IsSuperuser). +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 = #{password := Password}, AuthResult, #{hash_type := HashType, key_as := As}) -> - Login = maps:get(As, ClientInfo), - case emqx_auth_mnesia_cli:lookup_user(Login) of +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; - [User] -> - case emqx_passwd:check_pass({User#emqx_user.password, Password}, HashType) of - ok -> - emqx_metrics:inc(?AUTH_METRICS(success)), - {stop, AuthResult#{is_superuser => is_superuser(User), - anonymous => false, - auth_result => success}}; - {error, Reason} -> - ?LOG(error, "[Mnesia] Auth from mnesia failed: ~p", [Reason]), + 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#{auth_result => password_error, anonymous => false}} + {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". -%%-------------------------------------------------------------------- -%% Internal functions -%%-------------------------------------------------------------------- -is_superuser(#emqx_user{is_superuser = true}) -> - true; -is_superuser(_) -> - false. +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 index 7c527b0fd..ee52fcf36 100644 --- a/apps/emqx_auth_mnesia/src/emqx_auth_mnesia_api.erl +++ b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia_api.erl @@ -17,100 +17,206 @@ -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]). --rest_api(#{name => list_emqx_user, - method => 'GET', - path => "/mqtt_user", - func => list, - descr => "List available mnesia in the cluster" - }). - --rest_api(#{name => lookup_emqx_user, - method => 'GET', - path => "/mqtt_user/:bin:login", - func => lookup, - descr => "Lookup mnesia in the cluster" - }). - --rest_api(#{name => add_emqx_user, - method => 'POST', - path => "/mqtt_user", - func => add, - descr => "Add mnesia in the cluster" - }). - --rest_api(#{name => update_emqx_user, - method => 'PUT', - path => "/mqtt_user/:bin:login", - func => update, - descr => "Update mnesia in the cluster" - }). - --rest_api(#{name => delete_emqx_user, - method => 'DELETE', - path => "/mqtt_user/:bin:login", - func => delete, - descr => "Delete mnesia in the cluster" - }). - --export([ list/2 - , lookup/2 - , add/2 - , update/2 - , delete/2 +-export([ list_clientid/2 + , lookup_clientid/2 + , add_clientid/2 + , update_clientid/2 + , delete_clientid/2 ]). --export([paginate/3]). +-rest_api(#{name => list_clientid, + method => 'GET', + path => "/auth_clientid", + func => list_clientid, + descr => "List available clientid in the cluster" + }). -list(_Bindings, Params) -> - return({ok, paginate(emqx_user, Params, fun format/1)}). +-rest_api(#{name => lookup_clientid, + method => 'GET', + path => "/auth_clientid/:bin:clientid", + func => lookup_clientid, + descr => "Lookup clientid in the cluster" + }). -lookup(#{login := Login}, _Params) -> - return({ok, format(emqx_auth_mnesia_cli:lookup_user(urldecode(Login)))}). +-rest_api(#{name => add_clientid, + method => 'POST', + path => "/auth_clientid", + func => add_clientid, + descr => "Add clientid in the cluster" + }). -add(_Bindings, Params) -> +-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(add_user(Params, [])); - false -> return(add_user([Params], [])) + 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. -add_user([ Params | ParamsN ], ReList ) -> - Login = urldecode(get_value(<<"login">>, Params)), - Password = urldecode(get_value(<<"password">>, Params)), - IsSuperuser = get_value(<<"is_superuser">>, Params), - Re = case validate([login, password, is_superuser], [Login, Password, IsSuperuser]) of - ok -> - emqx_auth_mnesia_cli:add_user(Login, Password, IsSuperuser); - Err -> Err - end, - add_user(ParamsN, [{Login, format_msg(Re)} | ReList]); - -add_user([], ReList) -> +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}. -update(#{login := Login}, Params) -> +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), - IsSuperuser = get_value(<<"is_superuser">>, Params), - case validate([password, is_superuser], [Password, IsSuperuser]) of - ok -> return(emqx_auth_mnesia_cli:update_user(urldecode(Login), urldecode(Password), IsSuperuser)); + case validate([password], [Password]) of + ok -> return(emqx_auth_mnesia_cli:update_user({clientid, urldecode(Clientid)}, urldecode(Password))); Err -> return(Err) end. -delete(#{login := Login}, _) -> - return(emqx_auth_mnesia_cli:remove_user(urldecode(Login))). +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, Params, RowFun) -> - Qh = query_handle(Tables), - Count = count(Tables), +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), @@ -121,21 +227,28 @@ paginate(Tables, Params, RowFun) -> Rows = qlc:next_answers(Cursor, Limit), qlc:delete_cursor(Cursor), #{meta => #{page => Page, limit => Limit, count => Count}, - data => [RowFun(Row) || Row <- Rows]}. + data => [RowFun(Row) || Row <- lists:sort(ComparingFun, Rows)]}. -query_handle(Table) when is_atom(Table) -> - qlc:q([R|| R <- ets:table(Table)]); -query_handle([Table]) when is_atom(Table) -> - qlc:q([R|| R <- ets:table(Table)]); -query_handle(Tables) -> - qlc:append([qlc:q([E || E <- ets:table(T)]) || T <- Tables]). +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) when is_atom(Table) -> - ets:info(Table, size); -count([Table]) when is_atom(Table) -> - ets:info(Table, size); -count(Tables) -> - lists:sum([count(T) || T <- Tables]). +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">>)). @@ -146,24 +259,28 @@ limit(Params) -> Size -> binary_to_integer(Size) end. - - %%------------------------------------------------------------------------------ %% Interval Funcs %%------------------------------------------------------------------------------ -format({emqx_user, Login, Password, IsSuperuser}) -> - #{login => Login, - password => Password, - is_superuser => IsSuperuser}; +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([]) -> - #{}; - -format([{emqx_user, Login, Password, IsSuperuser}]) -> - #{login => Login, - password => Password, - is_superuser => IsSuperuser}. + #{}. validate([], []) -> ok; @@ -173,14 +290,15 @@ validate([K|Keys], [V|Values]) -> true -> validate(Keys, Values) end. -do_validation(login, V) when is_binary(V) +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(is_superuser, V) when is_boolean(V) -> - true; do_validation(_, _) -> false. diff --git a/apps/emqx_auth_mnesia/src/emqx_auth_mnesia_app.erl b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia_app.erl index 094eba0ea..cfc9df995 100644 --- a/apps/emqx_auth_mnesia/src/emqx_auth_mnesia_app.erl +++ b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia_app.erl @@ -34,8 +34,10 @@ start(_StartType, _StartArgs) -> {ok, Sup} = emqx_auth_mnesia_sup:start_link(), - emqx_ctl:register_command('mqtt-user', {emqx_auth_mnesia_cli, auth_cli}, []), - emqx_ctl:register_command('mqtt-acl', {emqx_auth_mnesia_cli, acl_cli}, []), + 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}. @@ -43,28 +45,26 @@ start(_StartType, _StartArgs) -> prep_stop(State) -> emqx:unhook('client.authenticate', fun emqx_auth_mnesia:check/3), emqx:unhook('client.check_acl', fun emqx_acl_mnesia:check_acl/5), - emqx_ctl:unregister_command('mqtt-user'), - emqx_ctl:unregister_command('mqtt-acl'), + 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() -> - DefaultUsers = application:get_env(?APP, userlist, []), - ok = emqx_auth_mnesia:init(DefaultUsers), + 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), - key_as => application:get_env(emqx_auth_mnesia, as, username) + 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(), - Params = #{ - key_as => application:get_env(emqx_auth_mnesia, as, username) - }, - emqx:hook('client.check_acl', fun emqx_acl_mnesia:check_acl/5, [Params]). - + 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 index 83b1f32c0..b937eb238 100644 --- a/apps/emqx_auth_mnesia/src/emqx_auth_mnesia_cli.erl +++ b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia_cli.erl @@ -18,31 +18,32 @@ -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/3 - , update_user/3 +-export([ add_user/2 + , update_user/2 , remove_user/1 , lookup_user/1 , all_users/0 - ]). -%% Acl APIs --export([ add_acl/4 - , remove_acl/2 - , lookup_acl/1 - , all_acls/0 + , all_users/1 ]). %% Cli --export([ auth_cli/1 - , acl_cli/1]). +-export([ auth_clientid_cli/1 + , auth_username_cli/1 + ]). + +%% Helper +-export([comparing/2]). + %%-------------------------------------------------------------------- %% Auth APIs %%-------------------------------------------------------------------- %% @doc Add User --spec(add_user(binary(), binary(), atom()) -> ok | {error, any()}). -add_user(Login, Password, IsSuperuser) -> - User = #emqx_user{login = Login, password = encrypted_data(Password), is_superuser = IsSuperuser}, +-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}) -> @@ -52,30 +53,31 @@ insert_user(User = #emqx_user{login = Login}) -> end. %% @doc Update User --spec(update_user(binary(), binary(), atom()) -> ok | {error, any()}). -update_user(Login, NewPassword, IsSuperuser) -> - User = #emqx_user{login = Login, password = encrypted_data(NewPassword), is_superuser = IsSuperuser}, +-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 - [_|_] -> mnesia:write(User); + [{?TABLE, Login, _, CreateAt}] -> mnesia:write(User#emqx_user{created_at = CreateAt}); [] -> mnesia:abort(noexisted) end. %% @doc Lookup user by login --spec(lookup_user(binary()) -> list()). +-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 -> Re + Re -> + lists:sort(fun comparing/2, Re) end. %% @doc Remove user --spec(remove_user(binary()) -> ok | {error, any()}). +-spec(remove_user(tuple()) -> ok | {error, any()}). remove_user(Login) -> ret(mnesia:transaction(fun mnesia:delete/1, [{?TABLE, Login}])). @@ -83,111 +85,97 @@ remove_user(Login) -> -spec(all_users() -> list()). all_users() -> mnesia:dirty_all_keys(?TABLE). -%%-------------------------------------------------------------------- -%% Acl API -%%-------------------------------------------------------------------- - -%% @doc Add Acls --spec(add_acl(binary(), binary(), binary(), atom()) -> ok | {error, any()}). -add_acl(Login, Topic, Action, Allow) -> - Acls = #emqx_acl{login = Login, topic = Topic, action = Action, allow = Allow}, - ret(mnesia:transaction(fun mnesia:write/1, [Acls])). - -%% @doc Lookup acl by login --spec(lookup_acl(binary()) -> list()). -lookup_acl(undefined) -> []; -lookup_acl(Login) -> - case mnesia:dirty_read(emqx_acl, Login) of - {error, Reason} -> - ?LOG(error, "[Mnesia] do_check_acl error: ~p~n", [Reason]), - []; - Re -> Re - end. - -%% @doc Remove acl --spec(remove_acl(binary(), binary()) -> ok | {error, any()}). -remove_acl(Login, Topic) -> - [ ok = mnesia:dirty_delete_object(emqx_acl, #emqx_acl{login = Login, topic = Topic, action = Action, allow = Allow}) || [Action, Allow] <- ets:select(emqx_acl, [{{emqx_acl, Login, Topic,'$1','$2'}, [], ['$$']}])], - ok. - - -%% @doc All logins --spec(all_acls() -> list()). -all_acls() -> mnesia:dirty_all_keys(emqx_acl). +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, hash_type, sha256), - emqx_passwd:hash(HashType, 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 APIs +%% Auth Clientid Cli %%-------------------------------------------------------------------- -%% User -auth_cli(["add", Login, Password, IsSuperuser]) -> - case add_user(iolist_to_binary(Login), iolist_to_binary(Password), IsSuperuser) of +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_cli(["update", Login, NewPassword, IsSuperuser]) -> - case update_user(iolist_to_binary(Login), iolist_to_binary(NewPassword), IsSuperuser) of +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_cli(["del", Login]) -> - case remove_user(iolist_to_binary(Login)) of +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_cli(["show", P]) -> - [emqx_ctl:print("User(login = ~p is_super = ~p)~n", [Login, IsSuperuser]) - || {_, Login, _Password, IsSuperuser} <- lookup_user(iolist_to_binary(P))]; +auth_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_cli(["list"]) -> - [emqx_ctl:print("User(login = ~p)~n",[E]) - || E <- all_users()]; +%%-------------------------------------------------------------------- +%% Auth Username Cli +%%-------------------------------------------------------------------- -auth_cli(_) -> - emqx_ctl:usage([{"mqtt-user add ", "Add user"}, - {"mqtt-user update ", "Update user"}, - {"mqtt-user delete ", "Delete user"}, - {"mqtt-user show ", "Lookup user detail"}, - {"mqtt-user list", "List all users"}]). +auth_username_cli(["list"]) -> + [emqx_ctl:print("~s~n", [Username]) || {?TABLE, {username, Username}, _Password, _CreatedAt}<- all_users(username)]; -%% Acl -acl_cli(["add", Login, Topic, Action, Allow]) -> - case add_acl(iolist_to_binary(Login), iolist_to_binary(Topic), iolist_to_binary(Action), Allow) of +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; -acl_cli(["del", Login, Topic])-> - case remove_acl(iolist_to_binary(Login), iolist_to_binary(Topic)) of - ok -> emqx_ctl:print("ok~n"); +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; -acl_cli(["show", P]) -> - [emqx_ctl:print("Acl(login = ~p topic = ~p action = ~p allow = ~p)~n",[Login, Topic, Action, Allow]) - || {_, Login, Topic, Action, Allow} <- lookup_acl(iolist_to_binary(P)) ]; +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; -acl_cli(["list"]) -> - [emqx_ctl:print("Acl(login = ~p)~n",[E]) - || E <- all_acls() ]; - -acl_cli(_) -> - emqx_ctl:usage([{"mqtt-acl add ", "Add acl"}, - {"mqtt-acl show ", "Lookup acl detail"}, - {"mqtt-acl del ", "Delete acl"}, - {"mqtt-acl list","List all acls"}]). +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/test/emqx_acl_mnesia_SUITE.erl b/apps/emqx_auth_mnesia/test/emqx_acl_mnesia_SUITE.erl index 11cfca521..61356dd24 100644 --- a/apps/emqx_auth_mnesia/test/emqx_acl_mnesia_SUITE.erl +++ b/apps/emqx_auth_mnesia/test/emqx_acl_mnesia_SUITE.erl @@ -76,154 +76,41 @@ set_special_configs(_App) -> t_management(_Config) -> clean_all_acls(), ?assertEqual("Acl with Mnesia", emqx_acl_mnesia:description()), - ?assertEqual([], emqx_auth_mnesia_cli:all_acls()), + ?assertEqual([], emqx_acl_mnesia_cli:all_acls()), - ok = emqx_auth_mnesia_cli:add_acl(<<"test_username">>, <<"Topic/A">>, <<"sub">>, true), - ok = emqx_auth_mnesia_cli:add_acl(<<"test_username">>, <<"Topic/B">>, <<"pub">>, true), - ok = emqx_auth_mnesia_cli:add_acl(<<"test_username">>, <<"Topic/C">>, <<"pubsub">>, true), - - ?assertEqual([{emqx_acl,<<"test_username">>,<<"Topic/A">>,<<"sub">>, true}, - {emqx_acl,<<"test_username">>,<<"Topic/B">>,<<"pub">>, true}, - {emqx_acl,<<"test_username">>,<<"Topic/C">>,<<"pubsub">>, true}],emqx_auth_mnesia_cli:lookup_acl(<<"test_username">>)), - ok = emqx_auth_mnesia_cli:remove_acl(<<"test_username">>, <<"Topic/A">>), - ?assertEqual([{emqx_acl,<<"test_username">>,<<"Topic/B">>,<<"pub">>, true}, - {emqx_acl,<<"test_username">>,<<"Topic/C">>,<<"pubsub">>, true}], emqx_auth_mnesia_cli:lookup_acl(<<"test_username">>)), + ok = emqx_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), - - ok = emqx_auth_mnesia_cli:add_acl(<<"$all">>, <<"Topic/A">>, <<"sub">>, true), - ok = emqx_auth_mnesia_cli:add_acl(<<"$all">>, <<"Topic/B">>, <<"pub">>, true), - ok = emqx_auth_mnesia_cli:add_acl(<<"$all">>, <<"Topic/C">>, <<"pubsub">>, true), - - ?assertEqual([{emqx_acl,<<"$all">>,<<"Topic/A">>,<<"sub">>, true}, - {emqx_acl,<<"$all">>,<<"Topic/B">>,<<"pub">>, true}, - {emqx_acl,<<"$all">>,<<"Topic/C">>,<<"pubsub">>, true}],emqx_auth_mnesia_cli:lookup_acl(<<"$all">>)), - ok = emqx_auth_mnesia_cli:remove_acl(<<"$all">>, <<"Topic/A">>), - ?assertEqual([{emqx_acl,<<"$all">>,<<"Topic/B">>,<<"pub">>, true}, - {emqx_acl,<<"$all">>,<<"Topic/C">>,<<"pubsub">>, true}], emqx_auth_mnesia_cli:lookup_acl(<<"$all">>)). - -t_check_acl_as_clientid(_) -> - clean_all_acls(), - emqx_modules:load_module(emqx_mod_acl_internal, false), + ?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">>}, + 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_auth_mnesia_cli:add_acl(<<"test_clientid">>, <<"#">>, <<"sub">>, false), - ok = emqx_auth_mnesia_cli:add_acl(<<"test_clientid">>, <<"+/A">>, <<"pub">>, false), - ok = emqx_auth_mnesia_cli:add_acl(<<"test_clientid">>, <<"Topic/A/B">>, <<"pubsub">>, true), + 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, <<"#">>), - deny = emqx_access_control:check_acl(User1, subscribe, <<"Any">>), - deny = emqx_access_control:check_acl(User1, publish, <<"Any/A">>), - allow = emqx_access_control:check_acl(User1, publish, <<"Any/C">>), - allow = emqx_access_control:check_acl(User1, publish, <<"Topic/A/B">>), + ?assertEqual([], emqx_acl_mnesia_cli:all_acls()). - allow = emqx_access_control:check_acl(User2, subscribe, <<"Topic/C">>), - allow = emqx_access_control:check_acl(User2, publish, <<"Topic/D">>). - -t_check_acl_as_username(_Config) -> - clean_all_acls(), - emqx_modules:load_module(emqx_mod_acl_internal, false), - - User1 = #{zone => external, username => <<"test_username">>}, - User2 = #{zone => external, username => <<"no_exist">>}, - - ok = emqx_auth_mnesia_cli:add_acl(<<"test_username">>, <<"Topic/A">>, <<"sub">>, true), - ok = emqx_auth_mnesia_cli:add_acl(<<"test_username">>, <<"Topic/B">>, <<"pub">>, true), - ok = emqx_auth_mnesia_cli:add_acl(<<"test_username">>, <<"Topic/A/B">>, <<"pubsub">>, false), - allow = emqx_access_control:check_acl(User1, subscribe, <<"Topic/A">>), - allow = emqx_access_control:check_acl(User1, subscribe, <<"Topic/B">>), - deny = emqx_access_control:check_acl(User1, subscribe, <<"Topic/A/B">>), - allow = emqx_access_control:check_acl(User1, publish, <<"Topic/A">>), - allow = emqx_access_control:check_acl(User1, publish, <<"Topic/B">>), - deny = emqx_access_control:check_acl(User1, publish, <<"Topic/A/B">>), - - allow = emqx_access_control:check_acl(User2, subscribe, <<"Topic/C">>), - allow = emqx_access_control:check_acl(User2, publish, <<"Topic/D">>). - -t_check_acl_as_all(_) -> - clean_all_acls(), - emqx_modules:load_module(emqx_mod_acl_internal, false), - - ok = emqx_auth_mnesia_cli:add_acl(<<"$all">>, <<"Topic/A">>, <<"sub">>, false), - ok = emqx_auth_mnesia_cli:add_acl(<<"$all">>, <<"Topic/B">>, <<"pub">>, false), - ok = emqx_auth_mnesia_cli:add_acl(<<"$all">>, <<"Topic/A/B">>, <<"pubsub">>, true), - - User1 = #{zone => external, username => <<"test_username">>}, - User2 = #{zone => external, username => <<"no_exist">>}, - - ok = emqx_auth_mnesia_cli:add_acl(<<"test_username">>, <<"Topic/A">>, <<"sub">>, true), - ok = emqx_auth_mnesia_cli:add_acl(<<"test_username">>, <<"Topic/B">>, <<"pub">>, true), - ok = emqx_auth_mnesia_cli:add_acl(<<"test_username">>, <<"Topic/A/B">>, <<"pubsub">>, false), - - allow = emqx_access_control:check_acl(User1, subscribe, <<"Topic/A">>), - allow = emqx_access_control:check_acl(User1, subscribe, <<"Topic/B">>), - deny = emqx_access_control:check_acl(User1, subscribe, <<"Topic/A/B">>), - allow = emqx_access_control:check_acl(User1, publish, <<"Topic/A">>), - allow = emqx_access_control:check_acl(User1, publish, <<"Topic/B">>), - deny = emqx_access_control:check_acl(User1, publish, <<"Topic/A/B">>), - - deny = emqx_access_control:check_acl(User2, subscribe, <<"Topic/A">>), - deny = emqx_access_control:check_acl(User2, publish, <<"Topic/B">>), - allow = emqx_access_control:check_acl(User2, subscribe, <<"Topic/A/B">>), - allow = emqx_access_control:check_acl(User2, publish, <<"Topic/A/B">>), - allow = emqx_access_control:check_acl(User2, subscribe, <<"Topic/C">>), - allow = emqx_access_control:check_acl(User2, publish, <<"Topic/D">>). - -t_rest_api(_Config) -> - clean_all_acls(), - - {ok, Result} = request_http_rest_list(), - [] = get_http_data(Result), - - Params = #{<<"login">> => <<"test_username">>, <<"topic">> => <<"Topic/A">>, <<"action">> => <<"pubsub">>, <<"allow">> => true}, - {ok, _} = request_http_rest_add(Params), - {ok, Result1} = request_http_rest_lookup(<<"test_username">>), - #{<<"login">> := <<"test_username">>, <<"topic">> := <<"Topic/A">>, <<"action">> := <<"pubsub">>, <<"allow">> := true} = get_http_data(Result1), - - Params1 = [ - #{<<"login">> => <<"$all">>, <<"topic">> => <<"+/A">>, <<"action">> => <<"pub">>, <<"allow">> => true}, - #{<<"login">> => <<"test_username">>, <<"topic">> => <<"+/A">>, <<"action">> => <<"pub">>, <<"allow">> => true}, - #{<<"login">> => <<"test_username/1">>, <<"topic">> => <<"#">>, <<"action">> => <<"sub">>, <<"allow">> => true}, - #{<<"login">> => <<"test_username/2">>, <<"topic">> => <<"+/A">>, <<"action">> => <<"error_format">>, <<"allow">> => true} - ], - {ok, Result2} = request_http_rest_add(Params1), - #{ - <<"$all">> := <<"ok">>, - <<"test_username">> := <<"ok">>, - <<"test_username/1">> := <<"ok">>, - <<"test_username/2">> := <<"{error,action}">> - } = get_http_data(Result2), - - {ok, Result3} = request_http_rest_lookup(<<"test_username">>), - [#{<<"login">> := <<"test_username">>, <<"topic">> := <<"+/A">>, <<"action">> := <<"pub">>, <<"allow">> := true}, - #{<<"login">> := <<"test_username">>, <<"topic">> := <<"Topic/A">>, <<"action">> := <<"pubsub">>, <<"allow">> := true}] - = get_http_data(Result3), - - {ok, Result4} = request_http_rest_lookup(<<"$all">>), - #{<<"login">> := <<"$all">>, <<"topic">> := <<"+/A">>, <<"action">> := <<"pub">>, <<"allow">> := true} - = get_http_data(Result4), - - {ok, _} = request_http_rest_delete(<<"$all">>, <<"+/A">>), - {ok, _} = request_http_rest_delete(<<"test_username">>, <<"+/A">>), - {ok, _} = request_http_rest_delete(<<"test_username">>, <<"Topic/A">>), - {ok, _} = request_http_rest_delete(<<"test_username/1">>, <<"#">>), - {ok, Result5} = request_http_rest_list(), - [] = get_http_data(Result5). - - -t_run_command(_) -> - clean_all_acls(), - ?assertEqual(ok, emqx_ctl:run_command(["mqtt-acl", "add", "TestUser", "Topic/A", "sub", true])), - ?assertEqual([{emqx_acl,<<"TestUser">>,<<"Topic/A">>,<<"sub">>, true}],emqx_auth_mnesia_cli:lookup_acl(<<"TestUser">>)), - - ?assertEqual(ok, emqx_ctl:run_command(["mqtt-acl", "del", "TestUser", "Topic/A"])), - ?assertEqual([],emqx_auth_mnesia_cli:lookup_acl(<<"TestUser">>)), - - ?assertEqual(ok, emqx_ctl:run_command(["mqtt-acl", "show", "TestUser"])), - ?assertEqual(ok, emqx_ctl:run_command(["mqtt-acl", "list"])), - ?assertEqual(ok, emqx_ctl:run_command(["mqtt-acl"])). - -t_cli(_) -> +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), @@ -231,18 +118,67 @@ t_cli(_) -> meck:expect(emqx_ctl, usage, fun(Cmd, Descr) -> emqx_ctl:format_usage(Cmd, Descr) end), clean_all_acls(), - ?assertMatch({match, _}, re:run(emqx_auth_mnesia_cli:acl_cli(["add", "TestUser", "Topic/A", "sub", true]), "ok")), - ?assertMatch(["Acl(login = <<\"TestUser\">> topic = <<\"Topic/A\">> action = <<\"sub\">> allow = true)\n"], emqx_auth_mnesia_cli:acl_cli(["show", "TestUser"])), - ?assertMatch(["Acl(login = <<\"TestUser\">>)\n"], emqx_auth_mnesia_cli:acl_cli(["list"])), - ?assertMatch({match, _}, re:run(emqx_auth_mnesia_cli:acl_cli(["del", "TestUser", "Topic/A"]), "ok")), - ?assertMatch([], emqx_auth_mnesia_cli:acl_cli(["show", "TestUser"])), - ?assertMatch([], emqx_auth_mnesia_cli:acl_cli(["list"])), + ?assertEqual(0, length(emqx_acl_mnesia_cli:cli(["list"]))), - ?assertMatch({match, _}, re:run(emqx_auth_mnesia_cli:acl_cli([]), "mqtt-acl")), + 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 %%------------------------------------------------------------------------------ @@ -255,22 +191,22 @@ clean_all_acls() -> %% HTTP Request %%-------------------------------------------------------------------- -request_http_rest_list() -> - request_api(get, uri(), default_auth_header()). +request_http_rest_list(Path) -> + request_api(get, uri(Path), default_auth_header()). -request_http_rest_lookup(Login) -> - request_api(get, uri([Login]), default_auth_header()). +request_http_rest_lookup(Path) -> + request_api(get, uri(Path), default_auth_header()). -request_http_rest_add(Params) -> - request_api(post, uri(), [], default_auth_header(), Params). +request_http_rest_add(Path, Params) -> + request_api(post, uri(Path), [], default_auth_header(), Params). -request_http_rest_delete(Login, Topic) -> - request_api(delete, uri([Login, Topic]), default_auth_header()). +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, "mqtt_acl"| NParts]). + ?HOST ++ filename:join([?BASE_PATH, ?API_VERSION, "acl"| NParts]). %% @private b2l(B) when is_binary(B) -> diff --git a/apps/emqx_auth_mnesia/test/emqx_auth_mnesia_SUITE.erl b/apps/emqx_auth_mnesia/test/emqx_auth_mnesia_SUITE.erl index 8979f4755..0f4884247 100644 --- a/apps/emqx_auth_mnesia/test/emqx_auth_mnesia_SUITE.erl +++ b/apps/emqx_auth_mnesia/test/emqx_auth_mnesia_SUITE.erl @@ -2,10 +2,7 @@ %% 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 +%% 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, @@ -33,6 +30,12 @@ -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). @@ -81,143 +84,166 @@ set_special_configs(_App) -> %% Testcases %%------------------------------------------------------------------------------ -t_check_as_username(_Config) -> +t_management(_Config) -> clean_all_users(), - ok = emqx_auth_mnesia_cli:add_user(<<"test_username">>, <<"password">>, true), - {error, existed} = emqx_auth_mnesia_cli:add_user(<<"test_username">>, <<"password">>, true), + ok = emqx_auth_mnesia_cli: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:update_user(<<"test_username">>, <<"new_password">>, false), - {error,noexisted} = emqx_auth_mnesia_cli:update_user(<<"no_existed_user">>, <<"password">>, true), + 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)), - [<<"test_username">>] = emqx_auth_mnesia_cli:all_users(), - [{emqx_user, <<"test_username">>, _HashedPass, false}] = - emqx_auth_mnesia_cli:lookup_user(<<"test_username">>), + ?assertEqual(2,length(emqx_auth_mnesia_cli:all_users())), - User1 = #{username => <<"test_username">>, - password => <<"new_password">>, + 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, #{is_superuser := false, - auth_result := success, + {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(<<"test_username">>), + ok = emqx_auth_mnesia_cli:remove_user({username,?USERNAME}), {ok, #{auth_result := success, - anonymous := true }} = emqx_access_control:authenticate(User1). + anonymous := true }} = emqx_access_control:authenticate(User1), -t_check_as_clientid(_Config) -> - clean_all_users(), - - ok = emqx_auth_mnesia_cli:add_user(<<"test_clientid">>, <<"password">>, false), - {error, existed} = emqx_auth_mnesia_cli:add_user(<<"test_clientid">>, <<"password">>, false), - - ok = emqx_auth_mnesia_cli:update_user(<<"test_clientid">>, <<"new_password">>, true), - {error,noexisted} = emqx_auth_mnesia_cli:update_user(<<"no_existed_user">>, <<"password">>, true), - - [<<"test_clientid">>] = emqx_auth_mnesia_cli:all_users(), - [{emqx_user, <<"test_clientid">>, _HashedPass, true}] = - emqx_auth_mnesia_cli:lookup_user(<<"test_clientid">>), - - User1 = #{clientid => <<"test_clientid">>, - password => <<"new_password">>, + User2 = #{clientid => ?CLIENTID, + password => ?NPASSWORD, zone => external}, - {ok, #{is_superuser := true, - auth_result := success, - anonymous := false}} = emqx_access_control:authenticate(User1), - - {error,password_error} = emqx_access_control:authenticate(User1#{password => <<"error_password">>}), - - ok = emqx_auth_mnesia_cli:remove_user(<<"test_clientid">>), {ok, #{auth_result := success, - anonymous := true }} = emqx_access_control:authenticate(User1). + anonymous := false}} = emqx_access_control:authenticate(User2), -t_rest_api(_Config) -> + {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(), - {ok, Result1} = request_http_rest_list(), + 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), - Params = #{<<"login">> => <<"test_username">>, <<"password">> => <<"password">>, <<"is_superuser">> => true}, - {ok, _} = request_http_rest_add(Params), + Params1 = #{<<"clientid">> => ?CLIENTID, <<"password">> => ?PASSWORD}, + {ok, _} = request_http_rest_add(["auth_clientid"], Params1), - Params1 = [ - #{<<"login">> => <<"test_username">>, <<"password">> => <<"password">>, <<"is_superuser">> => true}, - #{<<"login">> => <<"test_username/1">>, <<"password">> => <<"password">>, <<"is_superuser">> => error_format}, - #{<<"login">> => <<"test_username/2">>, <<"password">> => <<"password">>, <<"is_superuser">> => true} - ], - {ok, Result2} = request_http_rest_add(Params1), - #{ - <<"test_username">> := <<"{error,existed}">>, - <<"test_username/1">> := <<"{error,is_superuser}">>, - <<"test_username/2">> := <<"ok">> - } = get_http_data(Result2), + 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)), - {ok, Result3} = request_http_rest_lookup(<<"test_username">>), - #{<<"login">> := <<"test_username">>, <<"is_superuser">> := true} = get_http_data(Result3), + 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, _} = request_http_rest_update(<<"test_username">>, <<"new_password">>, error_format), - {ok, _} = request_http_rest_update(<<"error_username">>, <<"new_password">>, false), + {ok, Result4} = request_http_rest_list(["auth_clientid"]), + ?assertEqual(3, length(get_http_data(Result4))), - {ok, _} = request_http_rest_update(<<"test_username">>, <<"new_password">>, false), - {ok, Result4} = request_http_rest_lookup(<<"test_username">>), - #{<<"login">> := <<"test_username">>, <<"is_superuser">> := false} = get_http_data(Result4), - - User1 = #{username => <<"test_username">>, - password => <<"new_password">>, - zone => external}, - - {ok, #{is_superuser := false, - auth_result := success, - anonymous := false}} = emqx_access_control:authenticate(User1), - - {ok, _} = request_http_rest_delete(<<"test_username">>), - {ok, #{auth_result := success, - anonymous := true }} = emqx_access_control:authenticate(User1). - -t_run_command(_) -> - clean_all_users(), - ?assertEqual(ok, emqx_ctl:run_command(["mqtt-user", "add", "TestUser", "Password", false])), - ?assertMatch([{emqx_user, <<"TestUser">>, _, false}], emqx_auth_mnesia_cli:lookup_user(<<"TestUser">>)), - - ?assertEqual(ok, emqx_ctl:run_command(["mqtt-user", "update", "TestUser", "NewPassword", true])), - ?assertMatch([{emqx_user, <<"TestUser">>, _, true}], emqx_auth_mnesia_cli:lookup_user(<<"TestUser">>)), - - ?assertEqual(ok, emqx_ctl:run_command(["mqtt-user", "del", "TestUser"])), - ?assertMatch([], emqx_auth_mnesia_cli:lookup_user(<<"TestUser">>)), - - ?assertEqual(ok, emqx_ctl:run_command(["mqtt-user", "show", "TestUser"])), - ?assertEqual(ok, emqx_ctl:run_command(["mqtt-user", "list"])), - ?assertEqual(ok, emqx_ctl:run_command(["mqtt-user"])). - -t_cli(_) -> - meck:new(emqx_ctl, [non_strict, passthrough]), - meck:expect(emqx_ctl, print, fun(Arg) -> emqx_ctl:format(Arg) end), - meck:expect(emqx_ctl, print, fun(Msg, Arg) -> emqx_ctl:format(Msg, Arg) end), - meck:expect(emqx_ctl, usage, fun(Usages) -> emqx_ctl:format_usage(Usages) end), - meck:expect(emqx_ctl, usage, fun(Cmd, Descr) -> emqx_ctl:format_usage(Cmd, Descr) end), + {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(), - ?assertMatch({match, _}, re:run(emqx_auth_mnesia_cli:auth_cli(["add", "TestUser", "Password", true]), "ok")), - ?assertMatch({match, _}, re:run(emqx_auth_mnesia_cli:auth_cli(["add", "TestUser", "Password", true]), "Error")), + {ok, Result1} = request_http_rest_list(["auth_username"]), + [] = get_http_data(Result1), - ?assertMatch({match, _}, re:run(emqx_auth_mnesia_cli:auth_cli(["update", "NoExisted", "Password", false]), "Error")), - ?assertMatch({match, _}, re:run(emqx_auth_mnesia_cli:auth_cli(["update", "TestUser", "Password", false]), "ok")), + Params1 = #{<<"username">> => ?USERNAME, <<"password">> => ?PASSWORD}, + {ok, _} = request_http_rest_add(["auth_username"], Params1), - ?assertMatch(["User(login = <<\"TestUser\">> is_super = false)\n"], emqx_auth_mnesia_cli:auth_cli(["show", "TestUser"])), - ?assertMatch(["User(login = <<\"TestUser\">>)\n"], emqx_auth_mnesia_cli:auth_cli(["list"])), + Params2 = #{<<"username">> => ?USERNAME, <<"password">> => ?NPASSWORD}, + {ok, _} = request_http_rest_update(["auth_username/" ++ binary_to_list(?USERNAME)], Params2), - ?assertMatch({match, _}, re:run(emqx_auth_mnesia_cli:auth_cli(["del", "TestUser"]), "ok")), - ?assertMatch([], emqx_auth_mnesia_cli:auth_cli(["show", "TestUser"])), - ?assertMatch([], emqx_auth_mnesia_cli:auth_cli(["list"])), + {ok, Result2} = request_http_rest_lookup(["auth_username/" ++ binary_to_list(?USERNAME)]), + ?assertMatch(#{<<"username">> := ?USERNAME}, get_http_data(Result2)), - ?assertMatch({match, _}, re:run(emqx_auth_mnesia_cli:auth_cli([]), "mqtt-user")), + 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)), - meck:unload(emqx_ctl). + {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 @@ -231,18 +257,17 @@ clean_all_users() -> %% HTTP Request %%-------------------------------------------------------------------- -request_http_rest_list() -> - request_api(get, uri(), default_auth_header()). +request_http_rest_list(Path) -> + request_api(get, uri(Path), default_auth_header()). -request_http_rest_lookup(Login) -> - request_api(get, uri([Login]), default_auth_header()). +request_http_rest_lookup(Path) -> + request_api(get, uri([Path]), default_auth_header()). -request_http_rest_add(Params) -> - request_api(post, uri(), [], default_auth_header(), Params). +request_http_rest_add(Path, Params) -> + request_api(post, uri(Path), [], default_auth_header(), Params). -request_http_rest_update(Login, Password, IsSuperuser) -> - Params = #{<<"password">> => Password, <<"is_superuser">> => IsSuperuser}, - request_api(put, uri([Login]), [], default_auth_header(), Params). +request_http_rest_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()). @@ -250,7 +275,7 @@ request_http_rest_delete(Login) -> uri() -> uri([]). uri(Parts) when is_list(Parts) -> NParts = [b2l(E) || E <- Parts], - ?HOST ++ filename:join([?BASE_PATH, ?API_VERSION, "mqtt_user"| NParts]). + ?HOST ++ filename:join([?BASE_PATH, ?API_VERSION | NParts]). %% @private b2l(B) when is_binary(B) -> diff --git a/apps/emqx_auth_mongo/.github/workflows/run_test_cases.yaml b/apps/emqx_auth_mongo/.github/workflows/run_test_cases.yaml deleted file mode 100644 index 94217cacb..000000000 --- a/apps/emqx_auth_mongo/.github/workflows/run_test_cases.yaml +++ /dev/null @@ -1,59 +0,0 @@ -name: Run test cases - -on: [push, pull_request] - -jobs: - run_test_cases: - runs-on: ubuntu-latest - - strategy: - matrix: - mongo_tag: - - 3 - - 4 - network_type: - - ipv4 - - ipv6 - connect_type: - - ssl - - tcp - - steps: - - name: install docker-compose - run: | - sudo curl -L "https://github.com/docker/compose/releases/download/1.25.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose - sudo chmod +x /usr/local/bin/docker-compose - - uses: actions/checkout@v1 - - name: run test cases - env: - MONGO_TAG: ${{ matrix.mongo_tag }} - NETWORK_TYPE: ${{ matrix.network_type }} - CONNECT_TYPE: ${{ matrix.connect_type }} - run: | - set -e -u -x - if [ "$NETWORK_TYPE" = "ipv6" ];then docker network create --driver bridge --ipv6 --subnet fd15:555::/64 tests_emqx_bridge --attachable; fi - if [ "$CONNECT_TYPE" = "ssl" ]; then - docker-compose -f ./docker-compose-ssl.yml -p tests up -d - docker exec -i $(docker ps -a -f name=tests_erlang_1 -q) sh -c "echo 'auth.mongo.ssl = true' >> /emqx_auth_mongo/etc/emqx_auth_mongo.conf" - docker exec -i $(docker ps -a -f name=tests_erlang_1 -q) sh -c "echo 'auth.mongo.ssl_opts.cacertfile = /emqx_auth_mongo/test/emqx_auth_mongo_SUITE_data/ca.pem' >> /emqx_auth_mongo/etc/emqx_auth_mongo.conf" - docker exec -i $(docker ps -a -f name=tests_erlang_1 -q) sh -c "echo 'auth.mongo.ssl_opts.certfile = /emqx_auth_mongo/test/emqx_auth_mongo_SUITE_data/client-cert.pem' >> /emqx_auth_mongo/etc/emqx_auth_mongo.conf" - docker exec -i $(docker ps -a -f name=tests_erlang_1 -q) sh -c "echo 'auth.mongo.ssl_opts.keyfile = /emqx_auth_mongo/test/emqx_auth_mongo_SUITE_data/client-key.pem' >> /emqx_auth_mongo/etc/emqx_auth_mongo.conf" - else - docker-compose -f ./docker-compose.yml -p tests up -d - fi - if [ "$NETWORK_TYPE" != "ipv6" ];then - docker exec -i $(docker ps -a -f name=tests_erlang_1 -q) sh -c "sed -i '/auth.mongo.server/c auth.mongo.server = mongo_server:27017' /emqx_auth_mongo/etc/emqx_auth_mongo.conf" - else - ipv6_address=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.GlobalIPv6Address}}{{end}}' $(docker ps -a -f name=tests_mongo_server_1 -q)) - docker exec -i $(docker ps -a -f name=tests_erlang_1 -q) sh -c "sed -i '/auth.mongo.server/c auth.mongo.server = $ipv6_address:27017' /emqx_auth_mongo/etc/emqx_auth_mongo.conf" - fi - docker exec -i tests_erlang_1 sh -c "make -C /emqx_auth_mongo xref" - docker exec -i tests_erlang_1 sh -c "make -C /emqx_auth_mongo eunit" - docker exec -i tests_erlang_1 sh -c "make -C /emqx_auth_mongo ct" - docker exec -i tests_erlang_1 sh -c "make -C /emqx_auth_mongo cover" - - uses: actions/upload-artifact@v1 - if: failure() - with: - name: logs_mongo${{ matrix.mongo_tag}}_${{ matrix.network_type }} - path: _build/test/logs - diff --git a/apps/emqx_auth_mongo/src/emqx_auth_mongo.app.src.script b/apps/emqx_auth_mongo/src/emqx_auth_mongo.app.src.script deleted file mode 100644 index 0e14ff23f..000000000 --- a/apps/emqx_auth_mongo/src/emqx_auth_mongo.app.src.script +++ /dev/null @@ -1,24 +0,0 @@ -%%-*- mode: erlang -*- -%% .app.src.script - -RemoveLeadingV = - fun(Tag) -> - case re:run(Tag, "^[v|e]?[0-9]\.[0-9]\.([0-9]|(rc|beta|alpha)\.[0-9])", [{capture, none}]) of - nomatch -> - re:replace(Tag, "/", "-", [{return ,list}]); - _ -> - %% if it is a version number prefixed by 'v' or 'e', then remove it - re:replace(Tag, "[v|e]", "", [{return ,list}]) - end - end, - -case os:getenv("EMQX_DEPS_DEFAULT_VSN") of - false -> CONFIG; % env var not defined - [] -> CONFIG; % env var set to empty string - Tag -> - [begin - AppConf0 = lists:keystore(vsn, 1, AppConf, {vsn, RemoveLeadingV(Tag)}), - {application, App, AppConf0} - end || Conf = {application, App, AppConf} <- CONFIG] -end. - diff --git a/apps/emqx_auth_mongo/src/emqx_auth_mongo.appup.src b/apps/emqx_auth_mongo/src/emqx_auth_mongo.appup.src deleted file mode 100644 index d4e259d5e..000000000 --- a/apps/emqx_auth_mongo/src/emqx_auth_mongo.appup.src +++ /dev/null @@ -1,37 +0,0 @@ -%%-*-: erlang -*- -{"4.2.3", - [ - {"4.2.2", [ - {load_module, emqx_auth_mongo_app, brutal_purge, soft_purge, []}, - {load_module, emqx_auth_mongo, brutal_purge, soft_purge, []}, - {load_module, emqx_acl_mongo, brutal_purge, soft_purge, [emqx_auth_mongo]} - ]}, - {"4.2.1", [ - {load_module, emqx_auth_mongo_app, brutal_purge, soft_purge, []}, - {load_module, emqx_auth_mongo, brutal_purge, soft_purge, []}, - {load_module, emqx_acl_mongo, brutal_purge, soft_purge, [emqx_auth_mongo]} - ]}, - {"4.2.0", [ - {load_module, emqx_auth_mongo_app, brutal_purge, soft_purge, []}, - {load_module, emqx_auth_mongo, brutal_purge, soft_purge, []}, - {load_module, emqx_acl_mongo, brutal_purge, soft_purge, [emqx_auth_mongo]} - ]} - ], - [ - {"4.2.2", [ - {load_module, emqx_auth_mongo_app, brutal_purge, soft_purge, []}, - {load_module, emqx_auth_mongo, brutal_purge, soft_purge, []}, - {load_module, emqx_acl_mongo, brutal_purge, soft_purge, [emqx_auth_mongo]} - ]}, - {"4.2.1", [ - {load_module, emqx_auth_mongo_app, brutal_purge, soft_purge, []}, - {load_module, emqx_auth_mongo, brutal_purge, soft_purge, []}, - {load_module, emqx_acl_mongo, brutal_purge, soft_purge, [emqx_auth_mongo]} - ]}, - {"4.2.0", [ - {load_module, emqx_auth_mongo_app, brutal_purge, soft_purge, []}, - {load_module, emqx_auth_mongo, brutal_purge, soft_purge, []}, - {load_module, emqx_acl_mongo, brutal_purge, soft_purge, [emqx_auth_mongo]} - ]} - ] -}. diff --git a/apps/emqx_auth_mysql/.github/workflows/run_test_cases.yaml b/apps/emqx_auth_mysql/.github/workflows/run_test_cases.yaml deleted file mode 100644 index 90f2d7437..000000000 --- a/apps/emqx_auth_mysql/.github/workflows/run_test_cases.yaml +++ /dev/null @@ -1,59 +0,0 @@ -name: Run test cases - -on: [push, pull_request] - -jobs: - run_test_cases: - runs-on: ubuntu-latest - - strategy: - matrix: - mysql_tag: - - 5.7 - - 8 - network_type: - - ipv4 - - ipv6 - connect_type: - - ssl - - tcp - - steps: - - name: install docker-compose - run: | - sudo curl -L "https://github.com/docker/compose/releases/download/1.25.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose - sudo chmod +x /usr/local/bin/docker-compose - - uses: actions/checkout@v1 - - name: run test cases - env: - MYSQL_TAG: ${{ matrix.mysql_tag }} - NETWORK_TYPE: ${{ matrix.network_type }} - CONNECT_TYPE: ${{ matrix.connect_type }} - run: | - if [ "$NETWORK_TYPE" = "ipv6" ];then docker network create --driver bridge --ipv6 --subnet fd15:555::/64 test_emqx_bridge --attachable; fi - if [ "$CONNECT_TYPE" = "ssl" ]; then - docker-compose -f ./docker-compose-ssl.yml -p test up -d - docker exec -i $(docker ps -a -f name=test_erlang_1 -q) sh -c "echo 'auth.mysql.ssl.cafile = /emqx_auth_mysql/test/emqx_auth_mysql_SUITE_data/ca.pem' >> /emqx_auth_mysql/etc/emqx_auth_mysql.conf" - docker exec -i $(docker ps -a -f name=test_erlang_1 -q) sh -c "echo 'auth.mysql.ssl.certfile = /emqx_auth_mysql/test/emqx_auth_mysql_SUITE_data/client-cert.pem' >> /emqx_auth_mysql/etc/emqx_auth_mysql.conf" - docker exec -i $(docker ps -a -f name=test_erlang_1 -q) sh -c "echo 'auth.mysql.ssl.keyfile = /emqx_auth_mysql/test/emqx_auth_mysql_SUITE_data/client-key.pem' >> /emqx_auth_mysql/etc/emqx_auth_mysql.conf" - else - docker-compose -f ./docker-compose.yml -p test up -d - fi - docker exec -i $(docker ps -a -f name=test_erlang_1 -q) sh -c "echo 'auth.mysql.username = root' >> /emqx_auth_mysql/etc/emqx_auth_mysql.conf " - docker exec -i $(docker ps -a -f name=test_erlang_1 -q) sh -c "echo 'auth.mysql.password = public' >> /emqx_auth_mysql/etc/emqx_auth_mysql.conf" - if [ "$NETWORK_TYPE" != "ipv6" ];then - docker exec -i $(docker ps -a -f name=test_erlang_1 -q) sh -c "sed -i '/auth.mysql.server/c auth.mysql.server = mysql_server:3306' /emqx_auth_mysql/etc/emqx_auth_mysql.conf" - else - ipv6_address=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.GlobalIPv6Address}}{{end}}' $(docker ps -a -f name=test_mysql_server_1 -q)) - docker exec -i $(docker ps -a -f name=test_erlang_1 -q) sh -c "sed -i '/auth.mysql.server/c auth.mysql.server = $ipv6_address:3306' /emqx_auth_mysql/etc/emqx_auth_mysql.conf" - fi - docker exec -i $(docker ps -a -f name=test_erlang_1 -q) sh -c "make -C /emqx_auth_mysql xref" - docker exec -i $(docker ps -a -f name=test_erlang_1 -q) sh -c "make -C /emqx_auth_mysql eunit" - docker exec -i $(docker ps -a -f name=test_erlang_1 -q) sh -c "make -C /emqx_auth_mysql ct" - docker exec -i $(docker ps -a -f name=test_erlang_1 -q) sh -c "make -C /emqx_auth_mysql cover" - - uses: actions/upload-artifact@v1 - if: failure() - with: - name: logs_mysql${{ matrix.mysql_tag }}_${{ matrix.network_type }} - path: _build/test/logs - diff --git a/apps/emqx_auth_mysql/src/emqx_auth_mysql.app.src.script b/apps/emqx_auth_mysql/src/emqx_auth_mysql.app.src.script deleted file mode 100644 index 0e14ff23f..000000000 --- a/apps/emqx_auth_mysql/src/emqx_auth_mysql.app.src.script +++ /dev/null @@ -1,24 +0,0 @@ -%%-*- mode: erlang -*- -%% .app.src.script - -RemoveLeadingV = - fun(Tag) -> - case re:run(Tag, "^[v|e]?[0-9]\.[0-9]\.([0-9]|(rc|beta|alpha)\.[0-9])", [{capture, none}]) of - nomatch -> - re:replace(Tag, "/", "-", [{return ,list}]); - _ -> - %% if it is a version number prefixed by 'v' or 'e', then remove it - re:replace(Tag, "[v|e]", "", [{return ,list}]) - end - end, - -case os:getenv("EMQX_DEPS_DEFAULT_VSN") of - false -> CONFIG; % env var not defined - [] -> CONFIG; % env var set to empty string - Tag -> - [begin - AppConf0 = lists:keystore(vsn, 1, AppConf, {vsn, RemoveLeadingV(Tag)}), - {application, App, AppConf0} - end || Conf = {application, App, AppConf} <- CONFIG] -end. - diff --git a/apps/emqx_auth_mysql/src/emqx_auth_mysql.appup.src b/apps/emqx_auth_mysql/src/emqx_auth_mysql.appup.src deleted file mode 100644 index e4c16f92b..000000000 --- a/apps/emqx_auth_mysql/src/emqx_auth_mysql.appup.src +++ /dev/null @@ -1,25 +0,0 @@ -%% -*-: erlang -*- -{"4.2.3", - [ - {"4.2.2", [ - {load_module, emqx_auth_mysql_cli, brutal_purge, soft_purge, []} - ]}, - {"4.2.1", [ - {load_module, emqx_auth_mysql_cli, brutal_purge, soft_purge, []} - ]}, - {"4.2.0", [ - {load_module, emqx_auth_mysql_cli, brutal_purge, soft_purge, []} - ]} - ], - [ - {"4.2.2", [ - {load_module, emqx_auth_mysql_cli, brutal_purge, soft_purge, []} - ]}, - {"4.2.1", [ - {load_module, emqx_auth_mysql_cli, brutal_purge, soft_purge, []} - ]}, - {"4.2.0", [ - {load_module, emqx_auth_mysql_cli, brutal_purge, soft_purge, []} - ]} - ] -}. diff --git a/apps/emqx_auth_pgsql/.ci/docker-compose.yml b/apps/emqx_auth_pgsql/.ci/docker-compose.yml deleted file mode 100644 index 8782a841d..000000000 --- a/apps/emqx_auth_pgsql/.ci/docker-compose.yml +++ /dev/null @@ -1,30 +0,0 @@ -version: '3' - -services: - erlang: - image: erlang:22.3 - volumes: - - ../:/emqx_auth_pgsql - networks: - - emqx_bridge - depends_on: - - pgsql_server - tty: true - - pgsql_server: - build: - context: ./pgsql - args: - BUILD_FROM: postgres:${PGSQL_TAG} - image: emqx-pgsql - restart: always - environment: - POSTGRES_PASSWORD: public - POSTGRES_USER: root - POSTGRES_DB: mqtt - networks: - - emqx_bridge - -networks: - emqx_bridge: - driver: bridge diff --git a/apps/emqx_auth_pgsql/.ci/pgsql/Dockerfile b/apps/emqx_auth_pgsql/.ci/pgsql/Dockerfile deleted file mode 100644 index 785bb875f..000000000 --- a/apps/emqx_auth_pgsql/.ci/pgsql/Dockerfile +++ /dev/null @@ -1,8 +0,0 @@ -ARG BUILD_FROM=postgres:11 -FROM ${BUILD_FROM} -COPY pg.conf /etc/postgresql/postgresql.conf -COPY server-cert.pem /etc/postgresql/server-cert.pem -COPY server-key.pem /etc/postgresql/server-key.pem -RUN chown -R postgres:postgres /etc/postgresql \ - && chmod 600 /etc/postgresql/*.pem -CMD ["-c", "config_file=/etc/postgresql/postgresql.conf"] diff --git a/apps/emqx_auth_pgsql/.github/workflows/run_test_cases.yaml b/apps/emqx_auth_pgsql/.github/workflows/run_test_cases.yaml deleted file mode 100644 index 389359fb3..000000000 --- a/apps/emqx_auth_pgsql/.github/workflows/run_test_cases.yaml +++ /dev/null @@ -1,51 +0,0 @@ -name: Run test cases - -on: [push, pull_request] - -jobs: - run_test_cases: - runs-on: ubuntu-latest - - strategy: - matrix: - pgsql_tag: - - 9 - - 10 - - 11 - - 12 - - 13 - network_type: - - ipv4 - - ipv6 - steps: - - name: install docker-compose - run: | - sudo curl -L "https://github.com/docker/compose/releases/download/1.25.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose - sudo chmod +x /usr/local/bin/docker-compose - - uses: actions/checkout@v1 - - name: run test cases - env: - PGSQL_TAG: ${{ matrix.pgsql_tag }} - NETWORK_TYPE: ${{ matrix.network_type }} - run: | - set -e -u -x - if [ "$NETWORK_TYPE" = "ipv6" ]; then docker network create --driver bridge --ipv6 --subnet fd15:555::/64 tests_emqx_bridge --attachable; fi - - cp test/emqx_auth_pgsql_SUITE_data/* .ci/pgsql/ - docker-compose -f .ci/docker-compose.yml -p tests up -d --build - if [ "$NETWORK_TYPE" != "ipv6" ]; then - docker exec -i $(docker ps -a -f name=tests_erlang_1 -q) sh -c "sed -i '/auth.pgsql.server/c auth.pgsql.server = pgsql_server:5432' /emqx_auth_pgsql/etc/emqx_auth_pgsql.conf" - else - ipv6_address=$(docker inspect -f '{{range.NetworkSettings.Networks}}{{.GlobalIPv6Address}}{{end}}' $(docker ps -a -f name=tests_pgsql_server_1 -q)) - docker exec -i $(docker ps -a -f name=tests_erlang_1 -q) sh -c "sed -i '/auth.pgsql.server/c auth.pgsql.server = $ipv6_address:5432' /emqx_auth_pgsql/etc/emqx_auth_pgsql.conf" - fi - - docker exec -i tests_erlang_1 sh -c "make -C /emqx_auth_pgsql xref" - docker exec -i tests_erlang_1 sh -c "make -C /emqx_auth_pgsql eunit" - docker exec -i tests_erlang_1 sh -c "make -C /emqx_auth_pgsql ct" - docker exec -i tests_erlang_1 sh -c "make -C /emqx_auth_pgsql cover" - - uses: actions/upload-artifact@v1 - if: failure() - with: - name: logs_for_pgsql${{ matrix.pgsql_tag }}_{{matrix.network_type}} - path: _build/test/logs diff --git a/apps/emqx_auth_pgsql/src/emqx_auth_pgsql.app.src.script b/apps/emqx_auth_pgsql/src/emqx_auth_pgsql.app.src.script deleted file mode 100644 index 0e14ff23f..000000000 --- a/apps/emqx_auth_pgsql/src/emqx_auth_pgsql.app.src.script +++ /dev/null @@ -1,24 +0,0 @@ -%%-*- mode: erlang -*- -%% .app.src.script - -RemoveLeadingV = - fun(Tag) -> - case re:run(Tag, "^[v|e]?[0-9]\.[0-9]\.([0-9]|(rc|beta|alpha)\.[0-9])", [{capture, none}]) of - nomatch -> - re:replace(Tag, "/", "-", [{return ,list}]); - _ -> - %% if it is a version number prefixed by 'v' or 'e', then remove it - re:replace(Tag, "[v|e]", "", [{return ,list}]) - end - end, - -case os:getenv("EMQX_DEPS_DEFAULT_VSN") of - false -> CONFIG; % env var not defined - [] -> CONFIG; % env var set to empty string - Tag -> - [begin - AppConf0 = lists:keystore(vsn, 1, AppConf, {vsn, RemoveLeadingV(Tag)}), - {application, App, AppConf0} - end || Conf = {application, App, AppConf} <- CONFIG] -end. - diff --git a/apps/emqx_auth_pgsql/src/emqx_auth_pgsql.appup.src b/apps/emqx_auth_pgsql/src/emqx_auth_pgsql.appup.src deleted file mode 100644 index 657b119a1..000000000 --- a/apps/emqx_auth_pgsql/src/emqx_auth_pgsql.appup.src +++ /dev/null @@ -1,25 +0,0 @@ -%% -*-: erlang -*- -{"4.2.3", - [ - {"4.2.2", [ - {load_module, emqx_auth_pgsql_cli, brutal_purge, soft_purge, []} - ]}, - {"4.2.1", [ - {load_module, emqx_auth_pgsql_cli, brutal_purge, soft_purge, []} - ]}, - {"4.2.0", [ - {load_module, emqx_auth_pgsql_cli, brutal_purge, soft_purge, []} - ]} - ], - [ - {"4.2.2", [ - {load_module, emqx_auth_pgsql_cli, brutal_purge, soft_purge, []} - ]}, - {"4.2.1", [ - {load_module, emqx_auth_pgsql_cli, brutal_purge, soft_purge, []} - ]}, - {"4.2.0", [ - {load_module, emqx_auth_pgsql_cli, brutal_purge, soft_purge, []} - ]} - ] -}. diff --git a/apps/emqx_auth_redis/.ci/docker-compose-tls.yml b/apps/emqx_auth_redis/.ci/docker-compose-tls.yml deleted file mode 100644 index 2247cd21b..000000000 --- a/apps/emqx_auth_redis/.ci/docker-compose-tls.yml +++ /dev/null @@ -1,31 +0,0 @@ -version: '3' - -services: - erlang: - image: erlang:22.3 - volumes: - - ../:/emqx_auth_redis - networks: - - emqx_bridge - depends_on: - - redis_server - tty: true - - redis_server: - image: redis:6.0.9 - volumes: - - ../test/emqx_auth_redis_SUITE_data/certs:/tls - command: - - redis-server - - "--bind 0.0.0.0 ::" - - --tls-port 6380 - - --tls-cert-file /tls/redis.crt - - --tls-key-file /tls/redis.key - - --tls-ca-cert-file /tls/ca.crt - restart: always - networks: - - emqx_bridge - -networks: - emqx_bridge: - driver: bridge diff --git a/apps/emqx_auth_redis/.ci/docker-compose.yml b/apps/emqx_auth_redis/.ci/docker-compose.yml deleted file mode 100644 index 6716262ad..000000000 --- a/apps/emqx_auth_redis/.ci/docker-compose.yml +++ /dev/null @@ -1,25 +0,0 @@ -version: '3' - -services: - erlang: - image: erlang:22.3 - volumes: - - ../:/emqx_auth_redis - networks: - - emqx_bridge - depends_on: - - redis_server - tty: true - - redis_server: - image: redis:${REDIS_TAG} - command: - - redis-server - - "--bind 0.0.0.0 ::" - restart: always - networks: - - emqx_bridge - -networks: - emqx_bridge: - driver: bridge diff --git a/apps/emqx_auth_redis/.github/workflows/run_test_cases.yaml b/apps/emqx_auth_redis/.github/workflows/run_test_cases.yaml deleted file mode 100644 index 5af7bdbc3..000000000 --- a/apps/emqx_auth_redis/.github/workflows/run_test_cases.yaml +++ /dev/null @@ -1,80 +0,0 @@ -name: Run test cases - -on: [push, pull_request] - -jobs: - run_tests_cases: - runs-on: ubuntu-latest - - strategy: - matrix: - redis_tag: - - 5.0.9 - - 6.0.9 - network_type: - - ipv4 - - ipv6 - connect_type: - - tcp - - tls - - steps: - - name: install docker-compose - run: | - sudo curl -L "https://github.com/docker/compose/releases/download/1.25.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose - sudo chmod +x /usr/local/bin/docker-compose - - uses: actions/checkout@v1 - - name: setup - if: matrix.connect_type == 'tcp' && matrix.network_type == 'ipv6' - env: - REDIS_TAG: ${{ matrix.redis_tag}} - run: | - set -e -u -x - docker network create --driver bridge --ipv6 --subnet fd15:555::/64 tests_emqx_bridge --attachable; - docker-compose -f ./.ci/docker-compose.yml -p tests up -d - ipv6_address=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.GlobalIPv6Address}}{{end}}' $(docker ps -a -f name=tests_redis_server_1 -q)) - sed -i "/auth.redis.server/c auth.redis.server = $ipv6_address:6379" ./etc/emqx_auth_redis.conf - - name: setup - if: matrix.connect_type == 'tcp' && matrix.network_type == 'ipv4' - env: - REDIS_TAG: ${{ matrix.redis_tag}} - run: | - set -e -u -x - docker-compose -f ./.ci/docker-compose.yml -p tests up -d - sed -i '/auth.redis.server/c auth.redis.server = redis_server:6379' ./etc/emqx_auth_redis.conf - - name: setup - if: matrix.connect_type == 'tls' && matrix.network_type == 'ipv6' && matrix.redis_tag == '6.0.9' - run: | - set -e -u -x - docker network create --driver bridge --ipv6 --subnet fd15:555::/64 tests_emqx_bridge --attachable; - docker-compose -f ./.ci/docker-compose-tls.yml -p tests up -d - ipv6_address=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.GlobalIPv6Address}}{{end}}' $(docker ps -a -f name=tests_redis_server_1 -q)) - sed -i "/auth.redis.server/c auth.redis.server = $ipv6_address:6380" ./etc/emqx_auth_redis.conf - echo '\n' >> ./etc/emqx_auth_redis.conf - echo 'auth.redis.ssl = on' >> ./etc/emqx_auth_redis.conf - echo 'auth.redis.cafile = /emqx_auth_redis/test/emqx_auth_redis_SUITE_data/certs/ca.crt' >> ./etc/emqx_auth_redis.conf - echo 'auth.redis.certfile = /emqx_auth_redis/test/emqx_auth_redis_SUITE_data/certs/redis.crt' >> ./etc/emqx_auth_redis.conf - echo 'auth.redis.keyfile = /emqx_auth_redis/test/emqx_auth_redis_SUITE_data/certs/redis.key' >> ./etc/emqx_auth_redis.conf - - name: setup - if: matrix.connect_type == 'tls' && matrix.network_type == 'ipv4' && matrix.redis_tag == '6.0.9' - run: | - set -e -u -x - docker-compose -f ./.ci/docker-compose-tls.yml -p tests up -d - sed -i '/auth.redis.server/c auth.redis.server = redis_server:6380' ./etc/emqx_auth_redis.conf - echo '\n' >> ./etc/emqx_auth_redis.conf - echo 'auth.redis.ssl = on' >> ./etc/emqx_auth_redis.conf - echo 'auth.redis.cafile = /emqx_auth_redis/test/emqx_auth_redis_SUITE_data/certs/ca.crt' >> ./etc/emqx_auth_redis.conf - echo 'auth.redis.certfile = /emqx_auth_redis/test/emqx_auth_redis_SUITE_data/certs/redis.crt' >> ./etc/emqx_auth_redis.conf - echo 'auth.redis.keyfile = /emqx_auth_redis/test/emqx_auth_redis_SUITE_data/certs/redis.key' >> ./etc/emqx_auth_redis.conf - - name: run test cases - if: matrix.connect_type == 'tcp' || (matrix.connect_type == 'tls' && matrix.redis_tag == '6.0.9') - run: | - docker exec -i tests_erlang_1 sh -c "make -C /emqx_auth_redis xref" - docker exec -i tests_erlang_1 sh -c "make -C /emqx_auth_redis eunit" - docker exec -i tests_erlang_1 sh -c "make -C /emqx_auth_redis ct" - docker exec -i tests_erlang_1 sh -c "make -C /emqx_auth_redis cover" - - uses: actions/upload-artifact@v1 - if: failure() - with: - name: logs_redis${{ matrix.redis_tag}}_${{ matrix.network_type }}_${{ matrix.connect_type }} - path: _build/test/logs diff --git a/apps/emqx_auth_redis/src/emqx_auth_redis.app.src.script b/apps/emqx_auth_redis/src/emqx_auth_redis.app.src.script deleted file mode 100644 index 0e14ff23f..000000000 --- a/apps/emqx_auth_redis/src/emqx_auth_redis.app.src.script +++ /dev/null @@ -1,24 +0,0 @@ -%%-*- mode: erlang -*- -%% .app.src.script - -RemoveLeadingV = - fun(Tag) -> - case re:run(Tag, "^[v|e]?[0-9]\.[0-9]\.([0-9]|(rc|beta|alpha)\.[0-9])", [{capture, none}]) of - nomatch -> - re:replace(Tag, "/", "-", [{return ,list}]); - _ -> - %% if it is a version number prefixed by 'v' or 'e', then remove it - re:replace(Tag, "[v|e]", "", [{return ,list}]) - end - end, - -case os:getenv("EMQX_DEPS_DEFAULT_VSN") of - false -> CONFIG; % env var not defined - [] -> CONFIG; % env var set to empty string - Tag -> - [begin - AppConf0 = lists:keystore(vsn, 1, AppConf, {vsn, RemoveLeadingV(Tag)}), - {application, App, AppConf0} - end || Conf = {application, App, AppConf} <- CONFIG] -end. - diff --git a/apps/emqx_auth_redis/src/emqx_auth_redis.appup.src b/apps/emqx_auth_redis/src/emqx_auth_redis.appup.src deleted file mode 100644 index 671b9274f..000000000 --- a/apps/emqx_auth_redis/src/emqx_auth_redis.appup.src +++ /dev/null @@ -1,36 +0,0 @@ -{"4.2.3", - [ - {"4.2.2", [ - {load_module, emqx_auth_redis_cli, brutal_purge, soft_purge, []}, - {load_module, emqx_auth_redis_sup, brutal_purge, soft_purge, []} - ] - }, - {"4.2.1", [ - {load_module, emqx_auth_redis_cli, brutal_purge, soft_purge, []}, - {load_module, emqx_auth_redis_sup, brutal_purge, soft_purge, []} - ] - }, - {"4.2.0", [ - {load_module, emqx_auth_redis_cli, brutal_purge, soft_purge, []}, - {load_module, emqx_auth_redis_sup, brutal_purge, soft_purge, []} - ] - } - ], - [ - {"4.2.2", [ - {load_module, emqx_auth_redis_cli, brutal_purge, soft_purge, []}, - {load_module, emqx_auth_redis_sup, brutal_purge, soft_purge, []} - ] - }, - {"4.2.1", [ - {load_module, emqx_auth_redis_cli, brutal_purge, soft_purge, []}, - {load_module, emqx_auth_redis_sup, brutal_purge, soft_purge, []} - ] - }, - {"4.2.0", [ - {load_module, emqx_auth_redis_cli, brutal_purge, soft_purge, []}, - {load_module, emqx_auth_redis_sup, brutal_purge, soft_purge, []} - ] - } - ] -}. \ No newline at end of file diff --git a/apps/emqx_bridge_mqtt/.github/workflows/run_test_cases.yaml b/apps/emqx_bridge_mqtt/.github/workflows/run_test_cases.yaml deleted file mode 100644 index 3b4fa29ec..000000000 --- a/apps/emqx_bridge_mqtt/.github/workflows/run_test_cases.yaml +++ /dev/null @@ -1,28 +0,0 @@ -name: Run test cases - -on: [push, pull_request] - -jobs: - run_test_cases: - runs-on: ubuntu-latest - - container: - image: erlang:22.1 - - steps: - - uses: actions/checkout@v1 - - name: run test cases - run: | - make eunit - make ct - make cover - - uses: actions/upload-artifact@v1 - if: always() - with: - name: logs - path: _build/test/logs - - uses: actions/upload-artifact@v1 - with: - name: cover - path: _build/test/cover - diff --git a/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt.app.src.script b/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt.app.src.script deleted file mode 100644 index 0e14ff23f..000000000 --- a/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt.app.src.script +++ /dev/null @@ -1,24 +0,0 @@ -%%-*- mode: erlang -*- -%% .app.src.script - -RemoveLeadingV = - fun(Tag) -> - case re:run(Tag, "^[v|e]?[0-9]\.[0-9]\.([0-9]|(rc|beta|alpha)\.[0-9])", [{capture, none}]) of - nomatch -> - re:replace(Tag, "/", "-", [{return ,list}]); - _ -> - %% if it is a version number prefixed by 'v' or 'e', then remove it - re:replace(Tag, "[v|e]", "", [{return ,list}]) - end - end, - -case os:getenv("EMQX_DEPS_DEFAULT_VSN") of - false -> CONFIG; % env var not defined - [] -> CONFIG; % env var set to empty string - Tag -> - [begin - AppConf0 = lists:keystore(vsn, 1, AppConf, {vsn, RemoveLeadingV(Tag)}), - {application, App, AppConf0} - end || Conf = {application, App, AppConf} <- CONFIG] -end. - diff --git a/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt.appup.src b/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt.appup.src deleted file mode 100644 index 8264abc25..000000000 --- a/apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt.appup.src +++ /dev/null @@ -1,32 +0,0 @@ -%% -*-: erlang -*- - -{"4.2.3", - [ - {"4.2.2", [ - {load_module, emqx_bridge_mqtt_actions, brutal_purge, soft_purge, []}, - {apply, {emqx_rule_engine, load_providers, []}} - ]}, - {"4.2.1", [ - {load_module, emqx_bridge_mqtt_actions, brutal_purge, soft_purge, []}, - {apply, {emqx_rule_engine, load_providers, []}} - ]}, - {"4.2.0", [ - {load_module, emqx_bridge_mqtt_actions, brutal_purge, soft_purge, []}, - {apply, {emqx_rule_engine, load_providers, []}} - ]} - ], - [ - {"4.2.2", [ - {load_module, emqx_bridge_mqtt_actions, brutal_purge, soft_purge, []}, - {apply, {emqx_rule_engine, load_providers, []}} - ]}, - {"4.2.1", [ - {load_module, emqx_bridge_mqtt_actions, brutal_purge, soft_purge, []}, - {apply, {emqx_rule_engine, load_providers, []}} - ]}, - {"4.2.0", [ - {load_module, emqx_bridge_mqtt_actions, brutal_purge, soft_purge, []}, - {apply, {emqx_rule_engine, load_providers, []}} - ]} - ] -}. diff --git a/apps/emqx_coap/.github/workflows/run_test_cases.yaml b/apps/emqx_coap/.github/workflows/run_test_cases.yaml deleted file mode 100644 index b8e722570..000000000 --- a/apps/emqx_coap/.github/workflows/run_test_cases.yaml +++ /dev/null @@ -1,29 +0,0 @@ -name: Run test cases - -on: [push, pull_request] - -jobs: - run_test_cases: - runs-on: ubuntu-latest - - container: - image: erlang:22.1 - - steps: - - uses: actions/checkout@v1 - - name: run test cases - run: | - make xref - make eunit - make ct - make cover - - uses: actions/upload-artifact@v1 - if: always() - with: - name: logs - path: _build/test/logs - - uses: actions/upload-artifact@v1 - with: - name: cover - path: _build/test/cover - diff --git a/apps/emqx_coap/src/emqx_coap.app.src.script b/apps/emqx_coap/src/emqx_coap.app.src.script deleted file mode 100644 index 0e14ff23f..000000000 --- a/apps/emqx_coap/src/emqx_coap.app.src.script +++ /dev/null @@ -1,24 +0,0 @@ -%%-*- mode: erlang -*- -%% .app.src.script - -RemoveLeadingV = - fun(Tag) -> - case re:run(Tag, "^[v|e]?[0-9]\.[0-9]\.([0-9]|(rc|beta|alpha)\.[0-9])", [{capture, none}]) of - nomatch -> - re:replace(Tag, "/", "-", [{return ,list}]); - _ -> - %% if it is a version number prefixed by 'v' or 'e', then remove it - re:replace(Tag, "[v|e]", "", [{return ,list}]) - end - end, - -case os:getenv("EMQX_DEPS_DEFAULT_VSN") of - false -> CONFIG; % env var not defined - [] -> CONFIG; % env var set to empty string - Tag -> - [begin - AppConf0 = lists:keystore(vsn, 1, AppConf, {vsn, RemoveLeadingV(Tag)}), - {application, App, AppConf0} - end || Conf = {application, App, AppConf} <- CONFIG] -end. - diff --git a/apps/emqx_dashboard/.github/workflows/run_test_cases.yaml b/apps/emqx_dashboard/.github/workflows/run_test_cases.yaml deleted file mode 100644 index b8e722570..000000000 --- a/apps/emqx_dashboard/.github/workflows/run_test_cases.yaml +++ /dev/null @@ -1,29 +0,0 @@ -name: Run test cases - -on: [push, pull_request] - -jobs: - run_test_cases: - runs-on: ubuntu-latest - - container: - image: erlang:22.1 - - steps: - - uses: actions/checkout@v1 - - name: run test cases - run: | - make xref - make eunit - make ct - make cover - - uses: actions/upload-artifact@v1 - if: always() - with: - name: logs - path: _build/test/logs - - uses: actions/upload-artifact@v1 - with: - name: cover - path: _build/test/cover - diff --git a/apps/emqx_dashboard/src/emqx_dashboard.app.src.script b/apps/emqx_dashboard/src/emqx_dashboard.app.src.script deleted file mode 100644 index 0e14ff23f..000000000 --- a/apps/emqx_dashboard/src/emqx_dashboard.app.src.script +++ /dev/null @@ -1,24 +0,0 @@ -%%-*- mode: erlang -*- -%% .app.src.script - -RemoveLeadingV = - fun(Tag) -> - case re:run(Tag, "^[v|e]?[0-9]\.[0-9]\.([0-9]|(rc|beta|alpha)\.[0-9])", [{capture, none}]) of - nomatch -> - re:replace(Tag, "/", "-", [{return ,list}]); - _ -> - %% if it is a version number prefixed by 'v' or 'e', then remove it - re:replace(Tag, "[v|e]", "", [{return ,list}]) - end - end, - -case os:getenv("EMQX_DEPS_DEFAULT_VSN") of - false -> CONFIG; % env var not defined - [] -> CONFIG; % env var set to empty string - Tag -> - [begin - AppConf0 = lists:keystore(vsn, 1, AppConf, {vsn, RemoveLeadingV(Tag)}), - {application, App, AppConf0} - end || Conf = {application, App, AppConf} <- CONFIG] -end. - diff --git a/apps/emqx_dashboard/src/emqx_dashboard.appup.src b/apps/emqx_dashboard/src/emqx_dashboard.appup.src deleted file mode 100644 index 61f9dffb4..000000000 --- a/apps/emqx_dashboard/src/emqx_dashboard.appup.src +++ /dev/null @@ -1,18 +0,0 @@ -%% -*-: erlang -*- - -{"4.2.3", - [ - {<<"4.2.*">>, - [ - {restart_application, emqx_dashboard}, - {apply, {emqx_plugins, load, []}} - ]} - ], - [ - {<<"4.2.*">>, - [ - {restart_application, emqx_dashboard}, - {apply, {emqx_plugins, load, []}} - ]} - ] -}. diff --git a/apps/emqx_exhook/.github/workflows/run_test_cases.yaml b/apps/emqx_exhook/.github/workflows/run_test_cases.yaml deleted file mode 100644 index fed706984..000000000 --- a/apps/emqx_exhook/.github/workflows/run_test_cases.yaml +++ /dev/null @@ -1,31 +0,0 @@ -name: Run test cases - -on: [push, pull_request] - -jobs: - run_test_cases: - runs-on: ubuntu-latest - - container: - image: erlang:22.1 - - steps: - - uses: actions/checkout@v1 - - uses: actions/setup-java@v1 - with: - java-version: '8.0.x' - java-package: jdk - - name: run test cases - run: | - make eunit - make ct - make cover - - uses: actions/upload-artifact@v1 - if: always() - with: - name: logs - path: _build/test/logs - - uses: actions/upload-artifact@v1 - with: - name: cover - path: _build/test/cover diff --git a/apps/emqx_exproto/.github/workflows/run_test_case.yaml b/apps/emqx_exproto/.github/workflows/run_test_case.yaml deleted file mode 100644 index 7b7aeb627..000000000 --- a/apps/emqx_exproto/.github/workflows/run_test_case.yaml +++ /dev/null @@ -1,38 +0,0 @@ -name: Run test case - -on: [push, pull_request] - -jobs: - - run_test_case: - - runs-on: ubuntu-latest - - container: - image: erlang:22.3 - - steps: - - uses: actions/checkout@v1 - - uses: actions/setup-java@v1 - with: - java-version: '8.0.x' - java-package: jdk - - name: Code dialyzer - run: | - make xref - make dialyzer - - name: Run tests - run: | - make eunit - make ct - make cover - #- name: Coveralls - # env: - # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # run: | - # make coveralls - - uses: actions/upload-artifact@v1 - if: always() - with: - name: logs - path: _build/test/logs diff --git a/apps/emqx_lua_hook/.github/workflows/run_test_cases.yaml b/apps/emqx_lua_hook/.github/workflows/run_test_cases.yaml deleted file mode 100644 index b8e722570..000000000 --- a/apps/emqx_lua_hook/.github/workflows/run_test_cases.yaml +++ /dev/null @@ -1,29 +0,0 @@ -name: Run test cases - -on: [push, pull_request] - -jobs: - run_test_cases: - runs-on: ubuntu-latest - - container: - image: erlang:22.1 - - steps: - - uses: actions/checkout@v1 - - name: run test cases - run: | - make xref - make eunit - make ct - make cover - - uses: actions/upload-artifact@v1 - if: always() - with: - name: logs - path: _build/test/logs - - uses: actions/upload-artifact@v1 - with: - name: cover - path: _build/test/cover - diff --git a/apps/emqx_lua_hook/src/emqx_lua_hook.app.src.script b/apps/emqx_lua_hook/src/emqx_lua_hook.app.src.script deleted file mode 100644 index 0e14ff23f..000000000 --- a/apps/emqx_lua_hook/src/emqx_lua_hook.app.src.script +++ /dev/null @@ -1,24 +0,0 @@ -%%-*- mode: erlang -*- -%% .app.src.script - -RemoveLeadingV = - fun(Tag) -> - case re:run(Tag, "^[v|e]?[0-9]\.[0-9]\.([0-9]|(rc|beta|alpha)\.[0-9])", [{capture, none}]) of - nomatch -> - re:replace(Tag, "/", "-", [{return ,list}]); - _ -> - %% if it is a version number prefixed by 'v' or 'e', then remove it - re:replace(Tag, "[v|e]", "", [{return ,list}]) - end - end, - -case os:getenv("EMQX_DEPS_DEFAULT_VSN") of - false -> CONFIG; % env var not defined - [] -> CONFIG; % env var set to empty string - Tag -> - [begin - AppConf0 = lists:keystore(vsn, 1, AppConf, {vsn, RemoveLeadingV(Tag)}), - {application, App, AppConf0} - end || Conf = {application, App, AppConf} <- CONFIG] -end. - diff --git a/apps/emqx_lwm2m/.github/workflows/run_test_cases.yaml b/apps/emqx_lwm2m/.github/workflows/run_test_cases.yaml deleted file mode 100644 index b8e722570..000000000 --- a/apps/emqx_lwm2m/.github/workflows/run_test_cases.yaml +++ /dev/null @@ -1,29 +0,0 @@ -name: Run test cases - -on: [push, pull_request] - -jobs: - run_test_cases: - runs-on: ubuntu-latest - - container: - image: erlang:22.1 - - steps: - - uses: actions/checkout@v1 - - name: run test cases - run: | - make xref - make eunit - make ct - make cover - - uses: actions/upload-artifact@v1 - if: always() - with: - name: logs - path: _build/test/logs - - uses: actions/upload-artifact@v1 - with: - name: cover - path: _build/test/cover - diff --git a/apps/emqx_lwm2m/src/emqx_lwm2m.app.src.script b/apps/emqx_lwm2m/src/emqx_lwm2m.app.src.script deleted file mode 100644 index 0e14ff23f..000000000 --- a/apps/emqx_lwm2m/src/emqx_lwm2m.app.src.script +++ /dev/null @@ -1,24 +0,0 @@ -%%-*- mode: erlang -*- -%% .app.src.script - -RemoveLeadingV = - fun(Tag) -> - case re:run(Tag, "^[v|e]?[0-9]\.[0-9]\.([0-9]|(rc|beta|alpha)\.[0-9])", [{capture, none}]) of - nomatch -> - re:replace(Tag, "/", "-", [{return ,list}]); - _ -> - %% if it is a version number prefixed by 'v' or 'e', then remove it - re:replace(Tag, "[v|e]", "", [{return ,list}]) - end - end, - -case os:getenv("EMQX_DEPS_DEFAULT_VSN") of - false -> CONFIG; % env var not defined - [] -> CONFIG; % env var set to empty string - Tag -> - [begin - AppConf0 = lists:keystore(vsn, 1, AppConf, {vsn, RemoveLeadingV(Tag)}), - {application, App, AppConf0} - end || Conf = {application, App, AppConf} <- CONFIG] -end. - diff --git a/apps/emqx_management/.github/workflows/run_test_cases.yaml b/apps/emqx_management/.github/workflows/run_test_cases.yaml deleted file mode 100644 index 67a45af00..000000000 --- a/apps/emqx_management/.github/workflows/run_test_cases.yaml +++ /dev/null @@ -1,30 +0,0 @@ -name: Run test cases - -on: [push, pull_request] - -jobs: - run_test_cases: - runs-on: ubuntu-latest - - container: - image: erlang:22.3 - - steps: - - uses: actions/checkout@v1 - - name: run test cases - run: | - echo "https://zhanghongtong%40foxmail.com:${{ secrets.AccessToken }}@github.com" > $HOME/.git-credentials - git config --global credential.helper store - make eunit - make ct - make cover - - uses: actions/upload-artifact@v1 - if: always() - with: - name: logs - path: _build/test/logs - - uses: actions/upload-artifact@v1 - with: - name: cover - path: _build/test/cover - diff --git a/apps/emqx_management/src/emqx_management.app.src.script b/apps/emqx_management/src/emqx_management.app.src.script deleted file mode 100644 index 0e14ff23f..000000000 --- a/apps/emqx_management/src/emqx_management.app.src.script +++ /dev/null @@ -1,24 +0,0 @@ -%%-*- mode: erlang -*- -%% .app.src.script - -RemoveLeadingV = - fun(Tag) -> - case re:run(Tag, "^[v|e]?[0-9]\.[0-9]\.([0-9]|(rc|beta|alpha)\.[0-9])", [{capture, none}]) of - nomatch -> - re:replace(Tag, "/", "-", [{return ,list}]); - _ -> - %% if it is a version number prefixed by 'v' or 'e', then remove it - re:replace(Tag, "[v|e]", "", [{return ,list}]) - end - end, - -case os:getenv("EMQX_DEPS_DEFAULT_VSN") of - false -> CONFIG; % env var not defined - [] -> CONFIG; % env var set to empty string - Tag -> - [begin - AppConf0 = lists:keystore(vsn, 1, AppConf, {vsn, RemoveLeadingV(Tag)}), - {application, App, AppConf0} - end || Conf = {application, App, AppConf} <- CONFIG] -end. - diff --git a/apps/emqx_management/src/emqx_management.appup.src b/apps/emqx_management/src/emqx_management.appup.src deleted file mode 100644 index 538a008d8..000000000 --- a/apps/emqx_management/src/emqx_management.appup.src +++ /dev/null @@ -1,30 +0,0 @@ -{"4.2.3", - [ - {"4.2.2", [ - {load_module, emqx_mgmt, brutal_purge, soft_purge, []}, - {load_module, emqx_mgmt_api_data, brutal_purge, soft_purge, []} - ]}, - {"4.2.1", [ - {load_module, emqx_mgmt, brutal_purge, soft_purge, []}, - {load_module, emqx_mgmt_api_data, brutal_purge, soft_purge, []} - ]}, - {"4.2.0", [ - {load_module, emqx_mgmt, brutal_purge, soft_purge, []}, - {load_module, emqx_mgmt_api_data, brutal_purge, soft_purge, []} - ]} - ], - [ - {"4.2.2", [ - {load_module, emqx_mgmt, brutal_purge, soft_purge, []}, - {load_module, emqx_mgmt_api_data, brutal_purge, soft_purge, []} - ]}, - {"4.2.1", [ - {load_module, emqx_mgmt, brutal_purge, soft_purge, []}, - {load_module, emqx_mgmt_api_data, brutal_purge, soft_purge, []} - ]}, - {"4.2.0", [ - {load_module, emqx_mgmt, brutal_purge, soft_purge, []}, - {load_module, emqx_mgmt_api_data, brutal_purge, soft_purge, []} - ]} - ] -}. diff --git a/apps/emqx_passwd/.github/workflows/run_test_cases.yaml b/apps/emqx_passwd/.github/workflows/run_test_cases.yaml deleted file mode 100644 index 735676f21..000000000 --- a/apps/emqx_passwd/.github/workflows/run_test_cases.yaml +++ /dev/null @@ -1,88 +0,0 @@ -name: Run test cases - -on: [push, pull_request] - -jobs: - - #windows: - # runs-on: windows-latest - - # steps: - # - uses: actions/checkout@v1 - # - uses: ilammy/msvc-dev-cmd@v1 - # - name: Run tests - # run: | - # set-executionpolicy remotesigned -s cu - # iex (new-object net.webclient).downloadstring('https://get.scoop.sh') - # scoop bucket add extras https://github.com/lukesampson/scoop-extras.git - # $env:path + ";" + $env:USERPROFILE + "\scoop\shims" - # scoop update - # scoop install sudo curl 7zip ojdkbuild8 vcredist2013 - # scoop install erlang@22.3 - # $rebar3 = $env:USERPROFILE + "\rebar3" - # (New-Object System.Net.WebClient).DownloadFile('https://s3.amazonaws.com/rebar3/rebar3', $rebar3) - # ## Code dialyzer - # escript $rebar3 xref - # escript $rebar3 dialyzer - # ## Run tests - # escript $rebar3 ct - - mac: - runs-on: macos-latest - - steps: - - uses: actions/checkout@v1 - - name: Install compile env - run: | - /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" - brew install curl zip unzip gnu-sed erlang@22 openssl@1.1 - echo "::add-path::/usr/local/opt/erlang@22/bin" - echo "::add-path::/usr/local/bin" - - name: install rebar3 - run: | - curl -fsSL -o /usr/local/bin/rebar3 https://s3.amazonaws.com/rebar3/rebar3 - chmod +x /usr/local/bin/rebar3 - - name: Run tests - run: | - rebar3 ct - - linux: - runs-on: ubuntu-latest - - strategy: - matrix: - os: - - ubuntu18.04 - - ubuntu16.04 - - ubuntu14.04 - - debian10 - - debian9 - - debian8 - - opensuse - - centos7 - - centos6 - - raspbian10 - - raspbian9 - - raspbian8 - - steps: - - uses: actions/checkout@v1 - - name: run test cases - env: - ERL_OTP: erl22.1 - SYSTEM: ${{ matrix.os }} - run: | - version=$(echo ${{ github.ref }} | sed -r "s .*/.*/(.*) \1 g") - sudo docker run --rm --privileged multiarch/qemu-user-static:register --reset - sudo docker run -i --name $SYSTEM -v $(pwd):/emqx_passwd emqx/build-env:$ERL_OTP-$SYSTEM sh -c "cd /emqx_passwd && rebar3 ct" - - docker: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - name: run test cases - env: - ERL_OTP: erl22.1 - run: docker run -i --name alpine -v $(pwd):/emqx_passwd emqx/build-env:$ERL_OTP-alpine3.10-amd64 sh -c "cd /emqx_passwd && rebar3 ct" - diff --git a/apps/emqx_passwd/src/emqx_passwd.app.src.script b/apps/emqx_passwd/src/emqx_passwd.app.src.script deleted file mode 100644 index c93f83caf..000000000 --- a/apps/emqx_passwd/src/emqx_passwd.app.src.script +++ /dev/null @@ -1,14 +0,0 @@ -%%-*- mode: erlang -*- -%% .app.src.script - -Config = case os:type() =:= {win32, nt} orelse os:getenv("EMQX_DESC") =:= "EMQ X Edge" of - true -> - [begin - Applications0 = proplists:get_value(applications, AppConf), - Applications = Applications0 -- [bcrypt], - AppConf0 = lists:keystore(applications, 1, AppConf, {applications, Applications}), - {application, App, AppConf0} - end || Conf = {application, App, AppConf} <- CONFIG]; - false -> - CONFIG -end. diff --git a/apps/emqx_plugin_template/.github/workflows/run_test_cases.yaml b/apps/emqx_plugin_template/.github/workflows/run_test_cases.yaml deleted file mode 100644 index 3b4fa29ec..000000000 --- a/apps/emqx_plugin_template/.github/workflows/run_test_cases.yaml +++ /dev/null @@ -1,28 +0,0 @@ -name: Run test cases - -on: [push, pull_request] - -jobs: - run_test_cases: - runs-on: ubuntu-latest - - container: - image: erlang:22.1 - - steps: - - uses: actions/checkout@v1 - - name: run test cases - run: | - make eunit - make ct - make cover - - uses: actions/upload-artifact@v1 - if: always() - with: - name: logs - path: _build/test/logs - - uses: actions/upload-artifact@v1 - with: - name: cover - path: _build/test/cover - diff --git a/apps/emqx_plugin_template/src/emqx_plugin_template.app.src.script b/apps/emqx_plugin_template/src/emqx_plugin_template.app.src.script deleted file mode 100644 index 0e14ff23f..000000000 --- a/apps/emqx_plugin_template/src/emqx_plugin_template.app.src.script +++ /dev/null @@ -1,24 +0,0 @@ -%%-*- mode: erlang -*- -%% .app.src.script - -RemoveLeadingV = - fun(Tag) -> - case re:run(Tag, "^[v|e]?[0-9]\.[0-9]\.([0-9]|(rc|beta|alpha)\.[0-9])", [{capture, none}]) of - nomatch -> - re:replace(Tag, "/", "-", [{return ,list}]); - _ -> - %% if it is a version number prefixed by 'v' or 'e', then remove it - re:replace(Tag, "[v|e]", "", [{return ,list}]) - end - end, - -case os:getenv("EMQX_DEPS_DEFAULT_VSN") of - false -> CONFIG; % env var not defined - [] -> CONFIG; % env var set to empty string - Tag -> - [begin - AppConf0 = lists:keystore(vsn, 1, AppConf, {vsn, RemoveLeadingV(Tag)}), - {application, App, AppConf0} - end || Conf = {application, App, AppConf} <- CONFIG] -end. - diff --git a/apps/emqx_prometheus/.github/workflows/run_test_cases.yaml b/apps/emqx_prometheus/.github/workflows/run_test_cases.yaml deleted file mode 100644 index b8e722570..000000000 --- a/apps/emqx_prometheus/.github/workflows/run_test_cases.yaml +++ /dev/null @@ -1,29 +0,0 @@ -name: Run test cases - -on: [push, pull_request] - -jobs: - run_test_cases: - runs-on: ubuntu-latest - - container: - image: erlang:22.1 - - steps: - - uses: actions/checkout@v1 - - name: run test cases - run: | - make xref - make eunit - make ct - make cover - - uses: actions/upload-artifact@v1 - if: always() - with: - name: logs - path: _build/test/logs - - uses: actions/upload-artifact@v1 - with: - name: cover - path: _build/test/cover - diff --git a/apps/emqx_prometheus/src/emqx_prometheus.app.src.script b/apps/emqx_prometheus/src/emqx_prometheus.app.src.script deleted file mode 100644 index 0e14ff23f..000000000 --- a/apps/emqx_prometheus/src/emqx_prometheus.app.src.script +++ /dev/null @@ -1,24 +0,0 @@ -%%-*- mode: erlang -*- -%% .app.src.script - -RemoveLeadingV = - fun(Tag) -> - case re:run(Tag, "^[v|e]?[0-9]\.[0-9]\.([0-9]|(rc|beta|alpha)\.[0-9])", [{capture, none}]) of - nomatch -> - re:replace(Tag, "/", "-", [{return ,list}]); - _ -> - %% if it is a version number prefixed by 'v' or 'e', then remove it - re:replace(Tag, "[v|e]", "", [{return ,list}]) - end - end, - -case os:getenv("EMQX_DEPS_DEFAULT_VSN") of - false -> CONFIG; % env var not defined - [] -> CONFIG; % env var set to empty string - Tag -> - [begin - AppConf0 = lists:keystore(vsn, 1, AppConf, {vsn, RemoveLeadingV(Tag)}), - {application, App, AppConf0} - end || Conf = {application, App, AppConf} <- CONFIG] -end. - diff --git a/apps/emqx_psk_file/.github/workflows/run_test_cases.yaml b/apps/emqx_psk_file/.github/workflows/run_test_cases.yaml deleted file mode 100644 index b8e722570..000000000 --- a/apps/emqx_psk_file/.github/workflows/run_test_cases.yaml +++ /dev/null @@ -1,29 +0,0 @@ -name: Run test cases - -on: [push, pull_request] - -jobs: - run_test_cases: - runs-on: ubuntu-latest - - container: - image: erlang:22.1 - - steps: - - uses: actions/checkout@v1 - - name: run test cases - run: | - make xref - make eunit - make ct - make cover - - uses: actions/upload-artifact@v1 - if: always() - with: - name: logs - path: _build/test/logs - - uses: actions/upload-artifact@v1 - with: - name: cover - path: _build/test/cover - diff --git a/apps/emqx_psk_file/src/emqx_psk_file.app.src.script b/apps/emqx_psk_file/src/emqx_psk_file.app.src.script deleted file mode 100644 index 0e14ff23f..000000000 --- a/apps/emqx_psk_file/src/emqx_psk_file.app.src.script +++ /dev/null @@ -1,24 +0,0 @@ -%%-*- mode: erlang -*- -%% .app.src.script - -RemoveLeadingV = - fun(Tag) -> - case re:run(Tag, "^[v|e]?[0-9]\.[0-9]\.([0-9]|(rc|beta|alpha)\.[0-9])", [{capture, none}]) of - nomatch -> - re:replace(Tag, "/", "-", [{return ,list}]); - _ -> - %% if it is a version number prefixed by 'v' or 'e', then remove it - re:replace(Tag, "[v|e]", "", [{return ,list}]) - end - end, - -case os:getenv("EMQX_DEPS_DEFAULT_VSN") of - false -> CONFIG; % env var not defined - [] -> CONFIG; % env var set to empty string - Tag -> - [begin - AppConf0 = lists:keystore(vsn, 1, AppConf, {vsn, RemoveLeadingV(Tag)}), - {application, App, AppConf0} - end || Conf = {application, App, AppConf} <- CONFIG] -end. - diff --git a/apps/emqx_recon/.github/workflows/run_test_cases.yaml b/apps/emqx_recon/.github/workflows/run_test_cases.yaml deleted file mode 100644 index b8e722570..000000000 --- a/apps/emqx_recon/.github/workflows/run_test_cases.yaml +++ /dev/null @@ -1,29 +0,0 @@ -name: Run test cases - -on: [push, pull_request] - -jobs: - run_test_cases: - runs-on: ubuntu-latest - - container: - image: erlang:22.1 - - steps: - - uses: actions/checkout@v1 - - name: run test cases - run: | - make xref - make eunit - make ct - make cover - - uses: actions/upload-artifact@v1 - if: always() - with: - name: logs - path: _build/test/logs - - uses: actions/upload-artifact@v1 - with: - name: cover - path: _build/test/cover - diff --git a/apps/emqx_recon/src/emqx_recon.app.src.script b/apps/emqx_recon/src/emqx_recon.app.src.script deleted file mode 100644 index 0e14ff23f..000000000 --- a/apps/emqx_recon/src/emqx_recon.app.src.script +++ /dev/null @@ -1,24 +0,0 @@ -%%-*- mode: erlang -*- -%% .app.src.script - -RemoveLeadingV = - fun(Tag) -> - case re:run(Tag, "^[v|e]?[0-9]\.[0-9]\.([0-9]|(rc|beta|alpha)\.[0-9])", [{capture, none}]) of - nomatch -> - re:replace(Tag, "/", "-", [{return ,list}]); - _ -> - %% if it is a version number prefixed by 'v' or 'e', then remove it - re:replace(Tag, "[v|e]", "", [{return ,list}]) - end - end, - -case os:getenv("EMQX_DEPS_DEFAULT_VSN") of - false -> CONFIG; % env var not defined - [] -> CONFIG; % env var set to empty string - Tag -> - [begin - AppConf0 = lists:keystore(vsn, 1, AppConf, {vsn, RemoveLeadingV(Tag)}), - {application, App, AppConf0} - end || Conf = {application, App, AppConf} <- CONFIG] -end. - diff --git a/apps/emqx_retainer/.github/workflows/run_test_cases.yaml b/apps/emqx_retainer/.github/workflows/run_test_cases.yaml deleted file mode 100644 index b8e722570..000000000 --- a/apps/emqx_retainer/.github/workflows/run_test_cases.yaml +++ /dev/null @@ -1,29 +0,0 @@ -name: Run test cases - -on: [push, pull_request] - -jobs: - run_test_cases: - runs-on: ubuntu-latest - - container: - image: erlang:22.1 - - steps: - - uses: actions/checkout@v1 - - name: run test cases - run: | - make xref - make eunit - make ct - make cover - - uses: actions/upload-artifact@v1 - if: always() - with: - name: logs - path: _build/test/logs - - uses: actions/upload-artifact@v1 - with: - name: cover - path: _build/test/cover - diff --git a/apps/emqx_retainer/src/emqx_retainer.app.src.script b/apps/emqx_retainer/src/emqx_retainer.app.src.script deleted file mode 100644 index 0e14ff23f..000000000 --- a/apps/emqx_retainer/src/emqx_retainer.app.src.script +++ /dev/null @@ -1,24 +0,0 @@ -%%-*- mode: erlang -*- -%% .app.src.script - -RemoveLeadingV = - fun(Tag) -> - case re:run(Tag, "^[v|e]?[0-9]\.[0-9]\.([0-9]|(rc|beta|alpha)\.[0-9])", [{capture, none}]) of - nomatch -> - re:replace(Tag, "/", "-", [{return ,list}]); - _ -> - %% if it is a version number prefixed by 'v' or 'e', then remove it - re:replace(Tag, "[v|e]", "", [{return ,list}]) - end - end, - -case os:getenv("EMQX_DEPS_DEFAULT_VSN") of - false -> CONFIG; % env var not defined - [] -> CONFIG; % env var set to empty string - Tag -> - [begin - AppConf0 = lists:keystore(vsn, 1, AppConf, {vsn, RemoveLeadingV(Tag)}), - {application, App, AppConf0} - end || Conf = {application, App, AppConf} <- CONFIG] -end. - diff --git a/apps/emqx_rule_engine/.github/workflows/run_test_cases.yaml b/apps/emqx_rule_engine/.github/workflows/run_test_cases.yaml deleted file mode 100644 index 245eef68b..000000000 --- a/apps/emqx_rule_engine/.github/workflows/run_test_cases.yaml +++ /dev/null @@ -1,29 +0,0 @@ -name: Run test cases - -on: [push, pull_request] - -jobs: - run_test_cases: - runs-on: ubuntu-latest - - container: - image: erlang:22.1 - - steps: - - uses: actions/checkout@v1 - - name: run test cases - run: | - #make xref - make eunit - make ct - make cover - - uses: actions/upload-artifact@v1 - if: always() - with: - name: logs - path: _build/test/logs - - uses: actions/upload-artifact@v1 - with: - name: cover - path: _build/test/cover - diff --git a/apps/emqx_rule_engine/src/emqx_rule_engine.app.src.script b/apps/emqx_rule_engine/src/emqx_rule_engine.app.src.script deleted file mode 100644 index 0e14ff23f..000000000 --- a/apps/emqx_rule_engine/src/emqx_rule_engine.app.src.script +++ /dev/null @@ -1,24 +0,0 @@ -%%-*- mode: erlang -*- -%% .app.src.script - -RemoveLeadingV = - fun(Tag) -> - case re:run(Tag, "^[v|e]?[0-9]\.[0-9]\.([0-9]|(rc|beta|alpha)\.[0-9])", [{capture, none}]) of - nomatch -> - re:replace(Tag, "/", "-", [{return ,list}]); - _ -> - %% if it is a version number prefixed by 'v' or 'e', then remove it - re:replace(Tag, "[v|e]", "", [{return ,list}]) - end - end, - -case os:getenv("EMQX_DEPS_DEFAULT_VSN") of - false -> CONFIG; % env var not defined - [] -> CONFIG; % env var set to empty string - Tag -> - [begin - AppConf0 = lists:keystore(vsn, 1, AppConf, {vsn, RemoveLeadingV(Tag)}), - {application, App, AppConf0} - end || Conf = {application, App, AppConf} <- CONFIG] -end. - diff --git a/apps/emqx_rule_engine/src/emqx_rule_engine.appup.src b/apps/emqx_rule_engine/src/emqx_rule_engine.appup.src deleted file mode 100644 index 36551e73b..000000000 --- a/apps/emqx_rule_engine/src/emqx_rule_engine.appup.src +++ /dev/null @@ -1,44 +0,0 @@ -%% -*-: erlang -*- - -{"4.2.3", - [ - {"4.2.0", [ - {load_module, emqx_rule_events, brutal_purge, soft_purge, []}, - {load_module, emqx_rule_funcs, brutal_purge, soft_purge, []}, - {load_module, emqx_rule_maps, brutal_purge, soft_purge, []}, - {load_module, emqx_rule_engine, brutal_purge, soft_purge, []}, - {load_module, emqx_rule_actions, brutal_purge, soft_purge, []} - ]}, - {"4.2.1", [ - {load_module, emqx_rule_funcs, brutal_purge, soft_purge, []}, - {load_module, emqx_rule_maps, brutal_purge, soft_purge, []}, - {load_module, emqx_rule_engine, brutal_purge, soft_purge, []}, - {load_module, emqx_rule_actions, brutal_purge, soft_purge, []} - ]}, - {"4.2.2", [ - {load_module, emqx_rule_funcs, brutal_purge, soft_purge, []}, - {load_module, emqx_rule_engine, brutal_purge, soft_purge, []}, - {load_module, emqx_rule_actions, brutal_purge, soft_purge, []} - ]} - ], - [ - {"4.2.0", [ - {load_module, emqx_rule_events, brutal_purge, soft_purge, []}, - {load_module, emqx_rule_funcs, brutal_purge, soft_purge, []}, - {load_module, emqx_rule_maps, brutal_purge, soft_purge, []}, - {load_module, emqx_rule_engine, brutal_purge, soft_purge, []}, - {load_module, emqx_rule_actions, brutal_purge, soft_purge, []} - ]}, - {"4.2.1", [ - {load_module, emqx_rule_funcs, brutal_purge, soft_purge, []}, - {load_module, emqx_rule_maps, brutal_purge, soft_purge, []}, - {load_module, emqx_rule_engine, brutal_purge, soft_purge, []}, - {load_module, emqx_rule_actions, brutal_purge, soft_purge, []} - ]}, - {"4.2.2", [ - {load_module, emqx_rule_actions, brutal_purge, soft_purge, []}, - {load_module, emqx_rule_engine, brutal_purge, soft_purge, []}, - {load_module, emqx_rule_funcs, brutal_purge, soft_purge, []} - ]} - ] -}. diff --git a/apps/emqx_sasl/.github/workflows/run_test_case.yaml b/apps/emqx_sasl/.github/workflows/run_test_case.yaml deleted file mode 100644 index 2f7c808a4..000000000 --- a/apps/emqx_sasl/.github/workflows/run_test_case.yaml +++ /dev/null @@ -1,31 +0,0 @@ -name: Run test case - -on: - push: - pull_request: - -jobs: - - run_test_case: - - runs-on: ubuntu-latest - - container: - image: erlang:22.1 - - steps: - - uses: actions/checkout@v1 - - name: Run tests - run: | - make eunit - make ct - make cover - - uses: actions/upload-artifact@v1 - if: always() - with: - name: logs - path: _build/test/logs - - uses: actions/upload-artifact@v1 - with: - name: cover - path: _build/test/cover \ No newline at end of file diff --git a/apps/emqx_sasl/src/emqx_sasl.app.src.script b/apps/emqx_sasl/src/emqx_sasl.app.src.script deleted file mode 100644 index ad78864a1..000000000 --- a/apps/emqx_sasl/src/emqx_sasl.app.src.script +++ /dev/null @@ -1,33 +0,0 @@ -%%-*- mode: erlang -*- -%% .app.src.script - -Config = case os:getenv("EMQX_DESC") of - false -> CONFIG; % env var not defined - [] -> CONFIG; % env var set to empty string - Desc -> - [begin - AppConf0 = lists:keystore(description, 1, AppConf, {description, Desc}), - {application, App, AppConf0} - end || Conf = {application, App, AppConf} <- CONFIG] -end, - -RemoveLeadingV = - fun(Tag) -> - case re:run(Tag, "^[v|e]?[0-9]\.[0-9]\.([0-9]|(rc|beta|alpha)\.[0-9])", [{capture, none}]) of - nomatch -> - re:replace(Tag, "/", "-", [{return ,list}]); - _ -> - %% if it is a version number prefixed by 'v' or 'e', then remove it - re:replace(Tag, "[v|e]", "", [{return ,list}]) - end - end, - -case os:getenv("EMQX_DEPS_DEFAULT_VSN") of - false -> Config; % env var not defined - [] -> Config; % env var set to empty string - Tag -> - [begin - AppConf0 = lists:keystore(vsn, 1, AppConf, {vsn, RemoveLeadingV(Tag)}), - {application, App, AppConf0} - end || Conf = {application, App, AppConf} <- Config] -end. diff --git a/apps/emqx_sasl/src/emqx_sasl.appup.src b/apps/emqx_sasl/src/emqx_sasl.appup.src deleted file mode 100644 index e7b8c62a9..000000000 --- a/apps/emqx_sasl/src/emqx_sasl.appup.src +++ /dev/null @@ -1,30 +0,0 @@ -{"4.2.3", - [ - {"4.2.0", [ - {load_module, emqx_sasl_api, brutal_purge, soft_purge, []}, - {load_module, emqx_sasl_cli, brutal_purge, soft_purge, []} - ]}, - {"4.2.1", [ - {load_module, emqx_sasl_api, brutal_purge, soft_purge, []}, - {load_module, emqx_sasl_cli, brutal_purge, soft_purge, []} - ]}, - {"4.2.2", [ - {load_module, emqx_sasl_api, brutal_purge, soft_purge, []}, - {load_module, emqx_sasl_cli, brutal_purge, soft_purge, []} - ]} - ], - [ - {"4.2.0", [ - {load_module, emqx_sasl_api, brutal_purge, soft_purge, []}, - {load_module, emqx_sasl_cli, brutal_purge, soft_purge, []} - ]}, - {"4.2.1", [ - {load_module, emqx_sasl_api, brutal_purge, soft_purge, []}, - {load_module, emqx_sasl_cli, brutal_purge, soft_purge, []} - ]}, - {"4.2.2", [ - {load_module, emqx_sasl_api, brutal_purge, soft_purge, []}, - {load_module, emqx_sasl_cli, brutal_purge, soft_purge, []} - ]} - ] -}. diff --git a/apps/emqx_sn/.github/workflows/run_test_cases.yaml b/apps/emqx_sn/.github/workflows/run_test_cases.yaml deleted file mode 100644 index 50fa9632e..000000000 --- a/apps/emqx_sn/.github/workflows/run_test_cases.yaml +++ /dev/null @@ -1,31 +0,0 @@ -name: Run test cases - -on: [push, pull_request] - -jobs: - run_test_cases: - runs-on: ubuntu-latest - - container: - image: erlang:22.1 - - steps: - - uses: actions/checkout@v1 - - name: run test cases - run: | - make dialyzer - make xref - make eunit - make ct - make proper - make cover - - uses: actions/upload-artifact@v1 - if: always() - with: - name: logs - path: _build/test/logs - - uses: actions/upload-artifact@v1 - with: - name: cover - path: _build/test/cover - diff --git a/apps/emqx_sn/src/emqx_sn.app.src.script b/apps/emqx_sn/src/emqx_sn.app.src.script deleted file mode 100644 index 0e14ff23f..000000000 --- a/apps/emqx_sn/src/emqx_sn.app.src.script +++ /dev/null @@ -1,24 +0,0 @@ -%%-*- mode: erlang -*- -%% .app.src.script - -RemoveLeadingV = - fun(Tag) -> - case re:run(Tag, "^[v|e]?[0-9]\.[0-9]\.([0-9]|(rc|beta|alpha)\.[0-9])", [{capture, none}]) of - nomatch -> - re:replace(Tag, "/", "-", [{return ,list}]); - _ -> - %% if it is a version number prefixed by 'v' or 'e', then remove it - re:replace(Tag, "[v|e]", "", [{return ,list}]) - end - end, - -case os:getenv("EMQX_DEPS_DEFAULT_VSN") of - false -> CONFIG; % env var not defined - [] -> CONFIG; % env var set to empty string - Tag -> - [begin - AppConf0 = lists:keystore(vsn, 1, AppConf, {vsn, RemoveLeadingV(Tag)}), - {application, App, AppConf0} - end || Conf = {application, App, AppConf} <- CONFIG] -end. - diff --git a/apps/emqx_sn/src/emqx_sn.appup.src b/apps/emqx_sn/src/emqx_sn.appup.src deleted file mode 100644 index 30f295134..000000000 --- a/apps/emqx_sn/src/emqx_sn.appup.src +++ /dev/null @@ -1,25 +0,0 @@ -%% -*-: erlang -*- -{"4.2.3", - [ - {"4.2.2", [ - {load_module, emqx_sn_gateway, brutal_purge, soft_purge, []} - ]}, - {"4.2.1", [ - {load_module, emqx_sn_gateway, brutal_purge, soft_purge, []} - ]}, - {"4.2.0", [ - {load_module, emqx_sn_gateway, brutal_purge, soft_purge, []} - ]} - ], - [ - {"4.2.2", [ - {load_module, emqx_sn_gateway, brutal_purge, soft_purge, []} - ]}, - {"4.2.1", [ - {load_module, emqx_sn_gateway, brutal_purge, soft_purge, []} - ]}, - {"4.2.0", [ - {load_module, emqx_sn_gateway, brutal_purge, soft_purge, []} - ]} - ] -}. diff --git a/apps/emqx_stomp/.github/workflows/run_test_cases.yaml b/apps/emqx_stomp/.github/workflows/run_test_cases.yaml deleted file mode 100644 index b8e722570..000000000 --- a/apps/emqx_stomp/.github/workflows/run_test_cases.yaml +++ /dev/null @@ -1,29 +0,0 @@ -name: Run test cases - -on: [push, pull_request] - -jobs: - run_test_cases: - runs-on: ubuntu-latest - - container: - image: erlang:22.1 - - steps: - - uses: actions/checkout@v1 - - name: run test cases - run: | - make xref - make eunit - make ct - make cover - - uses: actions/upload-artifact@v1 - if: always() - with: - name: logs - path: _build/test/logs - - uses: actions/upload-artifact@v1 - with: - name: cover - path: _build/test/cover - diff --git a/apps/emqx_stomp/src/emqx_stomp.app.src.script b/apps/emqx_stomp/src/emqx_stomp.app.src.script deleted file mode 100644 index 0e14ff23f..000000000 --- a/apps/emqx_stomp/src/emqx_stomp.app.src.script +++ /dev/null @@ -1,24 +0,0 @@ -%%-*- mode: erlang -*- -%% .app.src.script - -RemoveLeadingV = - fun(Tag) -> - case re:run(Tag, "^[v|e]?[0-9]\.[0-9]\.([0-9]|(rc|beta|alpha)\.[0-9])", [{capture, none}]) of - nomatch -> - re:replace(Tag, "/", "-", [{return ,list}]); - _ -> - %% if it is a version number prefixed by 'v' or 'e', then remove it - re:replace(Tag, "[v|e]", "", [{return ,list}]) - end - end, - -case os:getenv("EMQX_DEPS_DEFAULT_VSN") of - false -> CONFIG; % env var not defined - [] -> CONFIG; % env var set to empty string - Tag -> - [begin - AppConf0 = lists:keystore(vsn, 1, AppConf, {vsn, RemoveLeadingV(Tag)}), - {application, App, AppConf0} - end || Conf = {application, App, AppConf} <- CONFIG] -end. - diff --git a/apps/emqx_telemetry/src/emqx_telemetry.appup.src b/apps/emqx_telemetry/src/emqx_telemetry.appup.src deleted file mode 100644 index 57077db96..000000000 --- a/apps/emqx_telemetry/src/emqx_telemetry.appup.src +++ /dev/null @@ -1,24 +0,0 @@ -{"4.2.3", - [ - {"4.2.2", [ - {load_module, emqx_telemetry, brutal_purge, soft_purge, []} - ]}, - {"4.2.1", [ - {load_module, emqx_telemetry, brutal_purge, soft_purge, []} - ]}, - {"4.2.0", [ - {load_module, emqx_telemetry, brutal_purge, soft_purge, []} - ]} - ], - [ - {"4.2.2", [ - {load_module, emqx_telemetry, brutal_purge, soft_purge, []} - ]}, - {"4.2.1", [ - {load_module, emqx_telemetry, brutal_purge, soft_purge, []} - ]}, - {"4.2.0", [ - {load_module, emqx_telemetry, brutal_purge, soft_purge, []} - ]} - ] -}. diff --git a/apps/emqx_web_hook/.github/workflows/run_test_cases.yaml b/apps/emqx_web_hook/.github/workflows/run_test_cases.yaml deleted file mode 100644 index e174c4a98..000000000 --- a/apps/emqx_web_hook/.github/workflows/run_test_cases.yaml +++ /dev/null @@ -1,33 +0,0 @@ -name: Run test cases - -on: [push, pull_request] - -jobs: - run_test_cases: - runs-on: ubuntu-latest - - container: - image: erlang:22.1 - - steps: - - uses: actions/checkout@v1 - - name: code dialyzer - run: | - make xref - make dialyzer - - name: run test cases - run: | - make eunit - make ct - make proper - make cover - - uses: actions/upload-artifact@v1 - if: always() - with: - name: logs - path: _build/test/logs - - uses: actions/upload-artifact@v1 - with: - name: cover - path: _build/test/cover - diff --git a/apps/emqx_web_hook/src/emqx_web_hook.app.src.script b/apps/emqx_web_hook/src/emqx_web_hook.app.src.script deleted file mode 100644 index 0e14ff23f..000000000 --- a/apps/emqx_web_hook/src/emqx_web_hook.app.src.script +++ /dev/null @@ -1,24 +0,0 @@ -%%-*- mode: erlang -*- -%% .app.src.script - -RemoveLeadingV = - fun(Tag) -> - case re:run(Tag, "^[v|e]?[0-9]\.[0-9]\.([0-9]|(rc|beta|alpha)\.[0-9])", [{capture, none}]) of - nomatch -> - re:replace(Tag, "/", "-", [{return ,list}]); - _ -> - %% if it is a version number prefixed by 'v' or 'e', then remove it - re:replace(Tag, "[v|e]", "", [{return ,list}]) - end - end, - -case os:getenv("EMQX_DEPS_DEFAULT_VSN") of - false -> CONFIG; % env var not defined - [] -> CONFIG; % env var set to empty string - Tag -> - [begin - AppConf0 = lists:keystore(vsn, 1, AppConf, {vsn, RemoveLeadingV(Tag)}), - {application, App, AppConf0} - end || Conf = {application, App, AppConf} <- CONFIG] -end. - diff --git a/apps/emqx_web_hook/src/emqx_web_hook.appup.src b/apps/emqx_web_hook/src/emqx_web_hook.appup.src deleted file mode 100644 index 55f99d668..000000000 --- a/apps/emqx_web_hook/src/emqx_web_hook.appup.src +++ /dev/null @@ -1,36 +0,0 @@ -%% -*-: erlang -*- - -{"4.2.3", - [ - {"4.2.2", [ - {load_module, emqx_web_hook_actions, brutal_purge, soft_purge, []}, - {apply, {emqx_rule_engine, load_providers, []}} - ]}, - {"4.2.1", [ - {load_module, emqx_web_hook, brutal_purge, soft_purge, []}, - {load_module, emqx_web_hook_actions, brutal_purge, soft_purge, [emqx_rule_engine]}, - {apply, {emqx_rule_engine, load_providers, []}} - ]}, - {"4.2.0", [ - {load_module, emqx_web_hook, brutal_purge, soft_purge, []}, - {load_module, emqx_web_hook_actions, brutal_purge, soft_purge, [emqx_rule_engine]}, - {apply, {emqx_rule_engine, load_providers, []}} - ]} - ], - [ - {"4.2.2", [ - {load_module, emqx_web_hook_actions, brutal_purge, soft_purge, []}, - {apply, {emqx_rule_engine, load_providers, []}} - ]}, - {"4.2.1", [ - {load_module, emqx_web_hook, brutal_purge, soft_purge, []}, - {load_module, emqx_web_hook_actions, brutal_purge, soft_purge, [emqx_rule_engine]}, - {apply, {emqx_rule_engine, load_providers, []}} - ]}, - {"4.2.0", [ - {load_module, emqx_web_hook, brutal_purge, soft_purge, []}, - {load_module, emqx_web_hook_actions, brutal_purge, soft_purge, [emqx_rule_engine]}, - {apply, {emqx_rule_engine, load_providers, []}} - ]} - ] -}. diff --git a/sync-apps.sh b/sync-apps.sh index 46ad0e706..c7caaba3c 100755 --- a/sync-apps.sh +++ b/sync-apps.sh @@ -8,7 +8,6 @@ apps=( "emqx_auth_http" "emqx_auth_jwt" "emqx_auth_ldap" -"emqx_auth_mnesia" "emqx_auth_mongo" "emqx_auth_mysql" "emqx_auth_pgsql" @@ -57,6 +56,7 @@ download_zip() { default_vsn="dev/v4.3.0" download_zip "emqx_passwd" "v1.1.1" +download_zip "emqx_auth_mnesia" "e4.2.2" for app in ${apps[@]}; do download_zip "$app" "$default_vsn" done @@ -79,17 +79,22 @@ extract_zip(){ } extract_zip "emqx_passwd" "v1.1.1" "1.1.1" +extract_zip "emqx_auth_mnesia" "e4.2.2" "e4.2.2" for app in ${apps[@]}; do extract_zip "$app" "$default_vsn" done cleanup_app(){ local app="$1" - rm -f "apps/$app/Makefile" - rm -f "apps/$app/rebar.config.script" + pushd "apps/$app" + rm -f Makefile rebar.config.script + rm -rf ".github" ".ci" + rm -rf src/*.app.src.script + rm -rf src/*.appup.src + popd } -apps+=( "emqx_passwd" ) +apps+=( "emqx_passwd" "emqx_auth_mnesia" ) for app in ${apps[@]}; do cleanup_app $app done