Skip to content

Commit

Permalink
Pull out extra data structures
Browse files Browse the repository at this point in the history
There were some extra data structures that made it more difficult to use
`VintageNet` so I pulled those out. This should make getting and setting
configurations between `VintageNet` and `VintageNetWizard` more straight
forward.
  • Loading branch information
mattludwigs committed Jan 27, 2021
1 parent 2e0f841 commit 8877785
Show file tree
Hide file tree
Showing 17 changed files with 144 additions and 472 deletions.
10 changes: 6 additions & 4 deletions lib/vintage_net_wizard/backend.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ defmodule VintageNetWizard.Backend do
messages, and scanning the network
"""

alias VintageNetWizard.WiFiConfiguration
alias VintageNetWiFi.AccessPoint

@type device_info_name() :: String.t()
Expand All @@ -31,8 +30,11 @@ defmodule VintageNetWizard.Backend do

@doc """
Apply the WiFi configurations
The configurations passed are network configurations that can be passed into
the `:network` list in a `VintageNetWiFi` configuration.
"""
@callback apply([WiFiConfiguration.t()], state :: any()) ::
@callback apply([map()], state :: any()) ::
{:ok, state :: any()} | {:error, :invalid_state}

@doc """
Expand Down Expand Up @@ -67,7 +69,7 @@ defmodule VintageNetWizard.Backend do
@callback reset(state :: any()) :: state :: any()

@doc """
Perform final completion steps.
Perform final completion steps for the network configurations
"""
@callback complete([WiFiConfiguration.t()], state :: any()) :: {:ok, state :: any()}
@callback complete([map()], state :: any()) :: {:ok, state :: any()}
end
5 changes: 1 addition & 4 deletions lib/vintage_net_wizard/backend/default.ex
Original file line number Diff line number Diff line change
Expand Up @@ -148,13 +148,10 @@ defmodule VintageNetWizard.Backend.Default do
def handle_info(_, state), do: {:noreply, state}

defp apply_configurations(wifi_configurations, state) do
vintage_net_config =
Enum.map(wifi_configurations, &WiFiConfiguration.to_vintage_net_configuration/1)

VintageNet.configure(state.ifname, %{
type: VintageNetWiFi,
vintage_net_wifi: %{
networks: vintage_net_config
networks: wifi_configurations
},
ipv4: %{method: :dhcp}
})
Expand Down
22 changes: 17 additions & 5 deletions lib/vintage_net_wizard/backend_server.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule VintageNetWizard.BackendServer do
"""
use GenServer

alias VintageNetWizard.{Backend, WiFiConfiguration}
alias VintageNetWizard.Backend
alias VintageNetWiFi.AccessPoint

defmodule State do
Expand Down Expand Up @@ -96,17 +96,20 @@ defmodule VintageNetWizard.BackendServer do
end

@doc """
Save a `WiFiConfiguration` to the backend
Save a network configuration to the backend
The network configuration is a map that can be included in the `:network`
field of a `VintageNetWiFi` configuration.
"""
@spec save(WiFiConfiguration.t()) :: :ok | {:error, any()}
@spec save(map()) :: :ok | {:error, any()}
def save(config) do
GenServer.call(__MODULE__, {:save, config})
end

@doc """
Get a list of the current configurations
"""
@spec configurations() :: [WiFiConfiguration.t()]
@spec configurations() :: [map()]
def configurations() do
GenServer.call(__MODULE__, :configurations)
end
Expand Down Expand Up @@ -225,7 +228,12 @@ defmodule VintageNetWizard.BackendServer do
end

def handle_call(:configurations, _from, %State{configurations: configs} = state) do
{:reply, build_config_list(configs), state}
cleaned_configs =
configs
|> build_config_list()
|> Enum.map(&clean_config/1)

{:reply, cleaned_configs, state}
end

def handle_call(
Expand Down Expand Up @@ -326,4 +334,8 @@ defmodule VintageNetWizard.BackendServer do

priority_index + 1
end

defp clean_config(config) do
Map.drop(config, [:psk, :password])
end
end
2 changes: 1 addition & 1 deletion lib/vintage_net_wizard/web/api.ex
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ defmodule VintageNetWizard.Web.Api do
conn
|> get_body()
|> Map.put("ssid", ssid)
|> WiFiConfiguration.from_params()
|> WiFiConfiguration.json_to_network_config()
end

defp make_error_message({:error, :password_required}) do
Expand Down
4 changes: 2 additions & 2 deletions lib/vintage_net_wizard/web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ defmodule VintageNetWizard.Web.Router do
password = conn.body_params["password"]
params = Map.put(conn.body_params, "ssid", ssid)

case WiFiConfiguration.from_params(params) do
case WiFiConfiguration.json_to_network_config(params) do
{:ok, wifi_config} ->
:ok = BackendServer.save(wifi_config)
redirect(conn, "/")
Expand Down Expand Up @@ -103,7 +103,7 @@ defmodule VintageNetWizard.Web.Router do

case Map.get(conn.body_params, "key_mgmt") do
"none" ->
{:ok, config} = WiFiConfiguration.from_params(conn.body_params)
{:ok, config} = WiFiConfiguration.json_to_network_config(conn.body_params)
:ok = BackendServer.save(config)

redirect(conn, "/")
Expand Down
113 changes: 61 additions & 52 deletions lib/vintage_net_wizard/wifi_configuration.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,72 +3,81 @@ defmodule VintageNetWizard.WiFiConfiguration do
Module for working with various WiFi configurations
"""

