DNSCrypt Proxy Plugin

SettingsController extends ApiMutableModelControllerBase
in package

An ApiMutableModelControllerBase class used to perform settings related actions for dnscrypt-proxy.

This API is accessible at the following URL endpoint:

/api/dnscryptproxy/settings

This class creates the following API endpoints:

  grid
  import
  export
  restoreSources

Functions with a name ending in "Action" become API endpoints by extending ApiMutableModelControllerBase.

Table of Contents

$valid_grid_targets  : array<string|int, mixed>
Array for defining valid targets to use with the functions within this class.
$internalModelClass  : string
Base model class to reference.
$internalModelName  : string
This variable defines what to call the <model> that is defined for this Class by Phalcon. That is to say the model XML that has the same name as this controller's name, "Settings".
bootgridConfigd()  : array<string|int, mixed>
Execute a configd command, and return the output in a format consumable by bootgrid.
exportAction()  : mixed
Export entries out of an ArrayField type node in the config.. Uses a pre-defined set of targets (paths) to prevent arbitrary export of data.
gridAction()  : array<string|int, mixed>
This is a super API for Bootgrid which will do all the things.
importAction()  : mixed
Import data provided by the user in a file upload into ArrayField type nodes in the config.
indexAction()  : array<string|int, mixed>
An API endpoint to call when no parameters are provided for the API. Can be used to test the API is working.
initialize()  : mixed
Initilize the class, populate the valid_grid_targets with values from the form XML for this form.
restoreSourcesAction()  : array<string|int, mixed>
Special function to restore the default sources into the config.
searchGrids()  : array<string|int, mixed>
Form parser for bootgrid fields.

Properties

$valid_grid_targets

Array for defining valid targets to use with the functions within this class.

public array<string|int, mixed> $valid_grid_targets = array()

$internalModelClass

Base model class to reference.

protected static string $internalModelClass = 'OPNsense\Dnscryptproxy\Settings'

This variable defines which class to call for getMode(). It is used in a ReflectionClass call to establish the model object. This class is defined in the models directory alongside the model XML, and has the same name as this Controller. This class extends BaseModel which reads the model XML that has the same name as the class.

In this case, these are the model XML file, and class definition file:

model/OPNsense/Dnscryptproxy/Settings.xml

model/OPNsense/Dnscryptproxy/Settings.php

These together will establish several API endpoints on this Controller's endpoint including:

/api/dnscryptproxy/settings/get

/api/dnscryptproxy/settings/set

These are both defined in the ApiMutableModelControllerBase Class:

function getAction()

function setAction()

$internalModelName

This variable defines what to call the <model> that is defined for this Class by Phalcon. That is to say the model XML that has the same name as this controller's name, "Settings".

protected static string $internalModelName = 'settings'

In this case, it is the model XML file:

model/OPNsense/Dnscryptproxy/Settings.xml

The model name is then used as the name of the array returned by setBase() and getBase(). In the form XMLs, the prefix used on the field IDs must match this name as API actions use the same name in their transactions. For example, the key_name in an API JSON response, will be this model name. This name is also used as the API endpoint for this Controller.

/api/dnscryptproxy/settings

This locks activies of this Class to this specific model, so it won't save to other models, even within the same plugin.

Methods

bootgridConfigd()

Execute a configd command, and return the output in a format consumable by bootgrid.

public bootgridConfigd(string $configd_cmd, array<string|int, mixed> $fields) : array<string|int, mixed>

It executes configd with the given commands, and returns JSON for bootrid to consume. It works similar to, and sourced mostly from searchBase(), but with some differences and added functionality.

Takes most parameters via POST just like *Base() functions.

Lots of comments because this function is a bit confusing to start.

Parameters
$configd_cmd : string

path to search, relative to this model

$fields : array<string|int, mixed>

field names to fetch in result

Return values
array<string|int, mixed>

output from the configd command

exportAction()

Export entries out of an ArrayField type node in the config.. Uses a pre-defined set of targets (paths) to prevent arbitrary export of data.

public exportAction() : mixed

API endpoint: /api/dnscryptproxy/settings/export

Expects to receive a value "target" defined in the data in the GET request.

