couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From klaus_trai...@apache.org
Subject couchdb-peruser git commit: Rename application to 'couch_peruser'
Date Thu, 20 Aug 2015 12:57:55 GMT
Repository: couchdb-peruser
Updated Branches:
  refs/heads/master 7530ed1d7 -> 27f4799ab


Rename application to 'couch_peruser'


Project: http://git-wip-us.apache.org/repos/asf/couchdb-peruser/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-peruser/commit/27f4799a
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-peruser/tree/27f4799a
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-peruser/diff/27f4799a

Branch: refs/heads/master
Commit: 27f4799ab76d272919a75eace63b2e5df6c726de
Parents: 7530ed1
Author: Klaus Trainer <klaus_trainer@posteo.de>
Authored: Thu Aug 20 14:56:43 2015 +0200
Committer: Klaus Trainer <klaus_trainer@posteo.de>
Committed: Thu Aug 20 14:56:43 2015 +0200

----------------------------------------------------------------------
 README.md                     |   4 +-
 src/couch_peruser.app.src     |  18 +++
 src/couch_peruser.erl         | 215 ++++++++++++++++++++++++++++
 src/couchdb_peruser.app.src   |  18 ---
 src/couchdb_peruser.erl       | 215 ----------------------------
 test/couch_peruser_test.erl   | 279 +++++++++++++++++++++++++++++++++++++
 test/couchdb_peruser_test.erl | 279 -------------------------------------
 7 files changed, 514 insertions(+), 514 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-peruser/blob/27f4799a/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index 4ada11c..f33841d 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
-couchdb_peruser
+couch_peruser
 ===============
 
-couchdb_peruser is a CouchDB daemon that ensures that a private per-user
+couch_peruser is a CouchDB daemon that ensures that a private per-user
 database exists for each document in _users. These databases are
 writable only by the corresponding user. Databases are in the form:
 

http://git-wip-us.apache.org/repos/asf/couchdb-peruser/blob/27f4799a/src/couch_peruser.app.src
----------------------------------------------------------------------
diff --git a/src/couch_peruser.app.src b/src/couch_peruser.app.src
new file mode 100644
index 0000000..fb6d45b
--- /dev/null
+++ b/src/couch_peruser.app.src
@@ -0,0 +1,18 @@
+% 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.
+
+{application, couch_peruser, [
+    {description, "couch_peruser - maintains per-user databases in CouchDB"},
+    {vsn, git},
+    {registered, []},
+    {applications, [kernel, stdlib, config, couch, fabric]}
+]}.

