Compare commits

..

No commits in common. "45b5bc3d2d7f32011c80dd3e07106e4b666da70a" and "eb5810929299056cdbd411e2b2e1e500b7a5a9e4" have entirely different histories.

3 changed files with 20 additions and 13 deletions

View File

@ -18,6 +18,8 @@
-export([bootstrap/3, start/2, stop/1]). -export([bootstrap/3, start/2, stop/1]).
-include_lib("dudeswave/include/defines.hrl").
start(_Type, StartArgs) -> start(_Type, StartArgs) ->
crypto:rand_seed(), crypto:rand_seed(),
@ -36,7 +38,6 @@ start(_Type, StartArgs) ->
Dispatch = cowboy_router:compile([ Dispatch = cowboy_router:compile([
{'_', [ {'_', [
{"/api/v1/auth", dudeswave_auth_handler, #{}},
{"/api/v1/user", dudeswave_user_handler, #{}}, {"/api/v1/user", dudeswave_user_handler, #{}},
{"/", dudeswave_handler, #{}} {"/", dudeswave_handler, #{}}
]} ]}

View File

@ -17,8 +17,8 @@
-moduledoc """ -moduledoc """
Dudes users management module. Dudes users management module.
Here lives all the functions for the APIs needed to create, update and delete Here lives all the functions needed to create, update and delete users
users from the dudeswave database. from the dudeswave database.
""". """.
-include_lib("dudeswave/include/defines.hrl"). -include_lib("dudeswave/include/defines.hrl").
@ -59,7 +59,7 @@ authenticate(User, {cookie, Cookie}) ->
{ok, [R]} -> {ok, [R]} ->
CurTime = calendar:now_to_universal_time(erlang:timestamp()), CurTime = calendar:now_to_universal_time(erlang:timestamp()),
CookieTime = R#object.value, CookieTime = R#object.value,
{user, CookieUser} = proplists:lookup(user, R#object.metadata), CookieUser = lists:keyfind(user, 1, R#object.metadata),
if if
CookieTime >= CurTime -> CookieTime >= CurTime ->
@ -83,14 +83,11 @@ authenticate(User, {password, Password}) ->
erlang:system_time(seconds) + ?DEFVALIDITY * 86400 erlang:system_time(seconds) + ?DEFVALIDITY * 86400
end, end,
{hash, Hash} = proplists:lookup(hash, R#object.metadata), {ok, Hash} = lists:keyfind(hash, 1, R#object.metadata),
{salt, Salt} = proplists:lookup(salt, R#object.metadata), {ok, Salt} = lists:keyfind(salt, 1, 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>>),
if if
Appr =/= true -> false;
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>>,
@ -126,7 +123,7 @@ Invalidate and delete `Cookie` associated with `User` from the system.
logout(User, Cookie) -> logout(User, Cookie) ->
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, User} = lists:keyfind(user, 1, R#object.metadata),
storage:delete(?COOKIESBUCK, Cookie); storage:delete(?COOKIESBUCK, Cookie);
{ok, []} -> {ok, []} ->
{error, not_found}; {error, not_found};
@ -174,7 +171,8 @@ Spec:
The `User` is created, and stored in the application's users bucket The `User` is created, and stored in the application's users bucket
`Password` is salted and hashed with SHA256 before being stored. `Password` is salted and hashed with SHA256 before being stored.
The new user is saved with a metadata `approved` of `false`, The new user is saved with a metadata `status` of `waiting_confirmation`,
based on the application settings, the confirmation method may vary.
""". """.
-spec new(User, Password, Email) -> ok | {error, Reason} when -spec new(User, Password, Email) -> ok | {error, Reason} when
User :: binary(), User :: binary(),
@ -187,7 +185,7 @@ new(User, Password, Email) ->
Hash = crypto:hash(sha256, <<Password/binary, Salt/binary>>), Hash = crypto:hash(sha256, <<Password/binary, Salt/binary>>),
Data = #{<<"email">> => Email}, Data = #{<<"email">> => Email},
Metadata = [{salt, Salt}, {hash, Hash}, {approved, false}], Metadata = [{salt, Salt}, {hash, Hash}, {status, waiting_confirmation}],
storage:write(?USERSBUCK, User, Data, Metadata). storage:write(?USERSBUCK, User, Data, Metadata).
@ -297,7 +295,7 @@ invalidate_cookies(Req) ->
Req1. Req1.
-doc """ -doc """
Set the authentication cookies for the provided client request Set the authentication cookies for the provided clien request
Spec: Spec:

View File

@ -17,6 +17,14 @@
-moduledoc """ -moduledoc """
JSON API to manage users. JSON API to manage users.
The username is passed in a cookie. The handler recover it from the
session. Cookies are:
```
dudename: the actual username
dudeauth: the authentication cookie
```
If the session is not valid, all the requests will return `403 Forbidden` to If the session is not valid, all the requests will return `403 Forbidden` to
the client. In case a technical problem occurs, `500 Internal Server Error` the client. In case a technical problem occurs, `500 Internal Server Error`
is returned. is returned.