@opaque t ::
VintageNetWizard.WiFiConfiguration.WPAPersonal.t()
| VintageNetWizard.WiFiConfiguration.NoSecurity.t()
| VintageNetWizard.WiFiConfiguration.PEAPEnterprise.t()
@type key_mgmt() :: :none | :wpa_psk | :wpa_eap

@type key_mgmt() :: :none | :wpa_psk

alias VintageNetWizard.WiFiConfiguration.{
Params,
WPAPersonal,
NoSecurity,
PEAPEnterprise
}

@doc """
A function on how to transform the map of params into a WiFiConfiguration
"""
@callback from_params(map()) :: {:ok, t()} | {:error, Params.param_error()}

@doc """
A function on how to take a WiFiConfiguration and make it into
a useable `vintage_net` WiFi configuration.
"""
@callback to_vintage_net_configuration(t()) :: map()
alias VintageNetWizard.WiFiConfiguration.Params

@doc """
Marshal a parameter map into a type of WiFi Configuration
Make a network config from a JSON request from the `VintageNetWizard` client
"""
@spec from_params(map()) :: {:ok, t()} | {:error, Params.param_error()}
def from_params(%{"key_mgmt" => "wpa_psk"} = params) do
WPAPersonal.from_params(params)
end
@spec json_to_network_config(map()) :: {:ok, map()} | {:error, Params.param_error()}
def json_to_network_config(%{"key_mgmt" => "none"} = params) do
case Params.ssid_from_params(params) do
{:ok, ssid} ->
{:ok,
%{
ssid: ssid,
key_mgmt: :none,
mode: :infrastructure,
priority: nil
}}

def from_params(%{"key_mgmt" => "none"} = params) do
NoSecurity.from_params(params)
error ->
error
end
end

def from_params(%{"key_mgmt" => "wpa_eap"} = params) do
PEAPEnterprise.from_params(params)
def json_to_network_config(%{"key_mgmt" => "wpa_psk"} = params) do
with {:ok, password} <- Params.password_from_params(params),
{:ok, ssid} <- Params.ssid_from_params(params),
:ok <- Params.validate_password(password) do
{:ok,
%{
ssid: ssid,
mode: :infrastructure,
key_mgmt: :wpa_psk,
psk: password,
priority: nil
}}
else
error -> error
end
end

@doc """
Take a particular type of WiFi configuration and make into a configuration
that `vintage_net` can use
"""
@spec to_vintage_net_configuration(struct()) :: map()
def to_vintage_net_configuration(config) do
module = config.__struct__
module.to_vintage_net_configuration(config)
def json_to_network_config(%{"key_mgmt" => "wpa_eap"} = params) do
with {:ok, ssid} <- Params.ssid_from_params(params),
{:ok, password} <- Params.password_from_params(params),
{:ok, user} <- Params.user_from_params(params),
:ok <- Params.validate_peap_password(password) do
{:ok,
%{
mode: :infrastructure,
key_mgmt: :wpa_eap,
eap: "PEAP",
phase2: "auth=MSCHAPV2",
ssid: ssid,
identity: user,
password: password,
priority: nil
}}
else
error -> error
end
end

