### Setup Mkdocs Development Environment Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/CONTRIBUTING.md Install Python dependencies and start the Mkdocs local development server to preview documentation changes. ```bash python3 -m pip install -r requirement.txt mkdocs serve ``` -------------------------------- ### Generate PHPDoc Documentation (Docker) Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/CONTRIBUTING.md Build the PHP documentation using Docker and then start a local development server to view the generated PHP reference. Requires Docker to be installed and running. ```bash # Build the docs using Docker docker run --rm -v $(pwd):/data phpdoc/phpdoc run -c phpdoc.dist.xml # Start a local development server cd .phpdoc/build php -S localhost:8000 ``` -------------------------------- ### Example Firewall Alias Configuration Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/GRAPHQL.md This is an example of a firewall alias configuration object. ```json [ { "id": 0, "name": "alias1", "type": "host", "address": [ "127.0.0.1" ], "detail": ["localhost"] } ] ``` -------------------------------- ### Install pfSense REST API Package on Plus Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/INSTALL_AND_CONFIG.md Use this command to install the REST API package on pfSense Plus. The -C /dev/null flag is specific to Plus installations. Verify the package URL matches your pfSense version. ```bash pkg-static -C /dev/null add https://github.com/pfrest/pfSense-pkg-RESTAPI/releases/latest/download/pfSense-26.03-pkg-RESTAPI.pkg ``` -------------------------------- ### Format PHP Files with Prettier Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/CONTRIBUTING.md Install Prettier and the Prettier-PHP plugin using npm. Then, format all project files by running the specified command from the project root. ```bash npm install ``` ```bash ./node_modules/.bin/prettier --write . ``` -------------------------------- ### Install REST API Package on pfSense Plus Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/README.md Use this command to install the REST API package on pfSense Plus. Ensure your pfSense version is supported. ```bash pkg-static -C /dev/null add https://github.com/pfrest/pfSense-pkg-RESTAPI/releases/latest/download/pfSense-26.03.1-pkg-RESTAPI.pkg ``` -------------------------------- ### Install REST API Package on pfSense CE Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/README.md Use this command to install the REST API package on pfSense CE. Ensure your pfSense version is supported. ```bash pkg-static add https://github.com/pfrest/pfSense-pkg-RESTAPI/releases/latest/download/pfSense-2.8.1-pkg-RESTAPI.pkg ``` -------------------------------- ### Minimal Test Case Example Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/AGENTS.md Demonstrates how to write a basic test case using the custom framework to assert that an invalid firewall alias name triggers a specific response. ```php assert_throws_response( response_id: "INVALID_FIREWALL_ALIAS_NAME", code: 400, callable: function () { $alias = new FirewallAlias(data: ["name" => "!!bad", "type" => "host"]); $alias->validate(); }, ); } } ``` -------------------------------- ### Format Python Files with Black Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/CONTRIBUTING.md Install Black using pip with requirements.txt. Then, format all Python files in the project by running the 'black .' command from the project root. ```bash pip install -r requirements.txt ``` ```bash black . ``` -------------------------------- ### Generate PHPDoc Documentation (Phar) Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/CONTRIBUTING.md Download the PHPDocumentor Phar, build the documentation using the configuration file, and start a local development server to view the generated PHP reference. ```bash # Download the phpdoc phar wget https://phpdoc.org/phpDocumentor.phar chmod +x phpDocumentor.phar # Build the docs ./phpDocumentor.phar -c phpdoc.dist.xml # Start a local development server cd .phpdoc/build php -S localhost:8000 ``` -------------------------------- ### Write a PHP Test Case Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/CONTRIBUTING.md Extend the TestCase class to create new tests. Methods starting with 'test' will be executed. Ensure necessary autoloader is included. ```php assert_is_true(true); } } ``` -------------------------------- ### Define Custom Model with CRUD Methods Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/BUILDING_CUSTOM_MODEL_CLASSES.md This example shows how to define a custom Model class extending the base Model. It includes setting up fields and implementing the _create, _update, and _delete methods for custom data manipulation. ```php internal_callable = 'fetch_data'; $this->many = true; # Set model fields $this->name = new StringField( required: true, unique: true, help_text: 'Demonstrates an example StringField.', ); $this->timeout = new IntegerField( default: 30, help_text: 'Demonstrates an example IntegerField.', ); $this->enabled = new BooleanField( default: true, indicates_true: "on", // The value stored in the XML configuration when the field is true indicates_false: "off", // The value stored in the XML configuration when the field is false help_text: 'Demonstrates an example BooleanField.', ); parent::__construct($id, $parent_id, $data, ...$options); } /** * Fetches data for the Model object. * @return array The data for the Model object. */ public function fetch_data(): array { return [ [ 'name' => 'EXAMPLE_NAME_1', 'timeout' => 60, 'enabled' => true, ], [ 'name' => 'EXAMPLE_NAME_2', 'timeout' => 90, 'enabled' => false, ], ]; } /** * Defines steps to 'create' an instance of this Model. */ public function _create(): void { # TODO: Add custom logic to create an object } /** * Defines steps to 'update' an instance of this Model. */ public function _update(): void { # TODO: Add custom logic to update an object } /** * Defines steps to 'delete' an instance of this Model. */ public function _delete(): void { # TODO: Add custom logic to delete an object } } ``` -------------------------------- ### Prettier Formatting Command Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/AGENTS.md Use this command to format PHP files according to Prettier standards with the @prettier/plugin-php plugin. Ensure Node.js and npm are installed. ```bash npm install ./node_modules/.bin/prettier --write ./pfSense-pkg-RESTAPI/files ``` -------------------------------- ### JSON Content Type Example Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/CONTENT_AND_ACCEPT_TYPES.md Use `application/json` to send JSON data in the request body. The data must be a valid JSON object or array. ```json {"key": "value"} ``` -------------------------------- ### Specify Required pfSense Packages Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/BUILDING_CUSTOM_MODEL_CLASSES.md Define an array of pfSense package short names required for the Model to function. An error is thrown if these packages are not installed when attempting to modify model objects. ```php $this->packages = ['pfSense-pkg-nmap', 'pfSense-pkg-sudo']; ``` -------------------------------- ### Define StringField with Choices Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/BUILDING_CUSTOM_MODEL_CLASSES.md Example of defining a StringField with a list of predefined choices. This ensures the field only accepts values from the specified list. ```php $this->field = new StringField( required: true, choices: ['choice1', 'choice2', 'choice3'] ); ``` ```php $this->field = new StringField( required: true, choices: ['choice1' => 'Choice 1', 'choice2' => 'Choice 2', 'choice3' => 'Choice 3'] ); ``` -------------------------------- ### Black Formatting Command Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/AGENTS.md Use this command to format Python files according to Black standards. Ensure Python and pip are installed and requirements.txt is present. ```bash pip install -r requirements.txt && black . ``` -------------------------------- ### Update pfSense REST API Package to Latest Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/INSTALL_AND_CONFIG.md Run this command to update the REST API package to the latest available version compatible with your pfSense installation. ```bash pfsense-restapi update ``` -------------------------------- ### Build pfSense Package with vagrant-build.sh Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/CONTRIBUTING.md Execute the vagrant-build.sh script from the project root to create a FreeBSD virtual machine and build the package. The resulting .pkg file will be in the current working directory. ```bash sh vagrant-build.sh ``` -------------------------------- ### POST /graphql - Create VLAN, Interface, and Gateway Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/GRAPHQL.md Demonstrates how to create a VLAN, assign an interface, create a gateway, and update the interface to use that gateway in a single request. ```APIDOC ## POST /graphql ### Description Performs a multi-step network configuration including VLAN creation, interface assignment, gateway creation, and interface update. ### Method POST ### Endpoint /graphql ### Request Body - **createInterfaceVLAN** (object) - Required - Parameters for VLAN creation. - **createInterface** (object) - Required - Parameters for interface configuration. - **createRoutingGateway** (object) - Required - Parameters for gateway creation. - **updateInterface** (object) - Required - Parameters to link the gateway to the interface. ### Request Example mutation { createInterfaceVLAN( if: "em0", tag: 5, descr: "Example VLAN Interface", ) { if tag descr } createInterface( if: "em0.5", descr: "Example Interface", type: VAL_STATICV4, ipaddr: "192.168.5.100", subnet: 24 ) { if descr type ipaddr subnet } createRoutingGateway( name: "example_gateway", ipporotocol: VAL_INET, interface: "opt1", gateway: "192.168.5.1" ) { name ipporotocol interface gateway } updateInterface( id: "opt1", gateway: "example_gateway", apply: true ) { id gateway } } ``` -------------------------------- ### Build pfSense Package with Vagrant Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/AGENTS.md Use this script to build the pfSense package on a development machine with VirtualBox and Vagrant. The output package will be located in the repository root. ```bash # Easiest path: VirtualBox + Vagrant on your dev machine sh vagrant-build.sh # Output: pfSense-pkg-RESTAPI-.pkg in the repo root ``` -------------------------------- ### Access Native Schema Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/NATIVE_SCHEMA.md Make a GET request to this endpoint to retrieve the native schema. Authentication is not required. ```http GET /api/v2/schema/native ``` -------------------------------- ### Initialize a Custom ContentHandler Class Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/BUILDING_CUSTOM_CONTENT_HANDLER_CLASSES.md Use this template to create a new ContentHandler. Place the file in /usr/local/pkg/RESTAPI/ContentHandlers/ with a .inc extension. ```php url = '/api/v2/my/custom/endpoint'; ``` -------------------------------- ### POST /graphql - Create Alias and Firewall Rule Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/GRAPHQL.md Demonstrates how to create a firewall alias and a corresponding firewall rule that references that alias in one request. ```APIDOC ## POST /graphql ### Description Creates a new firewall alias and a firewall rule referencing that alias in a single GraphQL mutation. ### Method POST ### Endpoint /graphql ### Request Body - **createFirewallAlias** (object) - Required - Contains name, type, address, and detail. - **createFirewallRule** (object) - Required - Contains interface, type, ipprotocol, protocol, source, destination, and descr. ### Request Example mutation { createFirewallAlias( name: "example_alias", type: VAL_HOST, address: ["example.com"], detail: ["Example FQDN"] ) { id } createFirewallRule( interface: "lan", type: VAL_PASS, ipprotocol: VAL_INET, protocol: VAL_TCP, source: "lan", destination: "example_alias", descr: "Allow traffic to hosts defined in the newly created alias" ) { id interface type ipprotocol protocol source destination descr } } ``` -------------------------------- ### Initialize a Custom Cache Class Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/BUILDING_CUSTOM_CACHE_CLASSES.md Use this template to create a new Cache class. Ensure the file is saved in /usr/local/pkg/RESTAPI/Caches/ with a .inc extension. ```php package_includes = ['nmap.inc', 'sudo.inc']; ``` -------------------------------- ### Implement the _process Method Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/BUILDING_CUSTOM_DISPATCHER_CLASSES.md Define the logic to be executed in the background within the _process method. ```php /** * Method to execute the Dispatcher operation */ protected function _process(): void { # TODO Add your operation code here } ``` -------------------------------- ### Create VLAN, Interface, and Gateway via GraphQL Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/GRAPHQL.md Chains multiple mutations to provision a VLAN, assign an interface, create a gateway, and update the interface configuration. ```graphql mutation { createInterfaceVLAN( if: "em0", tag: 5, descr: "Example VLAN Interface", ) { if tag descr } createInterface( if: "em0.5", descr: "Example Interface", type: VAL_STATICV4, ipaddr: "192.168.5.100", subnet: 24 ) { if descr type ipaddr subnet } createRoutingGateway( name: "example_gateway", ipporotocol: VAL_INET, interface: "opt1", gateway: "192.168.5.1" ) { name ipporotocol interface gateway } updateInterface( id: "opt1", gateway: "example_gateway", apply: true ) { id gateway } } ``` ```json { "data": { "createInterfaceVLAN": { "if": "em0", "tag": 5, "descr": "Example VLAN Interface" }, "createInterface": { "if": "em0.5", "descr": "Example Interface", "type": "VAL_STATICV4", "ipaddr": "192.168.5.100", "subnet": 24 }, "createRoutingGateway": { "name": "example_gateway", "ipporotocol": "VAL_INET", "interface": "opt1", "gateway": "192.168.5.1" }, "updateInterface": { "id": "opt1", "gateway": "example_gateway" } } } ``` -------------------------------- ### Spawn a Dispatcher Process Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/BUILDING_CUSTOM_DISPATCHER_CLASSES.md Execute the background operation by instantiating the class and calling the spawn_process method. ```php $dispatcher = new MyCustomDispatcher(async: true); $dispatcher->spawn_process(); ``` -------------------------------- ### Initialize Custom Endpoint Class Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/BUILDING_CUSTOM_ENDPOINT_CLASSES.md Use this template to create a new Endpoint class. Ensure the parent constructor is called at the end of the __construct method. ```php config_path = 'path/to/model/objects/in/config'; $this->many = true; # Set model fields $this->name = new StringField( required: true, unique: true, help_text: 'Demonstrates an example StringField.', ); $this->timeout = new IntegerField( default: 30, help_text: 'Demonstrates an example IntegerField.', ); $this->enabled = new BooleanField( default: true, indicates_true: "on", // The value stored in the XML configuration when the field is true indicates_false: "off", // The value stored in the XML configuration when the field is false help_text: 'Demonstrates an example BooleanField.', ); parent::__construct($id, $parent_id, $data, ...$options); } } ``` -------------------------------- ### Example of Object and Parent IDs in JSON Response Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/WORKING_WITH_OBJECT_IDS.md This JSON structure demonstrates how `id` and `parent_id` fields are used to represent parent-child relationships, particularly within nested arrays like 'aliases'. Note that `parent_id` references the parent's `id`, and each child also has its own `id`. ```json { "code": 200, "status": "ok", "response_id": "SUCCESS", "message": "", "data": { "id": 0, "host": "parent", "domain": "example.com", "ip": ["1.2.3.4"], "descr": "I am a parent Host Override object.", "aliases": [ { "parent_id": 0, "id": 0, "host": "child1", "domain": "example.com", "descr": "I am a child Host Override Alias object under my parent Host Override 'parent.example.com'" }, { "parent_id": 0, "id": 1, "host": "child2", "domain": "example.com", "descr": "I am also a child Host Override Alias object under my parent Host Override 'parent.example.com'" } ] } } ``` -------------------------------- ### Build REST API Endpoints Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/BUILDING_CUSTOM_ENDPOINT_CLASSES.md Generate PHP files for all implemented Endpoint classes in the pfSense web root by running this command in the terminal. ```shell pfsense-restapi buildendpoints ``` -------------------------------- ### Run Package Tests with Keyword Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/CONTRIBUTING.md Filter and run tests that contain a specific keyword using the command line interface. ```bash pfsense-restapi runtests ``` -------------------------------- ### Regenerate OpenAPI Schemas Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/CONTRIBUTING.md Run this command on your pfSense instance to regenerate the OpenAPI documentation after making changes to the package's codebase. ```bash pfsense-restapi buildschemas ``` -------------------------------- ### Run pfSense REST API Tests Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/AGENTS.md Execute the full test suite or filter tests by keyword directly on the pfSense host. These commands are part of the runtime CLIs. ```bash pfsense-restapi runtests # run the full test suite pfsense-restapi runtests # filter by keyword ``` -------------------------------- ### Clone pfSense-pkg-RESTAPI Repository Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/CONTRIBUTING.md Clone the project repository to your development machine using the provided Git command. ```bash git clone git@github.com:pfrest/pfSense-pkg-RESTAPI.git ``` -------------------------------- ### Create Alias and Firewall Rule via GraphQL Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/GRAPHQL.md Executes a mutation to define a new host alias and immediately reference it in a firewall rule. ```graphql mutation { createFirewallAlias( name: "example_alias", type: VAL_HOST, address: ["example.com"], detail: ["Example FQDN"] ) { id } createFirewallRule( interface: "lan", type: VAL_PASS, ipprotocol: VAL_INET, protocol: VAL_TCP, source: "lan", destination: "example_alias", descr: "Allow traffic to hosts defined in the newly created alias" ) { id interface type ipprotocol protocol source destination descr } ``` ```json { "data": { "createFirewallAlias": { "id": 1 }, "createFirewallRule": { "id": 4, "interface": [ "lan" ], "type": "VAL_PASS", "ipprotocol": "VAL_INET", "protocol": "VAL_TCP", "source": "lan", "destination": "alias2", "descr": "Allow traffic to hosts defined in the newly created alias" } } } ``` -------------------------------- ### Basic Authentication (Short Syntax) with curl Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/AUTHENTICATION_AND_AUTHORIZATION.md This short syntax for Basic authentication is convenient for curl. It automatically formats the Authorization header. ```bash curl -u admin:pfsense https://pfsense.example.com/api/v2/firewall/rules ``` -------------------------------- ### Basic Authentication (Full Syntax) with curl Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/AUTHENTICATION_AND_AUTHORIZATION.md Use this syntax for Basic authentication when providing the full Authorization header. Ensure the base64 encoded string is correctly formatted. ```bash curl -H "Authorization: Basic YWRtaW46cGZzZW5zZQo=" https://pfsense.example.com/api/v2/firewall/rules ``` -------------------------------- ### Initialize Custom Validator Class Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/BUILDING_CUSTOM_VALIDATOR_CLASSES.md Use this template to define a new Validator class. Place the file in the /usr/local/pkg/RESTAPI/Validators/ directory with a .inc extension. ```php config_path = 'unbound/hosts'; ``` -------------------------------- ### Generate OpenAPI and GraphQL Schemas Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/BUILDING_CUSTOM_ENDPOINT_CLASSES.md Regenerate the OpenAPI and GraphQL schemas for all Endpoint classes by executing this command. ```shell pfsense-restapi buildschemas ``` -------------------------------- ### Define the get_data_to_cache Method Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/BUILDING_CUSTOM_CACHE_CLASSES.md Implement this method to return the array of data that the system will store in the cache file. ```php /** * Method to fetch the data to cache * @return array The data to cache */ protected function get_data_to_cache(): array { # TODO: Add your data fetching logic here } ``` -------------------------------- ### Local Code Style and Syntax Checks Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/AGENTS.md Perform local checks for code style and syntax without requiring a pfSense instance. These include checks for JavaScript, PHP, and Python code. ```bash ./node_modules/.bin/prettier --check ./pfSense-pkg-RESTAPI/files # style phplint -vvv --no-cache # syntax black --check . ``` ```bash pylint $(git ls-files '*.py') ``` ```bash ./phpdoc # PHPDoc render check ``` -------------------------------- ### Basic GraphQL Mutation Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/GRAPHQL.md Creates a new firewall alias with specified attributes and returns selected fields of the created object. ```graphql mutation { createFirewallAlias(name: "alias2", type: VAL_HOST, address: ["127.0.0.1"], detail: ["localhost"]) { id name address } } ``` -------------------------------- ### Custom Model Class Template Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/BUILDING_CUSTOM_MODEL_CLASSES.md Use this template to initialize a new custom Model class. Ensure the file is placed in the correct directory and the constructor signature and parent call are maintained. ```php ' with the desired version number. ```bash pfsense-restapi revert ``` -------------------------------- ### GraphQL Query with Variables Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/GRAPHQL.md Demonstrates parameterizing a query by defining variables in the request body. ```json { "query": "query ReadFirewallAlias($id: Int!) { readFirewallAlias(id: $id) { name address } }", "variables": { "id": 0 } } ``` -------------------------------- ### Define a Custom Dispatcher Class Source: https://github.com/pfrest/pfsense-pkg-restapi/blob/master/docs/BUILDING_CUSTOM_DISPATCHER_CLASSES.md Create a new Dispatcher class by extending the base Dispatcher class and placing it in the appropriate directory. ```php