diff --git a/config/config.exs b/config/config.exs index 1c8e46b..5a4ef8f 100644 --- a/config/config.exs +++ b/config/config.exs @@ -14,7 +14,7 @@ config :org, Org.Endpoint, url: [host: "localhost"], root: Path.dirname(__DIR__), secret_key_base: "dbaUFzsX9uXxHHCvaccSgGphSF+a+z9WYnY/J9qjYToo0UUgXgYkTqBpPsBllbJv", - render_errors: [accepts: ~w(html json)], + render_errors: [accepts: ~w(json)], pubsub: [name: Org.PubSub, adapter: Phoenix.PubSub.PG2] @@ -27,11 +27,6 @@ config :logger, :console, # of this file so it overrides the configuration defined above. import_config "#{Mix.env}.exs" -# Configure phoenix generators -config :phoenix, :generators, - migration: false, - binary_id: true - config :org, GitHub, client_id: System.get_env("GITHUB_CLIENT_ID"), client_secret: System.get_env("GITHUB_CLIENT_SECRET"), diff --git a/config/dev.exs b/config/dev.exs index 33e331d..9d992db 100644 --- a/config/dev.exs +++ b/config/dev.exs @@ -8,7 +8,7 @@ use Mix.Config # with brunch.io to recompile .js and .css sources. config :org, Org.Endpoint, http: [port: 4000], - debug_errors: true, + debug_errors: false, code_reloader: true, check_origin: false, watchers: [node: ["node_modules/brunch/bin/brunch", "watch", "--stdin", diff --git a/mix.exs b/mix.exs index 1c20316..1c336c5 100644 --- a/mix.exs +++ b/mix.exs @@ -39,6 +39,7 @@ defmodule Org.Mixfile do {:gettext, "~> 0.11"}, {:oauth2, "~> 0.5"}, {:cowboy, "~> 1.0"}, + {:ex_machina, "~> 2.0", only: [:test]}, {:credo, "~> 0.7", only: [:dev, :test]}] end diff --git a/mix.lock b/mix.lock index 145ab57..3fea981 100644 --- a/mix.lock +++ b/mix.lock @@ -7,6 +7,7 @@ "db_connection": {:hex, :db_connection, "1.1.2", "2865c2a4bae0714e2213a0ce60a1b12d76a6efba0c51fbda59c9ab8d1accc7a8", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, optional: false]}, {:poolboy, "~> 1.5", [hex: :poolboy, optional: true]}, {:sbroker, "~> 1.0", [hex: :sbroker, optional: true]}]}, "decimal": {:hex, :decimal, "1.3.1", "157b3cedb2bfcb5359372a7766dd7a41091ad34578296e951f58a946fcab49c6", [:mix], []}, "ecto": {:hex, :ecto, "2.1.4", "d1ba932813ec0e0d9db481ef2c17777f1cefb11fc90fa7c142ff354972dfba7e", [:mix], [{:db_connection, "~> 1.1", [hex: :db_connection, optional: true]}, {:decimal, "~> 1.2", [hex: :decimal, optional: false]}, {:mariaex, "~> 0.8.0", [hex: :mariaex, optional: true]}, {:poison, "~> 2.2 or ~> 3.0", [hex: :poison, optional: true]}, {:poolboy, "~> 1.5", [hex: :poolboy, optional: false]}, {:postgrex, "~> 0.13.0", [hex: :postgrex, optional: true]}, {:sbroker, "~> 1.0", [hex: :sbroker, optional: true]}]}, + "ex_machina": {:hex, :ex_machina, "2.0.0", "ec284c6f57233729cea9319e083f66e613e82549f78eccdb2059aeba5d0df9f3", [:mix], [{:ecto, "~> 2.1", [hex: :ecto, optional: true]}]}, "fs": {:hex, :fs, "0.9.2", "ed17036c26c3f70ac49781ed9220a50c36775c6ca2cf8182d123b6566e49ec59", [:rebar], []}, "gettext": {:hex, :gettext, "0.13.1", "5e0daf4e7636d771c4c71ad5f3f53ba09a9ae5c250e1ab9c42ba9edccc476263", [:mix], []}, "hackney": {:hex, :hackney, "1.5.7", "f3809c0a17a3e523a865c65f6552b526f6b799acd0389803a05f88573ea26162", [:rebar3], [{:certifi, "0.4.0", [hex: :certifi, optional: false]}, {:idna, "1.2.0", [hex: :idna, optional: false]}, {:metrics, "1.0.1", [hex: :metrics, optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, optional: false]}, {:ssl_verify_fun, "1.1.0", [hex: :ssl_verify_fun, optional: false]}]}, diff --git a/priv/repo/migrations/1_create_user.exs b/priv/repo/migrations/00000000000001_create_user.exs similarity index 100% rename from priv/repo/migrations/1_create_user.exs rename to priv/repo/migrations/00000000000001_create_user.exs index feb3979..1b72c42 100644 --- a/priv/repo/migrations/1_create_user.exs +++ b/priv/repo/migrations/00000000000001_create_user.exs @@ -8,8 +8,8 @@ defmodule Org.Repo.Migrations.CreateUser do add :name, :string add :login, :string add :company, :string - add :location, :string add :created_at, :string + add :location, :string add :has_applied, :boolean, default: false, null: false add :role, :string add :comments, :string diff --git a/priv/repo/migrations/2_create_group.exs b/priv/repo/migrations/00000000000002_create_group.exs similarity index 100% rename from priv/repo/migrations/2_create_group.exs rename to priv/repo/migrations/00000000000002_create_group.exs diff --git a/priv/repo/seeds.exs b/priv/repo/seeds.exs index 8adb3f0..c29fe94 100644 --- a/priv/repo/seeds.exs +++ b/priv/repo/seeds.exs @@ -9,3 +9,21 @@ # # We recommend using the bang functions (`insert!`, `update!` # and so on) as they will fail if something goes wrong. + +alias Org.Repo +alias Org.User + +for admin <- ["Troy Mullaney", "Kevin Lanni"] do + Repo.get_by(User, name: admin) || + Repo.insert!(%User{name: admin, role: "admin"}) +end + +for member <- ["Dwyane Wade", "LeBron James"] do + Repo.get_by(User, name: member) || + Repo.insert!(%User{name: member, role: "member"}) +end + +for user <- ["John Doe", "Jane Doe"] do + Repo.get_by(User, name: user) || + Repo.insert!(%User{name: user, role: "user"}) +end diff --git a/test/controllers/admin/group_controller_test.exs b/test/controllers/admin/group_controller_test.exs index ab9db47..0e5b43b 100644 --- a/test/controllers/admin/group_controller_test.exs +++ b/test/controllers/admin/group_controller_test.exs @@ -1,66 +1,66 @@ -defmodule Org.Admin.GroupControllerTest do - use Org.ConnCase +# defmodule Org.Admin.GroupControllerTest do +# use Org.ConnCase - alias Org.Group - @valid_attrs %{description: "some content", title: "some content", url: "some content"} - @invalid_attrs %{} +# alias Org.Group +# @valid_attrs %{description: "some content", title: "some content", url: "some content"} +# @invalid_attrs %{} - test "lists all entries on index", %{conn: conn} do - conn = get conn, group_path(conn, :index) - assert html_response(conn, 200) =~ "Listing groups" - end +# test "lists all entries on index", %{conn: conn} do +# conn = get conn, group_path(conn, :index) +# assert html_response(conn, 200) =~ "Listing groups" +# end - test "renders form for new resources", %{conn: conn} do - conn = get conn, group_path(conn, :new) - assert html_response(conn, 200) =~ "New group" - end +# test "renders form for new resources", %{conn: conn} do +# conn = get conn, group_path(conn, :new) +# assert html_response(conn, 200) =~ "New group" +# end - test "creates resource and redirects when data is valid", %{conn: conn} do - conn = post conn, group_path(conn, :create), group: @valid_attrs - assert redirected_to(conn) == group_path(conn, :index) - assert Repo.get_by(Group, @valid_attrs) - end +# test "creates resource and redirects when data is valid", %{conn: conn} do +# conn = post conn, group_path(conn, :create), group: @valid_attrs +# assert redirected_to(conn) == group_path(conn, :index) +# assert Repo.get_by(Group, @valid_attrs) +# end - test "does not create resource and renders errors when data is invalid", %{conn: conn} do - conn = post conn, group_path(conn, :create), group: @invalid_attrs - assert html_response(conn, 200) =~ "New group" - end +# test "does not create resource and renders errors when data is invalid", %{conn: conn} do +# conn = post conn, group_path(conn, :create), group: @invalid_attrs +# assert html_response(conn, 200) =~ "New group" +# end - test "shows chosen resource", %{conn: conn} do - group = Repo.insert! %Group{} - conn = get conn, group_path(conn, :show, group) - assert html_response(conn, 200) =~ "Show group" - end +# test "shows chosen resource", %{conn: conn} do +# group = Repo.insert! %Group{} +# conn = get conn, group_path(conn, :show, group) +# assert html_response(conn, 200) =~ "Show group" +# end - test "renders page not found when id is nonexistent", %{conn: conn} do - assert_error_sent 404, fn -> - get conn, group_path(conn, :show, "11111111-1111-1111-1111-111111111111") - end - end +# test "renders page not found when id is nonexistent", %{conn: conn} do +# assert_error_sent 404, fn -> +# get conn, group_path(conn, :show, "11111111-1111-1111-1111-111111111111") +# end +# end - test "renders form for editing chosen resource", %{conn: conn} do - group = Repo.insert! %Group{} - conn = get conn, group_path(conn, :edit, group) - assert html_response(conn, 200) =~ "Edit group" - end +# test "renders form for editing chosen resource", %{conn: conn} do +# group = Repo.insert! %Group{} +# conn = get conn, group_path(conn, :edit, group) +# assert html_response(conn, 200) =~ "Edit group" +# end - test "updates chosen resource and redirects when data is valid", %{conn: conn} do - group = Repo.insert! %Group{} - conn = put conn, group_path(conn, :update, group), group: @valid_attrs - assert redirected_to(conn) == group_path(conn, :show, group) - assert Repo.get_by(Group, @valid_attrs) - end +# test "updates chosen resource and redirects when data is valid", %{conn: conn} do +# group = Repo.insert! %Group{} +# conn = put conn, group_path(conn, :update, group), group: @valid_attrs +# assert redirected_to(conn) == group_path(conn, :show, group) +# assert Repo.get_by(Group, @valid_attrs) +# end - test "does not update chosen resource and renders errors when data is invalid", %{conn: conn} do - group = Repo.insert! %Group{} - conn = put conn, group_path(conn, :update, group), group: @invalid_attrs - assert html_response(conn, 200) =~ "Edit group" - end +# test "does not update chosen resource and renders errors when data is invalid", %{conn: conn} do +# group = Repo.insert! %Group{} +# conn = put conn, group_path(conn, :update, group), group: @invalid_attrs +# assert html_response(conn, 200) =~ "Edit group" +# end - test "deletes chosen resource", %{conn: conn} do - group = Repo.insert! %Group{} - conn = delete conn, group_path(conn, :delete, group) - assert redirected_to(conn) == group_path(conn, :index) - refute Repo.get(Group, group.id) - end -end +# test "deletes chosen resource", %{conn: conn} do +# group = Repo.insert! %Group{} +# conn = delete conn, group_path(conn, :delete, group) +# assert redirected_to(conn) == group_path(conn, :index) +# refute Repo.get(Group, group.id) +# end +# end diff --git a/test/controllers/admin/user_controller_test.exs b/test/controllers/admin/user_controller_test.exs index 350dea4..4313b92 100644 --- a/test/controllers/admin/user_controller_test.exs +++ b/test/controllers/admin/user_controller_test.exs @@ -1,66 +1,66 @@ -defmodule Org.Admin.UserControllerTest do - use Org.ConnCase +# defmodule Org.Admin.UserControllerTest do +# use Org.ConnCase - alias Org.User - @valid_attrs %{email: "some content", name: "some content"} - @invalid_attrs %{} +# alias Org.User +# @valid_attrs %{email: "some content", name: "some content"} +# @invalid_attrs %{} - test "lists all entries on index", %{conn: conn} do - conn = get conn, user_path(conn, :index) - assert html_response(conn, 200) =~ "Listing users" - end +# test "lists all entries on index", %{conn: conn} do +# conn = get conn, user_path(conn, :index) +# assert html_response(conn, 200) =~ "Listing users" +# end - test "renders form for new resources", %{conn: conn} do - conn = get conn, user_path(conn, :new) - assert html_response(conn, 200) =~ "New user" - end +# test "renders form for new resources", %{conn: conn} do +# conn = get conn, user_path(conn, :new) +# assert html_response(conn, 200) =~ "New user" +# end - test "creates resource and redirects when data is valid", %{conn: conn} do - conn = post conn, user_path(conn, :create), user: @valid_attrs - assert redirected_to(conn) == user_path(conn, :index) - assert Repo.get_by(User, @valid_attrs) - end +# test "creates resource and redirects when data is valid", %{conn: conn} do +# conn = post conn, user_path(conn, :create), user: @valid_attrs +# assert redirected_to(conn) == user_path(conn, :index) +# assert Repo.get_by(User, @valid_attrs) +# end - test "does not create resource and renders errors when data is invalid", %{conn: conn} do - conn = post conn, user_path(conn, :create), user: @invalid_attrs - assert html_response(conn, 200) =~ "New user" - end +# test "does not create resource and renders errors when data is invalid", %{conn: conn} do +# conn = post conn, user_path(conn, :create), user: @invalid_attrs +# assert html_response(conn, 200) =~ "New user" +# end - test "shows chosen resource", %{conn: conn} do - user = Repo.insert! %User{} - conn = get conn, user_path(conn, :show, user) - assert html_response(conn, 200) =~ "Show user" - end +# test "shows chosen resource", %{conn: conn} do +# user = Repo.insert! %User{} +# conn = get conn, user_path(conn, :show, user) +# assert html_response(conn, 200) =~ "Show user" +# end - test "renders page not found when id is nonexistent", %{conn: conn} do - assert_error_sent 404, fn -> - get conn, user_path(conn, :show, "11111111-1111-1111-1111-111111111111") - end - end +# test "renders page not found when id is nonexistent", %{conn: conn} do +# assert_error_sent 404, fn -> +# get conn, user_path(conn, :show, "11111111-1111-1111-1111-111111111111") +# end +# end - test "renders form for editing chosen resource", %{conn: conn} do - user = Repo.insert! %User{} - conn = get conn, user_path(conn, :edit, user) - assert html_response(conn, 200) =~ "Edit user" - end +# test "renders form for editing chosen resource", %{conn: conn} do +# user = Repo.insert! %User{} +# conn = get conn, user_path(conn, :edit, user) +# assert html_response(conn, 200) =~ "Edit user" +# end - test "updates chosen resource and redirects when data is valid", %{conn: conn} do - user = Repo.insert! %User{} - conn = put conn, user_path(conn, :update, user), user: @valid_attrs - assert redirected_to(conn) == user_path(conn, :show, user) - assert Repo.get_by(User, @valid_attrs) - end +# test "updates chosen resource and redirects when data is valid", %{conn: conn} do +# user = Repo.insert! %User{} +# conn = put conn, user_path(conn, :update, user), user: @valid_attrs +# assert redirected_to(conn) == user_path(conn, :show, user) +# assert Repo.get_by(User, @valid_attrs) +# end - test "does not update chosen resource and renders errors when data is invalid", %{conn: conn} do - user = Repo.insert! %User{} - conn = put conn, user_path(conn, :update, user), user: @invalid_attrs - assert html_response(conn, 200) =~ "Edit user" - end +# test "does not update chosen resource and renders errors when data is invalid", %{conn: conn} do +# user = Repo.insert! %User{} +# conn = put conn, user_path(conn, :update, user), user: @invalid_attrs +# assert html_response(conn, 200) =~ "Edit user" +# end - test "deletes chosen resource", %{conn: conn} do - user = Repo.insert! %User{} - conn = delete conn, user_path(conn, :delete, user) - assert redirected_to(conn) == user_path(conn, :index) - refute Repo.get(User, user.id) - end -end +# test "deletes chosen resource", %{conn: conn} do +# user = Repo.insert! %User{} +# conn = delete conn, user_path(conn, :delete, user) +# assert redirected_to(conn) == user_path(conn, :index) +# refute Repo.get(User, user.id) +# end +# end diff --git a/test/controllers/group_controller_test.exs b/test/controllers/group_controller_test.exs index 43bf747..7b5e4cc 100644 --- a/test/controllers/group_controller_test.exs +++ b/test/controllers/group_controller_test.exs @@ -1,66 +1,66 @@ -defmodule Org.GroupControllerTest do - use Org.ConnCase +# defmodule Org.GroupControllerTest do +# use Org.ConnCase - alias Org.Group - @valid_attrs %{description: "some content", title: "some content", url: "some content"} - @invalid_attrs %{} +# alias Org.Group +# @valid_attrs %{description: "some content", title: "some content", url: "some content"} +# @invalid_attrs %{} - test "lists all entries on index", %{conn: conn} do - conn = get conn, group_path(conn, :index) - assert html_response(conn, 200) =~ "Listing groups" - end +# test "lists all entries on index", %{conn: conn} do +# conn = get conn, group_path(conn, :index) +# assert html_response(conn, 200) =~ "Listing groups" +# end - test "renders form for new resources", %{conn: conn} do - conn = get conn, group_path(conn, :new) - assert html_response(conn, 200) =~ "New group" - end +# test "renders form for new resources", %{conn: conn} do +# conn = get conn, group_path(conn, :new) +# assert html_response(conn, 200) =~ "New group" +# end - test "creates resource and redirects when data is valid", %{conn: conn} do - conn = post conn, group_path(conn, :create), group: @valid_attrs - assert redirected_to(conn) == group_path(conn, :index) - assert Repo.get_by(Group, @valid_attrs) - end +# test "creates resource and redirects when data is valid", %{conn: conn} do +# conn = post conn, group_path(conn, :create), group: @valid_attrs +# assert redirected_to(conn) == group_path(conn, :index) +# assert Repo.get_by(Group, @valid_attrs) +# end - test "does not create resource and renders errors when data is invalid", %{conn: conn} do - conn = post conn, group_path(conn, :create), group: @invalid_attrs - assert html_response(conn, 200) =~ "New group" - end +# test "does not create resource and renders errors when data is invalid", %{conn: conn} do +# conn = post conn, group_path(conn, :create), group: @invalid_attrs +# assert html_response(conn, 200) =~ "New group" +# end - test "shows chosen resource", %{conn: conn} do - group = Repo.insert! %Group{} - conn = get conn, group_path(conn, :show, group) - assert html_response(conn, 200) =~ "Show group" - end +# test "shows chosen resource", %{conn: conn} do +# group = Repo.insert! %Group{} +# conn = get conn, group_path(conn, :show, group) +# assert html_response(conn, 200) =~ "Show group" +# end - test "renders page not found when id is nonexistent", %{conn: conn} do - assert_error_sent 404, fn -> - get conn, group_path(conn, :show, "11111111-1111-1111-1111-111111111111") - end - end +# test "renders page not found when id is nonexistent", %{conn: conn} do +# assert_error_sent 404, fn -> +# get conn, group_path(conn, :show, "11111111-1111-1111-1111-111111111111") +# end +# end - test "renders form for editing chosen resource", %{conn: conn} do - group = Repo.insert! %Group{} - conn = get conn, group_path(conn, :edit, group) - assert html_response(conn, 200) =~ "Edit group" - end +# test "renders form for editing chosen resource", %{conn: conn} do +# group = Repo.insert! %Group{} +# conn = get conn, group_path(conn, :edit, group) +# assert html_response(conn, 200) =~ "Edit group" +# end - test "updates chosen resource and redirects when data is valid", %{conn: conn} do - group = Repo.insert! %Group{} - conn = put conn, group_path(conn, :update, group), group: @valid_attrs - assert redirected_to(conn) == group_path(conn, :show, group) - assert Repo.get_by(Group, @valid_attrs) - end +# test "updates chosen resource and redirects when data is valid", %{conn: conn} do +# group = Repo.insert! %Group{} +# conn = put conn, group_path(conn, :update, group), group: @valid_attrs +# assert redirected_to(conn) == group_path(conn, :show, group) +# assert Repo.get_by(Group, @valid_attrs) +# end - test "does not update chosen resource and renders errors when data is invalid", %{conn: conn} do - group = Repo.insert! %Group{} - conn = put conn, group_path(conn, :update, group), group: @invalid_attrs - assert html_response(conn, 200) =~ "Edit group" - end +# test "does not update chosen resource and renders errors when data is invalid", %{conn: conn} do +# group = Repo.insert! %Group{} +# conn = put conn, group_path(conn, :update, group), group: @invalid_attrs +# assert html_response(conn, 200) =~ "Edit group" +# end - test "deletes chosen resource", %{conn: conn} do - group = Repo.insert! %Group{} - conn = delete conn, group_path(conn, :delete, group) - assert redirected_to(conn) == group_path(conn, :index) - refute Repo.get(Group, group.id) - end -end +# test "deletes chosen resource", %{conn: conn} do +# group = Repo.insert! %Group{} +# conn = delete conn, group_path(conn, :delete, group) +# assert redirected_to(conn) == group_path(conn, :index) +# refute Repo.get(Group, group.id) +# end +# end diff --git a/test/controllers/page_controller_test.exs b/test/controllers/page_controller_test.exs index 38bf09c..fc7fa68 100644 --- a/test/controllers/page_controller_test.exs +++ b/test/controllers/page_controller_test.exs @@ -1,8 +1,8 @@ -defmodule Org.PageControllerTest do - use Org.ConnCase +# defmodule Org.PageControllerTest do +# use Org.ConnCase - test "GET /", %{conn: conn} do - conn = get conn, "/" - assert html_response(conn, 200) =~ "Welcome to Phoenix!" - end -end +# test "GET /", %{conn: conn} do +# conn = get conn, "/" +# assert html_response(conn, 200) =~ "Welcome to Phoenix!" +# end +# end diff --git a/test/controllers/user_controller_test.exs b/test/controllers/user_controller_test.exs index 67c0e43..4b9c71d 100644 --- a/test/controllers/user_controller_test.exs +++ b/test/controllers/user_controller_test.exs @@ -1,66 +1,93 @@ defmodule Org.UserControllerTest do use Org.ConnCase - alias Org.User - @valid_attrs %{email: "some content", name: "some content"} - @invalid_attrs %{} + alias Org.Api.UserView - test "lists all entries on index", %{conn: conn} do + setup %{conn: conn} = config do + if role = config[:login_as] do + user = insert(:user, role: role) + conn = assign(build_conn(), :current_user, user) + {:ok, conn: conn, user: user} + else + :ok + end + end + + # Tests for index/2 action + @tag login_as: "member" + test "index/2 lists all non-user role users", %{conn: conn, user: member} do + [admin, _] = [insert(:user, role: "admin"), insert(:user, role: "user")] + conn = get conn, user_path(conn, :index) + assert json_response(conn, 200) == render_json(UserView, "index.json", users: [member, admin]) + end + + @tag login_as: "admin" + test "index/2 lists all users", %{conn: conn, user: admin} do + [user, member] = [insert(:user, role: "user"), insert(:user, role: "member")] conn = get conn, user_path(conn, :index) - assert html_response(conn, 200) =~ "Listing users" + assert json_response(conn, 200) == render_json(UserView, "index.json", users: [admin, user, member]) end - test "renders form for new resources", %{conn: conn} do - conn = get conn, user_path(conn, :new) - assert html_response(conn, 200) =~ "New user" + test "returns a 401 when a user is not authorized", %{conn: conn} do + conn = get conn, user_path(conn, :index) + assert json_response(conn, 401) == render_json(Org.ErrorView, "401.json") end - test "creates resource and redirects when data is valid", %{conn: conn} do - conn = post conn, user_path(conn, :create), user: @valid_attrs - assert redirected_to(conn) == user_path(conn, :index) - assert Repo.get_by(User, @valid_attrs) + @tag login_as: "user" + test "index/2 returns a 403 when a \"user\" attempts to access it", %{conn: conn} do + conn = get conn, user_path(conn, :index) + assert json_response(conn, 403) == render_json(Org.ErrorView, "403.json") end - test "does not create resource and renders errors when data is invalid", %{conn: conn} do - conn = post conn, user_path(conn, :create), user: @invalid_attrs - assert html_response(conn, 200) =~ "New user" + # Tests for show/2 action + @tag login_as: "member" + test "show/2 renders a user", %{conn: conn, user: member} do + conn = get conn, user_path(conn, :show, member) + assert json_response(conn, 200) == render_json(UserView, "show.json", user: member) end - test "shows chosen resource", %{conn: conn} do - user = Repo.insert! %User{} - conn = get conn, user_path(conn, :show, user) - assert html_response(conn, 200) =~ "Show user" + @tag login_as: "member" + test "show/2 returns a 404 when id is nonexistent", %{conn: conn} do + assert_error_sent 404, fn -> + get conn, user_path(conn, :show, 1234) + end end - test "renders page not found when id is nonexistent", %{conn: conn} do + @tag login_as: "member" + test "show/2 returns a 404 when the id is of a \"user\" and the current_user is a member", %{conn: conn} do assert_error_sent 404, fn -> - get conn, user_path(conn, :show, "11111111-1111-1111-1111-111111111111") + user = insert(:user, role: "user") + get conn, user_path(conn, :show, user) end end - test "renders form for editing chosen resource", %{conn: conn} do - user = Repo.insert! %User{} - conn = get conn, user_path(conn, :edit, user) - assert html_response(conn, 200) =~ "Edit user" + # Tests for update/2 action + @tag login_as: "member" + test "update/2 returns an updated member", %{conn: conn, user: member} do + params = %{bio: "My new bio"} + conn = put conn, user_path(conn, :update, member), user: params + assert json_response(conn, 200)["data"]["bio"] == params.bio end - test "updates chosen resource and redirects when data is valid", %{conn: conn} do - user = Repo.insert! %User{} - conn = put conn, user_path(conn, :update, user), user: @valid_attrs - assert redirected_to(conn) == user_path(conn, :show, user) - assert Repo.get_by(User, @valid_attrs) + @tag login_as: "member" + test "update/2 returns a 403 when a member tries to update another member", %{conn: conn} do + assert_error_sent 403, fn -> + member = insert(:user, role: "member") + put conn, user_path(conn, :update, member), user: %{bio: "bio"} + end end - test "does not update chosen resource and renders errors when data is invalid", %{conn: conn} do - user = Repo.insert! %User{} - conn = put conn, user_path(conn, :update, user), user: @invalid_attrs - assert html_response(conn, 200) =~ "Edit user" + @tag login_as: "user" + test "update/2 returns a 403 when a user tries to access the action", %{conn: conn, user: user} do + conn = put conn, user_path(conn, :update, user) + assert json_response(conn, 403) == render_json(Org.ErrorView, "403.json") end - test "deletes chosen resource", %{conn: conn} do - user = Repo.insert! %User{} - conn = delete conn, user_path(conn, :delete, user) - assert redirected_to(conn) == user_path(conn, :index) - refute Repo.get(User, user.id) + @tag login_as: "member" + test "update/2 returns a 409 when provided an invalid changeset", %{conn: conn, user: member} do + conn = put conn, user_path(conn, :update, member), user: %{} + assert json_response(conn, 409) == render_json(Org.ErrorView, "409.json") end + + # Tests for #apply action end diff --git a/test/models/admin/group_test.exs b/test/models/admin/group_test.exs index e8e944c..ef85cc6 100644 --- a/test/models/admin/group_test.exs +++ b/test/models/admin/group_test.exs @@ -1,18 +1,18 @@ -defmodule Org.Admin.GroupTest do - use Org.ModelCase +# defmodule Org.Admin.GroupTest do +# use Org.ModelCase - alias Org.Group +# alias Org.Group - @valid_attrs %{description: "some content", title: "some content", url: "some content"} - @invalid_attrs %{} +# @valid_attrs %{description: "some content", title: "some content", url: "some content"} +# @invalid_attrs %{} - test "changeset with valid attributes" do - changeset = Group.changeset(%Group{}, @valid_attrs) - assert changeset.valid? - end +# test "changeset with valid attributes" do +# changeset = Group.changeset(%Group{}, @valid_attrs) +# assert changeset.valid? +# end - test "changeset with invalid attributes" do - changeset = Group.changeset(%Group{}, @invalid_attrs) - refute changeset.valid? - end -end +# test "changeset with invalid attributes" do +# changeset = Group.changeset(%Group{}, @invalid_attrs) +# refute changeset.valid? +# end +# end diff --git a/test/models/admin/user_test.exs b/test/models/admin/user_test.exs index 8349dc0..4a905c1 100644 --- a/test/models/admin/user_test.exs +++ b/test/models/admin/user_test.exs @@ -1,18 +1,18 @@ -defmodule Org.Admin.UserTest do - use Org.ModelCase +# defmodule Org.Admin.UserTest do +# use Org.ModelCase - alias Org.User +# alias Org.User - @valid_attrs %{email: "some content", name: "some content"} - @invalid_attrs %{} +# @valid_attrs %{email: "some content", name: "some content"} +# @invalid_attrs %{} - test "changeset with valid attributes" do - changeset = User.changeset(%User{}, @valid_attrs) - assert changeset.valid? - end +# test "changeset with valid attributes" do +# changeset = User.changeset(%User{}, @valid_attrs) +# assert changeset.valid? +# end - test "changeset with invalid attributes" do - changeset = User.changeset(%User{}, @invalid_attrs) - refute changeset.valid? - end -end +# test "changeset with invalid attributes" do +# changeset = User.changeset(%User{}, @invalid_attrs) +# refute changeset.valid? +# end +# end diff --git a/test/models/user_test.exs b/test/models/user_test.exs index 6f84a2b..7336989 100644 --- a/test/models/user_test.exs +++ b/test/models/user_test.exs @@ -6,13 +6,13 @@ defmodule Org.UserTest do @valid_attrs %{avatar: "some content", bio: "some content", blog: "some content", company: "some content", created_at: "some content", email: "some content", followers: 42, following: 42, github_id: 42, hireable: true, html_url: "some content", location: "some content", login: "some content", name: "some content", public_gists: 42, public_repos: 42, role: "some content", type: "some content"} @invalid_attrs %{} - test "changeset with valid attributes" do - changeset = User.changeset(%User{}, @valid_attrs) + test "registration_changeset with valid attributes" do + changeset = User.registration_changeset(%User{}, @valid_attrs) assert changeset.valid? end - test "changeset with invalid attributes" do - changeset = User.changeset(%User{}, @invalid_attrs) + test "registration_changeset with invalid attributes" do + changeset = User.registration_changeset(%User{}, @invalid_attrs) refute changeset.valid? end end diff --git a/test/plugs/auth_test.exs b/test/plugs/auth_test.exs new file mode 100644 index 0000000..2d0431a --- /dev/null +++ b/test/plugs/auth_test.exs @@ -0,0 +1,72 @@ +defmodule Org.Plugs.AuthTest do + use Org.ConnCase + alias Org.Plugs.Auth + alias Org.User + + setup %{conn: conn} do + conn = + conn + |> bypass_through(Org.Router, :api) + + {:ok, %{conn: conn}} + end + + test "call places user from session into assigns", %{conn: conn} do + user = insert(:user) + conn = + conn + |> get("/") + |> put_session(:current_user, user.id) + |> Auth.call([]) + + assert conn.assigns.current_user.id == user.id + end + + test "call with no session sets current_user assign to nil", %{conn: conn} do + conn = + conn + |> get("/") + |> Auth.call([]) + + assert conn.assigns.current_user == nil + end + + test "authenticated continues when current_user exists", %{conn: conn} do + conn = + conn + |> get("/") + |> assign(:current_user, %User{}) + |> Auth.authenticated([]) + + refute conn.halted + end + + test "authenticated halts when no current_user exists", %{conn: conn} do + conn = + conn + |> get("/") + |> Auth.authenticated([]) + + assert conn.halted + end + + test "authenticate_for_roles continues when the current_user matches the specified roles", %{conn: conn} do + conn = + conn + |> get("/") + |> assign(:current_user, %User{role: "member"}) + |> Auth.authenticate_for_roles(["member"]) + + refute conn.halted + end + + test "authenticate_for_roles halts when the current_user does not match the specified roles", %{conn: conn} do + conn = + conn + |> get("/") + |> assign(:current_user, %User{role: "member"}) + |> Auth.authenticate_for_roles(["admin"]) + + assert conn.halted + end +end diff --git a/test/support/conn_case.ex b/test/support/conn_case.ex index 09b1ede..a091a81 100644 --- a/test/support/conn_case.ex +++ b/test/support/conn_case.ex @@ -25,6 +25,8 @@ defmodule Org.ConnCase do import Ecto.Changeset import Ecto.Query + import Org.Factory + import Org.TestHelpers import Org.Router.Helpers # The default endpoint for testing @@ -36,7 +38,7 @@ defmodule Org.ConnCase do :ok = Ecto.Adapters.SQL.Sandbox.checkout(Org.Repo) unless tags[:async] do - Ecto.Adapters.SQL.Sandbox.mode(Org.Repo, {:shared, self()}) + Ecto.Adapters.SQL.Sandbox.mode(Org.Repo, {:shared, self()}) end {:ok, conn: Phoenix.ConnTest.build_conn()} diff --git a/test/support/factory.ex b/test/support/factory.ex new file mode 100644 index 0000000..ca0b93c --- /dev/null +++ b/test/support/factory.ex @@ -0,0 +1,10 @@ +defmodule Org.Factory do + use ExMachina.Ecto, repo: Org.Repo + + def user_factory do + %Org.User{ + name: "John Doe", + role: "member" + } + end +end diff --git a/test/support/model_case.ex b/test/support/model_case.ex index 7a6de43..2c1f4b1 100644 --- a/test/support/model_case.ex +++ b/test/support/model_case.ex @@ -22,6 +22,7 @@ defmodule Org.ModelCase do import Ecto.Changeset import Ecto.Query import Org.ModelCase + import Org.Factory end end diff --git a/test/support/test_helpers.ex b/test/support/test_helpers.ex new file mode 100644 index 0000000..805b557 --- /dev/null +++ b/test/support/test_helpers.ex @@ -0,0 +1,8 @@ +defmodule Org.TestHelpers do + def render_json(view, template, assigns \\ %{}) do + template + |> view.render(assigns) + |> Poison.encode! + |> Poison.decode! + end +end diff --git a/test/test_helper.exs b/test/test_helper.exs index 7841bed..02691be 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -2,3 +2,4 @@ ExUnit.start Ecto.Adapters.SQL.Sandbox.mode(Org.Repo, :manual) +{:ok, _} = Application.ensure_all_started(:ex_machina) diff --git a/test/views/api/user_view_test.exs b/test/views/api/user_view_test.exs new file mode 100644 index 0000000..6ea1ac5 --- /dev/null +++ b/test/views/api/user_view_test.exs @@ -0,0 +1,30 @@ +defmodule Org.Api.UserViewTest do + use Org.ModelCase + alias Org.Api.UserView + + test "user.json" do + user = insert(:user) + rendered_user = UserView.render("user.json", %{user: user}) + + assert rendered_user == %{ + name: user.name, + email: user.email, + role: user.role, + bio: user.bio + } + end + + test "index.json" do + user = insert(:user) + rendered_users = UserView.render("index.json", %{users: [user]}) + + assert rendered_users == %{data: [UserView.render("user.json", %{user: user})]} + end + + test "show.json" do + user = insert(:user) + rendered_user = UserView.render("show.json", %{user: user}) + + assert rendered_user == %{data: UserView.render("user.json", %{user: user})} + end +end diff --git a/test/views/error_view_test.exs b/test/views/error_view_test.exs index 45d928e..e27768d 100644 --- a/test/views/error_view_test.exs +++ b/test/views/error_view_test.exs @@ -1,21 +1,31 @@ defmodule Org.ErrorViewTest do use Org.ConnCase, async: true + alias Org.ErrorView + # Bring render/3 and render_to_string/3 for testing custom views import Phoenix.View test "renders 404.html" do - assert render_to_string(Org.ErrorView, "404.html", []) == + assert render_to_string(ErrorView, "404.html", []) == "Page not found" end test "render 500.html" do - assert render_to_string(Org.ErrorView, "500.html", []) == + assert render_to_string(ErrorView, "500.html", []) == "Internal server error" end + test "render 401.json" do + assert ErrorView.render("401.json", []) == %{message: "Unauthorized"} + end + + test "render 403.json" do + assert ErrorView.render("403.json", []) == %{message: "Forbidden"} + end + test "render any other" do - assert render_to_string(Org.ErrorView, "505.html", []) == + assert render_to_string(ErrorView, "505.html", []) == "Internal server error" end end diff --git a/web/controllers/admin/user_controller.ex b/web/controllers/admin/user_controller.ex deleted file mode 100644 index f1e66c3..0000000 --- a/web/controllers/admin/user_controller.ex +++ /dev/null @@ -1,67 +0,0 @@ -defmodule Org.Admin.UserController do - use Org.Web, :controller - - alias Org.User - - plug :scrub_params, "user" when action in [:create, :update] - - def index(conn, _params) do - users = Repo.all(User) - render(conn, "index.html", users: users) - end - - def new(conn, _params) do - changeset = User.changeset(%User{}) - render(conn, "new.html", changeset: changeset) - end - - def create(conn, %{"user" => user_params}) do - changeset = User.changeset(%User{}, user_params) - - case Repo.insert(changeset) do - {:ok, _user} -> - conn - |> put_flash(:info, "User created successfully.") - |> redirect(to: user_path(conn, :index)) - {:error, changeset} -> - render(conn, "new.html", changeset: changeset) - end - end - - def show(conn, %{"id" => id}) do - user = Repo.get!(User, id) - render(conn, "show.html", user: user) - end - - def edit(conn, %{"id" => id}) do - user = Repo.get!(User, id) - changeset = User.changeset(user) - render(conn, "edit.html", user: user, changeset: changeset) - end - - def update(conn, %{"id" => id, "user" => user_params}) do - user = Repo.get!(User, id) - changeset = User.changeset(user, user_params) - - case Repo.update(changeset) do - {:ok, user} -> - conn - |> put_flash(:info, "User updated successfully.") - |> redirect(to: user_path(conn, :show, user)) - {:error, changeset} -> - render(conn, "edit.html", user: user, changeset: changeset) - end - end - - def delete(conn, %{"id" => id}) do - user = Repo.get!(User, id) - - # Here we use delete! (with a bang) because we expect - # it to always work (and if it does not, it will raise). - Repo.delete!(user) - - conn - |> put_flash(:info, "User deleted successfully.") - |> redirect(to: user_path(conn, :index)) - end -end diff --git a/web/controllers/auth_controller.ex b/web/controllers/auth_controller.ex index c5a4189..e7fbe32 100644 --- a/web/controllers/auth_controller.ex +++ b/web/controllers/auth_controller.ex @@ -13,7 +13,6 @@ defmodule Org.AuthController do def delete(conn, _params) do conn - |> put_flash(:info, "You have been logged out!") |> configure_session(drop: true) |> redirect(to: "/") end @@ -38,10 +37,10 @@ defmodule Org.AuthController do |> redirect(to: "/") end - defp authorize_url!("github"), do: GitHub.authorize_url! + defp authorize_url!("github"), do: GitHub.authorize_url! defp authorize_url!(_), do: raise "No matching provider available" - defp get_token!("github", code), do: GitHub.get_token!(code: code) + defp get_token!("github", code), do: GitHub.get_token!(code: code) defp get_token!(_, _), do: raise "No matching provider available" defp get_user!("github", token) do @@ -69,11 +68,13 @@ defmodule Org.AuthController do end defp find_or_create_user(user) do - case Repo.get_by(User, github_id: user[:github_id]) do + user = case Repo.get_by(User, github_id: user[:github_id]) do nil -> %User{} # User not found, we build one user -> user # User exists, let's use it end - |> User.changeset(user) + + user + |> User.changeset |> Repo.insert_or_update! end end diff --git a/web/controllers/helpers.ex b/web/controllers/helpers.ex new file mode 100644 index 0000000..b0922dd --- /dev/null +++ b/web/controllers/helpers.ex @@ -0,0 +1,3 @@ +defmodule Org.Controller.Helpers do + def current_user(conn), do: conn.assigns.current_user +end diff --git a/web/controllers/user_controller.ex b/web/controllers/user_controller.ex index ccca9ae..2610b78 100644 --- a/web/controllers/user_controller.ex +++ b/web/controllers/user_controller.ex @@ -1,53 +1,38 @@ -defmodule Org.UserController do +defmodule Org.Api.UserController do use Org.Web, :controller + import Org.User.Permissions + import Org.Controller.Helpers + alias Org.User - plug :scrub_params, "user" when action in [:create, :update, :apply] + plug :authenticate_for_roles, ~w(admin member) when action in [:index, :show, :update] def index(conn, _params) do - users = Repo.all(from u in User, where: u.role != "user") - render(conn, "index.html", users: users) - end - - def create(conn, %{"user" => user_params}) do - changeset = User.changeset(%User{}, user_params) + users = + User + |> limit_for(current_user(conn).role) + |> Repo.all - case Repo.insert(changeset) do - {:ok, _user} -> - conn - |> put_flash(:info, "User created successfully.") - |> redirect(to: user_path(conn, :index)) - {:error, changeset} -> - render(conn, "new.html", changeset: changeset) - end + render(conn, "index.json", users: users) end def show(conn, %{"id" => id}) do - user = User - |> Repo.get!(id) - |> Repo.preload(:groups) - render(conn, "show.html", user: user) - end + user = + User + |> limit_for(current_user(conn).role) + |> Repo.get!(id) - def edit(conn, %{"id" => id}) do - user = Repo.get!(User, id) - changeset = User.changeset(user) - render(conn, "edit.html", user: user, changeset: changeset) + render(conn, "show.json", user: user) end def update(conn, %{"id" => id, "user" => user_params}) do - user = Repo.get!(User, id) - changeset = User.changeset(user, user_params) - - case Repo.update(changeset) do - {:ok, user} -> - conn - |> put_flash(:info, "User updated successfully.") - |> redirect(to: user_path(conn, :show, user)) - {:error, changeset} -> - render(conn, "edit.html", user: user, changeset: changeset) - end + User + |> limit_for(current_user(conn).role) + |> Repo.get!(id) + |> authorize!(:update, current_user(conn)) + |> User.changeset(user_params) + |> update_user(conn) end def apply(conn, %{"id" => id, "user" => user_params}) do @@ -66,13 +51,14 @@ defmodule Org.UserController do end end - def delete(conn, %{"id" => id}) do - user = Repo.get!(User, id) - - Repo.delete!(user) - - conn - |> put_flash(:info, "User deleted successfully.") - |> redirect(to: user_path(conn, :index)) + defp update_user(changeset, conn) do + case Repo.update(changeset) do + {:ok, user} -> + render(conn, "show.json", user: user) + {:error, %{errors: errors}} -> + conn + |> put_status(409) + |> render(Org.ErrorView, "409.json", errors: errors) + end end end diff --git a/web/exceptions/forbidden.ex b/web/exceptions/forbidden.ex new file mode 100644 index 0000000..c603edd --- /dev/null +++ b/web/exceptions/forbidden.ex @@ -0,0 +1,3 @@ +defmodule Org.Forbidden do + defexception [message: "Forbidden", plug_status: 403] +end diff --git a/web/models/user.ex b/web/models/user.ex index 454e383..a1e73a1 100644 --- a/web/models/user.ex +++ b/web/models/user.ex @@ -6,6 +6,7 @@ defmodule Org.User do field :bio, :string field :blog, :string field :company, :string + # This is the GitHub created_at date field :created_at, :string field :email, :string field :followers, :integer @@ -20,11 +21,11 @@ defmodule Org.User do field :public_repos, :integer field :role, :string, default: "user" field :type, :string - field :has_applied, :boolean, default: false + field :has_applied, :boolean, default: false, null: false field :comments, :string - has_many :groups, Org.Group - embeds_one :languages, Org.Language + # has_many :groups, Org.Group + # embeds_one :languages, Org.Language timestamps() end @@ -33,6 +34,12 @@ defmodule Org.User do Builds a changeset based on the `struct` and `params`. """ def changeset(struct, params \\ %{}) do + struct + |> cast(params, [:bio]) + |> validate_required([:bio]) + end + + def registration_changeset(struct, params \\ %{}) do struct |> cast(params, [:avatar, :bio, :blog, :company, :created_at, :email, :followers, :following, :hireable, :html_url, :github_id, :location, @@ -45,4 +52,8 @@ defmodule Org.User do ]) |> unique_constraint(:github_id) end + + def constants do + %{roles: ~w(user member admin)} + end end diff --git a/web/permissions/user_permissions.ex b/web/permissions/user_permissions.ex new file mode 100644 index 0000000..09b19fa --- /dev/null +++ b/web/permissions/user_permissions.ex @@ -0,0 +1,16 @@ +defmodule Org.User.Permissions do + import Ecto.Query + + alias Org.User + + def limit_for(User, "admin"), do: User + def limit_for(User, "member"), do: where(User, [u], u.role != "user") + def limit_for(User, _role), do: where(User, false) + + def authorize!(user, :update, %{role: "admin"}), + do: user + def authorize!(user, :update, %{role: "member"} = current_user), + do: if current_user.id == user.id, do: user, else: raise Org.Forbidden + def authorize!(_user, :update, _current_user), + do: raise Org.Forbidden +end diff --git a/web/plugs/auth.ex b/web/plugs/auth.ex new file mode 100644 index 0000000..c8d9cf3 --- /dev/null +++ b/web/plugs/auth.ex @@ -0,0 +1,46 @@ +defmodule Org.Plugs.Auth do + @behaviour Plug + + import Plug.Conn + import Phoenix.Controller + + alias Org.Repo + alias Org.User + + def init(default), do: default + + def call(conn, _opts) do + user_id = get_session(conn, :current_user) + + cond do + current_user = conn.assigns[:current_user] -> + conn + current_user = user_id && Repo.get(User, user_id) -> + assign(conn, :current_user, current_user) + true -> + assign(conn, :current_user, nil) + end + end + + def authenticated(conn, _opts) do + if conn.assigns.current_user do + conn + else + conn + |> put_status(401) + |> render(Org.ErrorView, "401.json", []) + |> halt() + end + end + + def authenticate_for_roles(conn, roles) do + if Enum.member?(roles, conn.assigns.current_user.role) do + conn + else + conn + |> put_status(403) + |> render(Org.ErrorView, "403.json", []) + |> halt() + end + end +end diff --git a/web/plugs/authenticated.ex b/web/plugs/authenticated.ex deleted file mode 100644 index 7fb2b93..0000000 --- a/web/plugs/authenticated.ex +++ /dev/null @@ -1,34 +0,0 @@ -defmodule Org.Plugs.Authenticated do - @behaviour Plug - - import Plug.Conn - import Phoenix.Controller - - alias Org.Repo - alias Org.User - - def init(default), do: default - - def call(conn, _) do - current_user = get_session(conn, :current_user) - - if current_user do - case Repo.get(User, current_user) do - nil -> conn - |> configure_session(drop: true) # Drop invalid user session - |> flash_and_redirect - user -> assign(conn, :current_user, user) - end - else - conn - |> flash_and_redirect - end - end - - defp flash_and_redirect(conn) do - conn - |> put_flash(:error, "Please sign in") - |> redirect(to: "/") - |> halt - end -end diff --git a/web/router.ex b/web/router.ex index 78d604e..2f35f73 100644 --- a/web/router.ex +++ b/web/router.ex @@ -7,25 +7,13 @@ defmodule Org.Router do plug :fetch_flash plug :protect_from_forgery plug :put_secure_browser_headers - plug Org.Plugs.AssignCurrentUser - end - - pipeline :authenticated do - plug Org.Plugs.Authenticated - end - - pipeline :auth_admin do - plug Org.Plugs.Authenticated - plug Org.Plugs.Authorized, ["admin"] - end - - pipeline :auth_member do - plug Org.Plugs.Authenticated - plug Org.Plugs.Authorized, ["member", "admin"] + plug Org.Plugs.Auth end pipeline :api do plug :accepts, ["json"] + plug :fetch_session + plug Org.Plugs.Auth end # Scope for OAuth2 routes @@ -37,19 +25,11 @@ defmodule Org.Router do delete "/logout", AuthController, :delete end - # Scope for admin-only routes - scope "/", Org.Admin do - pipe_through [:browser, :auth_admin] + scope "/api", Org.Api do + pipe_through [:api, :authenticated] - resources "/users", UserController, except: [:show, :new, :update] - resources "/groups", GroupController, except: [:index, :show] - end - - # Scope for member-only routes - scope "/", Org do - pipe_through [:browser, :auth_member] - - resources "/users", UserController, only: [:index, :show] + resources "/users", UserController, only: [:index, :show, :update] + put "/apply/:id", UserController, :apply end # Scope for authenticated-only routes (user is logged in) @@ -59,7 +39,6 @@ defmodule Org.Router do get "/apply", PageController, :apply put "/apply/:id", UserController, :apply get "/thanks", PageController, :thanks - resources "/users", UserController, only: [:index, :show, :update] end # Scope for all other routes @@ -70,9 +49,4 @@ defmodule Org.Router do get "/signin", PageController, :signin resources "/groups", GroupController, only: [:index, :show] end - - # Other scopes may use custom stacks. - # scope "/api", Org do - # pipe_through :api - # end end diff --git a/web/views/api/user_view.ex b/web/views/api/user_view.ex new file mode 100644 index 0000000..86efd62 --- /dev/null +++ b/web/views/api/user_view.ex @@ -0,0 +1,20 @@ +defmodule Org.Api.UserView do + use Org.Web, :view + + def render("index.json", %{users: users}) do + %{data: render_many(users, Org.Api.UserView, "user.json")} + end + + def render("show.json", %{user: user}) do + %{data: render_one(user, Org.Api.UserView, "user.json")} + end + + def render("user.json", %{user: user}) do + %{ + name: user.name, + email: user.email, + role: user.role, + bio: user.bio + } + end +end diff --git a/web/views/error_view.ex b/web/views/error_view.ex index 6492430..2e77c39 100644 --- a/web/views/error_view.ex +++ b/web/views/error_view.ex @@ -9,6 +9,26 @@ defmodule Org.ErrorView do "Internal server error" end + def render("401.json", _assigns) do + %{message: "Unauthorized"} + end + + def render("403.json", _assigns) do + %{message: "Forbidden"} + end + + def render("404.json", _assigns) do + %{message: "Not Found"} + end + + def render("409.json", _assigns) do + %{message: "Conflict"} + end + + def render("500.json", _assigns) do + %{message: "Internal Server Error"} + end + # In case no render clause matches or no # template is found, let's render it as 500 def template_not_found(_template, assigns) do diff --git a/web/views/user_view.ex b/web/views/user_view.ex deleted file mode 100644 index 70fa6e8..0000000 --- a/web/views/user_view.ex +++ /dev/null @@ -1,3 +0,0 @@ -defmodule Org.UserView do - use Org.Web, :view -end diff --git a/web/web.ex b/web/web.ex index 1c5cb18..d396576 100644 --- a/web/web.ex +++ b/web/web.ex @@ -23,9 +23,6 @@ defmodule Org.Web do import Ecto import Ecto.Changeset import Ecto.Query - - @primary_key {:id, :binary_id, autogenerate: true} - @foreign_key_type :binary_id end end @@ -39,6 +36,7 @@ defmodule Org.Web do import Org.Router.Helpers import Org.Gettext + import Org.Plugs.Auth, only: [authenticated: 2, authenticate_for_roles: 2] end end @@ -61,6 +59,7 @@ defmodule Org.Web do def router do quote do use Phoenix.Router + import Org.Plugs.Auth, only: [authenticated: 2] end end