From 51675065a90f512330953bc1bed6a7427497de4f Mon Sep 17 00:00:00 2001 From: absc Date: Fri, 9 Aug 2024 20:37:47 +0000 Subject: [PATCH] Pass the user for authentication with cookies in a cookie itself. --- dudeswave/src/dudeswave_app.erl | 2 +- dudeswave/src/dudeswave_user_handler.erl | 43 +++++++++++------------- 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/dudeswave/src/dudeswave_app.erl b/dudeswave/src/dudeswave_app.erl index 09cb839..7cc00b7 100644 --- a/dudeswave/src/dudeswave_app.erl +++ b/dudeswave/src/dudeswave_app.erl @@ -40,7 +40,7 @@ start(_Type, StartArgs) -> Dispatch = cowboy_router:compile([ {'_', [ - {"/api/v1/user/:username", dudeswave_user_handler, #{bucket => ?USERSBUCK, + {"/api/v1/user", dudeswave_user_handler, #{bucket => ?USERSBUCK, cookies => ?COOKIESBUCK}}, {"/", dudeswave_handler, #{bucket => ?APPBUCK}} ]} diff --git a/dudeswave/src/dudeswave_user_handler.erl b/dudeswave/src/dudeswave_user_handler.erl index 09d5a11..9bd14e4 100644 --- a/dudeswave/src/dudeswave_user_handler.erl +++ b/dudeswave/src/dudeswave_user_handler.erl @@ -17,32 +17,28 @@ -moduledoc """ 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 the client. In case a technical problem occurs, `500 Internal Server Error` is returned. 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 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. -- DELETE /api/v1/user/:username +- DELETE /api/v1/user Remove a user forever. The data is delete immediately. However, 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 @@ -50,7 +46,7 @@ This module accepts four methods: for the simple reason that we may make the call asynchronous 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, 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 @@ -58,7 +54,7 @@ This module accepts four methods: JSON APIs -GET /api/v1/user/:username +GET /api/v1/user ``` { @@ -74,7 +70,7 @@ Response codes: - 200 OK (Success) - 404 Not Found -PUT /api/v1/user/:username +PUT /api/v1/user ``` { @@ -89,7 +85,7 @@ Response codes: - 400 Bad Request - 409 Conflict (User already exists) -POST /api/v1/user/:username +POST /api/v1/user ``` { @@ -105,7 +101,7 @@ Response codes: - 400 Bad Request - 404 Not Found -DELETE /api/v1/user/:username +DELETE /api/v1/user - 202 Accepted - 404 Not Found @@ -145,9 +141,9 @@ forbidden(Req, State) -> <<"PUT">> -> {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), - User = cowboy_req:binding(username, Req), case dudeswave_auth:authenticate({cookie, User, Auth}, Bucket) of {error, service_unavailable} -> exit(service_unavailable); @@ -177,7 +173,7 @@ content_types_accepted(Req, State) -> end. resource_exists(Req, State) -> - User = cowboy_req:binding(username, Req), + #{dudename := User} = cowboy_req:match_cookies([dudename], Req), {ok, Bucket} = maps:find(bucket, State), case dudeswave_auth:user_details(User, Bucket) of @@ -204,7 +200,7 @@ allow_missing_post(Req, State) -> {false, Req, State}. delete_resource(Req, 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 ok -> {true, Req, State}; @@ -219,7 +215,7 @@ delete_completed(Req, State) -> {false, Req, State}. create_user(Req, 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)), @@ -230,7 +226,7 @@ create_user(Req, State) -> modify_user(Req, 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, <<"name">> := Name} = json:decode(cowboy_req:body(req)), @@ -242,7 +238,8 @@ modify_user(Req, State) -> user_details(Req, 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}.