Skip to content

Commit

Permalink
chore: sync code from enterprise
Browse files Browse the repository at this point in the history
  • Loading branch information
terry-xiaoyu committed May 6, 2023
1 parent d9f8c09 commit ee50359
Show file tree
Hide file tree
Showing 8 changed files with 252 additions and 39 deletions.
4 changes: 4 additions & 0 deletions .ci/docker-compose-file/docker-compose-emqx-cluster.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ services:
image: $TARGET:$EMQX_TAG
env_file:
- conf.cluster.env
volumes:
- ../../:/src/
environment:
- "EMQX_HOST=node1.emqx.io"
command:
Expand All @@ -57,6 +59,8 @@ services:
image: $TARGET:$EMQX_TAG
env_file:
- conf.cluster.env
volumes:
- ../../:/src/
environment:
- "EMQX_HOST=node2.emqx.io"
command:
Expand Down
4 changes: 3 additions & 1 deletion .ci/docker-compose-file/docker-compose-mongo-tcp.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ version: '3.9'

services:
mongo_server:
container_name: mongo
container_name: mongo
image: mongo:${MONGO_TAG}
restart: always
environment:
MONGO_INITDB_DATABASE: mqtt
expose:
- 27017
networks:
- emqx_bridge
command:
Expand Down
3 changes: 3 additions & 0 deletions .ci/docker-compose-file/docker-compose-toxiproxy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ services:
- "./toxiproxy.json:/config/toxiproxy.json"
ports:
- 8474:8474
- 27011:27011
- 27016:27016
- 27017:27017
command:
- "-host=0.0.0.0"
- "-config=/config/toxiproxy.json"
36 changes: 36 additions & 0 deletions .ci/docker-compose-file/toxiproxy.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,41 @@
"listen": "0.0.0.0:27017",
"upstream": "mongo:27017",
"enabled": true
},
{
"name": "mongo_rs1",
"listen": "0.0.0.0:27011",
"upstream": "mongo_rs1:27017",
"enabled": true
},
{
"name": "mongo_rs2",
"listen": "0.0.0.0:27012",
"upstream": "mongo_rs2:27017",
"enabled": true
},
{
"name": "mongo_rs3",
"listen": "0.0.0.0:27013",
"upstream": "mongo_rs3:27017",
"enabled": true
},
{
"name": "mongo_sharded1",
"listen": "0.0.0.0:27014",
"upstream": "mongosharded1:27017",
"enabled": true
},
{
"name": "mongo_sharded2",
"listen": "0.0.0.0:27015",
"upstream": "mongosharded2:27017",
"enabled": true
},
{
"name": "mongo_sharded3",
"listen": "0.0.0.0:27016",
"upstream": "mongosharded3:27017",
"enabled": true
}
]
2 changes: 1 addition & 1 deletion apps/emqx_auth_pgsql/src/emqx_auth_pgsql.app.src
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{application, emqx_auth_pgsql,
[{description, "EMQX Authentication/ACL with PostgreSQL"},
{vsn, "4.4.6"}, % strict semver, bump manually!
{vsn, "4.4.7"}, % strict semver, bump manually!
{modules, []},
{registered, [emqx_auth_pgsql_sup]},
{applications, [kernel,stdlib,epgsql,ecpool]},
Expand Down
18 changes: 12 additions & 6 deletions apps/emqx_auth_pgsql/src/emqx_auth_pgsql.appup.src
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
%% -*- mode: erlang -*-
%% Unless you know what you are doing, DO NOT edit manually!!
{VSN,
[{"4.4.5",
[{load_module,emqx_auth_pgsql,brutal_purge,soft_purge,[]},
[{"4.4.6",[{load_module,emqx_auth_pgsql_cli,brutal_purge,soft_purge,[]}]},
{"4.4.5",
[{load_module,emqx_auth_pgsql_cli,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_pgsql,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_pgsql,brutal_purge,soft_purge,[]}]},
{"4.4.4",
[{load_module,emqx_acl_pgsql,brutal_purge,soft_purge,[]},
[{load_module,emqx_auth_pgsql_cli,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_pgsql,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_pgsql,brutal_purge,soft_purge,[]}]},
{"4.4.3",
[{load_module,emqx_acl_pgsql,brutal_purge,soft_purge,[]},
Expand All @@ -17,11 +20,14 @@
{load_module,emqx_auth_pgsql,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_pgsql_app,brutal_purge,soft_purge,[]}]},
{<<".*">>,[]}],
[{"4.4.5",
[{load_module,emqx_auth_pgsql,brutal_purge,soft_purge,[]},
[{"4.4.6",[{load_module,emqx_auth_pgsql_cli,brutal_purge,soft_purge,[]}]},
{"4.4.5",
[{load_module,emqx_auth_pgsql_cli,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_pgsql,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_pgsql,brutal_purge,soft_purge,[]}]},
{"4.4.4",
[{load_module,emqx_acl_pgsql,brutal_purge,soft_purge,[]},
[{load_module,emqx_auth_pgsql_cli,brutal_purge,soft_purge,[]},
{load_module,emqx_acl_pgsql,brutal_purge,soft_purge,[]},
{load_module,emqx_auth_pgsql,brutal_purge,soft_purge,[]}]},
{"4.4.3",
[{load_module,emqx_acl_pgsql,brutal_purge,soft_purge,[]},
Expand Down
112 changes: 95 additions & 17 deletions apps/emqx_auth_pgsql/src/emqx_auth_pgsql_cli.erl
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,22 @@

-include_lib("emqx/include/emqx.hrl").
-include_lib("emqx/include/logger.hrl").
-include_lib("epgsql/include/epgsql.hrl").

-export([connect/1]).
-export([parse_query/2]).
-export([parse_query/2, pgvar/2]).
-export([ equery/4
, equery/3
]).

-export([ get_sql_conf/1
, put_sql_conf/2
, clear_sql_conf/1
, get_cached_statement/1
, put_cached_statement/2
, clear_cached_statement/1
]).

-type client_info() :: #{username := _,
clientid := _,
peerhost := _,
Expand All @@ -44,9 +53,9 @@ parse_query(Par, Sql) ->
case re:run(Sql, "'%[ucCad]'", [global, {capture, all, list}]) of
{match, Variables} ->
Params = [Var || [Var] <- Variables],
{atom_to_list(Par), Params};
{str(Par), Params};
nomatch ->
{atom_to_list(Par), []}
{str(Par), []}
end.

pgvar(Sql, Params) ->
Expand Down Expand Up @@ -86,16 +95,24 @@ connect(Opts) ->
{error, Reason}
end.

conn_post(Connection) ->
lists:foreach(fun(Par) ->
Sql0 = application:get_env(?APP, Par, undefined),
case parse_query(Par, Sql0) of
undefined -> ok;
{_, Params} ->
Sql = pgvar(Sql0, Params),
epgsql:parse(Connection, atom_to_list(Par), Sql, [])
end
end, [auth_query, acl_query, super_query]).
conn_post(Conn) ->
lists:foreach(fun(PreparedStKey) ->
case prepare_statement(Conn, PreparedStKey) of
{ok, St} -> put_cached_statement(PreparedStKey, St);
Error -> Error
end
end, [auth_query, acl_query, super_query]).

prepare_statement(Conn, PreparedStKey) ->
%% for emqx_auth_pgsql plugin, the PreparedStKey is an atom(),
%% but for emqx_module_auth_pgsql, it is a list().
Sql0 = get_sql_conf(PreparedStKey),
case parse_query(PreparedStKey, Sql0) of
undefined -> ok;
{_, Params} ->
Sql = pgvar(Sql0, Params),
epgsql:parse(Conn, str(PreparedStKey), Sql, [])
end.

conn_opts(Opts) ->
conn_opts(Opts, []).
Expand All @@ -115,12 +132,50 @@ conn_opts([_Opt|Opts], Acc) ->
conn_opts(Opts, Acc).

-spec(equery(atom(), string() | epgsql:statement(), Parameters::[any()]) -> {ok, ColumnsDescription :: [any()], RowsValues :: [any()]} | {error, any()} ).
equery(Pool, Sql, Params) ->
ecpool:with_client(Pool, fun(C) -> epgsql:prepared_query(C, Sql, Params) end).
equery(Pool, PreparedStKey, Params) ->
do_equery(Pool, PreparedStKey, Params).

-spec(equery(atom(), string() | epgsql:statement(), Parameters::[any()], client_info()) -> {ok, ColumnsDescription :: [any()], RowsValues :: [any()]} | {error, any()} ).
equery(Pool, Sql, Params, ClientInfo) ->
ecpool:with_client(Pool, fun(C) -> epgsql:prepared_query(C, Sql, replvar(Params, ClientInfo)) end).
equery(Pool, PreparedStKey, Params, ClientInfo) ->
Params1 = replvar(Params, ClientInfo),
equery(Pool, PreparedStKey, Params1).

get_sql_conf(PreparedStKey) ->
application:get_env(?APP, prpst_key_to_atom(PreparedStKey), undefined).

put_sql_conf(PreparedStKey, Sql) ->
application:set_env(?APP, prpst_key_to_atom(PreparedStKey), Sql).

clear_sql_conf(PreparedStKey) ->
application:unset_env(?APP, prpst_key_to_atom(PreparedStKey)).

get_cached_statement(PreparedStKey) ->
application:get_env(?APP, statement_key(PreparedStKey), PreparedStKey).

put_cached_statement(PreparedStKey, St) ->
application:set_env(?APP, statement_key(PreparedStKey), St).

clear_cached_statement(PreparedStKey) ->
application:unset_env(?APP, statement_key(PreparedStKey)).

do_equery(Pool, PreparedStKey, Params) ->
ecpool:with_client(Pool, fun(Conn) ->
StOrKey = get_cached_statement(PreparedStKey),
case epgsql:prepared_query(Conn, StOrKey, Params) of
{error, #error{severity = error, code = <<"26000">>}} ->
%% invalid_sql_statement_name, we need to prepare the statement and try again
case prepare_statement(Conn, PreparedStKey) of
{ok, St} ->
ok = put_cached_statement(PreparedStKey, St),
epgsql:prepared_query(Conn, St, Params);
{error, _} = Error ->
Error
end;
Return ->
Return
end

end).

replvar(Params, ClientInfo) ->
replvar(Params, ClientInfo, []).
Expand All @@ -147,3 +202,26 @@ safe_get(K, ClientInfo) ->
bin(A) when is_atom(A) -> atom_to_binary(A, utf8);
bin(B) when is_binary(B) -> B;
bin(X) -> X.

str(B) when is_binary(B) -> binary_to_list(B);
str(A) when is_atom(A) -> atom_to_list(A);
str(S) when is_list(S) -> S.

prpst_key_to_atom(super_query) -> super_query;
prpst_key_to_atom("super_query") -> super_query;
prpst_key_to_atom(auth_query) -> auth_query;
prpst_key_to_atom("auth_query") -> auth_query;
prpst_key_to_atom(acl_query) -> acl_query;
prpst_key_to_atom("acl_query") -> acl_query;
prpst_key_to_atom(PreparedStKey) ->
throw({unsupported_prepared_statement_key, PreparedStKey}).

%% the spec of application:get_env(App, Key, Def) requires an atom() Key
statement_key(super_query) -> statement_super_query;
statement_key("super_query") -> statement_super_query;
statement_key(auth_query) -> statement_auth_query;
statement_key("auth_query") -> statement_auth_query;
statement_key(acl_query) -> statement_acl_query;
statement_key("acl_query") -> statement_acl_query;
statement_key(PreparedStKey) ->
throw({unsupported_prepared_statement_key, PreparedStKey}).
Loading

0 comments on commit ee50359

Please sign in to comment.