Skip to content

Commit

Permalink
Merge pull request #79 from epochtalk/board-controller-authorizations
Browse files Browse the repository at this point in the history
Board controller authorizations
  • Loading branch information
unenglishable authored Nov 7, 2023
2 parents 55c7cc0 + 0564914 commit 4dfd4fb
Show file tree
Hide file tree
Showing 6 changed files with 423 additions and 55 deletions.
26 changes: 22 additions & 4 deletions lib/epochtalk_server_web/controllers/board.ex
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ defmodule EpochtalkServerWeb.Controllers.Board do
Used to retrieve categorized boards
"""
def by_category(conn, attrs) do
with stripped <- Validate.cast(attrs, "stripped", :boolean, default: false),
with :ok <- ACL.allow!(conn, "boards.allCategories"),
stripped <- Validate.cast(attrs, "stripped", :boolean, default: false),
user_priority <- ACL.get_user_priority(conn),
board_mapping <- BoardMapping.all(stripped: stripped),
board_moderators <- BoardModerator.all(),
Expand All @@ -36,8 +37,11 @@ defmodule EpochtalkServerWeb.Controllers.Board do
Used to find a specific board
"""
def find(conn, attrs) do
with id <- Validate.cast(attrs, "id", :integer, required: true),
with :ok <- ACL.allow!(conn, "boards.find"),
id <- Validate.cast(attrs, "id", :integer, required: true),
user_priority <- ACL.get_user_priority(conn),
{:can_read, {:ok, true}} <-
{:can_read, Board.get_read_access_by_id(id, user_priority)},
board_mapping <- BoardMapping.all(),
board_moderators <- BoardModerator.all(),
{:board, [_board]} <-
Expand All @@ -49,8 +53,22 @@ defmodule EpochtalkServerWeb.Controllers.Board do
user_priority: user_priority
})
else
{:board, []} -> ErrorHelpers.render_json_error(conn, 400, "Error, board does not exist")
_ -> ErrorHelpers.render_json_error(conn, 400, "Error, cannot fetch boards")
# if user can't read board, return 404, user doesn't need to know hidden board exists
{:can_read, {:ok, false}} ->
ErrorHelpers.render_json_error(
conn,
404,
"Board not found"
)

{:can_read, {:error, :board_does_not_exist}} ->
ErrorHelpers.render_json_error(conn, 400, "Error, board does not exist")

{:board, []} ->
ErrorHelpers.render_json_error(conn, 400, "Error, board does not exist")

_ ->
ErrorHelpers.render_json_error(conn, 400, "Error, cannot fetch boards")
end
end

Expand Down
8 changes: 4 additions & 4 deletions test/epochtalk_server/models/mention_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,10 @@ defmodule Test.EpochtalkServer.Models.Mention do
assert result["mentioned_ids"] == []
end

@tag :banned
test "given a user without acl permission, errors", %{thread: thread} do
{:ok, user} = EpochtalkServer.Models.User.by_username("user")