@doc """
Get the expected timeout in milisecs for a particular configuration
"""
@spec timeout(t()) :: non_neg_integer()
def timeout(%NoSecurity{}), do: 30_000
def timeout(%WPAPersonal{}), do: 30_000
def timeout(%PEAPEnterprise{}), do: 75_000
@spec timeout(%{key_mgmt: key_mgmt()}) :: 30_000 | 75_000
def timeout(%{key_mgmt: :none}), do: 30_000
def timeout(%{key_mgmt: :wpa_psk}), do: 30_000
def timeout(%{key_mgmt: :wpa_eap}), do: 75_000

@doc """
Get the `key_mgmt` type from the particular WiFi Configuration
"""
@spec get_key_mgmt(t()) :: key_mgmt()
def get_key_mgmt(%WPAPersonal{}), do: :wpa_psk
def get_key_mgmt(%NoSecurity{}), do: :none
def get_key_mgmt(%PEAPEnterprise{}), do: :wpa_eap
@spec get_key_mgmt(map()) :: key_mgmt()
def get_key_mgmt(%{key_mgmt: key_mgmt}), do: key_mgmt

@doc """
Convert a key_mgmt string into a key_mgmt
Expand All @@ -82,8 +91,8 @@ defmodule VintageNetWizard.WiFiConfiguration do
@doc """
Get a human friendly name for the type of security of a WiFiConfiguration
"""
@spec security_name(t()) :: String.t()
def security_name(%WPAPersonal{}), do: "WPA Personal"
def security_name(%NoSecurity{}), do: "None"
def security_name(%PEAPEnterprise{}), do: "WPA Enterprise"
@spec security_name(%{key_mgmt: key_mgmt()}) :: String.t()
def security_name(%{key_mgmt: :wpa_psk}), do: "WPA Personal"
def security_name(%{key_mgmt: :wpa_eap}), do: "WPA Enterprise"
def security_name(%{key_mgmt: :none}), do: "None"
end
41 changes: 0 additions & 41 deletions lib/vintage_net_wizard/wifi_configuration/no_security.ex

This file was deleted.

29 changes: 28 additions & 1 deletion lib/vintage_net_wizard/wifi_configuration/params.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ defmodule VintageNetWizard.WiFiConfiguration.Params do

alias VintageNetWiFi.WPA2

@type param_error :: :invalid_ssid | :password_required | WPA2.invalid_passphrase_error()
@type param_error() ::
:invalid_ssid | :password_required | :user_required | WPA2.invalid_passphrase_error()

@doc """
Get the ssid form the configuration params
Expand All @@ -13,6 +14,16 @@ defmodule VintageNetWizard.WiFiConfiguration.Params do
def ssid_from_params(%{"ssid" => ssid}), do: {:ok, ssid}
def ssid_from_params(_), do: {:error, :invalid_ssid}

@doc """
Get the priority level from the params
This field is optional so this function will return `nil` if the params did
not the priority set.
"""
@spec priority_from_params(map()) :: non_neg_integer() | nil
def priority_from_params(%{"priority" => priority}), do: String.to_integer(priority)
def priority_from_params(_), do: nil

@doc """
Get and validate the password from the configuration params
Expand All @@ -35,10 +46,26 @@ defmodule VintageNetWizard.WiFiConfiguration.Params do

def password_from_params(_, _), do: {:error, :password_required}

@doc """
Try to get the user field from the parameters
"""
@spec user_from_params(map()) :: {:ok, String.t()} | {:error, param_error()}
def user_from_params(%{"user" => nil}), do: {:error, :user_required}
def user_from_params(%{"user" => user}), do: {:ok, user}
def user_from_params(_), do: {:error, :user_required}

@doc """
The default function used to valid a password
"""
@spec validate_password(String.t()) :: :ok | {:error, param_error()}
def validate_password(nil), do: {:error, :password_required}
def validate_password(password), do: WPA2.validate_passphrase(password)

@doc """
Validate enterprise passwords
"""
@spec validate_peap_password(String.t()) :: :ok | {:error, param_error()}
def validate_peap_password(nil), do: {:error, :password_required}
def validate_peap_password(""), do: {:error, :password_required}
def validate_peap_password(_pw), do: :ok
end

0 comments on commit 8877785

Please sign in to comment.