Skip to content

Commit

Permalink
Setup user, apiToken, project, creds via iex (#2370)
Browse files Browse the repository at this point in the history
* concept

* wip

* names

* create user via iex

* cl
  • Loading branch information
taylordowns2000 authored Aug 10, 2024
1 parent 070d447 commit 3623008
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 2 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ and this project adheres to

### Added

- Added an `iex` command to setup a user, apiToken, project, and credential so
that it's possible to get a fully running lightning instance via external
shell script. (This is a tricky requirement for a distributed set of local
deployments) [#2369](https://github.com/OpenFn/lightning/issues/2369)

### Changed

### Fixed
Expand Down
57 changes: 57 additions & 0 deletions lib/lightning/setup_utils.ex
Original file line number Diff line number Diff line change
Expand Up @@ -868,4 +868,61 @@ defmodule Lightning.SetupUtils do
|> limit(1)
|> Repo.one!()
end

@doc """
In some (mostly remote-controlled) deployments, it's necessary to create a
user, empty projects that they can access, and credentials (shared with those
projects) that they own so that later `openfn deploy` calls can make use of
these artifacts.
When run _before_ `openfn deploy`, this function makes it possible to set up
an entire lightning instance with a working project (including secrets)
without using the web UI.
"""
def setup_user(user, token, project_names, credentials) do
# create user
{:ok, user} = Accounts.create_user(user)

# create token
Repo.insert!(%Lightning.Accounts.UserToken{
user_id: user.id,
context: "api",
token: token
})

# create projects
projects =
project_names
|> Enum.map(fn name ->
{:ok, project} =
Projects.create_project(
%{
name: name,
history_retention_period:
Application.get_env(:lightning, :default_retention_period),
project_users: [%{user_id: user.id, role: :owner}]
},
false
)

project
end)

# create credentials
Enum.each(credentials, fn credential ->
{:ok, _credential} =
Credentials.create_credential(
credential
|> Map.put(:user_id, user.id)
|> Map.put(
:project_credentials,
Enum.map(projects, fn project ->
%{project_id: project.id}
end)
)
)
end)

:ok
end
end
68 changes: 66 additions & 2 deletions test/lightning/setup_utils_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ defmodule Lightning.SetupUtilsTest do
import Swoosh.TestAssertions

alias Lightning.{Accounts, Projects, Workflows, Jobs, SetupUtils}
alias Lightning.Accounts.User
alias Lightning.Projects.{Project, ProjectUser, ProjectCredential}
alias Lightning.Accounts.{User, UserToken}
alias Lightning.Credentials.{Credential}

describe "Setup demo site seed data" do
setup do
Expand Down Expand Up @@ -34,7 +36,7 @@ defmodule Lightning.SetupUtilsTest do
User.valid_password?(super_user, "welcome123")

user_token =
Lightning.Repo.all(Lightning.Accounts.UserToken)
Lightning.Repo.all(UserToken)
|> List.first()

assert user_token.user_id == super_user.id
Expand Down Expand Up @@ -648,6 +650,68 @@ defmodule Lightning.SetupUtilsTest do
end
end

describe "setup_user/4" do
test "creates a user, an api token, projects, and credentials" do
assert :ok ==
Lightning.SetupUtils.setup_user(
%{
first_name: "Taylor",
last_name: "Downs",
email: "[email protected]",
password: "shh12345678!"
},
"abc123",
["project-a", "project-b"],
[
%{
name: "openmrs",
schema: "raw",
body: %{"a" => "secret"}
},
%{
name: "dhis2",
schema: "raw",
body: %{"b" => "safe"}
}
]
)

# check that the user and the API token has been created
assert %User{id: user_id} = Repo.get_by(User, email: "[email protected]")
assert %UserToken{} = Repo.get_by(UserToken, token: "abc123")

# check that both projects are there
assert [%Project{id: p1_id}, %Project{id: p2_id}] = Repo.all(Project)

# check that the user has owner access to both
assert [
%ProjectUser{project_id: ^p1_id, user_id: ^user_id, role: :owner},
%ProjectUser{project_id: ^p2_id, user_id: ^user_id, role: :owner}
] =
Repo.all(ProjectUser)

credentials =
Repo.all(Credential) |> Repo.preload(:project_credentials)

assert [
%Credential{
name: "openmrs",
project_credentials: [
%ProjectCredential{project_id: ^p1_id},
%ProjectCredential{project_id: ^p2_id}
]
},
%Credential{
name: "dhis2",
project_credentials: [
%ProjectCredential{project_id: ^p1_id},
%ProjectCredential{project_id: ^p2_id}
]
}
] = credentials
end
end

defp get_dataclip_body(dataclip_id) do
from(d in Lightning.Invocation.Dataclip,
select: type(d.body, :string),
Expand Down

0 comments on commit 3623008

Please sign in to comment.