test "given a user without acl permission, errors", %{
thread: thread,
users: %{private_user: user}
} do
attrs = %{
"thread" => thread.id,
"title" => "title",
Expand Down
10 changes: 5 additions & 5 deletions test/epochtalk_server/session_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,8 @@ defmodule Test.EpochtalkServer.Session do
@tag :banned
test "without remember me, handles baninfo ttl and ban_expiration (< 1 day ttl)", %{
conn: conn,
user_attrs: %{user: user_attrs},
users: %{user: user}
user_attrs: %{banned_user: user_attrs},
users: %{banned_user: user}
} do
pre_ban_baninfo_ttl = Redix.command!(:redix, ["TTL", "user:#{user.id}:baninfo"])

Expand Down Expand Up @@ -284,8 +284,8 @@ defmodule Test.EpochtalkServer.Session do
@tag :banned
test "with remember me, handles baninfo ttl and ban_expiration (< 4 weeks ttl)", %{
conn: conn,
user_attrs: %{user: user_attrs},
users: %{user: user}
user_attrs: %{banned_user: user_attrs},
users: %{banned_user: user}
} do
pre_ban_baninfo_ttl = Redix.command!(:redix, ["TTL", "user:#{user.id}:baninfo"])

Expand Down Expand Up @@ -447,7 +447,7 @@ defmodule Test.EpochtalkServer.Session do
assert banned_resource_user.ban_expiration == @max_date
end

@tag [authenticated: true, banned: true]
@tag [authenticated: :banned, banned: true]
test "given a banned user's id, when user is unbanned, deletes banned role", %{
conn: conn,
authed_user: authed_user
Expand Down
96 changes: 95 additions & 1 deletion test/epochtalk_server_web/controllers/board_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,17 @@ defmodule Test.EpochtalkServerWeb.Controllers.Board do
end

describe "by_category/2" do
@tag authenticated: :private
test "when authenticated with invalid permissions, raises InvalidPermission error", %{
conn: conn
} do
assert_raise InvalidPermission,
~r/^Forbidden, invalid permissions to perform this action/,
fn ->
get(conn, Routes.board_path(conn, :by_category))
end
end

test "finds all active boards", %{
conn: conn,
category: category,
Expand Down Expand Up @@ -130,7 +141,23 @@ defmodule Test.EpochtalkServerWeb.Controllers.Board do
assert response["message"] == "Error, board does not exist"
end

test "given an existing id, finds a board", %{conn: conn, parent_board: board} do
test "when unauthenticated, given an existing id above read access, errors", %{
conn: conn,
admin_board: admin_board
} do
response =
conn
|> get(Routes.board_path(conn, :find, admin_board.id))
|> json_response(404)

assert response["error"] == "Not Found"
assert response["message"] == "Board not found"
end

test "when unauthenticated, given an existing id within read access, finds a board", %{
conn: conn,
parent_board: board
} do
response =
conn
|> get(Routes.board_path(conn, :find, board.id))
Expand All @@ -146,6 +173,73 @@ defmodule Test.EpochtalkServerWeb.Controllers.Board do
assert response["disable_post_edit"] == board.meta["disable_post_edit"]
assert response["disable_signature"] == board.meta["disable_signature"]
end

@tag :authenticated
test "when authenticated, given an existing id above read access, errors", %{
conn: conn,
admin_board: admin_board
} do
response =
conn
|> get(Routes.board_path(conn, :find, admin_board.id))
|> json_response(404)

assert response["error"] == "Not Found"
assert response["message"] == "Board not found"
end

@tag :authenticated
test "when authenticated, given an existing id at read access, finds board", %{
conn: conn,
parent_board: board
} do
response =
conn
|> get(Routes.board_path(conn, :find, board.id))
|> json_response(200)

assert response["name"] == board.name
end

@tag authenticated: :admin
test "when authenticated as admin, given an existing id at read access, finds board", %{
conn: conn,
admin_board: admin_board
} do
response =
conn
|> get(Routes.board_path(conn, :find, admin_board.id))
|> json_response(200)

assert response["name"] == admin_board.name
end

@tag authenticated: :admin
test "when authenticated as admin, given an existing id above read access, errors", %{
conn: conn,
super_admin_board: super_admin_board
} do
response =
conn
|> get(Routes.board_path(conn, :find, super_admin_board.id))
|> json_response(404)

assert response["error"] == "Not Found"
assert response["message"] == "Board not found"
end

@tag authenticated: :super_admin
test "when authenticated as super admin, given an existing id at read access, finds board", %{
conn: conn,
super_admin_board: super_admin_board
} do
response =
conn
|> get(Routes.board_path(conn, :find, super_admin_board.id))
|> json_response(200)

assert response["name"] == super_admin_board.name
end
end

describe "slug_to_id/2" do
Expand Down
78 changes: 78 additions & 0 deletions test/seed/users.exs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,38 @@ test_admin_user_username = "admin"
test_admin_user_email = "[email protected]"
test_admin_user_password = "password"

test_global_mod_user_username = "globalmod"
test_global_mod_user_email = "[email protected]"
test_global_mod_user_password = "password"

test_mod_user_username = "mod"
test_mod_user_email = "[email protected]"
test_mod_user_password = "password"

test_user_username = "user"
test_user_email = "[email protected]"
test_user_password = "password"

test_patroller_user_username = "patroller"
test_patroller_user_email = "[email protected]"
test_patroller_user_password = "password"

test_newbie_user_username = "newbie"
test_newbie_user_email = "[email protected]"
test_newbie_user_password = "password"

test_banned_user_username = "banned"
test_banned_user_email = "[email protected]"
test_banned_user_password = "password"

test_anonymous_user_username = "anonymous"
test_anonymous_user_email = "[email protected]"
test_anonymous_user_password = "password"

test_private_user_username = "private"
test_private_user_email = "[email protected]"
test_private_user_password = "password"

test_no_login_user_username = "no_login"
test_no_login_user_email = "[email protected]"
test_no_login_user_password = "password"
Expand All @@ -30,12 +58,62 @@ build(:user,
)
|> with_role_id(2)

build(:user,
username: test_global_mod_user_username,
email: test_global_mod_user_email,
password: test_global_mod_user_password
)
|> with_role_id(3)

build(:user,
username: test_mod_user_username,
email: test_mod_user_email,
password: test_mod_user_password
)
|> with_role_id(4)

build(:user,
username: test_user_username,
email: test_user_email,
password: test_user_password
)

build(:user,
username: test_patroller_user_username,
email: test_patroller_user_email,
password: test_patroller_user_password
)
|> with_role_id(6)

build(:user,
username: test_newbie_user_username,
email: test_newbie_user_email,
password: test_newbie_user_password
)
|> with_role_id(7)

# TODO(akinsey): actually ban the user, this user only has banned role
build(:user,
username: test_banned_user_username,
email: test_banned_user_email,
password: test_banned_user_password
)
|> with_role_id(8)

build(:user,
username: test_anonymous_user_username,
email: test_anonymous_user_email,
password: test_anonymous_user_password
)
|> with_role_id(9)

build(:user,
username: test_private_user_username,
email: test_private_user_email,
password: test_private_user_password
)
|> with_role_id(10)

build(:user,
username: test_no_login_user_username,
email: test_no_login_user_email,
Expand Down
Loading

0 comments on commit 4dfd4fb

Please sign in to comment.