http://git-wip-us.apache.org/repos/asf/couchdb-peruser/blob/27f4799a/src/couch_peruser.erl
----------------------------------------------------------------------
diff --git a/src/couch_peruser.erl b/src/couch_peruser.erl
new file mode 100644
index 0000000..f20b979
--- /dev/null
+++ b/src/couch_peruser.erl
@@ -0,0 +1,215 @@
+% 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(couch_peruser).
+-behaviour(gen_server).
+-behaviour(config_listener).
+
+-include_lib("couch/include/couch_db.hrl").
+
+-define(USERDB_PREFIX, "userdb-").
+
+% gen_server callbacks
+-export([start_link/0, init/1, handle_call/3, handle_cast/2, handle_info/2,
+         terminate/2, code_change/3]).
+
+% config_listener callbacks
+-export([handle_config_change/5, handle_config_terminate/3]).
+
+-export([init_changes_handler/1, changes_handler/3]).
+
+-record(state, {parent, db_name, delete_dbs, changes_pid, changes_ref}).
+
+
+start_link() ->
+    gen_server:start_link(?MODULE, [], []).
+
+init() ->
+    case config:get_boolean("couch_peruser", "enable", false) of
+    false ->
+        #state{};
+    true ->
+        DbName = ?l2b(config:get(
+                         "couch_httpd_auth", "authentication_db", "_users")),
+        DeleteDbs = config:get_boolean("couch_peruser", "delete_dbs", false),
+        State = #state{parent = self(),
+                       db_name = DbName,
+                       delete_dbs = DeleteDbs},
+        {Pid, Ref} = spawn_opt(
+            ?MODULE, init_changes_handler, [State], [link, monitor]),
+        State#state{changes_pid=Pid, changes_ref=Ref}
+    end.
+
+init_changes_handler(#state{db_name=DbName} = State) ->
+    try
+        {ok, Db} = couch_db:open_int(DbName, [?ADMIN_CTX, sys_db]),
+        FunAcc = {fun ?MODULE:changes_handler/3, State},
+        (couch_changes:handle_db_changes(
+             #changes_args{feed="continuous", timeout=infinity},
+             {json_req, null},
+             Db))(FunAcc)
+    catch error:database_does_not_exist ->
+        ok
+    end.
+
+changes_handler({change, {Doc}, _Prepend}, _ResType, State=#state{}) ->
+    case couch_util:get_value(<<"id">>, Doc) of
+    <<"org.couchdb.user:",User/binary>> ->
+        case couch_util:get_value(<<"deleted">>, Doc, false) of
+        false ->
+            UserDb = ensure_user_db(User),
+            ok = ensure_security(User, UserDb, fun add_user/3),
+            State;
+        true ->
+            case State#state.delete_dbs of
+            true ->
+                _UserDb = delete_user_db(User),
+                State;
+            false ->
+                UserDb = user_db_name(User),
+                ok = ensure_security(User, UserDb, fun remove_user/3),
+                State
+            end
+        end;
+    _ ->
+        State
+    end;
+changes_handler(_Event, _ResType, State) ->
+    State.
+
+delete_user_db(User) ->
+    UserDb = user_db_name(User),
+    try
+        case fabric:delete_db(UserDb, [?ADMIN_CTX]) of
+        ok -> ok;
+        accepted -> ok
+        end
+    catch error:database_does_not_exist ->
+        ok
+    end,
+    UserDb.
+
+ensure_user_db(User) ->
+    UserDb = user_db_name(User),
+    try
+        {ok, _DbInfo} = fabric:get_db_info(UserDb)
+    catch error:database_does_not_exist ->
+        case fabric:create_db(UserDb, [?ADMIN_CTX]) of
+        ok -> ok;
+        accepted -> ok
+        end
+    end,
+    UserDb.
+
+add_user(User, Prop, {Modified, SecProps}) ->
+    {PropValue} = couch_util:get_value(Prop, SecProps, {[]}),
+    Names = couch_util:get_value(<<"names">>, PropValue, []),
+    case lists:member(User, Names) of
+    true ->
+        {Modified, SecProps};
+    false ->
+        {true,
+         lists:keystore(
+             Prop, 1, SecProps,
+             {Prop,
+              {lists:keystore(
+                   <<"names">>, 1, PropValue,
+                   {<<"names">>, [User | Names]})}})}
+    end.
+
+remove_user(User, Prop, {Modified, SecProps}) ->
+    {PropValue} = couch_util:get_value(Prop, SecProps, {[]}),
+    Names = couch_util:get_value(<<"names">>, PropValue, []),
+    case lists:member(User, Names) of
+    false ->
+        {Modified, SecProps};
+    true ->
+        {true,
+         lists:keystore(
+             Prop, 1, SecProps,
+             {Prop,
+              {lists:keystore(
+                   <<"names">>, 1, PropValue,
+                   {<<"names">>, lists:delete(User, Names)})}})}
+    end.
+
+ensure_security(User, UserDb, TransformFun) ->
+    {ok, Shards} = fabric:get_all_security(UserDb, [?ADMIN_CTX]),
+    {_ShardInfo, {SecProps}} = hd(Shards),
+    % assert that shards have the same security object
+    true = lists:all(fun ({_, {SecProps1}}) ->
+        SecProps =:= SecProps1
+    end, Shards),
+    case lists:foldl(
+           fun (Prop, SAcc) -> TransformFun(User, Prop, SAcc) end,
+           {false, SecProps},
+           [<<"admins">>, <<"members">>]) of
+    {false, _} ->
+        ok;
+    {true, SecProps1} ->
+        ok = fabric:set_security(UserDb, {SecProps1}, [?ADMIN_CTX])
+    end.
+
+user_db_name(User) ->
+    HexUser = list_to_binary(
+        [string:to_lower(integer_to_list(X, 16)) || <<X>> <= User]),
+    <<?USERDB_PREFIX,HexUser/binary>>.
+
+
+%% gen_server callbacks
+
+init([]) ->
+    ok = config:listen_for_changes(?MODULE, self()),
+    {ok, init()}.
+
+handle_call(_Msg, _From, State) ->
+    {reply, error, State}.
+
+handle_cast(update_config, State) when State#state.changes_pid =/= undefined ->
+    % we don't want to have multiple changes handler at the same time
+    demonitor(State#state.changes_ref, [flush]),
+    exit(State#state.changes_pid, kill),
+    {noreply, init()};
+handle_cast(update_config, _State) ->
+    {noreply, init()};
+handle_cast(stop, State) ->
+    {stop, normal, State};
+handle_cast(_Msg, State) ->
+    {noreply, State}.
+
+handle_info({'DOWN', Ref, _, _, _Reason}, #state{changes_ref=Ref} = State) ->
+    {stop, normal, State};
+handle_info(_Msg, State) ->
+    {noreply, State}.
+
+terminate(_Reason, _State) ->
+    %% Everything should be linked or monitored, let nature
+    %% take its course.
+    ok.
+
+code_change(_OldVsn, State, _Extra) ->
+    {ok, State}.
+
+
+%% config_listener callbacks
+
+handle_config_change("couch_httpd_auth", "authentication_db", _Value, _Persist, Server) ->
+    ok = gen_server:cast(Server, update_config),
+    {ok, Server};
+handle_config_change("couch_peruser", _Key, _Value, _Persist, Server) ->
+    ok = gen_server:cast(Server, update_config),
+    {ok, Server};
+handle_config_change(_Section, _Key, _Value, _Persist, Server) ->
+    {ok, Server}.
+
+handle_config_terminate(_Self, Reason, _Server) ->
+    {stop, Reason}.

http://git-wip-us.apache.org/repos/asf/couchdb-peruser/blob/27f4799a/src/couchdb_peruser.app.src
----------------------------------------------------------------------
diff --git a/src/couchdb_peruser.app.src b/src/couchdb_peruser.app.src
deleted file mode 100644
index 0bbf0cf..0000000
--- a/src/couchdb_peruser.app.src
+++ /dev/null
@@ -1,18 +0,0 @@
-% 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.
-
-{application, couchdb_peruser, [
-    {description, "couchdb_peruser - maintains per-user databases in CouchDB"},
-    {vsn, git},
-    {registered, []},
-    {applications, [kernel, stdlib, config, couch, fabric]}
-]}.

http://git-wip-us.apache.org/repos/asf/couchdb-peruser/blob/27f4799a/src/couchdb_peruser.erl
----------------------------------------------------------------------
diff --git a/src/couchdb_peruser.erl b/src/couchdb_peruser.erl
deleted file mode 100644
index a4c8a2e..0000000
--- a/src/couchdb_peruser.erl
+++ /dev/null
@@ -1,215 +0,0 @@
-% 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(couchdb_peruser).
--behaviour(gen_server).
--behaviour(config_listener).
-
--include_lib("couch/include/couch_db.hrl").
-
--define(USERDB_PREFIX, "userdb-").
-
-% gen_server callbacks
--export([start_link/0, init/1, handle_call/3, handle_cast/2, handle_info/2,
-         terminate/2, code_change/3]).
-
-% config_listener callbacks
--export([handle_config_change/5, handle_config_terminate/3]).
-
--export([init_changes_handler/1, changes_handler/3]).
-
--record(state, {parent, db_name, delete_dbs, changes_pid, changes_ref}).
-
-
-start_link() ->
-    gen_server:start_link(?MODULE, [], []).
-
-init() ->
-    case config:get_boolean("couchdb_peruser", "enable", false) of
-    false ->
-        #state{};
-    true ->
-        DbName = ?l2b(config:get(
-                         "couch_httpd_auth", "authentication_db", "_users")),
-        DeleteDbs = config:get_boolean("couchdb_peruser", "delete_dbs", false),
-        State = #state{parent = self(),
-                       db_name = DbName,
-                       delete_dbs = DeleteDbs},
-        {Pid, Ref} = spawn_opt(
-            ?MODULE, init_changes_handler, [State], [link, monitor]),
-        State#state{changes_pid=Pid, changes_ref=Ref}
-    end.
-
-init_changes_handler(#state{db_name=DbName} = State) ->
-    try
-        {ok, Db} = couch_db:open_int(DbName, [?ADMIN_CTX, sys_db]),
-        FunAcc = {fun ?MODULE:changes_handler/3, State},
-        (couch_changes:handle_db_changes(
-             #changes_args{feed="continuous", timeout=infinity},
-             {json_req, null},
-             Db))(FunAcc)
-    catch error:database_does_not_exist ->
-        ok
-    end.
-
-changes_handler({change, {Doc}, _Prepend}, _ResType, State=#state{}) ->
-    case couch_util:get_value(<<"id">>, Doc) of
-    <<"org.couchdb.user:",User/binary>> ->
-        case couch_util:get_value(<<"deleted">>, Doc, false) of
-        false ->
-            UserDb = ensure_user_db(User),
-            ok = ensure_security(User, UserDb, fun add_user/3),
-            State;
-        true ->
-            case State#state.delete_dbs of
-            true ->
-                _UserDb = delete_user_db(User),
-                State;
-            false ->
-                UserDb = user_db_name(User),
-                ok = ensure_security(User, UserDb, fun remove_user/3),
-                State
-            end
-        end;
-    _ ->
-        State
-    end;
-changes_handler(_Event, _ResType, State) ->
-    State.
-
-delete_user_db(User) ->
-    UserDb = user_db_name(User),
-    try
-        case fabric:delete_db(UserDb, [?ADMIN_CTX]) of
-        ok -> ok;
-        accepted -> ok
-        end
-    catch error:database_does_not_exist ->
-        ok
-    end,
-    UserDb.
-
-ensure_user_db(User) ->
-    UserDb = user_db_name(User),
-    try
-        {ok, _DbInfo} = fabric:get_db_info(UserDb)
-    catch error:database_does_not_exist ->
-        case fabric:create_db(UserDb, [?ADMIN_CTX]) of
-        ok -> ok;
-        accepted -> ok
-        end
-    end,
-    UserDb.
-
-add_user(User, Prop, {Modified, SecProps}) ->
-    {PropValue} = couch_util:get_value(Prop, SecProps, {[]}),
-    Names = couch_util:get_value(<<"names">>, PropValue, []),
-    case lists:member(User, Names) of
-    true ->
-        {Modified, SecProps};
-    false ->
-        {true,
-         lists:keystore(
-             Prop, 1, SecProps,
-             {Prop,
-              {lists:keystore(
-                   <<"names">>, 1, PropValue,
-                   {<<"names">>, [User | Names]})}})}
-    end.
-
-remove_user(User, Prop, {Modified, SecProps}) ->
-    {PropValue} = couch_util:get_value(Prop, SecProps, {[]}),
-    Names = couch_util:get_value(<<"names">>, PropValue, []),
-    case lists:member(User, Names) of
-    false ->
-        {Modified, SecProps};
-    true ->
-        {true,
-         lists:keystore(
-             Prop, 1, SecProps,
-             {Prop,
-              {lists:keystore(
-                   <<"names">>, 1, PropValue,
-                   {<<"names">>, lists:delete(User, Names)})}})}
-    end.
-
-ensure_security(User, UserDb, TransformFun) ->
-    {ok, Shards} = fabric:get_all_security(UserDb, [?ADMIN_CTX]),
-    {_ShardInfo, {SecProps}} = hd(Shards),
-    % assert that shards have the same security object
-    true = lists:all(fun ({_, {SecProps1}}) ->
-        SecProps =:= SecProps1
-    end, Shards),
-    case lists:foldl(
-           fun (Prop, SAcc) -> TransformFun(User, Prop, SAcc) end,
-           {false, SecProps},
-           [<<"admins">>, <<"members">>]) of
-    {false, _} ->
-        ok;
-    {true, SecProps1} ->
-        ok = fabric:set_security(UserDb, {SecProps1}, [?ADMIN_CTX])
-    end.
-
-user_db_name(User) ->
-    HexUser = list_to_binary(
-        [string:to_lower(integer_to_list(X, 16)) || <<X>> <= User]),
-    <<?USERDB_PREFIX,HexUser/binary>>.
-
-
-%% gen_server callbacks
-
-init([]) ->
-    ok = config:listen_for_changes(?MODULE, self()),
-    {ok, init()}.
-
-handle_call(_Msg, _From, State) ->
-    {reply, error, State}.
-
-handle_cast(update_config, State) when State#state.changes_pid =/= undefined ->
-    % we don't want to have multiple changes handler at the same time
-    demonitor(State#state.changes_ref, [flush]),
-    exit(State#state.changes_pid, kill),
-    {noreply, init()};
-handle_cast(update_config, _State) ->
-    {noreply, init()};
-handle_cast(stop, State) ->
-    {stop, normal, State};
-handle_cast(_Msg, State) ->
-    {noreply, State}.
-
-handle_info({'DOWN', Ref, _, _, _Reason}, #state{changes_ref=Ref} = State) ->
-    {stop, normal, State};
-handle_info(_Msg, State) ->
-    {noreply, State}.
-
-terminate(_Reason, _State) ->
-    %% Everything should be linked or monitored, let nature
-    %% take its course.
-    ok.
-
-code_change(_OldVsn, State, _Extra) ->
-    {ok, State}.
-
-
-%% config_listener callbacks
-
-handle_config_change("couch_httpd_auth", "authentication_db", _Value, _Persist, Server) ->
-    ok = gen_server:cast(Server, update_config),
-    {ok, Server};
-handle_config_change("couchdb_peruser", _Key, _Value, _Persist, Server) ->
-    ok = gen_server:cast(Server, update_config),
-    {ok, Server};
-handle_config_change(_Section, _Key, _Value, _Persist, Server) ->
-    {ok, Server}.
-
-handle_config_terminate(_Self, Reason, _Server) ->
-    {stop, Reason}.

http://git-wip-us.apache.org/repos/asf/couchdb-peruser/blob/27f4799a/test/couch_peruser_test.erl
----------------------------------------------------------------------
diff --git a/test/couch_peruser_test.erl b/test/couch_peruser_test.erl
new file mode 100644
index 0000000..aac52e8
--- /dev/null
+++ b/test/couch_peruser_test.erl
@@ -0,0 +1,279 @@
+% 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(couch_peruser_test).
+
+-include_lib("couch/include/couch_eunit.hrl").
+-include_lib("couch/include/couch_db.hrl").
+
+-define(ADMIN_USERNAME, "admin").
+-define(ADMIN_PASSWORD, "secret").
+
+setup_all() ->
+    TestCtx = test_util:start_couch([chttpd]),
+    config:set("admins", ?ADMIN_USERNAME, ?ADMIN_PASSWORD),
+    TestCtx.
+
+teardown_all(TestCtx) ->
+    config:delete("admins", ?ADMIN_USERNAME),
+    test_util:stop_couch(TestCtx).
+
+setup() ->
+    TestAuthDb = ?tempdb(),
+    do_request(put, get_base_url() ++ "/" ++ ?b2l(TestAuthDb)),
+    set_config("couch_httpd_auth", "authentication_db", ?b2l(TestAuthDb)),
+    set_config("couch_peruser", "enable", "true"),
+    TestAuthDb.
+
+teardown(TestAuthDb) ->
+    set_config("couch_httpd_auth", "authentication_db", "_users"),
+    set_config("couch_peruser", "enable", "false"),
+    set_config("couch_peruser", "delete_dbs", "false"),
+    do_request(delete, get_base_url() ++ "/" ++ ?b2l(TestAuthDb)),
+    lists:foreach(fun (DbName) ->
+        case DbName of
+        <<"userdb-",_/binary>> -> delete_db(DbName);
+        _ -> ok
+        end
+    end, all_dbs()).
+
+set_config(Section, Key, Value) ->
+    Url = lists:concat([
+        get_base_url(), "/_config/", Section, "/", Key]),
+    do_request(put, Url, "\"" ++ Value ++ "\"").
+
+do_request(Method, Url) ->
+    Headers = [{basic_auth, {?ADMIN_USERNAME, ?ADMIN_PASSWORD}}],
+    {ok, _, _, _} = test_request:request(Method, Url, Headers).
+
+do_request(Method, Url, Body) ->
+    Headers = [
+        {basic_auth, {?ADMIN_USERNAME, ?ADMIN_PASSWORD}},
+        {"Content-Type", "application/json"}],
+    {ok, _, _, _} = test_request:request(Method, Url, Headers, Body).
+
+create_db(DbName) ->
+    {ok, _, _, _} = do_request(put, get_cluster_base_url() ++ "/" ++ ?b2l(DbName)).
+
+delete_db(DbName) ->
+    {ok, _, _, _} = do_request(delete, get_cluster_base_url() ++ "/" ++ ?b2l(DbName)).
+
+create_user(AuthDb, Name) ->
+    Body = "{\"name\":\"" ++ Name ++
+        "\",\"type\":\"user\",\"roles\":[],\"password\":\"secret\"}",
+    Url = lists:concat([
+        get_base_url(), "/", ?b2l(AuthDb), "/org.couchdb.user:", Name]),
+    {ok, 201, _, _} = do_request(put, Url, Body),
+    % let's proceed after giving couch_peruser some time to create the user db
+    timer:sleep(1000).
+
+delete_user(AuthDb, Name) ->
+    Url = lists:concat([get_base_url(), "/", ?b2l(AuthDb),
+        "/org.couchdb.user:", Name]),
+    {ok, 200, _, Body} = do_request(get, Url),
+    {DocProps} = jiffy:decode(Body),
+    Rev = proplists:get_value(<<"_rev">>, DocProps),
+    {ok, 200, _, _} = do_request(delete, Url ++ "?rev=" ++ ?b2l(Rev)),
+    % let's proceed after giving couch_peruser some time to delete the user db
+    timer:sleep(1000).
+
+get_security(DbName) ->
+    Url = lists:concat([
+        get_cluster_base_url(), "/", ?b2l(DbName), "/_security"]),
+    {ok, 200, _, Body} = do_request(get, Url),
+    {SecurityProperties} = jiffy:decode(Body),
+    SecurityProperties.
+
+set_security(DbName, SecurityProperties) ->
+    Url = lists:concat([
+        get_cluster_base_url(), "/", ?b2l(DbName), "/_security"]),
+    Body = jiffy:encode({SecurityProperties}),
+    {ok, 200, _, _} = do_request(put, Url, Body).
+
+all_dbs() ->
+    {ok, 200, _, Body} = do_request(get, get_cluster_base_url() ++ "/_all_dbs"),
+    jiffy:decode(Body).
+
+get_base_url() ->
+    Addr = config:get("httpd", "bind_address", "127.0.0.1"),
+    Port = integer_to_list(mochiweb_socket_server:get(couch_httpd, port)),
+    "http://" ++ Addr ++ ":" ++ Port.
+
+get_cluster_base_url() ->
+    Addr = config:get("httpd", "bind_address", "127.0.0.1"),
+    Port = integer_to_list(mochiweb_socket_server:get(chttpd, port)),
+    "http://" ++ Addr ++ ":" ++ Port.
+
+should_create_user_db(TestAuthDb) ->
+    create_user(TestAuthDb, "foo"),
+    ?_assert(lists:member(<<"userdb-666f6f">>, all_dbs())).
+
+should_not_delete_user_db(TestAuthDb) ->
+    User = "foo",
+    UserDbName = <<"userdb-666f6f">>,
+    create_user(TestAuthDb, User),
+    ?assert(lists:member(UserDbName, all_dbs())),
+    delete_user(TestAuthDb, User),
+    ?_assert(lists:member(UserDbName, all_dbs())).
+
+should_delete_user_db(TestAuthDb) ->
+    User = "bar",
+    UserDbName = <<"userdb-626172">>,
+    set_config("couch_peruser", "delete_dbs", "true"),
+    create_user(TestAuthDb, User),
+    ?assert(lists:member(UserDbName, all_dbs())),
+    delete_user(TestAuthDb, User),
+    ?_assert(not lists:member(UserDbName, all_dbs())).
+
+should_reflect_config_changes(TestAuthDb) ->
+    User = "baz",
+    UserDbName = <<"userdb-62617a">>,
+    set_config("couch_peruser", "delete_dbs", "true"),
+    create_user(TestAuthDb, User),
+    ?assert(lists:member(UserDbName, all_dbs())),
+    delete_user(TestAuthDb, User),
+    ?assert(not lists:member(UserDbName, all_dbs())),
+    create_user(TestAuthDb, User),
+    ?assert(lists:member(UserDbName, all_dbs())),
+    set_config("couch_peruser", "delete_dbs", "false"),
+    delete_user(TestAuthDb, User),
+    ?assert(lists:member(UserDbName, all_dbs())),
+    create_user(TestAuthDb, User),
+    set_config("couch_peruser", "delete_dbs", "true"),
+    delete_user(TestAuthDb, User),
+    ?assert(not lists:member(UserDbName, all_dbs())),
+    set_config("couch_peruser", "enable", "false"),
+    create_user(TestAuthDb, User),
+    ?_assert(not lists:member(UserDbName, all_dbs())).
+
+should_add_user_to_db_admins(TestAuthDb) ->
+    User = "qux",
+    UserDbName = <<"userdb-717578">>,
+    create_user(TestAuthDb, User),
+    ?_assertEqual(
+        {[{<<"names">>,[<<"qux">>]}]},
+        proplists:get_value(<<"admins">>, get_security(UserDbName))).
+
+should_add_user_to_db_members(TestAuthDb) ->
+    User = "qux",
+    UserDbName = <<"userdb-717578">>,
+    create_user(TestAuthDb, User),
+    ?_assertEqual(
+        {[{<<"names">>,[<<"qux">>]}]},
+        proplists:get_value(<<"members">>, get_security(UserDbName))).
+
+should_not_remove_existing_db_admins(TestAuthDb) ->
+    User = "qux",
+    UserDbName = <<"userdb-717578">>,
+    SecurityProperties = [
+        {<<"admins">>,{[{<<"names">>,[<<"foo">>,<<"bar">>]}]}},
+        {<<"members">>,{[{<<"names">>,[<<"baz">>,<<"pow">>]}]}}
+    ],
+    create_db(UserDbName),
+    set_security(UserDbName, SecurityProperties),
+    create_user(TestAuthDb, User),
+    {AdminProperties} = proplists:get_value(<<"admins">>,
+        get_security(UserDbName)),
+    AdminNames = proplists:get_value(<<"names">>, AdminProperties),
+    ?_assert(lists:member(<<"foo">>, AdminNames)),
+    ?_assert(lists:member(<<"bar">>, AdminNames)),
+    ?_assert(lists:member(<<"qux">>, AdminNames)).
+
+should_not_remove_existing_db_members(TestAuthDb) ->
+    User = "qux",
+    UserDbName = <<"userdb-717578">>,
+    SecurityProperties = [
+        {<<"admins">>,{[{<<"names">>,[<<"pow">>,<<"wow">>]}]}},
+        {<<"members">>,{[{<<"names">>,[<<"pow">>,<<"wow">>]}]}}
+    ],
+    create_db(UserDbName),
+    set_security(UserDbName, SecurityProperties),
+    create_user(TestAuthDb, User),
+    {MemberProperties} = proplists:get_value(<<"members">>,
+        get_security(UserDbName)),
+    MemberNames = proplists:get_value(<<"names">>, MemberProperties),
+    ?_assert(lists:member(<<"pow">>, MemberNames)),
+    ?_assert(lists:member(<<"wow">>, MemberNames)),
+    ?_assert(lists:member(<<"qux">>, MemberNames)).
+
+should_remove_user_from_db_admins(TestAuthDb) ->
+    User = "qux",
+    UserDbName = <<"userdb-717578">>,
+    SecurityProperties = [
+        {<<"admins">>,{[{<<"names">>,[<<"foo">>,<<"bar">>]}]}},
+        {<<"members">>,{[{<<"names">>,[<<"baz">>,<<"pow">>]}]}}
+    ],
+    create_db(UserDbName),
+    set_security(UserDbName, SecurityProperties),
+    create_user(TestAuthDb, User),
+    {AdminProperties} = proplists:get_value(<<"admins">>,
+        get_security(UserDbName)),
+    AdminNames = proplists:get_value(<<"names">>, AdminProperties),
+    ?assert(lists:member(<<"foo">>, AdminNames)),
+    ?assert(lists:member(<<"bar">>, AdminNames)),
+    ?assert(lists:member(<<"qux">>, AdminNames)),
+    delete_user(TestAuthDb, User),
+    {NewAdminProperties} = proplists:get_value(<<"admins">>,
+        get_security(UserDbName)),
+    NewAdminNames = proplists:get_value(<<"names">>, NewAdminProperties),
+    ?_assert(lists:member(<<"foo">>, NewAdminNames)),
+    ?_assert(lists:member(<<"bar">>, NewAdminNames)),
+    ?_assert(not lists:member(<<"qux">>, NewAdminNames)).
+
+should_remove_user_from_db_members(TestAuthDb) ->
+    User = "qux",
+    UserDbName = <<"userdb-717578">>,
+    SecurityProperties = [
+        {<<"admins">>,{[{<<"names">>,[<<"pow">>,<<"wow">>]}]}},
+        {<<"members">>,{[{<<"names">>,[<<"pow">>,<<"wow">>]}]}}
+    ],
+    create_db(UserDbName),
+    set_security(UserDbName, SecurityProperties),
+    create_user(TestAuthDb, User),
+    {MemberProperties} = proplists:get_value(<<"members">>,
+        get_security(UserDbName)),
+    MemberNames = proplists:get_value(<<"names">>, MemberProperties),
+    ?assert(lists:member(<<"pow">>, MemberNames)),
+    ?assert(lists:member(<<"wow">>, MemberNames)),
+    ?assert(lists:member(<<"qux">>, MemberNames)),
+    delete_user(TestAuthDb, User),
+    {NewMemberProperties} = proplists:get_value(<<"members">>,
+        get_security(UserDbName)),
+    NewMemberNames = proplists:get_value(<<"names">>, NewMemberProperties),
+    ?_assert(lists:member(<<"foo">>, NewMemberNames)),
+    ?_assert(lists:member(<<"bar">>, NewMemberNames)),
+    ?_assert(not lists:member(<<"qux">>, NewMemberNames)).
+
+couch_peruser_test_() ->
+    {
+        "couch_peruser test",
+        {
+            setup,
+            fun setup_all/0, fun teardown_all/1,
+            {
+                foreach,
+                fun setup/0, fun teardown/1,
+                [
+                    fun should_create_user_db/1,
+                    fun should_not_delete_user_db/1,
+                    fun should_delete_user_db/1,
+                    fun should_reflect_config_changes/1,
+                    fun should_add_user_to_db_admins/1,
+                    fun should_add_user_to_db_members/1,
+                    fun should_not_remove_existing_db_admins/1,
+                    fun should_not_remove_existing_db_members/1,
+                    fun should_remove_user_from_db_admins/1,
+                    fun should_remove_user_from_db_members/1
+                ]
+            }
+        }
+    }.

http://git-wip-us.apache.org/repos/asf/couchdb-peruser/blob/27f4799a/test/couchdb_peruser_test.erl
----------------------------------------------------------------------
diff --git a/test/couchdb_peruser_test.erl b/test/couchdb_peruser_test.erl
deleted file mode 100644
index 3913d64..0000000
--- a/test/couchdb_peruser_test.erl
+++ /dev/null
@@ -1,279 +0,0 @@
-% 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(couchdb_peruser_test).
-
--include_lib("couch/include/couch_eunit.hrl").
--include_lib("couch/include/couch_db.hrl").
-
--define(ADMIN_USERNAME, "admin").
--define(ADMIN_PASSWORD, "secret").
-
-setup_all() ->
-    TestCtx = test_util:start_couch([chttpd]),
-    config:set("admins", ?ADMIN_USERNAME, ?ADMIN_PASSWORD),
-    TestCtx.
-
-teardown_all(TestCtx) ->
-    config:delete("admins", ?ADMIN_USERNAME),
-    test_util:stop_couch(TestCtx).
-
-setup() ->
-    TestAuthDb = ?tempdb(),
-    do_request(put, get_base_url() ++ "/" ++ ?b2l(TestAuthDb)),
-    set_config("couch_httpd_auth", "authentication_db", ?b2l(TestAuthDb)),
-    set_config("couchdb_peruser", "enable", "true"),
-    TestAuthDb.
-
-teardown(TestAuthDb) ->
-    set_config("couch_httpd_auth", "authentication_db", "_users"),
-    set_config("couchdb_peruser", "enable", "false"),
-    set_config("couchdb_peruser", "delete_dbs", "false"),
-    do_request(delete, get_base_url() ++ "/" ++ ?b2l(TestAuthDb)),
-    lists:foreach(fun (DbName) ->
-        case DbName of
-        <<"userdb-",_/binary>> -> delete_db(DbName);
-        _ -> ok
-        end
-    end, all_dbs()).
-
-set_config(Section, Key, Value) ->
-    Url = lists:concat([
-        get_base_url(), "/_config/", Section, "/", Key]),
-    do_request(put, Url, "\"" ++ Value ++ "\"").
-
-do_request(Method, Url) ->
-    Headers = [{basic_auth, {?ADMIN_USERNAME, ?ADMIN_PASSWORD}}],
-    {ok, _, _, _} = test_request:request(Method, Url, Headers).
-
-do_request(Method, Url, Body) ->
-    Headers = [
-        {basic_auth, {?ADMIN_USERNAME, ?ADMIN_PASSWORD}},
-        {"Content-Type", "application/json"}],
-    {ok, _, _, _} = test_request:request(Method, Url, Headers, Body).
-
-create_db(DbName) ->
-    {ok, _, _, _} = do_request(put, get_cluster_base_url() ++ "/" ++ ?b2l(DbName)).
-
-delete_db(DbName) ->
-    {ok, _, _, _} = do_request(delete, get_cluster_base_url() ++ "/" ++ ?b2l(DbName)).
-
-create_user(AuthDb, Name) ->
-    Body = "{\"name\":\"" ++ Name ++
-        "\",\"type\":\"user\",\"roles\":[],\"password\":\"secret\"}",
-    Url = lists:concat([
-        get_base_url(), "/", ?b2l(AuthDb), "/org.couchdb.user:", Name]),
-    {ok, 201, _, _} = do_request(put, Url, Body),
-    % let's proceed after giving couchdb_peruser some time to create the user db
-    timer:sleep(1000).
-
-delete_user(AuthDb, Name) ->
-    Url = lists:concat([get_base_url(), "/", ?b2l(AuthDb),
-        "/org.couchdb.user:", Name]),
-    {ok, 200, _, Body} = do_request(get, Url),
-    {DocProps} = jiffy:decode(Body),
-    Rev = proplists:get_value(<<"_rev">>, DocProps),
-    {ok, 200, _, _} = do_request(delete, Url ++ "?rev=" ++ ?b2l(Rev)),
-    % let's proceed after giving couchdb_peruser some time to delete the user db
-    timer:sleep(1000).
-
-get_security(DbName) ->
-    Url = lists:concat([
-        get_cluster_base_url(), "/", ?b2l(DbName), "/_security"]),
-    {ok, 200, _, Body} = do_request(get, Url),
-    {SecurityProperties} = jiffy:decode(Body),
-    SecurityProperties.
-
-set_security(DbName, SecurityProperties) ->
-    Url = lists:concat([
-        get_cluster_base_url(), "/", ?b2l(DbName), "/_security"]),
-    Body = jiffy:encode({SecurityProperties}),
-    {ok, 200, _, _} = do_request(put, Url, Body).
-
-all_dbs() ->
-    {ok, 200, _, Body} = do_request(get, get_cluster_base_url() ++ "/_all_dbs"),
-    jiffy:decode(Body).
-
-get_base_url() ->
-    Addr = config:get("httpd", "bind_address", "127.0.0.1"),
-    Port = integer_to_list(mochiweb_socket_server:get(couch_httpd, port)),
-    "http://" ++ Addr ++ ":" ++ Port.
-
-get_cluster_base_url() ->
-    Addr = config:get("httpd", "bind_address", "127.0.0.1"),
-    Port = integer_to_list(mochiweb_socket_server:get(chttpd, port)),
-    "http://" ++ Addr ++ ":" ++ Port.
-
-should_create_user_db(TestAuthDb) ->
-    create_user(TestAuthDb, "foo"),
-    ?_assert(lists:member(<<"userdb-666f6f">>, all_dbs())).
-
-should_not_delete_user_db(TestAuthDb) ->
-    User = "foo",
-    UserDbName = <<"userdb-666f6f">>,
-    create_user(TestAuthDb, User),
-    ?assert(lists:member(UserDbName, all_dbs())),
-    delete_user(TestAuthDb, User),
-    ?_assert(lists:member(UserDbName, all_dbs())).
-
-should_delete_user_db(TestAuthDb) ->
-    User = "bar",
-    UserDbName = <<"userdb-626172">>,
-    set_config("couchdb_peruser", "delete_dbs", "true"),
-    create_user(TestAuthDb, User),
-    ?assert(lists:member(UserDbName, all_dbs())),
-    delete_user(TestAuthDb, User),
-    ?_assert(not lists:member(UserDbName, all_dbs())).
-
-should_reflect_config_changes(TestAuthDb) ->
-    User = "baz",
-    UserDbName = <<"userdb-62617a">>,
-    set_config("couchdb_peruser", "delete_dbs", "true"),
-    create_user(TestAuthDb, User),
-    ?assert(lists:member(UserDbName, all_dbs())),
-    delete_user(TestAuthDb, User),
-    ?assert(not lists:member(UserDbName, all_dbs())),
-    create_user(TestAuthDb, User),
-    ?assert(lists:member(UserDbName, all_dbs())),
-    set_config("couchdb_peruser", "delete_dbs", "false"),
-    delete_user(TestAuthDb, User),
-    ?assert(lists:member(UserDbName, all_dbs())),
-    create_user(TestAuthDb, User),
-    set_config("couchdb_peruser", "delete_dbs", "true"),
-    delete_user(TestAuthDb, User),
-    ?assert(not lists:member(UserDbName, all_dbs())),
-    set_config("couchdb_peruser", "enable", "false"),
-    create_user(TestAuthDb, User),
-    ?_assert(not lists:member(UserDbName, all_dbs())).
-
-should_add_user_to_db_admins(TestAuthDb) ->
-    User = "qux",
-    UserDbName = <<"userdb-717578">>,
-    create_user(TestAuthDb, User),
-    ?_assertEqual(
-        {[{<<"names">>,[<<"qux">>]}]},
-        proplists:get_value(<<"admins">>, get_security(UserDbName))).
-
-should_add_user_to_db_members(TestAuthDb) ->
-    User = "qux",
-    UserDbName = <<"userdb-717578">>,
-    create_user(TestAuthDb, User),
-    ?_assertEqual(
-        {[{<<"names">>,[<<"qux">>]}]},
-        proplists:get_value(<<"members">>, get_security(UserDbName))).
-
-should_not_remove_existing_db_admins(TestAuthDb) ->
-    User = "qux",
-    UserDbName = <<"userdb-717578">>,
-    SecurityProperties = [
-        {<<"admins">>,{[{<<"names">>,[<<"foo">>,<<"bar">>]}]}},
-        {<<"members">>,{[{<<"names">>,[<<"baz">>,<<"pow">>]}]}}
-    ],
-    create_db(UserDbName),
-    set_security(UserDbName, SecurityProperties),
-    create_user(TestAuthDb, User),
-    {AdminProperties} = proplists:get_value(<<"admins">>,
-        get_security(UserDbName)),
-    AdminNames = proplists:get_value(<<"names">>, AdminProperties),
-    ?_assert(lists:member(<<"foo">>, AdminNames)),
-    ?_assert(lists:member(<<"bar">>, AdminNames)),
-    ?_assert(lists:member(<<"qux">>, AdminNames)).
-
-should_not_remove_existing_db_members(TestAuthDb) ->
-    User = "qux",
-    UserDbName = <<"userdb-717578">>,
-    SecurityProperties = [
-        {<<"admins">>,{[{<<"names">>,[<<"pow">>,<<"wow">>]}]}},
-        {<<"members">>,{[{<<"names">>,[<<"pow">>,<<"wow">>]}]}}
-    ],
-    create_db(UserDbName),
-    set_security(UserDbName, SecurityProperties),
-    create_user(TestAuthDb, User),
-    {MemberProperties} = proplists:get_value(<<"members">>,
-        get_security(UserDbName)),
-    MemberNames = proplists:get_value(<<"names">>, MemberProperties),
-    ?_assert(lists:member(<<"pow">>, MemberNames)),
-    ?_assert(lists:member(<<"wow">>, MemberNames)),
-    ?_assert(lists:member(<<"qux">>, MemberNames)).
-
-should_remove_user_from_db_admins(TestAuthDb) ->
-    User = "qux",
-    UserDbName = <<"userdb-717578">>,
-    SecurityProperties = [
-        {<<"admins">>,{[{<<"names">>,[<<"foo">>,<<"bar">>]}]}},
-        {<<"members">>,{[{<<"names">>,[<<"baz">>,<<"pow">>]}]}}
-    ],
-    create_db(UserDbName),
-    set_security(UserDbName, SecurityProperties),
-    create_user(TestAuthDb, User),
-    {AdminProperties} = proplists:get_value(<<"admins">>,
-        get_security(UserDbName)),
-    AdminNames = proplists:get_value(<<"names">>, AdminProperties),
-    ?assert(lists:member(<<"foo">>, AdminNames)),
-    ?assert(lists:member(<<"bar">>, AdminNames)),
-    ?assert(lists:member(<<"qux">>, AdminNames)),
-    delete_user(TestAuthDb, User),
-    {NewAdminProperties} = proplists:get_value(<<"admins">>,
-        get_security(UserDbName)),
-    NewAdminNames = proplists:get_value(<<"names">>, NewAdminProperties),
-    ?_assert(lists:member(<<"foo">>, NewAdminNames)),
-    ?_assert(lists:member(<<"bar">>, NewAdminNames)),
-    ?_assert(not lists:member(<<"qux">>, NewAdminNames)).
-
-should_remove_user_from_db_members(TestAuthDb) ->
-    User = "qux",
-    UserDbName = <<"userdb-717578">>,
-    SecurityProperties = [
-        {<<"admins">>,{[{<<"names">>,[<<"pow">>,<<"wow">>]}]}},
-        {<<"members">>,{[{<<"names">>,[<<"pow">>,<<"wow">>]}]}}
-    ],
-    create_db(UserDbName),
-    set_security(UserDbName, SecurityProperties),
-    create_user(TestAuthDb, User),
-    {MemberProperties} = proplists:get_value(<<"members">>,
-        get_security(UserDbName)),
-    MemberNames = proplists:get_value(<<"names">>, MemberProperties),
-    ?assert(lists:member(<<"pow">>, MemberNames)),
-    ?assert(lists:member(<<"wow">>, MemberNames)),
-    ?assert(lists:member(<<"qux">>, MemberNames)),
-    delete_user(TestAuthDb, User),
-    {NewMemberProperties} = proplists:get_value(<<"members">>,
-        get_security(UserDbName)),
-    NewMemberNames = proplists:get_value(<<"names">>, NewMemberProperties),
-    ?_assert(lists:member(<<"foo">>, NewMemberNames)),
-    ?_assert(lists:member(<<"bar">>, NewMemberNames)),
-    ?_assert(not lists:member(<<"qux">>, NewMemberNames)).
-
-couchdb_peruser_test_() ->
-    {
-        "couchdb_peruser test",
-        {
-            setup,
-            fun setup_all/0, fun teardown_all/1,
-            {
-                foreach,
-                fun setup/0, fun teardown/1,
-                [
-                    fun should_create_user_db/1,
-                    fun should_not_delete_user_db/1,
-                    fun should_delete_user_db/1,
-                    fun should_reflect_config_changes/1,
-                    fun should_add_user_to_db_admins/1,
-                    fun should_add_user_to_db_members/1,
-                    fun should_not_remove_existing_db_admins/1,
-                    fun should_not_remove_existing_db_members/1,
-                    fun should_remove_user_from_db_admins/1,
-                    fun should_remove_user_from_db_members/1
-                ]
-            }
-        }
-    }.


Mime
View raw message