nickva commented on code in PR #4814:
URL: https://github.com/apache/couchdb/pull/4814#discussion_r1378379078


##########
src/couch/src/couch_password_hasher.erl:
##########
@@ -45,29 +66,95 @@ start_link() ->
 
 init(_Args) ->
     hash_admin_passwords(true),
-    {ok, #state{}}.
+    ?IN_PROGRESS_ETS = ets:new(?IN_PROGRESS_ETS, [named_table, 
{read_concurrency, true}]),
+    {ok, start_worker_loop(#state{})}.
 
 handle_call(Msg, _From, #state{} = State) ->
     {stop, {invalid_call, Msg}, {invalid_call, Msg}, State}.
 
-handle_cast({hash_passwords, Persist}, State) ->
-    hash_admin_passwords(Persist),
+handle_cast({upgrade_password_hash, AuthModule, UserName, Password, 
UserProps}, State) ->
+    case ets:insert_new(?IN_PROGRESS_ETS, {{AuthModule, UserName}}) of
+        true ->
+            State#state.worker_pid !
+                {upgrade_password_hash, AuthModule, UserName, Password, 
UserProps};
+        false ->
+            ok
+    end,
+    {noreply, State};
+handle_cast({hash_admin_passwords, Persist}, State) ->
+    hash_admin_passwords_int(Persist),
     {noreply, State};
 handle_cast(Msg, State) ->
     {stop, {invalid_cast, Msg}, State}.
 
+handle_info({done, AuthModule, UserName}, State) ->
+    ets:delete(?IN_PROGRESS_ETS, {AuthModule, UserName}),
+    {noreply, State};
+handle_info({'DOWN', MonRef, _, _, normal}, #state{worker_mon = MonRef} = 
State) ->
+    ets:delete_all_objects(?IN_PROGRESS_ETS),
+    {noreply, start_worker_loop(State)};
+handle_info(Msg, State) ->
+    {stop, {invalid_info, Msg}, State}.
+
 code_change(_OldVsn, #state{} = State, _Extra) ->
     {ok, State}.
 
 %%%===================================================================
 %%% Internal functions
 %%%===================================================================
 
-hash_admin_passwords(Persist) ->
+hash_admin_passwords_int(Persist) ->
     lists:foreach(
         fun({User, ClearPassword}) ->
             HashedPassword = 
couch_passwords:hash_admin_password(ClearPassword),
             config:set("admins", User, ?b2l(HashedPassword), Persist)
         end,
         couch_passwords:get_unhashed_admins()
     ).
+
+is_admin(UserProps) ->
+    Roles = couch_util:get_value(<<"roles">>, UserProps, []),
+    lists:member(<<"_admin">>, Roles).
+
+needs_upgrade(UserProps) ->
+    CurrentScheme = couch_util:get_value(<<"password_scheme">>, UserProps, 
<<"simple">>),
+    TargetScheme = ?l2b(chttpd_util:get_chttpd_auth_config("password_scheme", 
"pbkdf2")),
+    CurrentPRF = couch_util:get_value(<<"pbkdf2_prf">>, UserProps, <<"sha">>),
+    TargetPRF = ?l2b(chttpd_util:get_chttpd_auth_config("pbkdf2_prf", 
"sha256")),
+    CurrentIterations = couch_util:to_integer(
+        couch_util:get_value(<<"iterations">>, UserProps, "10")
+    ),
+    TargetIterations = chttpd_util:get_chttpd_auth_config_integer(
+        "iterations", 10
+    ),
+    if
+        CurrentScheme == TargetScheme andalso TargetScheme == <<"simple">> 
andalso
+            CurrentIterations == TargetIterations ->
+            false;
+        CurrentScheme == TargetScheme andalso TargetScheme == <<"pbkdf2">> 
andalso
+            CurrentPRF == TargetPRF andalso CurrentIterations == 
TargetIterations ->
+            false;
+        true ->
+            true
+    end.
+
+in_progress(AuthModule, UserName) ->
+    ets:member(?IN_PROGRESS_ETS, {AuthModule, UserName}).
+
+start_worker_loop(State) ->
+    {WorkerPid, WorkerMon} = spawn_monitor(?MODULE, worker_loop, [self()]),

Review Comment:
   `spawn_monitor` will keep the worker up even after its parent crashes. 
Should we `spawn_link` it instead and then in a `terminate/2` function to 
`unlink` and `kill` it?
   
   If we expect it to crash often we could set the parent to trap exits and 
then react to an `{'EXIT', ...}` to log an error, cleanup the table and restart 
it again.
   
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscr...@couchdb.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to