Example usage (in Javascript): ajaxGet("/api/dnscryptproxy/settings/export", {"target": "allowed_names_internal"}, function(data, status){...

The second parameter is the data (array) where "target" is defined.

Return values
mixed

gridAction()

This is a super API for Bootgrid which will do all the things.

public gridAction(string $action, string $target[, string $uuid = null ]) : array<string|int, mixed>

Instead of having many copies of the same functions over and over, this function replaces all of them, and it requires only setting a couple of variables and adjusting the conditional statements to add or remove grids.

API endpoint:

/api/dnscryptproxy/settings/grid

Parameters for this function are passed in via POST/GET request in the URL like so:

|-------API Endpoint (Here)-----|api|----$target---|--------------$uuid----------------|
api/dnscryptproxy/settings/grid/get/servers.server/9d606689-19e0-48a7-84b2-9173525255d8

This handles all of the bootgrid API calls, and keeps everything in a single function. Everything is controled via the $target and pre-defined variables which include the config path, and the key name for the edit dialog.

A note on the edit dialog, the $key_name must match the prefix of the IDs of the fields defined in the form data for that dialog.

Example:

 <field>
    <id>server.enabled</id>
    <label>Enabled</label>
    <type>checkbox</type>
    <help>This will enable or disable the server stamp.</help>
 </field>

For the case above, the $key_name must be: "server"

This correlates to the config path:

//OPNsense/dnscrypt-proxy/servers/server

servers is the ArrayField that these bootgrid functions are designed for.

server is the final node in the config path, and are entries in the ArrayField.

The $key_name, the final node in the path, and the field ids in the form XML must match. The field is important because when mapDataToFormUI() runs to populate the fields with data, the scope is just the dialog box (which includes the fields). It will try to match ids with the data it receives, and it splits up the ids at the period, using the first element as its key_name for matching. This is also how the main form works, and why all of those ids are prefixed with the model name.

So get/set API calls return a JSON with a key named 'server', and the data gets sent to fields which have a dotted prefix of the same name. This links these elements together, though they are not directly linked, only merely aligned together.

Upon saving (using setBase()) it sends the POST data specified in the function call wholesale, that array has to overlay perfectly on the model.

Parameters
$action : string

The desired action to take for the API call.

$target : string

The desired pre-defined target for the API.

$uuid : string = null

The UUID of the target object.

Return values
array<string|int, mixed>

Array to be consumed by bootgrid.

importAction()

Import data provided by the user in a file upload into ArrayField type nodes in the config.

public importAction() : mixed

API endpoint:

/api/dnscryptproxy/settings/import

Takes data from POST variables data and target, validates accordingly, then updates existing objects with the same UUID, or creates new entries then saves the entries into the config.

Example usage (Javascript):

ajaxCall("/api/dnscryptproxy/settings/import",
         {'data': import_data,'target': 'allowed_names_internal' },
         function(data,status) {...

The second paramter is the data (array) where data, and target are defined.

No support for CSVListField types within an ArrayField type. Attempting currently returns error:

Error at /usr/local/opnsense/mvc/app/models/OPNsense/Base/FieldTypes/BaseField.php:639
It is not yet possible to assign complex types to properties (errno=2)

This was mostly copied from the firewall plugin.

Return values
mixed

indexAction()

An API endpoint to call when no parameters are provided for the API. Can be used to test the API is working.

public indexAction() : array<string|int, mixed>

API endpoint:

/api/dnscryptproxy/settings

Usage:

/api/dnscryptproxy/settings

Returns an array which gets converted to json in the POST response.

Return values
array<string|int, mixed>

includes status, saying everything is A-OK

initialize()

Initilize the class, populate the valid_grid_targets with values from the form XML for this form.

public initialize() : mixed

This parses the form XML for bootgrid fields, and puts them into a class variable for use by other functions within the class.

This eliminates the needs to duplicate this information statically in the class itself. All data is dynamically pulled from the form XML instead.

Return values
mixed

restoreSourcesAction()

Special function to restore the default sources into the config.

public restoreSourcesAction() : array<string|int, mixed>

WARNING: This function WIPES ALL existing sources.source entires.

API endpoint:

/api/dnscryptproxy/settings/restoreSources

This function will restore the sources back to the ones defined by the application author inlcluded in the example dnscrypt-proxy.toml.

This is probably not ideal with this data being hardcoded in the source. I'll probably visit this later to see if I can come up with another way.

It uses a bit of a janky approach but was the best approach I could figure out with the fewest lines of code, while also being fairly clear about what is happening.

Return values
array<string|int, mixed>

addBase() results

searchGrids()

Form parser for bootgrid fields.

private searchGrids(array<string|int, mixed> $tabs) : array<string|int, mixed>

This is used by initiatize() to walk through te tabs array to pull bootgrid fields, and their respsective targets, and fields.

This funciton utilizes recursion to reduce code duplication.

Parameters
$tabs : array<string|int, mixed>

The form's tabs to be parsed.

Return values
array<string|int, mixed>

Associtative array of targets, and their field names.

Search results