Pass the user for authentication with cookies in a cookie itself.

main
absc 2024-08-09 20:37:47 +00:00
parent 6acd5e3a5a
commit 51675065a9
2 changed files with 21 additions and 24 deletions

View File

@ -40,7 +40,7 @@ start(_Type, StartArgs) ->
Dispatch = cowboy_router:compile([ Dispatch = cowboy_router:compile([
{'_', [ {'_', [
{"/api/v1/user/:username", dudeswave_user_handler, #{bucket => ?USERSBUCK, {"/api/v1/user", dudeswave_user_handler, #{bucket => ?USERSBUCK,
cookies => ?COOKIESBUCK}}, cookies => ?COOKIESBUCK}},
{"/", dudeswave_handler, #{bucket => ?APPBUCK}} {"/", dudeswave_handler, #{bucket => ?APPBUCK}}
]} ]}

View File

@ -17,32 +17,28 @@
-moduledoc """ -moduledoc """
JSON API to manage users. JSON API to manage users.
The username should be passed as the last token in the request, like: The username is passed in a cookie. The handler recover it from the
session. Cookies are:
``` ```
/api/v1/user/foo dudename # the actual username
dudeauth # the authentication cookie
``` ```
Where `foo` is the actual username.
The user parameter must be called `username` as this module expects it
in order to work properly. All the requests must be done with a valid
session cookie in order to work.
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.
This module accepts four methods: This module accepts four methods:
- GET /api/v1/user/:username - GET /api/v1/user
Retrieve user's details. However, this call requires the user to have Retrieve user's details. However, this call requires the user to have
a valid cookie set. Not suitable for a public page. a valid cookie set. Not suitable for a public page.
- POST /api/v1/user/:username - POST /api/v1/user
Update user's details, like their name, description and whatnot. Update user's details, like their name, description and whatnot.
- DELETE /api/v1/user/:username - DELETE /api/v1/user
Remove a user forever. The data is delete immediately. However, Remove a user forever. The data is delete immediately. However,
it's content is left up there. Probably a specific option will be added it's content is left up there. Probably a specific option will be added
later. This request does not have a body. The call deletes the user later. This request does not have a body. The call deletes the user
@ -50,7 +46,7 @@ This module accepts four methods:
for the simple reason that we may make the call asynchronous for the simple reason that we may make the call asynchronous
to remove additional content in background. to remove additional content in background.
- PUT /api/v1/user/:username - PUT /api/v1/user
Register a user. The registration takes only three parameter: username, Register a user. The registration takes only three parameter: username,
password and e-mail. The e-mail is required if a confirmation message password and e-mail. The e-mail is required if a confirmation message
is to be sent. The plan is to have a separate process handle this, so the is to be sent. The plan is to have a separate process handle this, so the
@ -58,7 +54,7 @@ This module accepts four methods:
JSON APIs JSON APIs
GET /api/v1/user/:username GET /api/v1/user
``` ```
{ {
@ -74,7 +70,7 @@ Response codes:
- 200 OK (Success) - 200 OK (Success)
- 404 Not Found - 404 Not Found
PUT /api/v1/user/:username PUT /api/v1/user
``` ```
{ {
@ -89,7 +85,7 @@ Response codes:
- 400 Bad Request - 400 Bad Request
- 409 Conflict (User already exists) - 409 Conflict (User already exists)
POST /api/v1/user/:username POST /api/v1/user
``` ```
{ {
@ -105,7 +101,7 @@ Response codes:
- 400 Bad Request - 400 Bad Request
- 404 Not Found - 404 Not Found
DELETE /api/v1/user/:username DELETE /api/v1/user
- 202 Accepted - 202 Accepted
- 404 Not Found - 404 Not Found
@ -145,9 +141,9 @@ forbidden(Req, State) ->
<<"PUT">> -> <<"PUT">> ->
{false, Req, State}; {false, Req, State};
_ -> _ ->
#{dudeauth := Auth} = cowboy_req:match_cookies([dudeauth], Req), #{dudeauth := Auth, dudename := User} = cowboy_req:match_cookies([dudeauth,
dudename], Req),
{ok, Bucket} = maps:find(cookies, State), {ok, Bucket} = maps:find(cookies, State),
User = cowboy_req:binding(username, Req),
case dudeswave_auth:authenticate({cookie, User, Auth}, Bucket) of case dudeswave_auth:authenticate({cookie, User, Auth}, Bucket) of
{error, service_unavailable} -> exit(service_unavailable); {error, service_unavailable} -> exit(service_unavailable);
@ -177,7 +173,7 @@ content_types_accepted(Req, State) ->
end. end.
resource_exists(Req, State) -> resource_exists(Req, State) ->
User = cowboy_req:binding(username, Req), #{dudename := User} = cowboy_req:match_cookies([dudename], Req),
{ok, Bucket} = maps:find(bucket, State), {ok, Bucket} = maps:find(bucket, State),
case dudeswave_auth:user_details(User, Bucket) of case dudeswave_auth:user_details(User, Bucket) of
@ -204,7 +200,7 @@ allow_missing_post(Req, State) -> {false, Req, State}.
delete_resource(Req, State) -> delete_resource(Req, State) ->
{ok, Bucket} = maps:find(bucket, State), {ok, Bucket} = maps:find(bucket, State),
User = cowboy_req:binding(username, Req), #{dudename := User} = cowboy_req:match_cookies([dudename], Req),
case dudeswave_auth:delete(User, Bucket) of case dudeswave_auth:delete(User, Bucket) of
ok -> {true, Req, State}; ok -> {true, Req, State};
@ -219,7 +215,7 @@ delete_completed(Req, State) -> {false, Req, State}.
create_user(Req, State) -> create_user(Req, State) ->
{ok, Bucket} = maps:find(bucket, State), {ok, Bucket} = maps:find(bucket, State),
User = cowboy_req:binding(username, Req), #{dudename := User} = cowboy_req:match_cookies([dudename], Req),
#{<<"password">> := Pass, <<"email">> := Email} = json:decode(cowboy_req:body(req)), #{<<"password">> := Pass, <<"email">> := Email} = json:decode(cowboy_req:body(req)),
@ -230,7 +226,7 @@ create_user(Req, State) ->
modify_user(Req, State) -> modify_user(Req, State) ->
{ok, Bucket} = maps:find(bucket, State), {ok, Bucket} = maps:find(bucket, State),
User = cowboy_req:binding(username, Req), #{dudename := User} = cowboy_req:match_cookies([dudename], Req),
#{<<"email">> := Email, <<"description">> := Desc, #{<<"email">> := Email, <<"description">> := Desc,
<<"name">> := Name} = json:decode(cowboy_req:body(req)), <<"name">> := Name} = json:decode(cowboy_req:body(req)),
@ -242,7 +238,8 @@ modify_user(Req, State) ->
user_details(Req, State) -> user_details(Req, State) ->
#{details := Details} = State, #{details := Details} = State,
Data = Details#{user => cowboy_req:binding(username, Req)}, #{dudename := User} = cowboy_req:match_cookies([dudename], Req),
Data = Details#{user => User},
{iolist_to_binary(json:encode(Data)), Req, State}. {iolist_to_binary(json:encode(Data)), Req, State}.