Merge pull request #71 from poanetwork/ferigis.69.updating_users_endpoint

Ferigis.69.updating users endpoint
This commit is contained in:
Joseph Yiasemides 2018-09-06 14:43:31 +02:00 committed by GitHub
commit e76a6d65b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 361 additions and 5 deletions

View File

@ -170,9 +170,9 @@ content-length: 362
cache-control: max-age=0, private, must-revalidate
{&quot;token&quot;:&quot;eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJwb2FfYmFja2VuZCIsImV4cCI6MTUzMzkzNjMwNiwiaWF0IjoxNTMzOTMyNzA2LCJpc3MiOiJwb2FfYmFja2VuZCIsImp0aSI6ImI0MzBkNTMwLWExZDYtNDk1Yy1hMjYyLThjNTcxMmM1OTM4YSIsIm5iZiI6MTUzMzkzMjcwNSwic3ViIjoiUmp1YURzdi0iLCJ0eXAiOiJhY2Nlc3MifQ.E3gqpCxY5wAAhZwcr7vZVLcC7X-bSHcXfX6NgeJc-LMbpcDgJvZgcgYQ-VTIkulb2mWw_Fjc7sXVwYMeIIliMg&quot;}</code></pre>
<h2 id="module-user-endpoint" class="section-heading">
<a href="#module-user-endpoint" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
User Endpoint
<h2 id="module-create-user-endpoint" class="section-heading">
<a href="#module-create-user-endpoint" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
Create User Endpoint
</h2>
<p>This Endpoint is needed in order to add a new user. Only Admin people can do that.</p>
@ -352,6 +352,83 @@ server: Cowboy
date: Tue, 04 Sep 2018 13:49:45 GMT
content-length: 0
cache-control: max-age=0, private, must-revalidate</code></pre>
<h2 id="module-update-user-endpoint" class="section-heading">
<a href="#module-update-user-endpoint" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
Update User Endpoint
</h2>
<p>This Endpoint is needed in order to update a user. Currently only the <code class="inline">active</code> property can be updated. If a user is set to <code class="inline">active: false</code> means
it was banned. We can use this enpoint in order to ban or unban users too.</p>
<p><code class="inline">PATCH /user/:username</code></p>
<table>
<colgroup>
<col>
<col>
</colgroup>
<thead>
<tr>
<th style="text-align: left">HTTP header</th><th style="text-align: left">Values</th>
</tr>
</thead>
<tr>
<td style="text-align: left">content-type</td><td style="text-align: left">application/json or application/msgpack</td>
</tr>
<tr>
<td style="text-align: left">authorization</td><td style="text-align: left">Basic encodeBase64(adminname + “:” + password)</td>
</tr>
</table>
<table>
<colgroup>
<col>
<col>
</colgroup>
<thead>
<tr>
<th style="text-align: left">Payload</th><th style="text-align: left">Value</th>
</tr>
</thead>
<tr>
<td style="text-align: left">JSON</td><td style="text-align: left">{“active” : boolean()}</td>
</tr>
<tr>
<td style="text-align: left">MessagePack</td><td style="text-align: left">Same as JSON but packed with MessagePack</td>
</tr>
</table>
<p>Response</p>
<table>
<colgroup>
<col>
<col>
</colgroup>
<thead>
<tr>
<th style="text-align: left">CODE</th><th style="text-align: left">Description</th>
</tr>
</thead>
<tr>
<td style="text-align: left">204</td><td style="text-align: left">Success</td>
</tr>
<tr>
<td style="text-align: left">401</td><td style="text-align: left">Authentication failed</td>
</tr>
<tr>
<td style="text-align: left">404</td><td style="text-align: left">The user doesnt exist</td>
</tr>
<tr>
<td style="text-align: left">415</td><td style="text-align: left">Unsupported Media Type (only application/json and application/msgpack allowed)</td>
</tr>
<tr>
<td style="text-align: left">422</td><td style="text-align: left">Unprocessable entity (the active value is not a boolean)</td>
</tr>
</table>
<p>Example:</p>
<pre><code class="elixir">curl -i -X PATCH -H &quot;Authorization: Basic YWRtaW4xOnBhc3N3b3JkMTIzNDU2Nzg=&quot; -H &quot;Content-Type: application/json&quot; -d &#39;{&quot;active&quot;:false}&#39; https://localhost:4003/user/cZFxFfNT --insecure
HTTP/1.1 204 No Content
server: Cowboy
date: Wed, 05 Sep 2018 13:38:32 GMT
content-length: 0
cache-control: max-age=0, private, must-revalidate</code></pre>
<h2 id="module-blacklist-token-endpoint" class="section-heading">
<a href="#module-blacklist-token-endpoint" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
Blacklist Token Endpoint

View File

