Current section

Files

Jump to
nerves_hub_cli lib mix tasks nerves_hub.product.ex
Raw

lib/mix/tasks/nerves_hub.product.ex

defmodule Mix.Tasks.NervesHub.Product do
use Mix.Task
import Mix.NervesHubCLI.Utils
alias Mix.NervesHubCLI.Shell
@shortdoc "Manages your products"
@moduledoc """
Manages your products.
## create
Create a new NervesHub product. The shell will prompt for information about the
product. This information can be passed by specifying one or all of the command
line options.
mix nerves_hub.product create
### Command-line options
* `--name` - (Optional) The product name
## list
mix nerves_hub.product list
## delete
mix nerves_hub.product delete [product_name]
## update
Update product metadata.
Call `list` to retrieve product names and metadata keys
### Examples
Change product name
mix nerves_hub.product update example name example_new
# Managing user roles
The following functions allow the management of user roles within your product.
Roles are a way of granting users a permission level so they may perform
actions for your product. The following is a list of valid roles in order of
highest role to lowest role:
* `admin`
* `delete`
* `write`
* `read`
NervesHub will validate all actions with your user role. If an action you are
trying to perform requires `write`, the user performing the action will be
required to have an org role of `write` or higher (`admin`, `delete`).
Managing user roles for your product will require that your user has the
product role of `admin`.
## user list
List the users and their role for the product.
mix nerves_hub.product user list PRODUCT_NAME
## user add
Add an existing user to a product with a role.
mix nerves_hub.product user add PRODUCT_NAME USERNAME ROLE
## user update
Update an existing user for your product with a new role.
mix nerves_hub.product user update PRODUCT_NAME USERNAME ROLE
## user remove
Remove an existing user from having a role for your product.
mix nerves_hub.product user remove PRODUCT_NAME USERNAME
"""
@switches [
org: :string,
name: :string
]
def run(args) do
# compile the project in case we need CA certs from it
_ = Mix.Task.run("compile")
_ = Application.ensure_all_started(:nerves_hub_cli)
{opts, args} = OptionParser.parse!(args, strict: @switches)
show_api_endpoint()
org = org(opts)
case args do
["list"] ->
list(org)
["create"] ->
create(org, opts)
["delete", product_name] ->
delete(org, product_name)
["update", product, key, value] ->
update(org, product, key, value)
["user", "list", product] ->
user_list(org, product)
["user", "add", product, username, role] ->
user_add(org, product, username, role)
["user", "update", product, username, role] ->
user_update(org, product, username, role)
["user", "remove", product, username] ->
user_remove(org, product, username)
_ ->
render_help()
end
end
@spec render_help() :: no_return()
def render_help() do
Shell.raise("""
Invalid arguments to `mix nerves_hub.product`.
Usage:
mix nerves_hub.product list
mix nerves_hub.product create
mix nerves_hub.product delete PRODUCT_NAME
mix nerves_hub.product update PRODUCT_NAME KEY VALUE
mix nerves_hub.product user list PRODUCT_NAME
mix nerves_hub.product user add PRODUCT_NAME USERNAME ROLE
mix nerves_hub.product user update PRODUCT_NAME USERNAME ROLE
mix nerves_hub.product user remove PRODUCT_NAME USERNAME ROLE
Run `mix help nerves_hub.product` for more information.
""")
end
def list(org) do
auth = Shell.request_auth()
case NervesHubCLI.API.Product.list(org, auth) do
{:ok, %{"data" => []}} ->
Shell.info("No products have been created.")
{:ok, %{"data" => products}} ->
Shell.info("")
Shell.info("Products:")
Enum.each(products, fn params ->
Shell.info("------------")
render_product(params)
|> String.trim_trailing()
|> Shell.info()
end)
Shell.info("")
error ->
Shell.render_error(error)
end
end
def create(org, opts) do
config = Mix.Project.config()
name = opts[:name] || config[:name] || config[:app] || Shell.prompt("Product name:")
name = to_string(name)
Shell.info("")
Shell.info("Creating product '#{name}'...")
auth = Shell.request_auth()
case NervesHubCLI.API.Product.create(org, name, auth) do
{:ok, %{"data" => %{} = _product}} ->
Shell.info("Product '#{name}' created.")
error ->
Shell.render_error(error)
end
end
def delete(org, product_name) do
if Shell.yes?("Delete product '#{product_name}'?") do
auth = Shell.request_auth()
case NervesHubCLI.API.Product.delete(org, product_name, auth) do
{:ok, ""} ->
Shell.info("Product deleted successfully.")
error ->
Shell.render_error(error)
end
end
end
def update(org, product, key, value) do
auth = Shell.request_auth()
case NervesHubCLI.API.Product.update(org, product, Map.put(%{}, key, value), auth) do
{:ok, %{"data" => product}} ->
Shell.info("")
Shell.info("Product updated:")
render_product(product)
|> String.trim_trailing()
|> Shell.info()
Shell.info("")
error ->
Shell.render_error(error)
end
end
def user_list(org, product) do
auth = Shell.request_auth()
case NervesHubCLI.API.ProductUser.list(org, product, auth) do
{:ok, %{"data" => users}} ->
render_users(users)
error ->
Shell.info("Failed to list product users \nreason: #{inspect(error)}")
end
end
def user_add(org, product, username, role, auth \\ nil) do
Shell.info("")
Shell.info("Adding user '#{username}' to product '#{product}' with role '#{role}'...")
auth = auth || Shell.request_auth()
case NervesHubCLI.API.ProductUser.add(org, product, username, String.to_atom(role), auth) do
{:ok, %{"data" => %{} = _product_user}} ->
Shell.info("User '#{username}' was added.")
error ->
Shell.render_error(error)
end
end
def user_update(org, product, username, role) do
Shell.info("")
Shell.info("Updating user '#{username}' in product '#{product}' to role '#{role}'...")
auth = Shell.request_auth()
case NervesHubCLI.API.ProductUser.update(org, product, username, String.to_atom(role), auth) do
{:ok, %{"data" => %{} = _product_user}} ->
Shell.info("User '#{username}' was updated.")
{:error, %{"errors" => %{"detail" => "Not Found"}}} ->
Shell.error("""
'#{username}' is not a user for product '#{product}'.
""")
if Shell.yes?("Would you like to add them?") do
user_add(org, product, username, role, auth)
end
error ->
Shell.render_error(error)
end
end
def user_remove(org, product, username) do
Shell.info("")
Shell.info("Removing user '#{username}' from product '#{product}'...")
auth = Shell.request_auth()
case NervesHubCLI.API.ProductUser.remove(org, product, username, auth) do
{:ok, ""} ->
Shell.info("User '#{username}' was removed.")
{:error, %{"errors" => %{"detail" => "Not Found"}}} ->
Shell.error("""
'#{username}' is not a user for the product '#{product}'
""")
error ->
IO.inspect(error)
Shell.render_error(error)
end
end
defp render_product(params) do
"""
name: #{params["name"]}
"""
end
defp render_users(users) when is_list(users) do
Shell.info("\nProduct users:")
Enum.each(users, fn params ->
Shell.info("------------")
render_user(params)
end)
Shell.info("------------")
Shell.info("")
end
defp render_user(params) do
Shell.info(" username: #{params["username"]}")
Shell.info(" role: #{params["role"]}")
end
end