Phoenix skeleton
authorRoger Braun <roger@rogerbraun.net>
Fri, 17 Mar 2017 16:09:58 +0000 (17:09 +0100)
committerRoger Braun <roger@rogerbraun.net>
Fri, 17 Mar 2017 16:09:58 +0000 (17:09 +0100)
25 files changed:
.gitignore [new file with mode: 0644]
README.md [new file with mode: 0644]
config/config.exs [new file with mode: 0644]
config/dev.exs [new file with mode: 0644]
config/prod.exs [new file with mode: 0644]
config/test.exs [new file with mode: 0644]
lib/pleroma/application.ex [new file with mode: 0644]
lib/pleroma/repo.ex [new file with mode: 0644]
lib/pleroma/web/channels/user_socket.ex [new file with mode: 0644]
lib/pleroma/web/endpoint.ex [new file with mode: 0644]
lib/pleroma/web/gettext.ex [new file with mode: 0644]
lib/pleroma/web/router.ex [new file with mode: 0644]
lib/pleroma/web/views/error_helpers.ex [new file with mode: 0644]
lib/pleroma/web/views/error_view.ex [new file with mode: 0644]
lib/pleroma/web/web.ex [new file with mode: 0644]
mix.exs [new file with mode: 0644]
mix.lock [new file with mode: 0644]
priv/gettext/en/LC_MESSAGES/errors.po [new file with mode: 0644]
priv/gettext/errors.pot [new file with mode: 0644]
priv/repo/seeds.exs [new file with mode: 0644]
test/support/channel_case.ex [new file with mode: 0644]
test/support/conn_case.ex [new file with mode: 0644]
test/support/data_case.ex [new file with mode: 0644]
test/test_helper.exs [new file with mode: 0644]
test/web/views/error_view_test.exs [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..d26faf8
--- /dev/null
@@ -0,0 +1,16 @@
+# App artifacts
+/_build
+/db
+/deps
+/*.ez
+
+# Generated on crash by the VM
+erl_crash.dump
+
+# Files matching config/*.secret.exs pattern contain sensitive
+# data and you should not commit them into version control.
+#
+# Alternatively, you may comment the line below and commit the
+# secrets files as long as you replace their contents by environment
+# variables.
+/config/*.secret.exs
diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..3ccc175
--- /dev/null
+++ b/README.md
@@ -0,0 +1,19 @@
+# Pleroma
+
+To start your Phoenix server:
+
+  * Install dependencies with `mix deps.get`
+  * Create and migrate your database with `mix ecto.create && mix ecto.migrate`
+  * Start Phoenix endpoint with `mix phx.server`
+
+Now you can visit [`localhost:4000`](http://localhost:4000) from your browser.
+
+Ready to run in production? Please [check our deployment guides](http://www.phoenixframework.org/docs/deployment).
+
+## Learn more
+
+  * Official website: http://www.phoenixframework.org/
+  * Guides: http://phoenixframework.org/docs/overview
+  * Docs: https://hexdocs.pm/phoenix
+  * Mailing list: http://groups.google.com/group/phoenix-talk
+  * Source: https://github.com/phoenixframework/phoenix
diff --git a/config/config.exs b/config/config.exs
new file mode 100644 (file)
index 0000000..8eea4dd
--- /dev/null
@@ -0,0 +1,27 @@
+# This file is responsible for configuring your application
+# and its dependencies with the aid of the Mix.Config module.
+#
+# This configuration file is loaded before any dependency and
+# is restricted to this project.
+use Mix.Config
+
+# General application configuration
+config :pleroma,
+  ecto_repos: [Pleroma.Repo]
+
+# Configures the endpoint
+config :pleroma, Pleroma.Web.Endpoint,
+  url: [host: "localhost"],
+  secret_key_base: "aK4Abxf29xU9TTDKre9coZPUgevcVCFQJe/5xP/7Lt4BEif6idBIbjupVbOrbKxl",
+  render_errors: [view: Pleroma.Web.ErrorView, accepts: ~w(json)],
+  pubsub: [name: Pleroma.PubSub,
+           adapter: Phoenix.PubSub.PG2]
+
+# Configures Elixir's Logger
+config :logger, :console,
+  format: "$time $metadata[$level] $message\n",
+  metadata: [:request_id]
+
+# Import environment specific config. This must remain at the bottom
+# of this file so it overrides the configuration defined above.
+import_config "#{Mix.env}.exs"
diff --git a/config/dev.exs b/config/dev.exs
new file mode 100644 (file)
index 0000000..78f5437
--- /dev/null
@@ -0,0 +1,46 @@
+use Mix.Config
+
+# For development, we disable any cache and enable
+# debugging and code reloading.
+#
+# The watchers configuration can be used to run external
+# watchers to your application. For example, we use it
+# with brunch.io to recompile .js and .css sources.
+config :pleroma, Pleroma.Web.Endpoint,
+  http: [port: 4000],
+  debug_errors: true,
+  code_reloader: true,
+  check_origin: false,
+  watchers: []
+
+# ## SSL Support
+#
+# In order to use HTTPS in development, a self-signed
+# certificate can be generated by running the following
+# command from your terminal:
+#
+#     openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 -subj "/C=US/ST=Denial/L=Springfield/O=Dis/CN=www.example.com" -keyout priv/server.key -out priv/server.pem
+#
+# The `http:` config above can be replaced with:
+#
+#     https: [port: 4000, keyfile: "priv/server.key", certfile: "priv/server.pem"],
+#
+# If desired, both `http:` and `https:` keys can be
+# configured to run both http and https servers on
+# different ports.
+
+# Do not include metadata nor timestamps in development logs
+config :logger, :console, format: "[$level] $message\n"
+
+# Set a higher stacktrace during development. Avoid configuring such
+# in production as building large stacktraces may be expensive.
+config :phoenix, :stacktrace_depth, 20
+
+# Configure your database
+config :pleroma, Pleroma.Repo,
+  adapter: Ecto.Adapters.Postgres,
+  username: "postgres",
+  password: "postgres",
+  database: "pleroma_dev",
+  hostname: "localhost",
+  pool_size: 10
diff --git a/config/prod.exs b/config/prod.exs
new file mode 100644 (file)
index 0000000..732bab2
--- /dev/null
@@ -0,0 +1,64 @@
+use Mix.Config
+
+# For production, we often load configuration from external
+# sources, such as your system environment. For this reason,
+# you won't find the :http configuration below, but set inside
+# Pleroma.Web.Endpoint.load_from_system_env/1 dynamically.
+# Any dynamic configuration should be moved to such function.
+#
+# Don't forget to configure the url host to something meaningful,
+# Phoenix uses this information when generating URLs.
+#
+# Finally, we also include the path to a cache manifest
+# containing the digested version of static files. This
+# manifest is generated by the mix phoenix.digest task
+# which you typically run after static files are built.
+config :pleroma, Pleroma.Web.Endpoint,
+  on_init: {Pleroma.Web.Endpoint, :load_from_system_env, []},
+  url: [host: "example.com", port: 80],
+  cache_static_manifest: "priv/static/cache_manifest.json"
+
+# Do not print debug messages in production
+config :logger, level: :info
+
+# ## SSL Support
+#
+# To get SSL working, you will need to add the `https` key
+# to the previous section and set your `:url` port to 443:
+#
+#     config :pleroma, Pleroma.Web.Endpoint,
+#       ...
+#       url: [host: "example.com", port: 443],
+#       https: [:inet6,
+#               port: 443,
+#               keyfile: System.get_env("SOME_APP_SSL_KEY_PATH"),
+#               certfile: System.get_env("SOME_APP_SSL_CERT_PATH")]
+#
+# Where those two env variables return an absolute path to
+# the key and cert in disk or a relative path inside priv,
+# for example "priv/ssl/server.key".
+#
+# We also recommend setting `force_ssl`, ensuring no data is
+# ever sent via http, always redirecting to https:
+#
+#     config :pleroma, Pleroma.Web.Endpoint,
+#       force_ssl: [hsts: true]
+#
+# Check `Plug.SSL` for all available options in `force_ssl`.
+
+# ## Using releases
+#
+# If you are doing OTP releases, you need to instruct Phoenix
+# to start the server for all endpoints:
+#
+#     config :phoenix, :serve_endpoints, true
+#
+# Alternatively, you can configure exactly which server to
+# start per endpoint:
+#
+#     config :pleroma, Pleroma.Web.Endpoint, server: true
+#
+
+# Finally import the config/prod.secret.exs
+# which should be versioned separately.
+import_config "prod.secret.exs"
diff --git a/config/test.exs b/config/test.exs
new file mode 100644 (file)
index 0000000..bcd7af1
--- /dev/null
@@ -0,0 +1,19 @@
+use Mix.Config
+
+# We don't run a server during test. If one is required,
+# you can enable the server option below.
+config :pleroma, Pleroma.Web.Endpoint,
+  http: [port: 4001],
+  server: false
+
+# Print only warnings and errors during test
+config :logger, level: :warn
+
+# Configure your database
+config :pleroma, Pleroma.Repo,
+  adapter: Ecto.Adapters.Postgres,
+  username: "postgres",
+  password: "postgres",
+  database: "pleroma_test",
+  hostname: "localhost",
+  pool: Ecto.Adapters.SQL.Sandbox
diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex
new file mode 100644 (file)
index 0000000..e88a851
--- /dev/null
@@ -0,0 +1,24 @@
+defmodule Pleroma.Application do
+  use Application
+
+  # See http://elixir-lang.org/docs/stable/elixir/Application.html
+  # for more information on OTP Applications
+  def start(_type, _args) do
+    import Supervisor.Spec
+
+    # Define workers and child supervisors to be supervised
+    children = [
+      # Start the Ecto repository
+      supervisor(Pleroma.Repo, []),
+      # Start the endpoint when the application starts
+      supervisor(Pleroma.Web.Endpoint, []),
+      # Start your own worker by calling: Pleroma.Worker.start_link(arg1, arg2, arg3)
+      # worker(Pleroma.Worker, [arg1, arg2, arg3]),
+    ]
+
+    # See http://elixir-lang.org/docs/stable/elixir/Supervisor.html
+    # for other strategies and supported options
+    opts = [strategy: :one_for_one, name: Pleroma.Supervisor]
+    Supervisor.start_link(children, opts)
+  end
+end
diff --git a/lib/pleroma/repo.ex b/lib/pleroma/repo.ex
new file mode 100644 (file)
index 0000000..7cecd7b
--- /dev/null
@@ -0,0 +1,11 @@
+defmodule Pleroma.Repo do
+  use Ecto.Repo, otp_app: :pleroma
+
+  @doc """
+  Dynamically loads the repository url from the
+  DATABASE_URL environment variable.
+  """
+  def init(_, opts) do
+    {:ok, Keyword.put(opts, :url, System.get_env("DATABASE_URL"))}
+  end
+end
diff --git a/lib/pleroma/web/channels/user_socket.ex b/lib/pleroma/web/channels/user_socket.ex
new file mode 100644 (file)
index 0000000..7aa8e55
--- /dev/null
@@ -0,0 +1,37 @@
+defmodule Pleroma.Web.UserSocket do
+  use Phoenix.Socket
+
+  ## Channels
+  # channel "room:*", Pleroma.Web.RoomChannel
+
+  ## Transports
+  transport :websocket, Phoenix.Transports.WebSocket
+  # transport :longpoll, Phoenix.Transports.LongPoll
+
+  # Socket params are passed from the client and can
+  # be used to verify and authenticate a user. After
+  # verification, you can put default assigns into
+  # the socket that will be set for all channels, ie
+  #
+  #     {:ok, assign(socket, :user_id, verified_user_id)}
+  #
+  # To deny connection, return `:error`.
+  #
+  # See `Phoenix.Token` documentation for examples in
+  # performing token verification on connect.
+  def connect(_params, socket) do
+    {:ok, socket}
+  end
+
+  # Socket id's are topics that allow you to identify all sockets for a given user:
+  #
+  #     def id(socket), do: "user_socket:#{socket.assigns.user_id}"
+  #
+  # Would allow you to broadcast a "disconnect" event and terminate
+  # all active sockets and channels for a given user:
+  #
+  #     Pleroma.Web.Endpoint.broadcast("user_socket:#{user.id}", "disconnect", %{})
+  #
+  # Returning `nil` makes this socket anonymous.
+  def id(_socket), do: nil
+end
diff --git a/lib/pleroma/web/endpoint.ex b/lib/pleroma/web/endpoint.ex
new file mode 100644 (file)
index 0000000..a79b0dc
--- /dev/null
@@ -0,0 +1,52 @@
+defmodule Pleroma.Web.Endpoint do
+  use Phoenix.Endpoint, otp_app: :pleroma
+
+  socket "/socket", Pleroma.Web.UserSocket
+
+  # Serve at "/" the static files from "priv/static" directory.
+  #
+  # You should set gzip to true if you are running phoenix.digest
+  # when deploying your static files in production.
+  plug Plug.Static,
+    at: "/", from: :pleroma, gzip: false,
+    only: ~w(css fonts images js favicon.ico robots.txt)
+
+  # Code reloading can be explicitly enabled under the
+  # :code_reloader configuration of your endpoint.
+  if code_reloading? do
+    plug Phoenix.CodeReloader
+  end
+
+  plug Plug.RequestId
+  plug Plug.Logger
+
+  plug Plug.Parsers,
+    parsers: [:urlencoded, :multipart, :json],
+    pass: ["*/*"],
+    json_decoder: Poison
+
+  plug Plug.MethodOverride
+  plug Plug.Head
+
+  # The session will be stored in the cookie and signed,
+  # this means its contents can be read but not tampered with.
+  # Set :encryption_salt if you would also like to encrypt it.
+  plug Plug.Session,
+    store: :cookie,
+    key: "_pleroma_key",
+    signing_salt: "CqaoopA2"
+
+  plug Pleroma.Web.Router
+
+  @doc """
+  Dynamically loads configuration from the system environment
+  on startup.
+
+  It receives the endpoint configuration from the config files
+  and must return the updated configuration.
+  """
+  def load_from_system_env(config) do
+    port = System.get_env("PORT") || raise "expected the PORT environment variable to be set"
+    {:ok, Keyword.put(config, :http, [:inet6, port: port])}
+  end
+end
diff --git a/lib/pleroma/web/gettext.ex b/lib/pleroma/web/gettext.ex
new file mode 100644 (file)
index 0000000..5015455
--- /dev/null
@@ -0,0 +1,24 @@
+defmodule Pleroma.Web.Gettext do
+  @moduledoc """
+  A module providing Internationalization with a gettext-based API.
+
+  By using [Gettext](https://hexdocs.pm/gettext),
+  your module gains a set of macros for translations, for example:
+
+      import Pleroma.Web.Gettext
+
+      # Simple translation
+      gettext "Here is the string to translate"
+
+      # Plural translation
+      ngettext "Here is the string to translate",
+               "Here are the strings to translate",
+               3
+
+      # Domain-based translation
+      dgettext "errors", "Here is the error message to translate"
+
+  See the [Gettext Docs](https://hexdocs.pm/gettext) for detailed usage.
+  """
+  use Gettext, otp_app: :pleroma
+end
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
new file mode 100644 (file)
index 0000000..e0f1ac1
--- /dev/null
@@ -0,0 +1,11 @@
+defmodule Pleroma.Web.Router do
+  use Pleroma.Web, :router
+
+  pipeline :api do
+    plug :accepts, ["json"]
+  end
+
+  scope "/api", Pleroma.Web do
+    pipe_through :api
+  end
+end
diff --git a/lib/pleroma/web/views/error_helpers.ex b/lib/pleroma/web/views/error_helpers.ex
new file mode 100644 (file)
index 0000000..3981b27
--- /dev/null
@@ -0,0 +1,29 @@
+defmodule Pleroma.Web.ErrorHelpers do
+  @moduledoc """
+  Conveniences for translating and building error messages.
+  """
+
+  @doc """
+  Translates an error message using gettext.
+  """
+  def translate_error({msg, opts}) do
+    # Because error messages were defined within Ecto, we must
+    # call the Gettext module passing our Gettext backend. We
+    # also use the "errors" domain as translations are placed
+    # in the errors.po file.
+    # Ecto will pass the :count keyword if the error message is
+    # meant to be pluralized.
+    # On your own code and templates, depending on whether you
+    # need the message to be pluralized or not, this could be
+    # written simply as:
+    #
+    #     dngettext "errors", "1 file", "%{count} files", count
+    #     dgettext "errors", "is invalid"
+    #
+    if count = opts[:count] do
+      Gettext.dngettext(Pleroma.Web.Gettext, "errors", msg, msg, count, opts)
+    else
+      Gettext.dgettext(Pleroma.Web.Gettext, "errors", msg, opts)
+    end
+  end
+end
diff --git a/lib/pleroma/web/views/error_view.ex b/lib/pleroma/web/views/error_view.ex
new file mode 100644 (file)
index 0000000..6c589d3
--- /dev/null
@@ -0,0 +1,17 @@
+defmodule Pleroma.Web.ErrorView do
+  use Pleroma.Web, :view
+
+  def render("404.json", _assigns) do
+    %{errors: %{detail: "Page not found"}}
+  end
+
+  def render("500.json", _assigns) do
+    %{errors: %{detail: "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
+    render "500.json", assigns
+  end
+end
diff --git a/lib/pleroma/web/web.ex b/lib/pleroma/web/web.ex
new file mode 100644 (file)
index 0000000..f392af2
--- /dev/null
@@ -0,0 +1,63 @@
+defmodule Pleroma.Web do
+  @moduledoc """
+  A module that keeps using definitions for controllers,
+  views and so on.
+
+  This can be used in your application as:
+
+      use Pleroma.Web, :controller
+      use Pleroma.Web, :view
+
+  The definitions below will be executed for every view,
+  controller, etc, so keep them short and clean, focused
+  on imports, uses and aliases.
+
+  Do NOT define functions inside the quoted expressions
+  below.
+  """
+
+  def controller do
+    quote do
+      use Phoenix.Controller, namespace: Pleroma.Web
+      import Plug.Conn
+      import Pleroma.Web.Router.Helpers
+      import Pleroma.Web.Gettext
+    end
+  end
+
+  def view do
+    quote do
+      use Phoenix.View, root: "lib/pleroma/web/templates",
+                        namespace: Pleroma.Web
+
+      # Import convenience functions from controllers
+      import Phoenix.Controller, only: [get_csrf_token: 0, get_flash: 2, view_module: 1]
+
+      import Pleroma.Web.Router.Helpers
+      import Pleroma.Web.ErrorHelpers
+      import Pleroma.Web.Gettext
+    end
+  end
+
+  def router do
+    quote do
+      use Phoenix.Router
+      import Plug.Conn
+      import Phoenix.Controller
+    end
+  end
+
+  def channel do
+    quote do
+      use Phoenix.Channel
+      import Pleroma.Web.Gettext
+    end
+  end
+
+  @doc """
+  When used, dispatch to the appropriate controller/view/etc.
+  """
+  defmacro __using__(which) when is_atom(which) do
+    apply(__MODULE__, which, [])
+  end
+end
diff --git a/mix.exs b/mix.exs
new file mode 100644 (file)
index 0000000..f38ce95
--- /dev/null
+++ b/mix.exs
@@ -0,0 +1,50 @@
+defmodule Pleroma.Mixfile do
+  use Mix.Project
+
+  def project do
+    [app: :pleroma,
+     version: "0.0.1",
+     elixir: "~> 1.4",
+     elixirc_paths: elixirc_paths(Mix.env),
+     compilers: [:phoenix, :gettext] ++ Mix.compilers,
+     start_permanent: Mix.env == :prod,
+     aliases: aliases(),
+     deps: deps()]
+  end
+
+  # Configuration for the OTP application.
+  #
+  # Type `mix help compile.app` for more information.
+  def application do
+    [mod: {Pleroma.Application, []},
+     extra_applications: [:logger, :runtime_tools]]
+  end
+
+  # Specifies which paths to compile per environment.
+  defp elixirc_paths(:test), do: ["lib", "test/support"]
+  defp elixirc_paths(_),     do: ["lib"]
+
+  # Specifies your project dependencies.
+  #
+  # Type `mix help deps` for examples and options.
+  defp deps do
+    [{:phoenix, "~> 1.3.0-rc"},
+     {:phoenix_pubsub, "~> 1.0"},
+     {:phoenix_ecto, "~> 3.2"},
+     {:postgrex, ">= 0.0.0"},
+     {:gettext, "~> 0.11"},
+     {:cowboy, "~> 1.0"}]
+  end
+
+  # Aliases are shortcuts or tasks specific to the current project.
+  # For example, to create, migrate and run the seeds file at once:
+  #
+  #     $ mix ecto.setup
+  #
+  # See the documentation for `Mix` for more info on aliases.
+  defp aliases do
+    ["ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
+     "ecto.reset": ["ecto.drop", "ecto.setup"],
+     "test": ["ecto.create --quiet", "ecto.migrate", "test"]]
+  end
+end
diff --git a/mix.lock b/mix.lock
new file mode 100644 (file)
index 0000000..87383cc
--- /dev/null
+++ b/mix.lock
@@ -0,0 +1,16 @@
+%{"connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], []},
+  "cowboy": {:hex, :cowboy, "1.1.2", "61ac29ea970389a88eca5a65601460162d370a70018afe6f949a29dca91f3bb0", [:rebar3], [{:cowlib, "~> 1.0.2", [hex: :cowlib, optional: false]}, {:ranch, "~> 1.3.2", [hex: :ranch, optional: false]}]},
+  "cowlib": {:hex, :cowlib, "1.0.2", "9d769a1d062c9c3ac753096f868ca121e2730b9a377de23dec0f7e08b1df84ee", [:make], []},
+  "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]}]},
+  "gettext": {:hex, :gettext, "0.13.1", "5e0daf4e7636d771c4c71ad5f3f53ba09a9ae5c250e1ab9c42ba9edccc476263", [:mix], []},
+  "mime": {:hex, :mime, "1.1.0", "01c1d6f4083d8aa5c7b8c246ade95139620ef8effb009edde934e0ec3b28090a", [:mix], []},
+  "phoenix": {:hex, :phoenix, "1.3.0-rc.1", "0d04948a4bd24823f101024c07b6a4d35e58f1fd92a465c1bc75dd37acd1041a", [:mix], [{:cowboy, "~> 1.0", [hex: :cowboy, optional: true]}, {:phoenix_pubsub, "~> 1.0", [hex: :phoenix_pubsub, optional: false]}, {:plug, "~> 1.3.2 or ~> 1.4", [hex: :plug, optional: false]}, {:poison, "~> 2.2 or ~> 3.0", [hex: :poison, optional: false]}]},
+  "phoenix_ecto": {:hex, :phoenix_ecto, "3.2.3", "450c749876ff1de4a78fdb305a142a76817c77a1cd79aeca29e5fc9a6c630b26", [:mix], [{:ecto, "~> 2.1", [hex: :ecto, optional: false]}, {:phoenix_html, "~> 2.9", [hex: :phoenix_html, optional: true]}, {:plug, "~> 1.0", [hex: :plug, optional: false]}]},
+  "phoenix_pubsub": {:hex, :phoenix_pubsub, "1.0.1", "c10ddf6237007c804bf2b8f3c4d5b99009b42eca3a0dfac04ea2d8001186056a", [:mix], []},
+  "plug": {:hex, :plug, "1.3.4", "b4ef3a383f991bfa594552ded44934f2a9853407899d47ecc0481777fb1906f6", [:mix], [{:cowboy, "~> 1.0.1 or ~> 1.1", [hex: :cowboy, optional: true]}, {:mime, "~> 1.0", [hex: :mime, optional: false]}]},
+  "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], []},
+  "poolboy": {:hex, :poolboy, "1.5.1", "6b46163901cfd0a1b43d692657ed9d7e599853b3b21b95ae5ae0a777cf9b6ca8", [:rebar], []},
+  "postgrex": {:hex, :postgrex, "0.13.2", "2b88168fc6a5456a27bfb54ccf0ba4025d274841a7a3af5e5deb1b755d95154e", [:mix], [{:connection, "~> 1.0", [hex: :connection, optional: false]}, {:db_connection, "~> 1.1", [hex: :db_connection, optional: false]}, {:decimal, "~> 1.0", [hex: :decimal, optional: false]}]},
+  "ranch": {:hex, :ranch, "1.3.2", "e4965a144dc9fbe70e5c077c65e73c57165416a901bd02ea899cfd95aa890986", [:rebar3], []}}
diff --git a/priv/gettext/en/LC_MESSAGES/errors.po b/priv/gettext/en/LC_MESSAGES/errors.po
new file mode 100644 (file)
index 0000000..2211c98
--- /dev/null
@@ -0,0 +1,93 @@
+## `msgid`s in this file come from POT (.pot) files.
+##
+## Do not add, change, or remove `msgid`s manually here as
+## they're tied to the ones in the corresponding POT file
+## (with the same domain).
+##
+## Use `mix gettext.extract --merge` or `mix gettext.merge`
+## to merge POT files into PO files.
+msgid ""
+msgstr ""
+"Language: en\n"
+
+## From Ecto.Changeset.cast/4
+msgid "can't be blank"
+msgstr ""
+
+## From Ecto.Changeset.unique_constraint/3
+msgid "has already been taken"
+msgstr ""
+
+## From Ecto.Changeset.put_change/3
+msgid "is invalid"
+msgstr ""
+
+## From Ecto.Changeset.validate_format/3
+msgid "has invalid format"
+msgstr ""
+
+## From Ecto.Changeset.validate_subset/3
+msgid "has an invalid entry"
+msgstr ""
+
+## From Ecto.Changeset.validate_exclusion/3
+msgid "is reserved"
+msgstr ""
+
+## From Ecto.Changeset.validate_confirmation/3
+msgid "does not match confirmation"
+msgstr ""
+
+## From Ecto.Changeset.no_assoc_constraint/3
+msgid "is still associated with this entry"
+msgstr ""
+
+msgid "are still associated with this entry"
+msgstr ""
+
+## From Ecto.Changeset.validate_length/3
+msgid "should be %{count} character(s)"
+msgid_plural "should be %{count} character(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should have %{count} item(s)"
+msgid_plural "should have %{count} item(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should be at least %{count} character(s)"
+msgid_plural "should be at least %{count} character(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should have at least %{count} item(s)"
+msgid_plural "should have at least %{count} item(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should be at most %{count} character(s)"
+msgid_plural "should be at most %{count} character(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should have at most %{count} item(s)"
+msgid_plural "should have at most %{count} item(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+## From Ecto.Changeset.validate_number/3
+msgid "must be less than %{number}"
+msgstr ""
+
+msgid "must be greater than %{number}"
+msgstr ""
+
+msgid "must be less than or equal to %{number}"
+msgstr ""
+
+msgid "must be greater than or equal to %{number}"
+msgstr ""
+
+msgid "must be equal to %{number}"
+msgstr ""
diff --git a/priv/gettext/errors.pot b/priv/gettext/errors.pot
new file mode 100644 (file)
index 0000000..a964f84
--- /dev/null
@@ -0,0 +1,91 @@
+## This file is a PO Template file.
+##
+## `msgid`s here are often extracted from source code.
+## Add new translations manually only if they're dynamic
+## translations that can't be statically extracted.
+##
+## Run `mix gettext.extract` to bring this file up to
+## date. Leave `msgstr`s empty as changing them here as no
+## effect: edit them in PO (`.po`) files instead.
+
+## From Ecto.Changeset.cast/4
+msgid "can't be blank"
+msgstr ""
+
+## From Ecto.Changeset.unique_constraint/3
+msgid "has already been taken"
+msgstr ""
+
+## From Ecto.Changeset.put_change/3
+msgid "is invalid"
+msgstr ""
+
+## From Ecto.Changeset.validate_format/3
+msgid "has invalid format"
+msgstr ""
+
+## From Ecto.Changeset.validate_subset/3
+msgid "has an invalid entry"
+msgstr ""
+
+## From Ecto.Changeset.validate_exclusion/3
+msgid "is reserved"
+msgstr ""
+
+## From Ecto.Changeset.validate_confirmation/3
+msgid "does not match confirmation"
+msgstr ""
+
+## From Ecto.Changeset.no_assoc_constraint/3
+msgid "is still associated with this entry"
+msgstr ""
+
+msgid "are still associated with this entry"
+msgstr ""
+
+## From Ecto.Changeset.validate_length/3
+msgid "should be %{count} character(s)"
+msgid_plural "should be %{count} character(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should have %{count} item(s)"
+msgid_plural "should have %{count} item(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should be at least %{count} character(s)"
+msgid_plural "should be at least %{count} character(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should have at least %{count} item(s)"
+msgid_plural "should have at least %{count} item(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should be at most %{count} character(s)"
+msgid_plural "should be at most %{count} character(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should have at most %{count} item(s)"
+msgid_plural "should have at most %{count} item(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+## From Ecto.Changeset.validate_number/3
+msgid "must be less than %{number}"
+msgstr ""
+
+msgid "must be greater than %{number}"
+msgstr ""
+
+msgid "must be less than or equal to %{number}"
+msgstr ""
+
+msgid "must be greater than or equal to %{number}"
+msgstr ""
+
+msgid "must be equal to %{number}"
+msgstr ""
diff --git a/priv/repo/seeds.exs b/priv/repo/seeds.exs
new file mode 100644 (file)
index 0000000..1ab36ce
--- /dev/null
@@ -0,0 +1,11 @@
+# Script for populating the database. You can run it as:
+#
+#     mix run priv/repo/seeds.exs
+#
+# Inside the script, you can read and write to any of your
+# repositories directly:
+#
+#     Pleroma.Repo.insert!(%Pleroma.SomeSchema{})
+#
+# We recommend using the bang functions (`insert!`, `update!`
+# and so on) as they will fail if something goes wrong.
diff --git a/test/support/channel_case.ex b/test/support/channel_case.ex
new file mode 100644 (file)
index 0000000..aec3061
--- /dev/null
@@ -0,0 +1,37 @@
+defmodule Pleroma.Web.ChannelCase do
+  @moduledoc """
+  This module defines the test case to be used by
+  channel tests.
+
+  Such tests rely on `Phoenix.ChannelTest` and also
+  import other functionality to make it easier
+  to build common datastructures and query the data layer.
+
+  Finally, if the test case interacts with the database,
+  it cannot be async. For this reason, every test runs
+  inside a transaction which is reset at the beginning
+  of the test unless the test case is marked as async.
+  """
+
+  use ExUnit.CaseTemplate
+
+  using do
+    quote do
+      # Import conveniences for testing with channels
+      use Phoenix.ChannelTest
+
+      # The default endpoint for testing
+      @endpoint Pleroma.Web.Endpoint
+    end
+  end
+
+
+  setup tags do
+    :ok = Ecto.Adapters.SQL.Sandbox.checkout(Pleroma.Repo)
+    unless tags[:async] do
+      Ecto.Adapters.SQL.Sandbox.mode(Pleroma.Repo, {:shared, self()})
+    end
+    :ok
+  end
+
+end
diff --git a/test/support/conn_case.ex b/test/support/conn_case.ex
new file mode 100644 (file)
index 0000000..8d69698
--- /dev/null
@@ -0,0 +1,38 @@
+defmodule Pleroma.Web.ConnCase do
+  @moduledoc """
+  This module defines the test case to be used by
+  tests that require setting up a connection.
+
+  Such tests rely on `Phoenix.ConnTest` and also
+  import other functionality to make it easier
+  to build common datastructures and query the data layer.
+
+  Finally, if the test case interacts with the database,
+  it cannot be async. For this reason, every test runs
+  inside a transaction which is reset at the beginning
+  of the test unless the test case is marked as async.
+  """
+
+  use ExUnit.CaseTemplate
+
+  using do
+    quote do
+      # Import conveniences for testing with connections
+      use Phoenix.ConnTest
+      import Pleroma.Web.Router.Helpers
+
+      # The default endpoint for testing
+      @endpoint Pleroma.Web.Endpoint
+    end
+  end
+
+
+  setup tags do
+    :ok = Ecto.Adapters.SQL.Sandbox.checkout(Pleroma.Repo)
+    unless tags[:async] do
+      Ecto.Adapters.SQL.Sandbox.mode(Pleroma.Repo, {:shared, self()})
+    end
+    {:ok, conn: Phoenix.ConnTest.build_conn()}
+  end
+
+end
diff --git a/test/support/data_case.ex b/test/support/data_case.ex
new file mode 100644 (file)
index 0000000..3f40c36
--- /dev/null
@@ -0,0 +1,53 @@
+defmodule Pleroma.DataCase do
+  @moduledoc """
+  This module defines the setup for tests requiring
+  access to the application's data layer.
+
+  You may define functions here to be used as helpers in
+  your tests.
+
+  Finally, if the test case interacts with the database,
+  it cannot be async. For this reason, every test runs
+  inside a transaction which is reset at the beginning
+  of the test unless the test case is marked as async.
+  """
+
+  use ExUnit.CaseTemplate
+
+  using do
+    quote do
+      alias Pleroma.Repo
+
+      import Ecto
+      import Ecto.Changeset
+      import Ecto.Query
+      import Pleroma.DataCase
+    end
+  end
+
+  setup tags do
+    :ok = Ecto.Adapters.SQL.Sandbox.checkout(Pleroma.Repo)
+
+    unless tags[:async] do
+      Ecto.Adapters.SQL.Sandbox.mode(Pleroma.Repo, {:shared, self()})
+    end
+
+    :ok
+  end
+
+  @doc """
+  A helper that transform changeset errors to a map of messages.
+
+      changeset = Accounts.create_user(%{password: "short"})
+      assert "password is too short" in errors_on(changeset).password
+      assert %{password: ["password is too short"]} = errors_on(changeset)
+
+  """
+  def errors_on(changeset) do
+    Ecto.Changeset.traverse_errors(changeset, fn {message, opts} ->
+      Enum.reduce(opts, message, fn {key, value}, acc ->
+        String.replace(acc, "%{#{key}}", to_string(value))
+      end)
+    end)
+  end
+end
diff --git a/test/test_helper.exs b/test/test_helper.exs
new file mode 100644 (file)
index 0000000..602c5fc
--- /dev/null
@@ -0,0 +1,4 @@
+ExUnit.start()
+
+Ecto.Adapters.SQL.Sandbox.mode(Pleroma.Repo, :manual)
+
diff --git a/test/web/views/error_view_test.exs b/test/web/views/error_view_test.exs
new file mode 100644 (file)
index 0000000..48cdc51
--- /dev/null
@@ -0,0 +1,21 @@
+defmodule Pleroma.Web.ErrorViewTest do
+  use Pleroma.Web.ConnCase, async: true
+
+  # Bring render/3 and render_to_string/3 for testing custom views
+  import Phoenix.View
+
+  test "renders 404.json" do
+    assert render(Pleroma.Web.ErrorView, "404.json", []) ==
+           %{errors: %{detail: "Page not found"}}
+  end
+
+  test "render 500.json" do
+    assert render(Pleroma.Web.ErrorView, "500.json", []) ==
+           %{errors: %{detail: "Internal server error"}}
+  end
+
+  test "render any other" do
+    assert render(Pleroma.Web.ErrorView, "505.json", []) ==
+           %{errors: %{detail: "Internal server error"}}
+  end
+end