@ -57,7 +57,7 @@ defmodule POABackend.Auth.REST do
{"token":"eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJwb2FfYmFja2VuZCIsImV4cCI6MTUzMzkzNjMwNiwiaWF0IjoxNTMzOTMyNzA2LCJpc3MiOiJwb2FfYmFja2VuZCIsImp0aSI6ImI0MzBkNTMwLWExZDYtNDk1Yy1hMjYyLThjNTcxMmM1OTM4YSIsIm5iZiI6MTUzMzkzMjcwNSwic3ViIjoiUmp1YURzdi0iLCJ0eXAiOiJhY2Nlc3MifQ.E3gqpCxY5wAAhZwcr7vZVLcC7X-bSHcXfX6NgeJc-LMbpcDgJvZgcgYQ-VTIkulb2mWw_Fjc7sXVwYMeIIliMg"}
```
## User Endpoint
## Create User Endpoint
This Endpoint is needed in order to add a new user. Only Admin people can do that.
@ -170,6 +170,45 @@ defmodule POABackend.Auth.REST do
cache-control: max-age=0, private, must-revalidate
```
## Update User Endpoint
This Endpoint is needed in order to update a user. Currently only the `active` property can be updated. If a user is set to `active: false` means
it was banned. We can use this enpoint in order to ban or unban users too.
`PATCH /user/:username`
HTTP header | Values
-- | --
content-type | application/json or application/msgpack
authorization | Basic encodeBase64(adminname + : + password)
Payload | Value
-- | --
JSON | {"active" : boolean()}
MessagePack | Same as JSON but packed with MessagePack
Response
CODE | Description
-- | --
204 | Success
401 | Authentication failed
404 | The user doesn't exist
415 | Unsupported Media Type (only application/json and application/msgpack allowed)
422 | Unprocessable entity (the active value is not a boolean)
Example:
```
curl -i -X PATCH -H "Authorization: Basic YWRtaW4xOnBhc3N3b3JkMTIzNDU2Nzg=" -H "Content-Type: application/json" -d '{"active":false}' https://localhost:4003/user/cZFxFfNT --insecure
HTTP/1.1 204 No Content
server: Cowboy
date: Wed, 05 Sep 2018 13:38:32 GMT
content-length: 0
cache-control: max-age=0, private, must-revalidate
```
## Blacklist Token Endpoint
This Endpoint is used when we want to ban a single JWT Token (not the entire user) and that will convert that Token invalid. This Endpoint is only called by Admins.

View File

@ -107,6 +107,31 @@ defmodule POABackend.Auth.Router do
end
end
patch "/user/:user_name" do
with {"authorization", "Basic " <> base64} <- List.keyfind(conn.req_headers, "authorization", 0),
{:ok, decoded64} <- Base.decode64(base64),
[admin_name, admin_password] <- String.split(decoded64, ":"),
{:ok, :valid} <- Auth.authenticate_admin(admin_name, admin_password),
true <- is_boolean(conn.params["active"])
do
case Auth.get_user(user_name) do
nil -> send_resp(conn, 404, "")
user ->
set_active_user(user, conn.params["active"])
send_resp(conn, 204, "")
end
else
false ->
conn
|> send_resp(422, "")
|> halt
_error ->
conn
|> send_resp(401, "")
|> halt
end
end
post "/blacklist/user" do
with {"authorization", "Basic " <> base64} <- List.keyfind(conn.req_headers, "authorization", 0),
{:ok, decoded64} <- Base.decode64(base64),
@ -163,4 +188,13 @@ defmodule POABackend.Auth.Router do
send_resp(conn, 404, "")
end
defp set_active_user(user, true) do
Auth.activate_user(user)
:ok
end
defp set_active_user(user, false) do
Auth.deactivate_user(user)
:ok
end
end

View File

@ -9,7 +9,7 @@ defmodule POABackend.CustomHandler.REST.Plugs.ContentType do
accepted_content_type
end
def call(%Conn{method: method} = conn, accepted_content_type) when method in ["POST", "PUT"] do
def call(%Conn{method: method} = conn, accepted_content_type) when method in ["POST", "PUT", "PATCH"] do
import Plug.Conn
with {"content-type", content_type} <- List.keyfind(conn.req_headers, "content-type", 0),

View File

