Skip to content

Commit

Permalink
move seeds script to lib/auth/init for #174
Browse files Browse the repository at this point in the history
  • Loading branch information
nelsonic committed Jan 29, 2022
1 parent 70ccc1a commit c6fe5e7
Show file tree
Hide file tree
Showing 11 changed files with 178 additions and 156 deletions.
14 changes: 10 additions & 4 deletions .env_sample
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
export [email protected]
export AUTH_API_KEY=2PzB7PPnpuLsbWmWtXpGyI+kfSQSQ1zUW2Atz/+8PdZuSEJzHgzGnJWV35nTKRwx/dwylauth.herokuapp.com
export EMAIL_APP_URL=https://dwylmail.herokuapp.com
export AUTH_URL=dwylauth.herokuapp.com
export SECRET_KEY_BASE=2PzB7PPnpuLsbWmWtXpGyI+kfSQSQ1zUW2Atz/+8PdZuSEJzHgzGnJWV35nTKRwx
export ENCRYPTION_KEYS='nMdayQpR0aoasLaq1g94FLba+A+wB44JLko47sVQXMg=,L+ZVX8iheoqgqb22mUpATmMDsvVGtafoAeb0KN5uWf0='

export GITHUB_CLIENT_ID=CreateGitHubApp
export GITHUB_CLIENT_SECRET=SuperSecret
export GOOGLE_CLIENT_ID=YourAppsClientId.apps.googleusercontent.com
export GOOGLE_CLIENT_SECRET=SuperSecret
export SECRET_KEY_BASE=2PzB7PPnpuLsbWmWtXpGyI+kfSQSQ1zUW2Atz/+8PdZuSEJzHgzGnJWV35nTKRwx
export ENCRYPTION_KEYS='nMdayQpR0aoasLaq1g94FLba+A+wB44JLko47sVQXMg=,L+ZVX8iheoqgqb22mUpATmMDsvVGtafoAeb0KN5uWf0='

# Optional for sending emails:
export EMAIL_APP_URL=https://dwylmail.herokuapp.com

# Export this once your the auth db is initialized
export AUTH_API_KEY=2PzB7PPnpuLsbWmWtXpGyI+kfSQSQ1zUW2Atz/+8PdZuSEJzHgzGnJWV35nTKRwx/dwylauth.herokuapp.com
13 changes: 13 additions & 0 deletions lib/auth/init/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,18 @@ in the _main_
means they have to go _somewhere_ ...
that somewhere is right _here_!

## Required Environment Variables for `Auth` App

In order to initialize the **`Auth` Application**
+ `ADMIN_EMAIL` - the email address of the person who will
administer the **`Auth` App**.
+ `AUTH_URL` - the base URL where the application will be hosted,
e.g: `"auth.dwyl.com"` (exclude the protocol)
+ `SECRET_KEY_BASE` - the secret Phoenix uses to sign and encrypt important information.
see:
https://hexdocs.pm/phoenix/deployment.html#handling-of-your-application-secrets
+ `ENCRYPTION_KEYS` - a list of one or more encryption keys
used to encrypt data in the database.
see: `.env_sample` for example.


