Compare commits
6 Commits
5f14a4f6cb
...
ea339a1024
Author | SHA1 | Date |
---|---|---|
absc | ea339a1024 | |
absc | b1c4ab8e16 | |
absc | f51847fe97 | |
absc | 9e100b0317 | |
absc | c3731bf0f3 | |
absc | 9fd60a2dfa |
|
@ -5,6 +5,6 @@
|
||||||
dudeswave_backend_supervisor,
|
dudeswave_backend_supervisor,
|
||||||
dudeswave_backend_auth,dudeswave_backend_user]},
|
dudeswave_backend_auth,dudeswave_backend_user]},
|
||||||
{registered,[]},
|
{registered,[]},
|
||||||
{applications,[kernel,stdlib,erts,cowboy,ranch]},
|
{applications,[kernel,stdlib,erts]},
|
||||||
{mod,{dudeswave_backend_app,[]}},
|
{mod,{dudeswave_backend_app,[]}},
|
||||||
{start_phases,[]}]}.
|
{start_phases,[]}]}.
|
||||||
|
|
|
@ -24,8 +24,8 @@
|
||||||
-export([init/1, handle_call/3, handle_cast/2, terminate/2]).
|
-export([init/1, handle_call/3, handle_cast/2, terminate/2]).
|
||||||
|
|
||||||
% Public API exports
|
% Public API exports
|
||||||
-export([auth/3, logout/2, user_details/1, new_user/3,
|
-export([auth/4, logout/3, user_details/2, new_user/4,
|
||||||
update_user/4, delete_user/1]).
|
update_user/5, delete_user/2]).
|
||||||
|
|
||||||
%
|
%
|
||||||
% Startup functions
|
% Startup functions
|
||||||
|
@ -47,33 +47,33 @@ init([]) ->
|
||||||
% Users management
|
% Users management
|
||||||
%
|
%
|
||||||
|
|
||||||
auth(cookie, User, Cookie) ->
|
auth(cookie, User, Host, Cookie) ->
|
||||||
gen_server:call({local, ?MODULE}, {cookie, User, Cookie});
|
gen_server:call({local, ?MODULE}, {cookie, User, Host, Cookie});
|
||||||
|
|
||||||
auth(password, User, Password) ->
|
auth(password, User, Host, Password) ->
|
||||||
gen_server:call({local, ?MODULE}, {password, User, Password}).
|
gen_server:call({local, ?MODULE}, {password, User, Host, Password}).
|
||||||
|
|
||||||
logout(User, Cookie) ->
|
logout(User, Host, Cookie) ->
|
||||||
gen_server:call({local, ?MODULE}, {logout, User, Cookie}).
|
gen_server:call({local, ?MODULE}, {logout, User, Host, Cookie}).
|
||||||
|
|
||||||
user_details(User) ->
|
user_details(User, Host) ->
|
||||||
gen_server:call({local, ?MODULE}, {user_details, User}).
|
gen_server:call({local, ?MODULE}, {user_details, User, Host}).
|
||||||
|
|
||||||
new_user(User, Password, Email) ->
|
new_user(User, Host, Password, Email) ->
|
||||||
gen_server:call({local, ?MODULE}, {new_user, User, Password, Email}).
|
gen_server:call({local, ?MODULE}, {new_user, User, Host, Password, Email}).
|
||||||
|
|
||||||
update_user(User, Name, Email, Desc) ->
|
update_user(User, Host, Name, Email, Desc) ->
|
||||||
gen_server:call({local, ?MODULE}, {update_user, User, Name, Email, Desc}).
|
gen_server:call({local, ?MODULE}, {update_user, User, Host, Name, Email, Desc}).
|
||||||
|
|
||||||
delete_user(User) ->
|
delete_user(User, Host) ->
|
||||||
gen_server:call({local, ?MODULE}, {delete_user, User}).
|
gen_server:call({local, ?MODULE}, {delete_user, User, Host}).
|
||||||
|
|
||||||
%
|
%
|
||||||
% Callbacks
|
% Callbacks
|
||||||
%
|
%
|
||||||
|
|
||||||
handle_call({cookie, User, Cookie}, _From, State) ->
|
handle_call({cookie, User, Host, Cookie}, _From, State) ->
|
||||||
case dudeswave_users:authenticate(cookie, User, Cookie) of
|
case dudeswave_users:authenticate(cookie, User, Host, Cookie) of
|
||||||
true ->
|
true ->
|
||||||
{reply, true, State};
|
{reply, true, State};
|
||||||
false ->
|
false ->
|
||||||
|
@ -82,8 +82,8 @@ handle_call({cookie, User, Cookie}, _From, State) ->
|
||||||
{reply, {error, Reason}, State}
|
{reply, {error, Reason}, State}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
handle_call({password, User, Password}, _From, State) ->
|
handle_call({password, User, Host, Password}, _From, State) ->
|
||||||
case dudeswave_users:authenticate(password, User, Password) of
|
case dudeswave_users:authenticate(password, User, Host, Password) of
|
||||||
{true, Cookie, Validity} ->
|
{true, Cookie, Validity} ->
|
||||||
{reply, {true, Cookie, Validity}, State};
|
{reply, {true, Cookie, Validity}, State};
|
||||||
false ->
|
false ->
|
||||||
|
@ -92,33 +92,33 @@ handle_call({password, User, Password}, _From, State) ->
|
||||||
{reply, {error, Reason}, State}
|
{reply, {error, Reason}, State}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
handle_call({logout, User, Cookie}, _From, State) ->
|
handle_call({logout, User, Host, Cookie}, _From, State) ->
|
||||||
case dudeswave_users:logout(User, Cookie) of
|
case dudeswave_users:logout(User, Host, Cookie) of
|
||||||
ok -> {reply, ok, State};
|
ok -> {reply, ok, State};
|
||||||
{error, Reason} -> {reply, {error, Reason}, State}
|
{error, Reason} -> {reply, {error, Reason}, State}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
handle_call({user_details, User}, _From, State) ->
|
handle_call({user_details, User, Host}, _From, State) ->
|
||||||
case dudeswave_users:details(User) of
|
case dudeswave_users:details(User, Host) of
|
||||||
{error, not_found} -> {reply, not_found, State};
|
{error, not_found} -> {reply, not_found, State};
|
||||||
{error, Reason} -> {reply, {error, Reason}, State};
|
{error, Reason} -> {reply, {error, Reason}, State};
|
||||||
Val -> {reply, Val, State}
|
Val -> {reply, Val, State}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
handle_call({new_user, User, Password, Email}, _From, State) ->
|
handle_call({new_user, User, Host, Password, Email}, _From, State) ->
|
||||||
case dudeswave_users:new(User, Password, Email) of
|
case dudeswave_users:new(User, Host, Password, Email) of
|
||||||
ok -> {reply, ok, State};
|
ok -> {reply, ok, State};
|
||||||
{error, Reason} -> {reply, {error, Reason}, State}
|
{error, Reason} -> {reply, {error, Reason}, State}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
handle_call({update_user, User, Name, Email, Desc}, _From, State) ->
|
handle_call({update_user, User, Host, Name, Email, Desc}, _From, State) ->
|
||||||
case dudeswave_users:update(User, Name, Email, Desc) of
|
case dudeswave_users:update(User, Host, Name, Email, Desc) of
|
||||||
ok -> {reply, ok, State};
|
ok -> {reply, ok, State};
|
||||||
{error, Reason} -> {reply, {error, Reason}, State}
|
{error, Reason} -> {reply, {error, Reason}, State}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
handle_call({delete_user, User}, _From, State) ->
|
handle_call({delete_user, User, Host}, _From, State) ->
|
||||||
case dudeswave_users:delete(User) of
|
case dudeswave_users:delete(User, Host) of
|
||||||
ok -> {reply, ok, State};
|
ok -> {reply, ok, State};
|
||||||
{error, Reason} -> {reply, {error, Reason}, State}
|
{error, Reason} -> {reply, {error, Reason}, State}
|
||||||
end.
|
end.
|
||||||
|
|
|
@ -5,6 +5,6 @@
|
||||||
dudeswave_users_supervisor,
|
dudeswave_users_supervisor,
|
||||||
dudeswave_users_auth,dudeswave_users_user]},
|
dudeswave_users_auth,dudeswave_users_user]},
|
||||||
{registered,[]},
|
{registered,[]},
|
||||||
{applications,[kernel,stdlib,erts,cowboy,ranch]},
|
{applications,[kernel,stdlib,erts]},
|
||||||
{mod,{dudeswave_users_app,[]}},
|
{mod,{dudeswave_users_app,[]}},
|
||||||
{start_phases,[]}]}.
|
{start_phases,[]}]}.
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
%
|
|
||||||
% Copyright (c) 2024 Andrea Biscuola <a@abiscuola.com>
|
|
||||||
%
|
|
||||||
% Permission to use, copy, modify, and distribute this software for any
|
|
||||||
% purpose with or without fee is hereby granted, provided that the above
|
|
||||||
% copyright notice and this permission notice appear in all copies.
|
|
||||||
%
|
|
||||||
% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
%
|
|
||||||
|
|
||||||
-define(APPBUCK, dudeswave).
|
|
||||||
-define(USERSBUCK, dudes).
|
|
||||||
-define(COOKIESBUCK, cookies).
|
|
||||||
-define(RANDBYTES, 32).
|
|
||||||
-define(DEFVALIDITY, 365).
|
|
||||||
-define(DUDENAME, "dudename").
|
|
||||||
-define(DUDEAUTH, "dudeauth").
|
|
|
@ -20,10 +20,10 @@ Dudes authentication module
|
||||||
Here lives all the functions for the APIs needed to handle users authentication.
|
Here lives all the functions for the APIs needed to handle users authentication.
|
||||||
""".
|
""".
|
||||||
|
|
||||||
-include_lib("dudeswave_users/include/defines.hrl").
|
-include_lib("dudeswave_backend/include/defines.hrl").
|
||||||
-include_lib("storage/include/storage.hrl").
|
-include_lib("storage/include/storage.hrl").
|
||||||
|
|
||||||
-export([authenticate/3, logout/2]).
|
-export([authenticate/4, logout/3]).
|
||||||
|
|
||||||
-doc """
|
-doc """
|
||||||
Verify a session with an existing cookie.
|
Verify a session with an existing cookie.
|
||||||
|
@ -31,9 +31,10 @@ Verify a session with an existing cookie.
|
||||||
Spec:
|
Spec:
|
||||||
|
|
||||||
```
|
```
|
||||||
-spec authenticate(Type, User, Auth) -> true | false | {true, Cookie, Validity} | {error, Reason} when
|
-spec authenticate(Type, User, Host, Auth) -> true | false | {true, Cookie, Validity} | {error, Reason} when
|
||||||
Type :: cookie | password,
|
Type :: cookie | password,
|
||||||
User :: binary(),
|
User :: binary(),
|
||||||
|
Host :: binary(),
|
||||||
Auth :: {cookie, binary()} | {password, binary()},
|
Auth :: {cookie, binary()} | {password, binary()},
|
||||||
Cookie :: binary(),
|
Cookie :: binary(),
|
||||||
Validity :: pos_integer(),
|
Validity :: pos_integer(),
|
||||||
|
@ -46,15 +47,18 @@ after authenticating with `Password`.
|
||||||
If `Cookie` is valid, the function returns `true`. If the authentication is denied
|
If `Cookie` is valid, the function returns `true`. If the authentication is denied
|
||||||
returns `false`
|
returns `false`
|
||||||
""".
|
""".
|
||||||
-spec authenticate(Type, User, Auth) -> true | false | {true, Cookie, Validity} | {error, Reason} when
|
-spec authenticate(Type, User, Host, Auth) -> true | false | {true, Cookie, Validity} | {error, Reason} when
|
||||||
Type :: cookie | password,
|
Type :: cookie | password,
|
||||||
User :: binary(),
|
User :: binary(),
|
||||||
|
Host :: binary(),
|
||||||
Auth :: {cookie, binary()} | {password, binary()},
|
Auth :: {cookie, binary()} | {password, binary()},
|
||||||
Cookie :: binary(),
|
Cookie :: binary(),
|
||||||
Validity :: pos_integer(),
|
Validity :: pos_integer(),
|
||||||
Reason :: term().
|
Reason :: term().
|
||||||
|
|
||||||
authenticate(cookie, User, Cookie) ->
|
authenticate(cookie, User, Host, Cookie) ->
|
||||||
|
ComplUser = <<User/binary, "@", Host/binary>>,
|
||||||
|
|
||||||
case storage:read(?COOKIESBUCK, Cookie) of
|
case storage:read(?COOKIESBUCK, Cookie) of
|
||||||
{ok, [R]} ->
|
{ok, [R]} ->
|
||||||
CurTime = calendar:now_to_universal_time(erlang:timestamp()),
|
CurTime = calendar:now_to_universal_time(erlang:timestamp()),
|
||||||
|
@ -64,7 +68,7 @@ authenticate(cookie, User, Cookie) ->
|
||||||
if
|
if
|
||||||
CookieTime >= CurTime ->
|
CookieTime >= CurTime ->
|
||||||
if
|
if
|
||||||
User =:= CookieUser -> true;
|
ComplUser =:= CookieUser -> true;
|
||||||
true -> false
|
true -> false
|
||||||
end;
|
end;
|
||||||
true -> false
|
true -> false
|
||||||
|
@ -73,8 +77,10 @@ authenticate(cookie, User, Cookie) ->
|
||||||
{error, _} -> {error, service_unavailable}
|
{error, _} -> {error, service_unavailable}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
authenticate(password, User, Password) ->
|
authenticate(password, User, Host, Password) ->
|
||||||
case storage:read(?USERSBUCK, User) of
|
ComplUser = <<User/binary, "@", Host/binary>>,
|
||||||
|
|
||||||
|
case storage:read(?USERSBUCK, ComplUser) of
|
||||||
{ok, [R]} ->
|
{ok, [R]} ->
|
||||||
Validity = case application:get_env(cookie_validity) of
|
Validity = case application:get_env(cookie_validity) of
|
||||||
{ok, Value} ->
|
{ok, Value} ->
|
||||||
|
@ -83,8 +89,8 @@ authenticate(password, User, Password) ->
|
||||||
erlang:system_time(seconds) + ?DEFVALIDITY * 86400
|
erlang:system_time(seconds) + ?DEFVALIDITY * 86400
|
||||||
end,
|
end,
|
||||||
|
|
||||||
{hash, Hash} = proplists:lookup(hash, R#object.metadata),
|
{hash, Hash} = proplists:lookup(hash, R#object.value),
|
||||||
{salt, Salt} = proplists:lookup(salt, R#object.metadata),
|
{salt, Salt} = proplists:lookup(salt, R#object.value),
|
||||||
{approved, Appr} = proplists:lookup(approved, R#object.metadata),
|
{approved, Appr} = proplists:lookup(approved, R#object.metadata),
|
||||||
|
|
||||||
Auth = crypto:hash(sha256, <<Password/binary, Salt/binary>>),
|
Auth = crypto:hash(sha256, <<Password/binary, Salt/binary>>),
|
||||||
|
@ -94,7 +100,7 @@ authenticate(password, User, Password) ->
|
||||||
Auth =:= Hash ->
|
Auth =:= Hash ->
|
||||||
Cookie = base64:encode(rand:bytes(64)),
|
Cookie = base64:encode(rand:bytes(64)),
|
||||||
case storage:write(?COOKIESBUCK, <<Cookie/binary>>,
|
case storage:write(?COOKIESBUCK, <<Cookie/binary>>,
|
||||||
Validity, [{user, User}]) of
|
Validity, [{user, ComplUser}]) of
|
||||||
ok -> {true, Cookie, Validity};
|
ok -> {true, Cookie, Validity};
|
||||||
{error, Reason} -> {error, Reason}
|
{error, Reason} -> {error, Reason}
|
||||||
end;
|
end;
|
||||||
|
@ -110,23 +116,27 @@ Close an existing session
|
||||||
Spec:
|
Spec:
|
||||||
|
|
||||||
```
|
```
|
||||||
-spec logout(User, Cookie) -> ok | {error, Reason} when
|
-spec logout(User, Host, Cookie) -> ok | {error, Reason} when
|
||||||
User :: binary(),
|
User :: binary(),
|
||||||
|
Host :: binary(),
|
||||||
Cookie :: binary(),
|
Cookie :: binary(),
|
||||||
Reason :: term().
|
Reason :: term().
|
||||||
```
|
```
|
||||||
|
|
||||||
Invalidate and delete `Cookie` associated with `User` from the system.
|
Invalidate and delete `Cookie` associated with `User` from the system.
|
||||||
""".
|
""".
|
||||||
-spec logout(User, Cookie) -> ok | {error, Reason} when
|
-spec logout(User, Host, Cookie) -> ok | {error, Reason} when
|
||||||
User :: binary(),
|
User :: binary(),
|
||||||
|
Host :: binary(),
|
||||||
Cookie :: binary(),
|
Cookie :: binary(),
|
||||||
Reason :: term().
|
Reason :: term().
|
||||||
|
|
||||||
logout(User, Cookie) ->
|
logout(User, Host, Cookie) ->
|
||||||
|
ComplUser = <<User/binary, "@", Host/binary>>,
|
||||||
|
|
||||||
case storage:read(?COOKIESBUCK, Cookie) of
|
case storage:read(?COOKIESBUCK, Cookie) of
|
||||||
{ok, [R]} ->
|
{ok, [R]} ->
|
||||||
{user, User} = proplists:lookup(user, R#object.metadata),
|
{user, ComplUser} = proplists:lookup(user, R#object.metadata),
|
||||||
storage:delete(?COOKIESBUCK, Cookie);
|
storage:delete(?COOKIESBUCK, Cookie);
|
||||||
{ok, []} ->
|
{ok, []} ->
|
||||||
{error, not_found};
|
{error, not_found};
|
||||||
|
|
|
@ -15,10 +15,10 @@
|
||||||
%
|
%
|
||||||
-module(dudeswave_users_user).
|
-module(dudeswave_users_user).
|
||||||
|
|
||||||
-include_lib("dudeswave_users/include/defines.hrl").
|
-include_lib("dudeswave_backend/include/defines.hrl").
|
||||||
-include_lib("storage/include/storage.hrl").
|
-include_lib("storage/include/storage.hrl").
|
||||||
|
|
||||||
-export([details/1, new/3, update/4, delete/1]).
|
-export([details/2, new/4, update/5, delete/1]).
|
||||||
|
|
||||||
-doc """
|
-doc """
|
||||||
Return user details.
|
Return user details.
|
||||||
|
@ -26,22 +26,30 @@ Return user details.
|
||||||
Spec:
|
Spec:
|
||||||
|
|
||||||
```
|
```
|
||||||
-spec details(User) -> Value | {error, Reason} when
|
-spec details(User, Host) -> {ok, Value} | {error, Reason} when
|
||||||
User :: binary(),
|
User :: binary(),
|
||||||
|
Host :: binary(),
|
||||||
Value :: term(),
|
Value :: term(),
|
||||||
Reason :: term().
|
Reason :: term().
|
||||||
```
|
```
|
||||||
""".
|
""".
|
||||||
-spec details(User) -> Value | {error, Reason} when
|
-spec details(User, Host) -> {ok, Value} | {error, Reason} when
|
||||||
User :: binary(),
|
User :: binary(),
|
||||||
|
Host :: binary(),
|
||||||
Value :: term(),
|
Value :: term(),
|
||||||
Reason :: term().
|
Reason :: term().
|
||||||
|
|
||||||
details(User) ->
|
details(User, Host) ->
|
||||||
case storage:read(?USERSBUCK, User) of
|
ComplUser = <<User/binary, "@", Host/binary>>,
|
||||||
{ok, [R]} -> R#object.value;
|
|
||||||
{error, Reason} -> {error, Reason};
|
case storage:read(?USERSBUCK, ComplUser) of
|
||||||
{ok, []} -> {error, not_found}
|
{ok, [R]} ->
|
||||||
|
{details, Details} = proplists:lookup(details, R#object.value),
|
||||||
|
{ok, Details};
|
||||||
|
{error, Reason} ->
|
||||||
|
{error, Reason};
|
||||||
|
{ok, []} ->
|
||||||
|
{error, not_found}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-doc """
|
-doc """
|
||||||
|
@ -50,8 +58,9 @@ Create a new user.
|
||||||
Spec:
|
Spec:
|
||||||
|
|
||||||
```
|
```
|
||||||
-spec new(User, Password, Email) -> ok | {error, Reason} when
|
-spec new(User, Host, Password, Email) -> ok | {error, Reason} when
|
||||||
User :: binary(),
|
User :: binary(),
|
||||||
|
Host :: binary(),
|
||||||
Password :: binary(),
|
Password :: binary(),
|
||||||
Email :: binary(),
|
Email :: binary(),
|
||||||
Reason :: term().
|
Reason :: term().
|
||||||
|
@ -62,20 +71,23 @@ The `User` is created, and stored in the application's users bucket
|
||||||
|
|
||||||
The new user is saved with a metadata `approved` of `false`,
|
The new user is saved with a metadata `approved` of `false`,
|
||||||
""".
|
""".
|
||||||
-spec new(User, Password, Email) -> ok | {error, Reason} when
|
-spec new(User, Host, Password, Email) -> ok | {error, Reason} when
|
||||||
User :: binary(),
|
User :: binary(),
|
||||||
|
Host :: binary(),
|
||||||
Password :: binary(),
|
Password :: binary(),
|
||||||
Email :: binary(),
|
Email :: binary(),
|
||||||
Reason :: term().
|
Reason :: term().
|
||||||
|
|
||||||
new(User, Password, Email) ->
|
new(User, Host, Password, Email) ->
|
||||||
|
ComplUser = <<User/binary, "@", Host/binary>>,
|
||||||
|
|
||||||
Salt = rand:bytes(?RANDBYTES),
|
Salt = rand:bytes(?RANDBYTES),
|
||||||
Hash = crypto:hash(sha256, <<Password/binary, Salt/binary>>),
|
Hash = crypto:hash(sha256, <<Password/binary, Salt/binary>>),
|
||||||
|
|
||||||
Data = #{<<"email">> => Email},
|
Data = [{details, #{<<"email">> => Email}}, {salt, Salt}, {hash, Hash}],
|
||||||
Metadata = [{salt, Salt}, {hash, Hash}, {approved, false}],
|
Metadata = [{approved, false}],
|
||||||
|
|
||||||
storage:write(?USERSBUCK, User, Data, Metadata).
|
storage:write(?USERSBUCK, ComplUser, Data, Metadata).
|
||||||
|
|
||||||
-doc """
|
-doc """
|
||||||
Update user's details
|
Update user's details
|
||||||
|
@ -83,8 +95,9 @@ Update user's details
|
||||||
Spec:
|
Spec:
|
||||||
|
|
||||||
```
|
```
|
||||||
-spec update(User, Name, Email, Desc) -> ok | {error, Reason} when
|
-spec update(User, Host, Name, Email, Desc) -> ok | {error, Reason} when
|
||||||
User :: binary(),
|
User :: binary(),
|
||||||
|
Host :: binary(),
|
||||||
Name :: binary(),
|
Name :: binary(),
|
||||||
Email :: binary(),
|
Email :: binary(),
|
||||||
Desc :: binary(),
|
Desc :: binary(),
|
||||||
|
@ -95,24 +108,29 @@ The details apart from `User` are updated. The username itself is immutable
|
||||||
and cannot be modified. All the other fields, excluding the e-mail, are the
|
and cannot be modified. All the other fields, excluding the e-mail, are the
|
||||||
ones that can be seen in the public page.
|
ones that can be seen in the public page.
|
||||||
""".
|
""".
|
||||||
-spec update(User, Name, Email, Desc) -> ok | {error, Reason} when
|
-spec update(User, Host, Name, Email, Desc) -> ok | {error, Reason} when
|
||||||
User :: binary(),
|
User :: binary(),
|
||||||
|
Host :: binary(),
|
||||||
Name :: binary(),
|
Name :: binary(),
|
||||||
Email :: binary(),
|
Email :: binary(),
|
||||||
Desc :: binary(),
|
Desc :: binary(),
|
||||||
Reason :: term().
|
Reason :: term().
|
||||||
|
|
||||||
update(User, Name, Email, Desc) ->
|
update(User, Host, Name, Email, Desc) ->
|
||||||
{ok, CurData, Metadata} = case storage:read(?USERSBUCK, User) of
|
ComplUser = <<User/binary, "@", Host/binary>>,
|
||||||
|
|
||||||
|
{ok, Value, Metadata} = case storage:read(?USERSBUCK, ComplUser) of
|
||||||
{ok, [R]} ->
|
{ok, [R]} ->
|
||||||
{ok, R#object.value, R#object.metadata};
|
{ok, R#object.value, R#object.metadata};
|
||||||
{error, Reason} -> {error, Reason}
|
{error, Reason} -> {error, Reason}
|
||||||
end,
|
end,
|
||||||
|
|
||||||
Data = CurData#{<<"email">> => Email, <<"name">> => Name,
|
{details, CurDets} = proplists:lookup(details, Value),
|
||||||
|
NewDets = CurDets#{<<"email">> => Email, <<"name">> => Name,
|
||||||
<<"description">> => Desc},
|
<<"description">> => Desc},
|
||||||
|
NewData = lists:keyreplace(details, 1, Value, {details, NewDets}),
|
||||||
|
|
||||||
storage:write(?USERSBUCK, User, Data, Metadata).
|
storage:write(?USERSBUCK, ComplUser, NewData, Metadata).
|
||||||
|
|
||||||
-doc """
|
-doc """
|
||||||
Delete an existing user from the database.
|
Delete an existing user from the database.
|
||||||
|
|
Loading…
Reference in New Issue