[#67] deleting users endpoint

This commit is contained in:
Felipe Ripoll 2018-09-05 06:08:27 -06:00
parent e9eb5bf315
commit 323ce81506
9 changed files with 168 additions and 35 deletions

View File

@ -99,6 +99,20 @@ defmodule POABackend.Auth do
Repo.all(User)
end
@doc """
This function deletes the user associated with the user name passed as a parameter
"""
@spec delete_user(String.t) :: {:ok, :deleted} | {:error, :notfound}
def delete_user(user_name) do
case get_user(user_name) do
nil ->
{:error, :notfound}
user ->
Repo.delete!(user)
{:ok, :deleted}
end
end
@doc """
Authenticates an Admin
"""

View File

@ -107,7 +107,6 @@ defmodule POABackend.Auth.REST do
HTTP header | Values
-- | --
content-type | application/json or application/msgpack
authorization | Basic encodeBase64(adminname + : + password)
Response
@ -116,12 +115,11 @@ defmodule POABackend.Auth.REST do
-- | --
200 | Success: A list of users
401 | Authentication failed
415 | Unsupported Media Type (only application/json and application/msgpack allowed)
Example:
```
curl -i -X GET -H "Authorization: Basic YWRtaW4xOnBhc3N3b3JkMTIzNDU2Nzg=" -H "Content-Type: application/json" https://localhost:4003/user --insecure
curl -i -X GET -H "Authorization: Basic YWRtaW4xOnBhc3N3b3JkMTIzNDU2Nzg=" https://localhost:4003/user --insecure
HTTP/1.1 200 OK
server: Cowboy
@ -142,6 +140,36 @@ defmodule POABackend.Auth.REST do
}
```
## Delete User Endpoint
This Endpoint is needed in order to delete a user from the system.
`DELETE /user/:username`
HTTP header | Values
-- | --
authorization | Basic encodeBase64(adminname + : + password)
Response
CODE | Description
-- | --
204 | Success
401 | Authentication failed
404 | The user provided doesn't exist in the system
Example:
```
curl -i -X DELETE -H "Authorization: Basic YWRtaW4xOnBhc3N3b3JkMTIzNDU2Nzg=" https://localhost:4003/user/4uVIqWSf --insecure
HTTP/1.1 204 No Content
server: Cowboy
date: Tue, 04 Sep 2018 13:49:45 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

@ -9,7 +9,7 @@ defmodule POABackend.Auth.Router do
@token_default_ttl {1, :hour}
plug REST.Plugs.Accept, ["application/json", "application/msgpack"]
plug REST.Plugs.ContentType, ["application/json", "application/msgpack"]
plug Plug.Parsers, parsers: [Msgpax.PlugParser, :json], pass: ["application/msgpack", "application/json"], json_decoder: Poison
plug :match
plug :dispatch
@ -89,6 +89,24 @@ defmodule POABackend.Auth.Router do
end
end
delete "/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)
do
case Auth.delete_user(user_name) do
{:ok, :deleted} -> send_resp(conn, 204, "")
{:error, :notfound} -> send_resp(conn, 404, "")
end
else
_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),

View File

@ -248,7 +248,7 @@ defmodule POABackend.CustomHandler.REST do
alias POABackend.Protocol.DataType
alias POABackend.Protocol.Message
plug REST.Plugs.Accept, ["application/json", "application/msgpack"]
plug REST.Plugs.ContentType, ["application/json", "application/msgpack"]
plug Plug.Parsers, parsers: [Msgpax.PlugParser, :json], pass: ["application/msgpack", "application/json"], json_decoder: Poison
plug REST.Plugs.RequiredFields, ~w(id)
plug REST.Plugs.Authorization

View File

@ -1,25 +0,0 @@
defmodule POABackend.CustomHandler.REST.Plugs.Accept do
@moduledoc false
@behaviour Plug
def init(accept) do
accept
end
def call(conn, accept) do
import Plug.Conn
with {"content-type", content_type} <- List.keyfind(conn.req_headers, "content-type", 0),
true <- Enum.member?(accept, content_type)
do
conn
else
_error ->
conn
|> send_resp(415, "")
|> halt
end
end
end

View File

@ -0,0 +1,30 @@
defmodule POABackend.CustomHandler.REST.Plugs.ContentType do
@moduledoc false
alias Plug.Conn
@behaviour Plug
def init(accepted_content_type) do
accepted_content_type
end
def call(%Conn{method: method} = conn, accepted_content_type) when method in ["POST", "PUT"] do
import Plug.Conn
with {"content-type", content_type} <- List.keyfind(conn.req_headers, "content-type", 0),
true <- Enum.member?(accepted_content_type, content_type)
do
conn
else
_error ->
conn
|> send_resp(415, "")
|> halt
end
end
def call(conn, _) do
conn
end
end

View File

@ -319,9 +319,7 @@ defmodule Auth.APITest do
test "listing all the users stored" do
url = @base_url <> "/user"
mime_type = "application/msgpack"
headers = [
{"Content-Type", mime_type},
{"authorization", "Basic " <> Base.encode64(@admin <> ":" <> @admin_pwd)}
]
@ -339,9 +337,7 @@ defmodule Auth.APITest do
test "listing all the users stored with wrong Admin Credentials" do
url = @base_url <> "/user"
mime_type = "application/msgpack"
headers = [
{"Content-Type", mime_type},
{"authorization", "Basic " <> Base.encode64(@admin <> ":" <> "wrongpassword")}
]
@ -350,6 +346,47 @@ defmodule Auth.APITest do
assert {401, :nobody} == result
end
test "deleting a user which exists in the system" do
url = @base_url <> "/user"
headers = [
{"authorization", "Basic " <> Base.encode64(@admin <> ":" <> @admin_pwd)}
]
{200, [initial_user] = users} = get(url, headers)
assert length(users) == 1 # ferigis user is created at the begining of each test
assert initial_user["user"] == "ferigis"
assert {204, :nobody} == delete(url <> "/ferigis", headers)
assert {200, []} == get(url, headers)
end
test "deleting a user which doern't exist in the system" do
url = @base_url <> "/user"
headers = [
{"authorization", "Basic " <> Base.encode64(@admin <> ":" <> @admin_pwd)}
]
{200, [initial_user] = users} = get(url, headers)
assert length(users) == 1 # ferigis user is created at the begining of each test
assert initial_user["user"] == "ferigis"
assert {404, :nobody} == delete(url <> "/noexist", headers)
{200, ^users} = get(url, headers)
end
test "deleting a user with wrong admin credentials" do
url = @base_url <> "/user"
headers = [
{"authorization", "Basic " <> Base.encode64(@admin <> ":" <> "wrongpassword")}
]
assert {401, :nobody} == delete(url <> "/ferigis", headers)
end
# ----------------------------------------
# /blacklist/user Endpoint Tests
# ----------------------------------------
@ -693,4 +730,19 @@ defmodule Auth.APITest do
{response.status_code, body}
end
defp delete(url, headers) do
options = [ssl: [{:versions, [:'tlsv1.2']}], recv_timeout: 500]
{:ok, response} = HTTPoison.delete(url, headers, options)
body = case response.body do
"" ->
:nobody
_ ->
{:ok, body} = Poison.decode(response.body)
body
end
{response.status_code, body}
end
end

View File

@ -108,6 +108,22 @@ defmodule Auth.AuthTest do
assert Enum.member?(users, user2)
end
test "delete user" do
user_name = "ferigis"
password = "mypassword"
{:ok, user} = Auth.create_user(user_name, password)
assert [user] == Auth.list_users()
assert {:error, :notfound} == Auth.delete_user("thisuserdoesntexist")
assert [user] == Auth.list_users()
assert {:ok, :deleted} == Auth.delete_user(user_name)
assert [] == Auth.list_users()
end
# ----------------------------------------
# Token Tests
# ----------------------------------------

View File

@ -237,7 +237,7 @@ defmodule CustomHandler.RESTTest do
original_data = :original_data
assert(original_data == REST.Plugs.Accept.init(original_data))
assert(original_data == REST.Plugs.ContentType.init(original_data))
assert(original_data == REST.Plugs.Authorization.init(original_data))
assert(original_data == REST.Plugs.RequiredFields.init(original_data))
end