diff --git a/apps/aecore/lib/aecore.ex b/apps/aecore/lib/aecore.ex index e84b9dae..83a46ed6 100644 --- a/apps/aecore/lib/aecore.ex +++ b/apps/aecore/lib/aecore.ex @@ -8,7 +8,8 @@ defmodule Aecore do supervisor(Aecore.Keys.Worker.Supervisor, []), supervisor(Aecore.Chain.Worker.Supervisor, []), supervisor(Aecore.Miner.Worker.Supervisor, []), - supervisor(Aecore.Txs.Pool.Worker.Supervisor, []) + supervisor(Aecore.Txs.Pool.Worker.Supervisor, []), + supervisor(Aecore.Peers.Worker, []) ] Supervisor.start_link(children, strategy: :one_for_one) diff --git a/apps/aecore/lib/aecore/peers/worker.ex b/apps/aecore/lib/aecore/peers/worker.ex new file mode 100644 index 00000000..3c7dc4b6 --- /dev/null +++ b/apps/aecore/lib/aecore/peers/worker.ex @@ -0,0 +1,84 @@ +defmodule Aecore.Peers.Worker do + @moduledoc """ + Peer manager module + """ + + use GenServer + + alias Aehttpclient.Client + alias Aecore.Structures.Block + alias Aecore.Utils.Blockchain.BlockValidation + + def start_link do + GenServer.start_link(__MODULE__, [], name: __MODULE__) + end + + def init(initial_peers) do + {:ok, initial_peers} + end + + @spec add_peer(term) :: :ok | {:error, term()} | :error + def add_peer(uri) do + GenServer.call(__MODULE__, {:add_peer, uri}) + end + + @spec remove_peer(term) :: :ok | :error + def remove_peer(uri) do + GenServer.call(__MODULE__, {:remove_peer, uri}) + end + + @spec check_peers() :: :ok + def check_peers() do + GenServer.call(__MODULE__, :check_peers) + end + + @spec all_peers() :: list() + def all_peers() do + GenServer.call(__MODULE__, :all_peers) + end + + @spec genesis_block_header_hash() :: term() + def genesis_block_header_hash() do + Block.genesis_header() + |> BlockValidation.block_header_hash() + |> Base.encode16() + end + + def handle_call({:add_peer,uri}, _from, peers) do + if(!Enum.member?(peers,uri)) do + case(Client.get_info(uri)) do + {:ok, info} -> + if(Map.get(info,"genesis_block_hash") == genesis_block_header_hash()) do + {:reply, :ok, [uri | peers]} + else + {:reply, {:error, "Genesis header hash not valid"}, peers} + end + :error -> + {:reply, :error, peers} + end + else + {:reply, {:error, "Peer already in list"}, peers} + end + end + + def handle_call({:remove_peer, uri}, _from, peers) do + if(Enum.member?(peers,uri)) do + {:reply, :ok, List.delete(peers, uri)} + else + {:reply, {:error, "Peer not found"}, peers} + end + end + + def handle_call(:check_peers, _from, peers) do + updated_peers = Enum.filter(peers, fn(peer) -> + {status, info} = Client.get_info(peer) + :ok == status && + Map.get(info,"genesis_block_hash") == genesis_block_header_hash() + end) + {:reply, :ok, updated_peers} + end + + def handle_call(:all_peers, _from, peers) do + {:reply, peers, peers} + end +end diff --git a/apps/aecore/lib/aecore/peers/worker/supervisor.ex b/apps/aecore/lib/aecore/peers/worker/supervisor.ex new file mode 100644 index 00000000..3991db1b --- /dev/null +++ b/apps/aecore/lib/aecore/peers/worker/supervisor.ex @@ -0,0 +1,15 @@ +defmodule Aecore.Peers.Supervisor do + use Supervisor + + def start_link() do + Supervisor.start_link(__MODULE__, :ok) + end + + def init(:ok) do + children = [ + worker(Aecore.Peers.Worker, []) + ] + + supervise(children, strategy: :one_for_one) + end +end diff --git a/apps/aecore/lib/aecore/structures/block.ex b/apps/aecore/lib/aecore/structures/block.ex index aacfa59f..92192301 100644 --- a/apps/aecore/lib/aecore/structures/block.ex +++ b/apps/aecore/lib/aecore/structures/block.ex @@ -2,7 +2,6 @@ defmodule Aecore.Structures.Block do @moduledoc """ Structure of the block """ - alias Aecore.Structures.Block alias Aecore.Structures.Header diff --git a/apps/aecore/test/aecore_peers_test.exs b/apps/aecore/test/aecore_peers_test.exs new file mode 100644 index 00000000..548e426d --- /dev/null +++ b/apps/aecore/test/aecore_peers_test.exs @@ -0,0 +1,21 @@ +defmodule AecorePeersTest do + + use ExUnit.Case + + alias Aecore.Peers.Worker, as: Peers + + setup do + Peers.start_link() + [] + end + + test "add peer, get all peers, check peers and remove the peer" do + assert :ok = Peers.add_peer("localhost:4000") + assert {:error, "Peer already in list"} = Peers.add_peer("localhost:4000") + assert Enum.count(Peers.all_peers) == 1 + assert :ok = Peers.check_peers + assert :ok = Peers.remove_peer("localhost:4000") + assert {:error, "Peer not found"} = Peers.remove_peer("localhost:4001") + end + +end diff --git a/apps/aehttpclient/.gitignore b/apps/aehttpclient/.gitignore new file mode 100644 index 00000000..12179ea3 --- /dev/null +++ b/apps/aehttpclient/.gitignore @@ -0,0 +1,20 @@ +# The directory Mix will write compiled artifacts to. +/_build/ + +# If you run "mix test --cover", coverage assets end up here. +/cover/ + +# The directory Mix downloads your dependencies sources to. +/deps/ + +# Where 3rd-party dependencies like ExDoc output generated docs. +/doc/ + +# Ignore .fetch files in case you like to edit your project deps locally. +/.fetch + +# If the VM crashes, it generates a dump, let's ignore it too. +erl_crash.dump + +# Also ignore archive artifacts (built via "mix archive.build"). +*.ez diff --git a/apps/aehttpclient/README.md b/apps/aehttpclient/README.md new file mode 100644 index 00000000..a2070b82 --- /dev/null +++ b/apps/aehttpclient/README.md @@ -0,0 +1,21 @@ +# Aehttpclient + +A basic client for making requests to a node. + +## Installation + +If [available in Hex](https://hex.pm/docs/publish), the package can be installed +by adding `aehttpclient` to your list of dependencies in `mix.exs`: + +```elixir +def deps do + [ + {:aehttpclient, "~> 0.1.0"} + ] +end +``` + +Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc) +and published on [HexDocs](https://hexdocs.pm). Once published, the docs can +be found at [https://hexdocs.pm/aehttpclient](https://hexdocs.pm/aehttpclient). + diff --git a/apps/aehttpclient/config/config.exs b/apps/aehttpclient/config/config.exs new file mode 100644 index 00000000..032a12c8 --- /dev/null +++ b/apps/aehttpclient/config/config.exs @@ -0,0 +1,30 @@ +# This file is responsible for configuring your application +# and its dependencies with the aid of the Mix.Config module. +use Mix.Config + +# This configuration is loaded before any dependency and is restricted +# to this project. If another project depends on this project, this +# file won't be loaded nor affect the parent project. For this reason, +# if you want to provide default values for your application for +# 3rd-party users, it should be done in your "mix.exs" file. + +# You can configure your application as: +# +# config :aehttpclient, key: :value +# +# and access this configuration in your application as: +# +# Application.get_env(:aehttpclient, :key) +# +# You can also configure a 3rd-party app: +# +# config :logger, level: :info +# + +# It is also possible to import configuration files, relative to this +# directory. For example, you can emulate configuration per environment +# by uncommenting the line below and defining dev.exs, test.exs and such. +# Configuration from the imported file will override the ones defined +# here (which is why it is important to import them last). +# +# import_config "#{Mix.env}.exs" diff --git a/apps/aehttpclient/lib/client.ex b/apps/aehttpclient/lib/client.ex new file mode 100644 index 00000000..451bf135 --- /dev/null +++ b/apps/aehttpclient/lib/client.ex @@ -0,0 +1,18 @@ +defmodule Aehttpclient.Client do + @moduledoc """ + Client used for making requests to a node. + """ + + @spec get_info(term()) :: {:ok, map()} | :error + def get_info(uri) do + case(HTTPoison.get(uri <> "/info")) do + {:ok, %{body: body, status_code: 200}} -> + response = Poison.decode!(body) + {:ok, response} + {:ok, %HTTPoison.Response{status_code: 404}} -> + :error + {:error, %HTTPoison.Error{}} -> + :error + end + end +end diff --git a/apps/aehttpclient/mix.exs b/apps/aehttpclient/mix.exs new file mode 100644 index 00000000..b0e7db1f --- /dev/null +++ b/apps/aehttpclient/mix.exs @@ -0,0 +1,27 @@ +defmodule Aehttpclient.Mixfile do + use Mix.Project + + def project do + [ + app: :aehttpclient, + version: "0.1.0", + elixir: "~> 1.5", + start_permanent: Mix.env == :prod, + deps: deps() + ] + end + + # Run "mix help compile.app" to learn about applications. + def application do + [ + extra_applications: [:logger] + ] + end + + # Run "mix help deps" to learn about dependencies. + defp deps do + [ + {:httpoison, "~> 0.13"} + ] + end +end diff --git a/apps/aehttpclient/test/aehttpclient_test.exs b/apps/aehttpclient/test/aehttpclient_test.exs new file mode 100644 index 00000000..e98c05f6 --- /dev/null +++ b/apps/aehttpclient/test/aehttpclient_test.exs @@ -0,0 +1,5 @@ +defmodule AehttpclientTest do + + use ExUnit.Case + +end diff --git a/apps/aehttpclient/test/test_helper.exs b/apps/aehttpclient/test/test_helper.exs new file mode 100644 index 00000000..869559e7 --- /dev/null +++ b/apps/aehttpclient/test/test_helper.exs @@ -0,0 +1 @@ +ExUnit.start() diff --git a/apps/aehttpserver/.gitignore b/apps/aehttpserver/.gitignore new file mode 100644 index 00000000..ba24ced0 --- /dev/null +++ b/apps/aehttpserver/.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 \ No newline at end of file diff --git a/apps/aehttpserver/README.md b/apps/aehttpserver/README.md new file mode 100644 index 00000000..8da7e305 --- /dev/null +++ b/apps/aehttpserver/README.md @@ -0,0 +1,18 @@ +# Aehttpserver + +To start your Phoenix app: + + * Install dependencies with `mix deps.get` + * Start Phoenix endpoint with `mix phoenix.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/apps/aehttpserver/config/config.exs b/apps/aehttpserver/config/config.exs new file mode 100644 index 00000000..45c742c6 --- /dev/null +++ b/apps/aehttpserver/config/config.exs @@ -0,0 +1,15 @@ +# 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 + +# 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/apps/aehttpserver/config/dev.exs b/apps/aehttpserver/config/dev.exs new file mode 100644 index 00000000..3d2fdb9d --- /dev/null +++ b/apps/aehttpserver/config/dev.exs @@ -0,0 +1,34 @@ +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. +# +# 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 below 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. +config :aehttpserver, Aehttpserver.Endpoint, + http: [port: 4000], + debug_errors: true, + code_reloader: true, + check_origin: false, + watchers: [] + +# 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 diff --git a/apps/aehttpserver/config/prod.exs b/apps/aehttpserver/config/prod.exs new file mode 100644 index 00000000..bc65fe90 --- /dev/null +++ b/apps/aehttpserver/config/prod.exs @@ -0,0 +1,62 @@ +use Mix.Config + +# For production, we configure the host to read the PORT +# from the system environment. Therefore, you will need +# to set PORT=80 before running your server. +# +# You should also configure the url host to something +# meaningful, we use 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 :aehttpserver, Aehttpserver.Endpoint, + http: [:inet6, port: {:system, "PORT"}], + 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 :aehttpserver, Aehttpserver.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 :aehttpserver, Aehttpserver.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 :aehttpserver, Aehttpserver.Endpoint, server: true +# + +# Finally import the config/prod.secret.exs +# which should be versioned separately. +import_config "prod.secret.exs" diff --git a/apps/aehttpserver/config/test.exs b/apps/aehttpserver/config/test.exs new file mode 100644 index 00000000..8eae7c00 --- /dev/null +++ b/apps/aehttpserver/config/test.exs @@ -0,0 +1,10 @@ +use Mix.Config + +# We don't run a server during test. If one is required, +# you can enable the server option below. +config :aehttpserver, Aehttpserver.Endpoint, + http: [port: 4000], + server: true + +# Print only warnings and errors during test +config :logger, level: :warn diff --git a/apps/aehttpserver/lib/aehttpserver.ex b/apps/aehttpserver/lib/aehttpserver.ex new file mode 100644 index 00000000..b7aa8d71 --- /dev/null +++ b/apps/aehttpserver/lib/aehttpserver.ex @@ -0,0 +1,29 @@ +defmodule Aehttpserver do + use Application + + # See https://hexdocs.pm/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 endpoint when the application starts + supervisor(Aehttpserver.Endpoint, []), + # Start your own worker by calling: Aehttpserver.Worker.start_link(arg1, arg2, arg3) + # worker(Aehttpserver.Worker, [arg1, arg2, arg3]), + ] + + # See https://hexdocs.pm/elixir/Supervisor.html + # for other strategies and supported options + opts = [strategy: :one_for_one, name: Aehttpserver.Supervisor] + Supervisor.start_link(children, opts) + end + + # Tell Phoenix to update the endpoint configuration + # whenever the application is updated. + def config_change(changed, _new, removed) do + Aehttpserver.Endpoint.config_change(changed, removed) + :ok + end +end diff --git a/apps/aehttpserver/lib/aehttpserver/endpoint.ex b/apps/aehttpserver/lib/aehttpserver/endpoint.ex new file mode 100644 index 00000000..71decac6 --- /dev/null +++ b/apps/aehttpserver/lib/aehttpserver/endpoint.ex @@ -0,0 +1,37 @@ +defmodule Aehttpserver.Endpoint do + use Phoenix.Endpoint, otp_app: :aehttpserver + + socket "/socket", Aehttpserver.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: :aehttpserver, 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. + + 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: "_aehttpserver_key", + signing_salt: "EB5YKhDy" + + plug Aehttpserver.Router +end diff --git a/apps/aehttpserver/mix.exs b/apps/aehttpserver/mix.exs new file mode 100644 index 00000000..1613ddec --- /dev/null +++ b/apps/aehttpserver/mix.exs @@ -0,0 +1,40 @@ +defmodule Aehttpserver.Mixfile do + use Mix.Project + + def project do + [ + app: :aehttpserver, + version: "0.0.1", + elixir: "~> 1.4", + elixirc_paths: elixirc_paths(Mix.env), + compilers: [:phoenix, :gettext] ++ Mix.compilers, + start_permanent: Mix.env == :prod, + deps: deps() + ] + end + + # Configuration for the OTP application. + # + # Type `mix help compile.app` for more information. + def application do + [ + mod: {Aehttpserver, []}, + extra_applications: [:logger] + ] + end + + # Specifies which paths to compile per environment. + defp elixirc_paths(:test), do: ["lib", "web", "test/support"] + defp elixirc_paths(_), do: ["lib", "web"] + + # Specifies your project dependencies. + # + # Type `mix help deps` for examples and options. + defp deps do + [ + {:phoenix, "~> 1.3.0-rc"}, + {:gettext, "~> 0.11"}, + {:cowboy, "~> 1.0"} + ] + end +end diff --git a/apps/aehttpserver/test/test_helper.exs b/apps/aehttpserver/test/test_helper.exs new file mode 100644 index 00000000..2df156fe --- /dev/null +++ b/apps/aehttpserver/test/test_helper.exs @@ -0,0 +1,2 @@ +ExUnit.start + diff --git a/apps/aehttpserver/web/channels/user_socket.ex b/apps/aehttpserver/web/channels/user_socket.ex new file mode 100644 index 00000000..0eea3e65 --- /dev/null +++ b/apps/aehttpserver/web/channels/user_socket.ex @@ -0,0 +1,37 @@ +defmodule Aehttpserver.UserSocket do + use Phoenix.Socket + + ## Channels + # channel "room:*", Aehttpserver.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: "users_socket:#{socket.assigns.user_id}" + # + # Would allow you to broadcast a "disconnect" event and terminate + # all active sockets and channels for a given user: + # + # Aehttpserver.Endpoint.broadcast("users_socket:#{user.id}", "disconnect", %{}) + # + # Returning `nil` makes this socket anonymous. + def id(_socket), do: nil +end diff --git a/apps/aehttpserver/web/controllers/info_controller.ex b/apps/aehttpserver/web/controllers/info_controller.ex new file mode 100644 index 00000000..fe94c929 --- /dev/null +++ b/apps/aehttpserver/web/controllers/info_controller.ex @@ -0,0 +1,30 @@ +defmodule Aehttpserver.InfoController do + use Aehttpserver.Web, :controller + + alias Aecore.Structures.Block + alias Aecore.Chain.Worker, as: Chain + alias Aecore.Utils.Blockchain.BlockValidation + alias Aecore.Keys.Worker, as: Keys + + def info(conn, _params) do + latest_block = Chain.latest_block() + latest_block_header = latest_block.header + |> BlockValidation.block_header_hash() + |> Base.encode16() + + genesis_block_header = Block.genesis_header() + genesis_block_hash = genesis_block_header + |> BlockValidation.block_header_hash() + |> Base.encode16() + + {:ok, pubkey} = Keys.pubkey() + pubkey = Base.encode16(pubkey) + + json conn, %{current_block_version: latest_block.header.version, + current_block_height: latest_block.header.height, + current_block_hash: latest_block_header, + genesis_block_hash: genesis_block_hash, + difficulty_target: latest_block.header.difficulty_target, + public_key: pubkey} + end +end diff --git a/apps/aehttpserver/web/gettext.ex b/apps/aehttpserver/web/gettext.ex new file mode 100644 index 00000000..f5af7c69 --- /dev/null +++ b/apps/aehttpserver/web/gettext.ex @@ -0,0 +1,24 @@ +defmodule Aehttpserver.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 Aehttpserver.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: :aehttpserver +end diff --git a/apps/aehttpserver/web/router.ex b/apps/aehttpserver/web/router.ex new file mode 100644 index 00000000..6f2c688f --- /dev/null +++ b/apps/aehttpserver/web/router.ex @@ -0,0 +1,26 @@ +defmodule Aehttpserver.Router do + use Aehttpserver.Web, :router + + pipeline :browser do + plug :accepts, ["html"] + plug :fetch_session + plug :fetch_flash + plug :protect_from_forgery + plug :put_secure_browser_headers + end + + pipeline :api do + plug :accepts, ["json"] + end + + scope "/", Aehttpserver do + pipe_through :browser # Use the default browser stack + + get "/info", InfoController, :info + end + + # Other scopes may use custom stacks. + # scope "/api", Aehttpserver do + # pipe_through :api + # end +end diff --git a/apps/aehttpserver/web/web.ex b/apps/aehttpserver/web/web.ex new file mode 100644 index 00000000..4cbcd5cf --- /dev/null +++ b/apps/aehttpserver/web/web.ex @@ -0,0 +1,54 @@ +defmodule Aehttpserver.Web do + @moduledoc """ + The entrypoint for defining your web interface, such + as controllers, views, channels and so on. + + This can be used in your application as: + + use Aehttpserver.Web, :controller + use Aehttpserver.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. Instead, define any helper function in modules + and import those modules here. + """ + + def model do + quote do + # Define common model functionality + end + end + + def controller do + quote do + use Phoenix.Controller + + import Aehttpserver.Router.Helpers + import Aehttpserver.Gettext + end + end + + def router do + quote do + use Phoenix.Router + end + end + + def channel do + quote do + use Phoenix.Channel + import Aehttpserver.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/config/config.exs b/config/config.exs index 170712ab..0c8180b8 100644 --- a/config/config.exs +++ b/config/config.exs @@ -8,6 +8,7 @@ use Mix.Config # configure all applications here, we prefer to delegate # back to each application for organization purposes. import_config "../apps/*/config/config.exs" +path = Path.absname("apps/aecore") %{year: year, month: month, day: day} = DateTime.utc_now() timestamp = "#{year}-#{month}-#{day}_" @@ -18,13 +19,14 @@ config :aecore, :keys, config :logger, compile_time_purge_level: :info, - backends: [{LoggerFileBackend, :info}, + backends: [:console, + {LoggerFileBackend, :info}, {LoggerFileBackend, :error}] config :logger, :info, - path: "apps/aecore/logs/#{timestamp}info.log", + path: path <> "/logs/#{timestamp}info.log", level: :info config :logger, :error, - path: "apps/aecore/logs/#{timestamp}error.log", + path: path <> "/logs/#{timestamp}error.log", level: :error