File renamed without changes.
119 changes: 117 additions & 2 deletions lib/auth/init/init.ex
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,122 @@ defmodule Auth.Init do
"""

def hello do
IO.inspect("hello init")
require Logger
import Ecto.Changeset
alias Auth.{Person, Role, Repo, Status}

def main do
Logger.debug("Initialising the Auth Database ...")
# check required environment variables:
Envar.is_set_all?(~w/ADMIN_EMAIL ENCRYPTION_KEYS SECRET_KEY_BASE/)

admin = Auth.Init.create_admin()

Auth.Init.insert_statuses()

Auth.Init.create_apikey_for_admin(admin)

# Update status of Admin to "Verified"
Auth.Person.verify_person_by_id(1)

Auth.Init.create_default_roles()
# grant superadmin role to app owner:
Auth.PeopleRoles.upsert(1, 1, 1, 1)

:ok
end


# This is used exclusivvely during setup
# don't confuse it with AuthPlug.get_auth_url/2
defp get_auth_url do
# see .env_sample for example
Envar.get("AUTH_URL") || "localhost:4000"
end

def create_admin do
email = Envar.get("ADMIN_EMAIL")

person =
case Person.get_person_by_email(email) do
nil ->
%Person{}
|> Person.changeset(%{email: email})
# |> put_assoc(:statuses, [%Status{text: "verified"}])
|> Repo.insert!()

person ->
person
end

if(Mix.env() == :test) do
# don't print noise during tests
else
IO.inspect(person.id, label: "seeds.exs person.id")
IO.puts("- - - - - - - - - - - - - - - - - - - - - - ")
end

person
end

def create_apikey_for_admin(person) do
{:ok, app} =
%{
"name" => "default system app",
"desc" => "Created by /priv/repo/seeds.exs during setup.",
"url" => "localhost:4000",
"person_id" => person.id,
"status" => 3
}
|> Auth.App.create_app()

# set the api key to AUTH_API_KEY in env:
update_attrs = %{
"client_id" => AuthPlug.Token.client_id(),
"client_secret" => AuthPlug.Token.client_secret()
}

{:ok, key} =
Auth.Apikey.get_apikey_by_app_id(app.id)
|> cast(update_attrs, [:client_id, :client_secret])
|> Repo.update()

api_key = key.client_id <> "/" <> key.client_secret <> "/" <> get_auth_url()

# set the AUTH_API_KEY environment variable during test run:
IO.inspect(Mix.env(), label: "Mix.env()")
# IO.inspect(person)
case Mix.env() do
:test ->
Envar.set("AUTH_API_KEY", api_key)

:prod ->
Logger.info("export AUTH_API_KEY=#{api_key}")

_ ->
nil
end
end

# scripts for creating default roles and permissions
def get_json(filepath) do
path = File.cwd!() <> filepath
IO.inspect(path, label: "path")
{:ok, data} = File.read(path)
json = Jason.decode!(data)
json
end

def create_default_roles do
Enum.each(get_json("/lib/auth/init/default_roles.json"), fn role ->
Role.upsert_role(role)
end)
end

def insert_statuses do
Enum.each(get_json("/lib/auth/init/statuses.json"), fn status ->
Status.upsert_status(status)
end)
end

end
File renamed without changes.
19 changes: 19 additions & 0 deletions lib/auth/people_roles.ex
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,25 @@ defmodule Auth.PeopleRoles do
|> Repo.insert()
end

@doc """
upsert/4 grants a role to the given person
app_id for app the person is granted the role for (always scoped to app!)
grantee_id is the person.id of the person being granted the role
granter_id is the id of the person (admin) granting the role
role_id is the role.id (int, e.g: 4) of th role being granted.
"""
def upsert(app_id, grantee_id, granter_id, role_id) do

case get_roles_for_person_for_app(app_id, grantee_id) do
nil ->
insert(app_id, grantee_id, granter_id, role_id)

roles ->
roles
end
end


@doc """
revoke/3 grants a role to the given person
revoker_id is the id of the person (admin) granting the role
Expand Down
2 changes: 1 addition & 1 deletion lib/auth_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ defmodule AuthWeb.Router do

pipeline :auth do
plug(AuthPlug)
end
end

scope "/", AuthWeb do
pipe_through :browser
Expand Down
5 changes: 4 additions & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,11 @@ defmodule Auth.Mixfile do
# https://github.com/dwyl/elixir-auth-google
{:elixir_auth_google, "~> 1.6.1"},

# Check/get Environment Variables: https://github.com/dwyl/envar
{:envar, "~> 1.0.4"},

# https://github.com/dwyl/auth_plug
{:auth_plug, "~> 1.4.7"},
{:auth_plug, "~> 1.4.11 "},