@ -387,6 +387,198 @@ defmodule Auth.APITest do
assert {401, :nobody} == delete(url <> "/ferigis", headers)
end
test "updating user [JSON]" do
url = @base_url <> "/user"
mime_type = "application/json"
headers = [
{"Content-Type", mime_type},
{"authorization", "Basic " <> Base.encode64(@admin <> ":" <> @admin_pwd)}
]
{200, [initial_user]} = get(url, headers)
assert initial_user["active"]
result =
%{}
|> Map.put(:active, false)
|> Poison.encode!
|> patch(url <> "/ferigis", headers)
assert {204, :nobody} == result
{200, [initial_user]} = get(url, headers)
refute initial_user["active"]
result =
%{}
|> Map.put(:active, true)
|> Poison.encode!
|> patch(url <> "/ferigis", headers)
assert {204, :nobody} == result
{200, [initial_user]} = get(url, headers)
assert initial_user["active"]
end
test "updating user [MSGPACK]" do
url = @base_url <> "/user"
mime_type = "application/msgpack"
headers = [
{"Content-Type", mime_type},
{"authorization", "Basic " <> Base.encode64(@admin <> ":" <> @admin_pwd)}
]
{200, [initial_user]} = get(url, headers)
assert initial_user["active"]
result =
%{}
|> Map.put(:active, false)
|> Msgpax.pack!
|> patch(url <> "/ferigis", headers)
assert {204, :nobody} == result
{200, [initial_user]} = get(url, headers)
refute initial_user["active"]
result =
%{}
|> Map.put(:active, true)
|> Msgpax.pack!
|> patch(url <> "/ferigis", headers)
assert {204, :nobody} == result
{200, [initial_user]} = get(url, headers)
assert initial_user["active"]
end
test "updating user with wrong active value (not boolean) [JSON]" do
url = @base_url <> "/user"
mime_type = "application/json"
headers = [
{"Content-Type", mime_type},
{"authorization", "Basic " <> Base.encode64(@admin <> ":" <> @admin_pwd)}
]
{200, [initial_user]} = get(url, headers)
assert initial_user["active"]
result =
%{}
|> Map.put(:active, "wrong value")
|> Poison.encode!
|> patch(url <> "/ferigis", headers)
assert {422, :nobody} == result
{200, [initial_user]} = get(url, headers)
assert initial_user["active"]
end
test "updating user with wrong active value (not boolean) [MSGPACK]" do
url = @base_url <> "/user"
mime_type = "application/msgpack"
headers = [
{"Content-Type", mime_type},
{"authorization", "Basic " <> Base.encode64(@admin <> ":" <> @admin_pwd)}
]
{200, [initial_user]} = get(url, headers)
assert initial_user["active"]
result =
%{}
|> Map.put(:active, "wrong value")
|> Msgpax.pack!
|> patch(url <> "/ferigis", headers)
assert {422, :nobody} == result
{200, [initial_user]} = get(url, headers)
assert initial_user["active"]
end
test "updating user with wrong admin credentials [JSON]" do
url = @base_url <> "/user"
mime_type = "application/json"
headers = [
{"Content-Type", mime_type},
{"authorization", "Basic " <> Base.encode64(@admin <> ":" <> "wrongpassword")}
]
result =
%{}
|> Map.put(:active, false)
|> Poison.encode!
|> patch(url <> "/ferigis", headers)
assert {401, :nobody} == result
end
test "updating user with wrong admin credentials [MSGPACK]" do
url = @base_url <> "/user"
mime_type = "application/msgpack"
headers = [
{"Content-Type", mime_type},
{"authorization", "Basic " <> Base.encode64(@admin <> ":" <> "wrongpassword")}
]
result =
%{}
|> Map.put(:active, false)
|> Msgpax.pack!
|> patch(url <> "/ferigis", headers)
assert {401, :nobody} == result
end
test "updating user who doesn't exist [JSON]" do
url = @base_url <> "/user"
mime_type = "application/json"
headers = [
{"Content-Type", mime_type},
{"authorization", "Basic " <> Base.encode64(@admin <> ":" <> @admin_pwd)}
]
result =
%{}
|> Map.put(:active, true)
|> Poison.encode!
|> patch(url <> "/unnexistinguser", headers)
assert {404, :nobody} == result
end
test "updating user who doesn't exist [MSGPACK]" do
url = @base_url <> "/user"
mime_type = "application/msgpack"
headers = [
{"Content-Type", mime_type},
{"authorization", "Basic " <> Base.encode64(@admin <> ":" <> @admin_pwd)}
]
result =
%{}
|> Map.put(:active, true)
|> Msgpax.pack!
|> patch(url <> "/unnexistinguser", headers)
assert {404, :nobody} == result
end
# ----------------------------------------
# /blacklist/user Endpoint Tests
# ----------------------------------------
@ -745,4 +937,18 @@ defmodule Auth.APITest do
{response.status_code, body}
end
defp patch(data, url, headers) do
options = [ssl: [{:versions, [:'tlsv1.2']}], recv_timeout: 500]
{:ok, response} = HTTPoison.patch(url, data, headers, options)
body = case response.body do
"" ->
:nobody
_ ->
{:ok, body} = Poison.decode(response.body)
body
end
{response.status_code, body}
end
end