From: Roger Braun Date: Fri, 17 Mar 2017 16:09:58 +0000 (+0100) Subject: Phoenix skeleton X-Git-Url: https://git.squeep.com/?a=commitdiff_plain;h=a93f3421a704d6728a856d5d82cdbf9c43f3f897;p=akkoma Phoenix skeleton --- a93f3421a704d6728a856d5d82cdbf9c43f3f897 diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..d26faf840 --- /dev/null +++ b/.gitignore @@ -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 index 000000000..3ccc175fa --- /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 index 000000000..8eea4dd0a --- /dev/null +++ b/config/config.exs @@ -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 index 000000000..78f543720 --- /dev/null +++ b/config/dev.exs @@ -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 index 000000000..732bab2b0 --- /dev/null +++ b/config/prod.exs @@ -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 index 000000000..bcd7af1c5 --- /dev/null +++ b/config/test.exs @@ -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 index 000000000..e88a85196 --- /dev/null +++ b/lib/pleroma/application.ex @@ -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 index 000000000..7cecd7b38 --- /dev/null +++ b/lib/pleroma/repo.ex @@ -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 index 000000000..7aa8e556e --- /dev/null +++ b/lib/pleroma/web/channels/user_socket.ex @@ -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 index 000000000..a79b0dca9 --- /dev/null +++ b/lib/pleroma/web/endpoint.ex @@ -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 index 000000000..501545581 --- /dev/null +++ b/lib/pleroma/web/gettext.ex @@ -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 index 000000000..e0f1ac12f --- /dev/null +++ b/lib/pleroma/web/router.ex @@ -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 index 000000000..3981b270d --- /dev/null +++ b/lib/pleroma/web/views/error_helpers.ex @@ -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 index 000000000..6c589d3a1 --- /dev/null +++ b/lib/pleroma/web/views/error_view.ex @@ -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 index 000000000..f392af2ca --- /dev/null +++ b/lib/pleroma/web/web.ex @@ -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 index 000000000..f38ce95af --- /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 index 000000000..87383cc59 --- /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 index 000000000..2211c98e3 --- /dev/null +++ b/priv/gettext/en/LC_MESSAGES/errors.po @@ -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 index 000000000..a964f84ec --- /dev/null +++ b/priv/gettext/errors.pot @@ -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 index 000000000..1ab36cedc --- /dev/null +++ b/priv/repo/seeds.exs @@ -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 index 000000000..aec3061b3 --- /dev/null +++ b/test/support/channel_case.ex @@ -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 index 000000000..8d6969855 --- /dev/null +++ b/test/support/conn_case.ex @@ -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 index 000000000..3f40c3670 --- /dev/null +++ b/test/support/data_case.ex @@ -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 index 000000000..602c5fca4 --- /dev/null +++ b/test/test_helper.exs @@ -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 index 000000000..48cdc5159 --- /dev/null +++ b/test/web/views/error_view_test.exs @@ -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