# https://github.com/dwyl/rbac
{:rbac, "~> 0.5.3"},
Expand Down
3 changes: 2 additions & 1 deletion mix.lock
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
%{
"argon2_elixir": {:hex, :argon2_elixir, "2.4.0", "2a22ea06e979f524c53b42b598fc6ba38cdcbc977a155e33e057732cfb1fb311", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "4ea82e183cf8e7f66dab1f767fedcfe6a195e140357ef2b0423146b72e0a551d"},
"auth_plug": {:hex, :auth_plug, "1.4.7", "7e09f8d60488a5cd28a095423c2c7772454fc4c3135208bf287e6ff8ef2e371d", [:mix], [{:httpoison, "~> 1.8.0", [hex: :httpoison, repo: "hexpm", optional: false]}, {:jason, "~> 1.2.2", [hex: :jason, repo: "hexpm", optional: false]}, {:joken, "~> 2.4.1", [hex: :joken, repo: "hexpm", optional: false]}, {:plug, "~> 1.12.1", [hex: :plug, repo: "hexpm", optional: false]}, {:useful, "~> 0.4.0", [hex: :useful, repo: "hexpm", optional: false]}], "hexpm", "98faa2c2b8d5af42854c23d19c013cef13670c0dfbe2584c0761b105e50d33aa"},
"auth_plug": {:hex, :auth_plug, "1.4.11", "f6f35708e737f6d56aae20abd3d974e877d5fd7eedff4f68480354c239be4ac1", [:mix], [{:httpoison, "~> 1.8.0", [hex: :httpoison, repo: "hexpm", optional: false]}, {:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: false]}, {:joken, "~> 2.4.1", [hex: :joken, repo: "hexpm", optional: false]}, {:plug, "~> 1.12.1", [hex: :plug, repo: "hexpm", optional: false]}, {:useful, "~> 0.4.0", [hex: :useful, repo: "hexpm", optional: false]}], "hexpm", "3ddc43065d095c4111f185f9ee1fa594b6d2cef1a620f315acd7e9ae8786f389"},
"b58": {:hex, :b58, "1.0.2", "d758f42d89fbe84052f18b2f310bed2a8c8c5b38dd0af86970026974cc7daeda", [:mix], [], "hexpm", "148e299e2753eae222b13f399f461a0c4910fed608b8723fca3c33d1d4f82c17"},
"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"},
"castore": {:hex, :castore, "0.1.13", "ccf3ab251ffaebc4319f41d788ce59a6ab3f42b6c27e598ad838ffecee0b04f9", [:mix], [], "hexpm", "a14a7eecfec7e20385493dbb92b0d12c5d77ecfd6307de10102d58c94e8c49c0"},
Expand All @@ -20,6 +20,7 @@
"elixir_auth_github": {:hex, :elixir_auth_github, "1.6.0", "f100dd3917b2395219d533e5a834eb450abff3e0a53eab36632d53335e1beb92", [:mix], [{:httpoison, "~> 1.8.0", [hex: :httpoison, repo: "hexpm", optional: false]}, {:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "abc700b484bc5dfd4d6a2aa2acbbe79a7fd8ce112ca28d2c864ede169790ab1f"},
"elixir_auth_google": {:hex, :elixir_auth_google, "1.6.1", "37b4812bf129628e61fc3c5403346cd24cd267750c57790b06bcd453daabbdab", [:mix], [{:httpoison, "~> 1.8.0", [hex: :httpoison, repo: "hexpm", optional: false]}, {:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "bd59482ca0369bd4f27a725d12bc12a0f575e65c0130bc3acce17b2a29c5e626"},
"elixir_make": {:hex, :elixir_make, "0.6.3", "bc07d53221216838d79e03a8019d0839786703129599e9619f4ab74c8c096eac", [:mix], [], "hexpm", "f5cbd651c5678bcaabdbb7857658ee106b12509cd976c2c2fca99688e1daf716"},
"envar": {:hex, :envar, "1.0.4", "3264a6b13d5f9bca9a16e82ed2311c0efd08f3371d3c6b42dc5abe9d01da59aa", [:mix], [], "hexpm", "d7856849080745b907e39b33b825448810bc2348e3f5982ee32f8007d9b3226e"},
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
"esbuild": {:hex, :esbuild, "0.4.0", "9f17db148aead4cf1e6e6a584214357287a93407b5fb51a031f122b61385d4c2", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "b61e4e6b92ffe45e4ee4755a22de6211a67c67987dc02afb35a425a0add1d447"},
"ex_doc": {:hex, :ex_doc, "0.25.5", "ac3c5425a80b4b7c4dfecdf51fa9c23a44877124dd8ca34ee45ff608b1c6deb9", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "688cfa538cdc146bc4291607764a7f1fcfa4cce8009ecd62de03b27197528350"},
Expand Down
149 changes: 2 additions & 147 deletions priv/repo/seeds.exs
Original file line number Diff line number Diff line change
@@ -1,147 +1,2 @@
require Logger
# Script for populating the database. You can run it as:
#
# mix run priv/repo/seeds.exs
#
# The seeds.exs script will also run
# when you execute the following command
# to setup the database:
#
# mix ecto.setup
defmodule Auth.Seeds do
alias Auth.{Person, Repo, Status}
import Ecto.Changeset

def create_admin do
if is_nil(System.get_env("HEROKU")) && is_nil(System.get_env("GITHUB_TOKEN")) do
load_env()
end

email = System.get_env("ADMIN_EMAIL")

person =
case Person.get_person_by_email(email) do
nil ->
%Person{}
|> Person.changeset(%{email: email})
# |> put_assoc(:statuses, [%Status{text: "verified"}])
|> Repo.insert!()

person ->
person
end

if(Mix.env() == :test) do
# don't print noise during tests
else
IO.inspect(person.id, label: "seeds.exs person.id")
IO.puts("- - - - - - - - - - - - - - - - - - - - - - ")
end

person
end

# this is used exclusivvely in seeds
defp get_auth_url do
# see .env_sample for example
api_key = System.get_env("AUTH_API_KEY")

parts = String.split(api_key, "/");
# should return "dwylauth.herokuapp.com"
List.last(parts)
end

def create_apikey_for_admin(person) do
{:ok, app} =
%{
"name" => "default system app",
"desc" => "Created by /priv/repo/seeds.exs during setup.",
"url" => "localhost:4000",
"person_id" => person.id,
"status" => 3
}
|> Auth.App.create_app()

# set the api key to AUTH_API_KEY in env:
update_attrs = %{
"client_id" => AuthPlug.Token.client_id(),
"client_secret" => AuthPlug.Token.client_secret()
}

{:ok, key} =
Auth.Apikey.get_apikey_by_app_id(app.id)
|> cast(update_attrs, [:client_id, :client_secret])
|> Repo.update()

api_key = key.client_id <> "/" <> key.client_secret <> "/" <> get_auth_url()

# set the AUTH_API_KEY environment variable during test run:
IO.inspect(Mix.env(), label: "Mix.env()")
# IO.inspect(person)
case Mix.env() do
:test ->
System.put_env("AUTH_API_KEY", api_key)

:prod ->
Logger.info("export AUTH_API_KEY=#{api_key}")

_ ->
nil
end
end

# load the .env file
def load_env() do
path = File.cwd!() <> "/.env"
IO.inspect(path, label: ".env file path")
{:ok, data} = File.read(path)

data
|> String.trim()
|> String.split("\n")
|> Enum.each(fn line ->
with line <- String.replace(line, ["export ", "'"], ""),
[key | rest] <- String.split(line, "="),
value <- Enum.join(rest, "=") do
System.put_env(key, value)
end
end)
end
end

# scripts for creating default roles and permissions
defmodule SeedData do
alias Auth.{Role, Status}

def get_json(filepath) do
path = File.cwd!() <> filepath
{:ok, data} = File.read(path)
json = Jason.decode!(data)
json
end

def create_default_roles do
Enum.each(get_json("/priv/repo/default_roles.json"), fn role ->
Role.upsert_role(role)
end)
end

def insert_statuses do
Enum.each(get_json("/priv/repo/statuses.json"), fn status ->
Status.upsert_status(status)
end)
end
end

person = Auth.Seeds.create_admin()

SeedData.insert_statuses()

Auth.Seeds.create_apikey_for_admin(person)

# Update status of Admin to "Verified"
Auth.Person.verify_person_by_id(1)

SeedData.create_default_roles()
# grant superadmin role to app owner:
Auth.PeopleRoles.insert(1, 1, 1, 1)
Envar.is_set_all?(~w/ADMIN_EMAIL ENCRYPTION_KEYS SECRET_KEY_BASE/)
Auth.Init.main()
10 changes: 10 additions & 0 deletions test/auth/init/init_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
defmodule Auth.InitTest do
use Auth.DataCase, async: true

describe "Initialize the Auth Database" do
test "main/0" do
assert Auth.Init.main() == :ok
end
end

end

0 comments on commit c6fe5e7

Please sign in to comment.