Add more cleanups
This commit is contained in:
parent
686c006d6e
commit
8a12018863
|
@ -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
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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
|
|
@ -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 []
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
@ -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~!@#$%^&*()_+
|
||||
|
|
|
@ -1,16 +1,19 @@
|
|||
-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, {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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]).
|
||||
|
|
|
@ -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]);
|
||||
do_add([ Params | ParamsN ], ReList) ->
|
||||
do_add(ParamsN, [do_add(Params) | ReList]);
|
||||
|
||||
add_acl([], 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.
|
||||
|
||||
|
|
|
@ -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 <Clientid>", "Lookup clientid acl detail"}
|
||||
, {"acl show username <Username>", "Lookup username acl detail"}
|
||||
, {"acl aad clientid <Clientid> <Topic> <Action> <Access>", "Add clientid acl"}
|
||||
, {"acl add Username <Username> <Topic> <Action> <Access>", "Add username acl"}
|
||||
, {"acl add _all <Topic> <Action> <Access>", "Add $all acl"}
|
||||
, {"acl del clientid <Clientid> <Topic>", "Delete clientid acl"}
|
||||
, {"acl del username <Username> <Topic>", "Delete username acl"}
|
||||
, {"acl del _all, <Topic>", "Delete $all acl"}
|
||||
]).
|
||||
|
||||
|
|
@ -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.
|
||||
|
|
@ -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 || <<Salt:4/binary, Hash/binary>> <- 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, <<SaltBin/binary, Password/binary>>).
|
||||
|
|
|
@ -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]);
|
||||
do_add_clientid([ Params | ParamsN ], ReList ) ->
|
||||
Clientid = urldecode(get_value(<<"clientid">>, Params)),
|
||||
do_add_clientid(ParamsN, [{Clientid, format_msg(do_add_clientid(Params))} | ReList]);
|
||||
|
||||
add_user([], 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.
|
||||
|
||||
|
|
|
@ -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, [#{}]).
|
||||
|
|
|
@ -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(),
|
||||
<<SaltBin/binary, (hash(Password, SaltBin, HashType))/binary>>.
|
||||
|
||||
hash(undefined, SaltBin, HashType) ->
|
||||
hash(<<>>, SaltBin, HashType);
|
||||
hash(Password, SaltBin, HashType) ->
|
||||
emqx_passwd:hash(HashType, <<SaltBin/binary, Password/binary>>).
|
||||
|
||||
salt() ->
|
||||
rand:seed(exsplus, erlang:timestamp()),
|
||||
Salt = rand:uniform(16#ffffffff), <<Salt:32>>.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% 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 <Username> <Password>", "Add clientid auth rule"},
|
||||
{"clientid update <Username> <NewPassword>", "Update clientid auth rule"},
|
||||
{"clientid del <Username>", "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 <Login> <Password> <IsSuper>", "Add user"},
|
||||
{"mqtt-user update <Login> <NewPassword> <IsSuper>", "Update user"},
|
||||
{"mqtt-user delete <Login>", "Delete user"},
|
||||
{"mqtt-user show <Login>", "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
|
||||
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 <Login> <Topic> <Action> <Allow>", "Add acl"},
|
||||
{"mqtt-acl show <Login>", "Lookup acl detail"},
|
||||
{"mqtt-acl del <Login>", "Delete acl"},
|
||||
{"mqtt-acl list","List all acls"}]).
|
||||
auth_username_cli(_) ->
|
||||
emqx_ctl:usage([{"users list", "List username auth rules"},
|
||||
{"users add <Username> <Password>", "Add username auth rule"},
|
||||
{"users update <Username> <NewPassword>", "Update username auth rule"},
|
||||
{"users del <Username>", "Delete username auth rule"}]).
|
||||
|
|
|
@ -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),
|
||||
ok = emqx_acl_mnesia_cli:add_acl({clientid, <<"test_clientid">>}, <<"topic/%c">>, sub, allow),
|
||||
ok = emqx_acl_mnesia_cli:add_acl({clientid, <<"test_clientid">>}, <<"topic/+">>, pub, deny),
|
||||
ok = emqx_acl_mnesia_cli:add_acl({username, <<"test_username">>}, <<"topic/%u">>, sub, deny),
|
||||
ok = emqx_acl_mnesia_cli:add_acl({username, <<"test_username">>}, <<"topic/+">>, pub, allow),
|
||||
ok = emqx_acl_mnesia_cli:add_acl(all, <<"#">>, pubsub, deny),
|
||||
|
||||
?assertEqual([{emqx_acl,<<"test_username">>,<<"Topic/A">>,<<"sub">>, true},
|
||||
{emqx_acl,<<"test_username">>,<<"Topic/B">>,<<"pub">>, true},
|
||||
{emqx_acl,<<"test_username">>,<<"Topic/C">>,<<"pubsub">>, true}],emqx_auth_mnesia_cli:lookup_acl(<<"test_username">>)),
|
||||
ok = emqx_auth_mnesia_cli:remove_acl(<<"test_username">>, <<"Topic/A">>),
|
||||
?assertEqual([{emqx_acl,<<"test_username">>,<<"Topic/B">>,<<"pub">>, true},
|
||||
{emqx_acl,<<"test_username">>,<<"Topic/C">>,<<"pubsub">>, true}], emqx_auth_mnesia_cli:lookup_acl(<<"test_username">>)),
|
||||
|
||||
|
||||
ok = emqx_auth_mnesia_cli:add_acl(<<"$all">>, <<"Topic/A">>, <<"sub">>, true),
|
||||
ok = emqx_auth_mnesia_cli:add_acl(<<"$all">>, <<"Topic/B">>, <<"pub">>, true),
|
||||
ok = emqx_auth_mnesia_cli:add_acl(<<"$all">>, <<"Topic/C">>, <<"pubsub">>, true),
|
||||
|
||||
?assertEqual([{emqx_acl,<<"$all">>,<<"Topic/A">>,<<"sub">>, true},
|
||||
{emqx_acl,<<"$all">>,<<"Topic/B">>,<<"pub">>, true},
|
||||
{emqx_acl,<<"$all">>,<<"Topic/C">>,<<"pubsub">>, true}],emqx_auth_mnesia_cli:lookup_acl(<<"$all">>)),
|
||||
ok = emqx_auth_mnesia_cli:remove_acl(<<"$all">>, <<"Topic/A">>),
|
||||
?assertEqual([{emqx_acl,<<"$all">>,<<"Topic/B">>,<<"pub">>, true},
|
||||
{emqx_acl,<<"$all">>,<<"Topic/C">>,<<"pubsub">>, true}], emqx_auth_mnesia_cli:lookup_acl(<<"$all">>)).
|
||||
|
||||
t_check_acl_as_clientid(_) ->
|
||||
clean_all_acls(),
|
||||
emqx_modules:load_module(emqx_mod_acl_internal, false),
|
||||
?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) ->
|
||||
|
|
|
@ -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}, <<Salt:4/binary, Hash/binary>>, _}] = emqx_auth_mnesia_cli:lookup_user({clientid, ?CLIENTID}),
|
||||
?assertEqual(Hash, emqx_passwd:hash(HashType, <<Salt/binary, ?PASSWORD/binary>>)),
|
||||
|
||||
emqx_auth_mnesia_cli:auth_clientid_cli(["update", ?CLIENTID, ?NPASSWORD]),
|
||||
[{_, {clientid, ?CLIENTID}, <<Salt1:4/binary, Hash1/binary>>, _}] = emqx_auth_mnesia_cli:lookup_user({clientid, ?CLIENTID}),
|
||||
?assertEqual(Hash1, emqx_passwd:hash(HashType, <<Salt1/binary, ?NPASSWORD/binary>>)),
|
||||
|
||||
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}, <<Salt:4/binary, Hash/binary>>, _}] = emqx_auth_mnesia_cli:lookup_user({username, ?USERNAME}),
|
||||
?assertEqual(Hash, emqx_passwd:hash(HashType, <<Salt/binary, ?PASSWORD/binary>>)),
|
||||
|
||||
emqx_auth_mnesia_cli:auth_username_cli(["update", ?USERNAME, ?NPASSWORD]),
|
||||
[{_, {username, ?USERNAME}, <<Salt1:4/binary, Hash1/binary>>, _}] = emqx_auth_mnesia_cli:lookup_user({username, ?USERNAME}),
|
||||
?assertEqual(Hash1, emqx_passwd:hash(HashType, <<Salt1/binary, ?NPASSWORD/binary>>)),
|
||||
|
||||
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}
|
||||
Params2 = #{<<"clientid">> => ?CLIENTID, <<"password">> => ?NPASSWORD},
|
||||
{ok, _} = request_http_rest_update(["auth_clientid/" ++ binary_to_list(?CLIENTID)], Params2),
|
||||
|
||||
{ok, Result2} = request_http_rest_lookup(["auth_clientid/" ++ binary_to_list(?CLIENTID)]),
|
||||
?assertMatch(#{<<"clientid">> := ?CLIENTID}, get_http_data(Result2)),
|
||||
|
||||
Params3 = [ #{<<"clientid">> => ?CLIENTID, <<"password">> => ?PASSWORD}
|
||||
, #{<<"clientid">> => <<"clientid1">>, <<"password">> => ?PASSWORD}
|
||||
, #{<<"clientid">> => <<"clientid2">>, <<"password">> => ?PASSWORD}
|
||||
],
|
||||
{ok, Result2} = request_http_rest_add(Params1),
|
||||
#{
|
||||
<<"test_username">> := <<"{error,existed}">>,
|
||||
<<"test_username/1">> := <<"{error,is_superuser}">>,
|
||||
<<"test_username/2">> := <<"ok">>
|
||||
} = get_http_data(Result2),
|
||||
{ok, Result3} = request_http_rest_add(["auth_clientid"], Params3),
|
||||
?assertMatch(#{ ?CLIENTID := <<"{error,existed}">>
|
||||
, <<"clientid1">> := <<"ok">>
|
||||
, <<"clientid2">> := <<"ok">>
|
||||
}, get_http_data(Result3)),
|
||||
|
||||
{ok, Result3} = request_http_rest_lookup(<<"test_username">>),
|
||||
#{<<"login">> := <<"test_username">>, <<"is_superuser">> := true} = get_http_data(Result3),
|
||||
{ok, Result4} = request_http_rest_list(["auth_clientid"]),
|
||||
?assertEqual(3, length(get_http_data(Result4))),
|
||||
|
||||
{ok, _} = request_http_rest_update(<<"test_username">>, <<"new_password">>, error_format),
|
||||
{ok, _} = request_http_rest_update(<<"error_username">>, <<"new_password">>, false),
|
||||
|
||||
{ok, _} = request_http_rest_update(<<"test_username">>, <<"new_password">>, false),
|
||||
{ok, Result4} = request_http_rest_lookup(<<"test_username">>),
|
||||
#{<<"login">> := <<"test_username">>, <<"is_superuser">> := false} = get_http_data(Result4),
|
||||
|
||||
User1 = #{username => <<"test_username">>,
|
||||
password => <<"new_password">>,
|
||||
zone => external},
|
||||
|
||||
{ok, #{is_superuser := false,
|
||||
auth_result := success,
|
||||
anonymous := false}} = emqx_access_control:authenticate(User1),
|
||||
|
||||
{ok, _} = request_http_rest_delete(<<"test_username">>),
|
||||
{ok, #{auth_result := success,
|
||||
anonymous := true }} = emqx_access_control:authenticate(User1).
|
||||
|
||||
t_run_command(_) ->
|
||||
clean_all_users(),
|
||||
?assertEqual(ok, emqx_ctl:run_command(["mqtt-user", "add", "TestUser", "Password", false])),
|
||||
?assertMatch([{emqx_user, <<"TestUser">>, _, false}], emqx_auth_mnesia_cli:lookup_user(<<"TestUser">>)),
|
||||
|
||||
?assertEqual(ok, emqx_ctl:run_command(["mqtt-user", "update", "TestUser", "NewPassword", true])),
|
||||
?assertMatch([{emqx_user, <<"TestUser">>, _, true}], emqx_auth_mnesia_cli:lookup_user(<<"TestUser">>)),
|
||||
|
||||
?assertEqual(ok, emqx_ctl:run_command(["mqtt-user", "del", "TestUser"])),
|
||||
?assertMatch([], emqx_auth_mnesia_cli:lookup_user(<<"TestUser">>)),
|
||||
|
||||
?assertEqual(ok, emqx_ctl:run_command(["mqtt-user", "show", "TestUser"])),
|
||||
?assertEqual(ok, emqx_ctl:run_command(["mqtt-user", "list"])),
|
||||
?assertEqual(ok, emqx_ctl:run_command(["mqtt-user"])).
|
||||
|
||||
t_cli(_) ->
|
||||
meck:new(emqx_ctl, [non_strict, passthrough]),
|
||||
meck:expect(emqx_ctl, print, fun(Arg) -> emqx_ctl:format(Arg) end),
|
||||
meck:expect(emqx_ctl, print, fun(Msg, Arg) -> emqx_ctl:format(Msg, Arg) end),
|
||||
meck:expect(emqx_ctl, usage, fun(Usages) -> emqx_ctl:format_usage(Usages) end),
|
||||
meck:expect(emqx_ctl, usage, fun(Cmd, Descr) -> emqx_ctl:format_usage(Cmd, Descr) end),
|
||||
{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) ->
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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]}
|
||||
]}
|
||||
]
|
||||
}.
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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, []}
|
||||
]}
|
||||
]
|
||||
}.
|
|
@ -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
|
|
@ -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"]
|
|
@ -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
|
|
@ -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.
|
||||
|
|
@ -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, []}
|
||||
]}
|
||||
]
|
||||
}.
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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.
|
||||
|
|
@ -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, []}
|
||||
]
|
||||
}
|
||||
]
|
||||
}.
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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, []}}
|
||||
]}
|
||||
]
|
||||
}.
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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, []}}
|
||||
]}
|
||||
]
|
||||
}.
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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, []}
|
||||
]}
|
||||
]
|
||||
}.
|
|
@ -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"
|
||||
|
|
@ -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.
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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, []}
|
||||
]}
|
||||
]
|
||||
}.
|
|
@ -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
|
|
@ -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.
|
|
@ -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, []}
|
||||
]}
|
||||
]
|
||||
}.
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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, []}
|
||||
]}
|
||||
]
|
||||
}.
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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, []}
|
||||
]}
|
||||
]
|
||||
}.
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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, []}}
|
||||
]}
|
||||
]
|
||||
}.
|
13
sync-apps.sh
13
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
|
||||
|
|
Loading…
Reference in New Issue