diff --git a/.gitignore b/.gitignore index 04e9821..7d16ca7 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ erl_crash.dump # secrets files as long as you replace their contents by environment # variables. /config/*.secret.exs +/config/*.secret.json uploads diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..cb6507f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,52 @@ +# TODO: start of a docker file for build on a centos image +FROM quay.io/concur_platform/centos:7.3.1611-4390ad7 +MAINTAINER https://github.com/concur/docker-centos-elixir +LABEL Description="Build image with Erlang 20.2 | Elixir 1.5.2" + +ENV LANG=en_US.UTF-8 ELIXIR_VERSION=1.5.2 ERLANG_VERSION=20.2 +WORKDIR /root + +RUN yum -y install epel-release && \ + yum -y install gcc gcc-c++ glibc-devel make ncurses-devel wget \ + openssl-devel autoconf java-1.8.0-openjdk-devel \ + git wxBase.x86_64 unzip which && \ + yum clean all && \ + localedef -i en_US -f UTF-8 en_US.UTF-8 + +RUN curl -OLS --compressed https://raw.githubusercontent.com/kerl/kerl/master/kerl && \ + chmod a+x /root/kerl && \ + /root/kerl update releases && \ + /root/kerl build $ERLANG_VERSION $ERLANG_VERSION && \ + /root/kerl install $ERLANG_VERSION /usr/lib/erlang && \ + /root/kerl cleanup all && \ + ln -s /usr/lib/erlang/bin/ct_run /usr/bin/ct_run && \ + ln -s /usr/lib/erlang/bin/dialyzer /usr/bin/dialyzer && \ + ln -s /usr/lib/erlang/bin/epmd /usr/bin/epmd && \ + ln -s /usr/lib/erlang/bin/erl /usr/bin/erl && \ + ln -s /usr/lib/erlang/bin/erlc /usr/bin/erlc && \ + ln -s /usr/lib/erlang/bin/escript /usr/bin/escript && \ + ln -s /usr/lib/erlang/bin/run_erl /usr/bin/run_erl && \ + ln -s /usr/lib/erlang/bin/start /usr/bin/start && \ + ln -s /usr/lib/erlang/bin/start_erl /usr/bin/start_erl && \ + ln -s /usr/lib/erlang/bin/to_erl /usr/bin/to_erl && \ + ln -s /usr/lib/erlang/bin/typer /usr/bin/typer + +RUN curl -OLS --compressed https://github.com/elixir-lang/elixir/releases/download/v$ELIXIR_VERSION/Precompiled.zip && \ + unzip -o -d /usr/lib/elixir Precompiled.zip && \ + rm Precompiled.zip && \ + ln -s /usr/lib/elixir/bin/elixir /usr/bin/elixir && \ + ln -s /usr/lib/elixir/bin/mix /usr/bin/mix && \ + ln -s /usr/lib/elixir/bin/elixirc /usr/bin/elixirc && \ + ln -s /usr/lib/elixir/bin/iex /usr/bin/iex && \ + mix local.hex --force && \ + mix local.rebar --force && \ + mix hex.info + +# TODO: install yarn +# RUN curl -OLS --compressed https://nodejs.org/dist/v6.10.3/node-v6.10.3-linux-x64.tar.xz && \ +# tar xpvf node-v6.10.3-linux-x64.tar.xz && \ +# mv /root/node-v6.10.3-linux-x64 /usr/lib/node && \ +# ln -s /usr/lib/node/bin/node /usr/bin/node && \ +# ln -s /usr/lib/node/bin/npm /usr/bin/npm + +CMD "/bin/bash" diff --git a/client/app/util/oauth/oauth.ts b/client/app/util/oauth/oauth.ts index 82a3f59..870b323 100644 --- a/client/app/util/oauth/oauth.ts +++ b/client/app/util/oauth/oauth.ts @@ -1,36 +1,11 @@ -// for prod site -// TODO: -const prod_id = ''; -const prod_redirect_uri = 'https://dev.classicwowforums.com/oauth'; +const config = require('../../../../config/client.secret.json'); -// for dev site -const dev_id = 'dy22zpswn6b5q22zjparrcn83jkdre9h'; -const dev_redirect_uri = 'https://dev.classicwowforums.com/oauth'; - -// for local site -const local_id = 'h8fx6ad624ne9qw2njxx6343za7fux3j'; -const local_redirect_uri = 'https://localhost/oauth'; - -let client_id; -let redirect_uri; - -switch (process.env.NODE_ENV) { - case 'production': - client_id = prod_id; - redirect_uri = prod_redirect_uri; - break; - case 'dev': - client_id = dev_id; - redirect_uri = dev_redirect_uri; - break; - default: - client_id = local_id; - redirect_uri = local_redirect_uri; -} +const { bnet_client_id, bnet_redirect_uri } = config; // TODO: support for eu etc. const oauthUrl = - `https://us.battle.net/oauth/authorize?redirect_uri=${redirect_uri}&scope=wow.profile&client_id=${client_id}&response_type=code`; + `https://us.battle.net/oauth/authorize?redirect_uri=` + + `${bnet_redirect_uri}&scope=wow.profile&client_id=${bnet_client_id}&response_type=code`; const openOuathWindow = () => { window.open(oauthUrl, '_blank', 'resizeable=yes, height=900, width=1200'); diff --git a/client/package.json b/client/package.json index 8d5f831..576f9c2 100644 --- a/client/package.json +++ b/client/package.json @@ -1,18 +1,14 @@ { "name": "react_starter", - "version": "1.0.0", + "version": "0.0.1", "description": "A seed for a simple react application with typescript.", "scripts": { "build": "webpack -p --progress --colors", - "build:dev": "NODE_ENV=dev webpack -p --progress --colors", - "build:prod": "NODE_ENV=production webpack -p --progress --colors", "dev": "webpack --progress --colors --watch", "c9": "webpack-dev-server --host 0.0.0.0 --port 8080 --inline --history-api-fallback", "start": "webpack-dev-server --inline --history-api-fallback", "update-latest": "rm -rf node_modules && rm yarn.lock && ncu --upgrade --upgradeAll && yarn install" }, - "author": "Mitchell Gerber", - "license": "MIT", "dependencies": { "@types/fingerprintjs2": "^1.5.1", "@types/lodash": "^4.14.92", diff --git a/config/client.secret.json.template b/config/client.secret.json.template new file mode 100644 index 0000000..003c18c --- /dev/null +++ b/config/client.secret.json.template @@ -0,0 +1,4 @@ +{ + "bnet_client_id": "", + "bnet_redirect_uri": "" +} diff --git a/config/config.exs b/config/config.exs index 9e4c343..197c06e 100644 --- a/config/config.exs +++ b/config/config.exs @@ -26,7 +26,6 @@ config :logger, :console, # 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" -import_config "config.secret.exs" # user permissions for app - right now the read/write don't mean anything config :myapp, MyApp.Guardian, diff --git a/config/config.secret.exs.template b/config/config.secret.exs.template deleted file mode 100644 index 0a9d139..0000000 --- a/config/config.secret.exs.template +++ /dev/null @@ -1,16 +0,0 @@ -# secret dev configurations - api keys go here -use Mix.Config - -config :myapp, - bnet_client_id: "", - bnet_client_secret: "", - bnet_redirect_uri: "", - - # admin login credentials for site - admin_accounts: [%{ - "username" => "", - "password" => "", - "character_name" => "", - "character_avatar" => "", - "permissions" => "" - }] diff --git a/config/dev.exs b/config/dev.exs index 57931c5..479352e 100644 --- a/config/dev.exs +++ b/config/dev.exs @@ -51,3 +51,5 @@ config :myapp, MyApp.Repo, config :myapp, MyApp.Guardian, issuer: "myapp", secret_key: "secret" + +import_config "dev.secret.exs" diff --git a/config/dev.secret.exs.template b/config/dev.secret.exs.template new file mode 100644 index 0000000..e560fe4 --- /dev/null +++ b/config/dev.secret.exs.template @@ -0,0 +1,18 @@ +# secret dev configurations - api keys go here +use Mix.Config + +config :myapp, + bnet_client_id: "", + bnet_client_secret: "", + bnet_redirect_uri: "https://localhost/oauth", + + # admin login credentials for site + admin_accounts: [ + %{ + "username" => "", + "password" => "", + "character_name" => "", + "character_avatar" => "", + "permissions" => "" + }, +] diff --git a/config/prod.exs b/config/prod.exs index 4602ca0..0dbd024 100644 --- a/config/prod.exs +++ b/config/prod.exs @@ -14,9 +14,12 @@ use Mix.Config # manifest is generated by the mix phx.digest task # which you typically run after static files are built. config :myapp, MyAppWeb.Endpoint, - load_from_system_env: true, - url: [host: "example.com", port: 80] - # cache_static_manifest: "priv/static/cache_manifest.json" + code_reloader: false, + http: [port: 80], + url: [host: "classicwowforums.com", port: 80], + server: true, + root: ".", + version: Application.spec(:myapp, :vsn) # Do not print debug messages in production config :logger, level: :info diff --git a/config/prod.secret.exs.template b/config/prod.secret.exs.template index 57c38ec..64c2179 100644 --- a/config/prod.secret.exs.template +++ b/config/prod.secret.exs.template @@ -9,7 +9,7 @@ use Mix.Config # kept out of version control and might be hard to recover # or recreate for your teammates (or yourself later on). config :myapp, MyAppWeb.Endpoint, - secret_key_base: "Bv6Dz/0GVoxyCC8TKpgwX/7y8NHtsSEQB49UAzNQLzuAafmkOQR0wshC/7Wwyp3/" + secret_key_base: "TODO:" # Configure your database config :myapp, MyApp.Repo, @@ -23,18 +23,20 @@ config :myapp, MyApp.Repo, # Secret key. You can use `mix guardian.gen.secret` to get one config :myapp, MyApp.Guardian, issuer: "myapp", - secret_key: "secret" + secret_key: "TODO:" config :myapp, bnet_client_id: "", bnet_client_secret: "", bnet_redirect_uri: "", - # admin login credentials for site - admin_accounts: [%{ +# admin login credentials for site +admin_accounts: [ + %{ "username" => "", "password" => "", "character_name" => "", "character_avatar" => "", "permissions" => "" - }] + }, +] diff --git a/lib/myapp/release_tasks.ex b/lib/myapp/release_tasks.ex new file mode 100644 index 0000000..04dd1ed --- /dev/null +++ b/lib/myapp/release_tasks.ex @@ -0,0 +1,73 @@ +defmodule MyApp.ReleaseTasks do + + @start_apps [ + :crypto, + :ssl, + :postgrex, + :ecto + ] + + def myapp, do: :myapp + + def repos, do: Application.get_env(myapp(), :ecto_repos, []) + + def seed do + # Run migrations + migrate() + + # Run seed script + Enum.each(repos(), &run_seeds_for/1) + + # Signal shutdown + IO.puts "Success!" + :init.stop() + end + + defp prepare do + me = myapp() + + IO.puts "Loading #{me}.." + # Load the code for myapp, but don't start it + :ok = Application.load(me) + + IO.puts "Starting dependencies.." + # Start apps necessary for executing migrations + Enum.each(@start_apps, &Application.ensure_all_started/1) + + # Start the Repo(s) for myapp + IO.puts "Starting repos.." + Enum.each(repos(), &(&1.start_link(pool_size: 1))) + end + + def migrate do + prepare() + Enum.each(repos(), &run_migrations_for/1) + end + + def priv_dir(app), do: "#{:code.priv_dir(app)}" + + defp run_migrations_for(repo) do + app = Keyword.get(repo.config, :otp_app) + IO.puts "Running migrations for #{app}" + Ecto.Migrator.run(repo, migrations_path(repo), :up, all: true) + end + + def run_seeds_for(repo) do + # Run the seed script if it exists + seed_script = seeds_path(repo) + if File.exists?(seed_script) do + IO.puts "Running seed script.." + Code.eval_file(seed_script) + end + end + + def migrations_path(repo), do: priv_path_for(repo, "migrations") + + def seeds_path(repo), do: priv_path_for(repo, "seeds.exs") + + def priv_path_for(repo, filename) do + app = Keyword.get(repo.config, :otp_app) + repo_underscore = repo |> Module.split |> List.last |> Macro.underscore + Path.join([priv_dir(app), repo_underscore, filename]) + end +end diff --git a/lib/myapp_web/controllers/page_controller.ex b/lib/myapp_web/controllers/page_controller.ex index f8f42f4..a771cdc 100644 --- a/lib/myapp_web/controllers/page_controller.ex +++ b/lib/myapp_web/controllers/page_controller.ex @@ -6,11 +6,11 @@ defmodule MyAppWeb.PageController do def index(conn, _params) do # cache index.html if prod - file = case Mix.env do - :dev -> File.read!("./priv/static/index.html") - _ -> + file = case System.get_env("MIX_ENV") do + :prod -> file = Cachex.get(:myapp, "index.html") |> get_file + _ -> File.read!(Application.app_dir(:myapp, "priv/static/index.html")) end conn @@ -19,7 +19,7 @@ defmodule MyAppWeb.PageController do defp get_file({:ok, data}), do: data defp get_file({:missing, _}) do - file = File.read!("./priv/static/index.html") + file = File.read!(Application.app_dir(:myapp, "priv/static/index.html")) Cachex.set(:myapp, "index.html", file) file end diff --git a/makefile b/makefile new file mode 100644 index 0000000..360a10e --- /dev/null +++ b/makefile @@ -0,0 +1,11 @@ +clean: + rm -rf ./priv/static + rm -rf _build + +build-client: + cd client && yarn install && yarn run build + +build-server: + mix deps.get && MIX_ENV=prod mix release --env=prod + +all: clean build-client build-server diff --git a/mix.exs b/mix.exs index 2c81cf2..a1bbf3b 100644 --- a/mix.exs +++ b/mix.exs @@ -5,7 +5,7 @@ defmodule MyApp.Mixfile do [ app: :myapp, version: "0.0.1", - elixir: "~> 1.4", + elixir: "~> 1.5.2", elixirc_paths: elixirc_paths(Mix.env), compilers: [:phoenix, :gettext] ++ Mix.compilers, start_permanent: Mix.env == :prod, @@ -47,6 +47,7 @@ defmodule MyApp.Mixfile do {:dialyxir, "~> 0.5", only: [:dev], runtime: false}, {:ex_guard, "~> 1.3", only: :dev}, {:cachex, "~> 2.1"}, + {:distillery, "~> 1.5", runtime: false}, ] end diff --git a/mix.lock b/mix.lock index 5309f38..6e9e056 100644 --- a/mix.lock +++ b/mix.lock @@ -9,6 +9,7 @@ "db_connection": {:hex, :db_connection, "1.1.2", "2865c2a4bae0714e2213a0ce60a1b12d76a6efba0c51fbda59c9ab8d1accc7a8", [], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: true]}, {:sbroker, "~> 1.0", [hex: :sbroker, repo: "hexpm", optional: true]}], "hexpm"}, "decimal": {:hex, :decimal, "1.4.1", "ad9e501edf7322f122f7fc151cce7c2a0c9ada96f2b0155b8a09a795c2029770", [], [], "hexpm"}, "dialyxir": {:hex, :dialyxir, "0.5.1", "b331b091720fd93e878137add264bac4f644e1ddae07a70bf7062c7862c4b952", [], [], "hexpm"}, + "distillery": {:hex, :distillery, "1.5.2", "eec18b2d37b55b0bcb670cf2bcf64228ed38ce8b046bb30a9b636a6f5a4c0080", [], [], "hexpm"}, "ecto": {:hex, :ecto, "2.2.7", "2074106ff4a5cd9cb2b54b12ca087c4b659ddb3f6b50be4562883c1d763fb031", [], [{:db_connection, "~> 1.1", [hex: :db_connection, repo: "hexpm", optional: true]}, {:decimal, "~> 1.2", [hex: :decimal, repo: "hexpm", optional: false]}, {:mariaex, "~> 0.8.0", [hex: :mariaex, repo: "hexpm", optional: true]}, {:poison, "~> 2.2 or ~> 3.0", [hex: :poison, repo: "hexpm", optional: true]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.13.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:sbroker, "~> 1.0", [hex: :sbroker, repo: "hexpm", optional: true]}], "hexpm"}, "elixir_make": {:hex, :elixir_make, "0.4.0", "992f38fabe705bb45821a728f20914c554b276838433349d4f2341f7a687cddf", [], [], "hexpm"}, "eternal": {:hex, :eternal, "1.2.0", "e2a6b6ce3b8c248f7dc31451aefca57e3bdf0e48d73ae5043229380a67614c41", [], [], "hexpm"}, diff --git a/rel/commands/migrate.sh b/rel/commands/migrate.sh new file mode 100644 index 0000000..06b5b36 --- /dev/null +++ b/rel/commands/migrate.sh @@ -0,0 +1 @@ +$RELEASE_ROOT_DIR/bin/myapp command Elixir.MyApp.ReleaseTasks migrate diff --git a/rel/commands/seed.sh b/rel/commands/seed.sh new file mode 100644 index 0000000..94b04d0 --- /dev/null +++ b/rel/commands/seed.sh @@ -0,0 +1 @@ +$RELEASE_ROOT_DIR/bin/myapp command Elixir.MyApp.ReleaseTasks seed diff --git a/rel/config.exs b/rel/config.exs new file mode 100644 index 0000000..37c78d2 --- /dev/null +++ b/rel/config.exs @@ -0,0 +1,60 @@ +# Import all plugins from `rel/plugins` +# They can then be used by adding `plugin MyPlugin` to +# either an environment, or release definition, where +# `MyPlugin` is the name of the plugin module. +Path.join(["rel", "plugins", "*.exs"]) +|> Path.wildcard() +|> Enum.map(&Code.eval_file(&1)) + +use Mix.Releases.Config, + # This sets the default release built by `mix release` + default_release: :default, + # This sets the default environment used by `mix release` + default_environment: Mix.env() + +# For a full list of config options for both releases +# and environments, visit https://hexdocs.pm/distillery/configuration.html + + +# You may define one or more environments in this file, +# an environment's settings will override those of a release +# when building in that environment, this combination of release +# and environment configuration is called a profile + +environment :dev do + # If you are running Phoenix, you should make sure that + # server: true is set and the code reloader is disabled, + # even in dev mode. + # It is recommended that you build with MIX_ENV=prod and pass + # the --env flag to Distillery explicitly if you want to use + # dev mode. + set dev_mode: true + set include_erts: false + set cookie: :"b9u;]?ai%|bmZ=?Mny?$DU[Cm>vv>f