added self for nameservers for openApi defaults.

This commit is contained in:
tracer 2024-04-30 11:13:24 +02:00
parent d0224f6746
commit f25e90f292
13 changed files with 1114 additions and 668 deletions

148
bindapi.json Normal file
View File

@ -0,0 +1,148 @@
{
"openapi": "3.0.0",
"info": {
"title": "bindAPI",
"version": "1.0.9"
},
"servers": [
{
"url": "{schema}://{hostname}/api",
"description": "The bindAPI URL.",
"variables": {
"schema": {
"enum": [
"http",
"https"
],
"default": "https"
},
"hostname": {
"enum": [
"ns1.24unix.net",
"ns2.24unix.net"
],
"default": "ns2.24unix.net"
}
}
}
],
"paths": {
"/ping": {
"get": {
"tags": [
"Server"
],
"description": "Checks for connectivity and valid APIkey",
"operationId": "ping",
"responses": {
"200": {
"description": "OK"
},
"401": {
"description": "API key is missing or invalid."
}
},
"security": [
{
"Authorization": []
}
]
}
},
"/version": {
"get": {
"tags": [
"Server"
],
"description": "Check the API version of the nameserver.",
"operationId": "version",
"responses": {
"200": {
"description": "x.y.z, aka major, minor, patch"
},
"401": {
"description": "API key is missing or invalid."
}
},
"security": [
{
"Authorization": []
}
]
}
},
"/domains": {
"get": {
"tags": [
"Domains"
],
"summary": "List all domains.",
"description": "Returns a list of all domains on this server.",
"operationId": "getAllDomains",
"responses": {
"200": {
"description": "OK"
},
"401": {
"description": "API key is missing or invalid."
},
"404": {
"description": "Domain not found."
}
},
"security": [
{
"Authorization": []
}
]
}
},
"/domains/{name}": {
"get": {
"tags": [
"Domains"
],
"summary": "Returns a single domain.",
"description": "Returns information of a single domain specified by its domain name.",
"operationId": "getSingleDomain",
"parameters": [
{
"name": "name",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "OK"
},
"401": {
"description": "API key is missing or invalid."
},
"404": {
"description": "Domain not found."
}
},
"security": []
}
}
},
"components": {
"securitySchemes": {
"Authorization": {
"type": "apiKey",
"description": "Api Authentication",
"name": "X-API-Key",
"in": "header"
}
}
},
"tags": [
{
"name": "Server"
}
]
}

View File

@ -2,7 +2,7 @@
"name": "24unix/bindapi", "name": "24unix/bindapi",
"description": "manage Bind9 DNS server via REST API", "description": "manage Bind9 DNS server via REST API",
"version": "1.0.9", "version": "1.0.9",
"build_number": "359", "build_number": "361",
"authors": [ "authors": [
{ {
"name": "Micha Espey", "name": "Micha Espey",

View File

@ -1126,6 +1126,30 @@ return array (
'IS_GENERATED' => 'NEVER', 'IS_GENERATED' => 'NEVER',
'GENERATION_EXPRESSION' => NULL, 'GENERATION_EXPRESSION' => NULL,
), ),
'self' =>
array (
'TABLE_CATALOG' => 'def',
'TABLE_NAME' => 'nameservers',
'COLUMN_NAME' => 'self',
'ORDINAL_POSITION' => 7,
'COLUMN_DEFAULT' => NULL,
'IS_NULLABLE' => 'NO',
'DATA_TYPE' => 'enum',
'CHARACTER_MAXIMUM_LENGTH' => 3,
'CHARACTER_OCTET_LENGTH' => 12,
'NUMERIC_PRECISION' => NULL,
'NUMERIC_SCALE' => NULL,
'DATETIME_PRECISION' => NULL,
'CHARACTER_SET_NAME' => 'utf8mb4',
'COLLATION_NAME' => 'utf8mb4_unicode_ci',
'COLUMN_TYPE' => 'enum(\'yes\',\'no\')',
'COLUMN_KEY' => '',
'EXTRA' => '',
'PRIVILEGES' => 'select,insert,update,references',
'COLUMN_COMMENT' => '',
'IS_GENERATED' => 'NEVER',
'GENERATION_EXPRESSION' => NULL,
),
), ),
'indexes' => 'indexes' =>
array ( array (

View File

@ -1,13 +1,8 @@
{ {
"openapi": "3.0.2", "openapi": "3.0.0",
"info": { "info": {
"title": "bindAPI", "title": "bindAPI",
"version": "0.0.2", "version": "1.0.9"
"description": "TODO …",
"contact": {
"name": "Micha Espey",
"email": "tracer@24unix.net"
}
}, },
"servers": [ "servers": [
{ {
@ -16,31 +11,20 @@
"variables": { "variables": {
"schema": { "schema": {
"enum": [ "enum": [
"https", "http",
"http" "https"
], ],
"default": "https" "default": "https"
}, },
"hostname": { "hostname": {
"default": "ns1.24unix.net" "enum": [
} "ns1.24unix.net",
} "ns2.24unix.net",
} "ns3.24unix.net"
], ],
"tags": [ "default": "ns2.24unix.net"
{ }
"name": "Server"
},
{
"name": "DNS"
},
{
"name": "Domains"
} }
],
"security": [
{
"ApiKeyAuth": []
} }
], ],
"paths": { "paths": {
@ -49,59 +33,36 @@
"tags": [ "tags": [
"Server" "Server"
], ],
"summary": "Returning pong.", "description": "Checks for connectivity and valid APIkey",
"description": "Can be used to check API or server availability.", "operationId": "ping",
"operationId": "getPong",
"responses": {
"200": {
"$ref": "#/components/responses/ping"
},
"401": {
"$ref": "#/components/responses/401-unauthorized"
}
},
"security": [
{
"Authorization": [
"read"
]
}
]
}
},
"/dyndns/{hostname}": {
"post": {
"tags": [
"DNS"
],
"summary": "Updated a DynDNS host.",
"description": "Updates a predefined custom DNS entry.",
"operationId": "updateDynDNS",
"parameters": [
{
"name": "hostname",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"$ref": "#/components/requestBodies/dyndns-put"
},
"responses": { "responses": {
"200": { "200": {
"description": "OK" "description": "OK"
}, },
"204": { "401": {
"description": "No Content" "description": "API key is missing or invalid."
}
},
"security": [
{
"Authorization": []
}
]
}
},
"/version": {
"get": {
"tags": [
"Server"
],
"description": "Check the API version of the nameserver.",
"operationId": "version",
"responses": {
"200": {
"description": "x.y.z, aka major, minor, patch"
}, },
"401": { "401": {
"description": "API key is missing or invalid." "description": "API key is missing or invalid."
},
"404": {
"description": "Domain not found."
} }
}, },
"security": [ "security": [
@ -116,100 +77,9 @@
"tags": [ "tags": [
"Domains" "Domains"
], ],
"summary": "Returns all domains.", "summary": "List all domains.",
"description": "Returns information of a single domain specified by its domain name.", "description": "Returns a list of all domains on this server.",
"operationId": "getDomains", "operationId": "getAllDomains",
"responses": {
"200": {
"$ref": "#/components/responses/domain-array"
},
"401": {
"$ref": "#/components/responses/401-unauthorized"
}
},
"security": [
{
"Authorization": [
"read"
]
}
]
},
"post": {
"tags": [
"Domains"
],
"summary": "Create a domain.",
"description": "Create a new domain.",
"operationId": "putDomains",
"requestBody": {
"$ref": "#/components/requestBodies/domain-post"
},
"responses": {
"201": {
"$ref": "#/components/responses/201-created"
},
"400": {
"$ref": "#/components/responses/400-bad-request"
},
"401": {
"$ref": "#/components/responses/401-unauthorized"
}
}
}
},
"/domains/{id}": {
"get": {
"tags": [
"Domains"
],
"summary": "Returns a single domain.",
"description": "Returns information of a single domain specified by its ID.",
"operationId": "getSingleDomain",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"$ref": "#/components/responses/200-ok"
},
"400": {
"$ref": "#/components/responses/400-bad-request"
},
"401": {
"$ref": "#/components/responses/401-unauthorized"
}
}
},
"put": {
"tags": [
"Domains"
],
"summary": "Updates a domain.",
"description": "Updates a domain. Only supplied fields will be updated, existing won't be affected.",
"operationId": "putDomain",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"$ref": "#/components/requestBodies/domain-put"
},
"responses": { "responses": {
"200": { "200": {
"description": "OK" "description": "OK"
@ -226,49 +96,16 @@
"Authorization": [] "Authorization": []
} }
] ]
},
"delete": {
"tags": [
"Domains"
],
"summary": "Deletes a domain.",
"description": "Deletes a domain.",
"operationId": "73c6c14e6d84f759d2e09029cb7ab2be",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"204": {
"$ref": "#/components/responses/204-no-content"
},
"401": {
"$ref": "#/components/responses/401-unauthorized"
},
"404": {
"$ref": "#/components/responses/404-not-found"
}
}, "security": [
{
"Authorization": []
}
]
} }
}, },
"/domains/name/{name}": { "/domains/{name}": {
"get": { "get": {
"tags": [ "tags": [
"Domains" "Domains"
], ],
"summary": "Returns a single domain by name.", "summary": "Returns a single domain.",
"description": "Returns information of a single domain specified by its domain name.", "description": "Returns information of a single domain specified by its domain name.",
"operationId": "getSingleDomainByName", "operationId": "getSingleDomain",
"parameters": [ "parameters": [
{ {
"name": "name", "name": "name",
@ -281,15 +118,16 @@
], ],
"responses": { "responses": {
"200": { "200": {
"$ref": "#/components/responses/200-ok" "description": "OK"
},
"400": {
"$ref": "#/components/responses/400-bad-request"
}, },
"401": { "401": {
"$ref": "#/components/responses/401-unauthorized" "description": "API key is missing or invalid."
} },
"404": {
"description": "Domain not found."
} }
},
"security": []
} }
} }
}, },
@ -297,241 +135,15 @@
"securitySchemes": { "securitySchemes": {
"Authorization": { "Authorization": {
"type": "apiKey", "type": "apiKey",
"description": "Authentication Token", "description": "Api Authentication",
"name": "X-API-Key", "name": "X-API-Key",
"in": "header" "in": "header"
} }
},
"requestBodies": {
"dyndns-put": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/dyndns"
},
"example": {
"a": "1.2.3.4",
"aaaa": "1bad::babe"
}
}
} }
}, },
"domain-post": { "tags": [
"required": true, {
"content": { "name": "Server"
"application/json": {
"schema": {
"$ref": "#/components/schemas/domain"
} }
}
}
},
"domain-put": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/domain"
},
"example": {
"name": "example.com",
"panel_id": "8"
}
}
}
}
},
"responses": {
"ping": {
"description": "OK.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ping"
}
}
}
},
"domain": {
"description": "OK.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/domain"
}
}
}
},
"domain-array": {
"description": "OK.",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/domain"
}
}
}
}
},
"200-ok": {
"description": "OK."
},
"200-ok-updated": {
"description": "OK.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/created"
},
"example": {
"id": 8
}
}
}
},
"201-created": {
"description": "Created.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/created"
},
"example": {
"id": 8
}
}
}
},
"204-no-content": {
"description": "No content."
},
"400-bad-request": {
"description": "Bad request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/error"
},
"example": {
"code": "400 Bad Request",
"message": "Invalid request body."
}
}
}
},
"401-unauthorized": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/error"
},
"example": {
"code": "401 Unauthorized",
"message": "API key is missing or invalid."
}
}
}
},
"404-not-found": {
"description": "The specified resource was not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/error"
},
"example": {
"code": "404 Not Found",
"message": "The specified resource was not found."
}
}
}
}
},
"schemas": {
"ping": {
"type": "object",
"properties": {
"response": {
"type": "string",
"example": "pong"
}
}
},
"dyndns": {
"type": "object",
"properties": {
"a": {
"type": "string",
"example": "1.2.3.4"
},
"aaaa": {
"type": "string",
"example": "1bad::babe"
}
}
},
"domain": {
"description": "Representation of a domain.\n",
"type": "object",
"properties": {
"id": {
"type": "integer",
"readOnly": true,
"description": "The ID of the domain.",
"example": 8
},
"name": {
"type": "string",
"description": "The ASCII representation of the domain.",
"example": "example.com"
},
"panel_id": {
"type": "integer",
"description": "The KeyHelp Panel ID. Either this or at least one IP address is required",
"example": 4
},
"a": {
"type": "string",
"readOnly": true,
"description": "The IPv4 address.",
"example": "12.13.14.15"
},
"aaaa": {
"type": "string",
"readOnly": true,
"description": "The IPv6 address.",
"example": "1bad::babe"
}
}
},
"created": {
"type": "object",
"properties": {
"id": {
"type": "integer"
}
}
},
"error": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message#"
] ]
}
}
}
} }

View File

@ -0,0 +1,537 @@
{
"openapi": "3.0.2",
"info": {
"title": "bindAPI",
"version": "0.0.2",
"description": "TODO …",
"contact": {
"name": "Micha Espey",
"email": "tracer@24unix.net"
}
},
"servers": [
{
"url": "{schema}://{hostname}/api",
"description": "The bindAPI URL.",
"variables": {
"schema": {
"enum": [
"https",
"http"
],
"default": "https"
},
"hostname": {
"default": "ns1.24unix.net"
}
}
}
],
"tags": [
{
"name": "Server"
},
{
"name": "DNS"
},
{
"name": "Domains"
}
],
"security": [
{
"ApiKeyAuth": []
}
],
"paths": {
"/ping": {
"get": {
"tags": [
"Server"
],
"summary": "Returning pong.",
"description": "Can be used to check API or server availability.",
"operationId": "getPong",
"responses": {
"200": {
"$ref": "#/components/responses/ping"
},
"401": {
"$ref": "#/components/responses/401-unauthorized"
}
},
"security": [
{
"Authorization": [
"read"
]
}
]
}
},
"/dyndns/{hostname}": {
"post": {
"tags": [
"DNS"
],
"summary": "Updated a DynDNS host.",
"description": "Updates a predefined custom DNS entry.",
"operationId": "updateDynDNS",
"parameters": [
{
"name": "hostname",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"$ref": "#/components/requestBodies/dyndns-put"
},
"responses": {
"200": {
"description": "OK"
},
"204": {
"description": "No Content"
},
"401": {
"description": "API key is missing or invalid."
},
"404": {
"description": "Domain not found."
}
},
"security": [
{
"Authorization": []
}
]
}
},
"/domains": {
"get": {
"tags": [
"Domains"
],
"summary": "Returns all domains.",
"description": "Returns information of a single domain specified by its domain name.",
"operationId": "getDomains",
"responses": {
"200": {
"$ref": "#/components/responses/domain-array"
},
"401": {
"$ref": "#/components/responses/401-unauthorized"
}
},
"security": [
{
"Authorization": [
"read"
]
}
]
},
"post": {
"tags": [
"Domains"
],
"summary": "Create a domain.",
"description": "Create a new domain.",
"operationId": "putDomains",
"requestBody": {
"$ref": "#/components/requestBodies/domain-post"
},
"responses": {
"201": {
"$ref": "#/components/responses/201-created"
},
"400": {
"$ref": "#/components/responses/400-bad-request"
},
"401": {
"$ref": "#/components/responses/401-unauthorized"
}
}
}
},
"/domains/{id}": {
"get": {
"tags": [
"Domains"
],
"summary": "Returns a single domain.",
"description": "Returns information of a single domain specified by its ID.",
"operationId": "getSingleDomain",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"$ref": "#/components/responses/200-ok"
},
"400": {
"$ref": "#/components/responses/400-bad-request"
},
"401": {
"$ref": "#/components/responses/401-unauthorized"
}
}
},
"put": {
"tags": [
"Domains"
],
"summary": "Updates a domain.",
"description": "Updates a domain. Only supplied fields will be updated, existing won't be affected.",
"operationId": "putDomain",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"$ref": "#/components/requestBodies/domain-put"
},
"responses": {
"200": {
"description": "OK"
},
"401": {
"description": "API key is missing or invalid."
},
"404": {
"description": "Domain not found."
}
},
"security": [
{
"Authorization": []
}
]
},
"delete": {
"tags": [
"Domains"
],
"summary": "Deletes a domain.",
"description": "Deletes a domain.",
"operationId": "73c6c14e6d84f759d2e09029cb7ab2be",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"204": {
"$ref": "#/components/responses/204-no-content"
},
"401": {
"$ref": "#/components/responses/401-unauthorized"
},
"404": {
"$ref": "#/components/responses/404-not-found"
}
}, "security": [
{
"Authorization": []
}
]
}
},
"/domains/name/{name}": {
"get": {
"tags": [
"Domains"
],
"summary": "Returns a single domain by name.",
"description": "Returns information of a single domain specified by its domain name.",
"operationId": "getSingleDomainByName",
"parameters": [
{
"name": "name",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"$ref": "#/components/responses/200-ok"
},
"400": {
"$ref": "#/components/responses/400-bad-request"
},
"401": {
"$ref": "#/components/responses/401-unauthorized"
}
}
}
}
},
"components": {
"securitySchemes": {
"Authorization": {
"type": "apiKey",
"description": "Authentication Token",
"name": "X-API-Key",
"in": "header"
}
},
"requestBodies": {
"dyndns-put": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/dyndns"
},
"example": {
"a": "1.2.3.4",
"aaaa": "1bad::babe"
}
}
}
},
"domain-post": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/domain"
}
}
}
},
"domain-put": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/domain"
},
"example": {
"name": "example.com",
"panel_id": "8"
}
}
}
}
},
"responses": {
"ping": {
"description": "OK.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ping"
}
}
}
},
"domain": {
"description": "OK.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/domain"
}
}
}
},
"domain-array": {
"description": "OK.",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/domain"
}
}
}
}
},
"200-ok": {
"description": "OK."
},
"200-ok-updated": {
"description": "OK.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/created"
},
"example": {
"id": 8
}
}
}
},
"201-created": {
"description": "Created.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/created"
},
"example": {
"id": 8
}
}
}
},
"204-no-content": {
"description": "No content."
},
"400-bad-request": {
"description": "Bad request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/error"
},
"example": {
"code": "400 Bad Request",
"message": "Invalid request body."
}
}
}
},
"401-unauthorized": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/error"
},
"example": {
"code": "401 Unauthorized",
"message": "API key is missing or invalid."
}
}
}
},
"404-not-found": {
"description": "The specified resource was not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/error"
},
"example": {
"code": "404 Not Found",
"message": "The specified resource was not found."
}
}
}
}
},
"schemas": {
"ping": {
"type": "object",
"properties": {
"response": {
"type": "string",
"example": "pong"
}
}
},
"dyndns": {
"type": "object",
"properties": {
"a": {
"type": "string",
"example": "1.2.3.4"
},
"aaaa": {
"type": "string",
"example": "1bad::babe"
}
}
},
"domain": {
"description": "Representation of a domain.\n",
"type": "object",
"properties": {
"id": {
"type": "integer",
"readOnly": true,
"description": "The ID of the domain.",
"example": 8
},
"name": {
"type": "string",
"description": "The ASCII representation of the domain.",
"example": "example.com"
},
"panel_id": {
"type": "integer",
"description": "The KeyHelp Panel ID. Either this or at least one IP address is required",
"example": 4
},
"a": {
"type": "string",
"readOnly": true,
"description": "The IPv4 address.",
"example": "12.13.14.15"
},
"aaaa": {
"type": "string",
"readOnly": true,
"description": "The IPv6 address.",
"example": "1bad::babe"
}
}
},
"created": {
"type": "object",
"properties": {
"id": {
"type": "integer"
}
}
},
"error": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message#"
]
}
}
}
}

View File

@ -0,0 +1,6 @@
<?php
const DEFAULT_NS = 'ns2.24unix.net';
const NAMESERVERS = ['ns1.24unix.net', 'ns2.24unix.net', 'ns3.24unix.net'];
const VERSION = '1.0.9';

View File

@ -0,0 +1,5 @@
<?php
const DEFAULT_NS = 'ns2.24unix.net';
const NAMESERVERS = ['ns1.24unix.net', 'ns2.24unix.net'];

View File

@ -21,7 +21,7 @@
// Begin Swagger UI call region // Begin Swagger UI call region
let ui; let ui;
ui = SwaggerUIBundle({ ui = SwaggerUIBundle({
url: "/app/apidoc", url: "/openapi/bindapi.json",
dom_id: "#swagger-ui", dom_id: "#swagger-ui",
deepLinking: true, deepLinking: true,
presets: [ presets: [

View File

@ -47,6 +47,7 @@ class CLIController
{ {
private array $arguments; private array $arguments;
private CommandGroupContainer $commandGroupContainer; private CommandGroupContainer $commandGroupContainer;
private string $baseDir;
/** /**
* @throws Exception * @throws Exception
@ -66,6 +67,8 @@ class CLIController
private readonly bool $quiet private readonly bool $quiet
) )
{ {
$this->baseDir = dirname(path: __DIR__, levels: 2) . '/';
$this->commandGroupContainer = (new CommandGroupContainer()) $this->commandGroupContainer = (new CommandGroupContainer())
->addCommandGroup(commandGroup: (new CommandGroup(name: 'apikeys', description: 'API keys to access this bindAPI')) ->addCommandGroup(commandGroup: (new CommandGroup(name: 'apikeys', description: 'API keys to access this bindAPI'))
->addCommand(command: new Command( ->addCommand(command: new Command(
@ -120,6 +123,12 @@ class CLIController
$this->checkPanels(); $this->checkPanels();
}, },
optionalParameters: ['ID', 'fix=xes'])) optionalParameters: ['ID', 'fix=xes']))
->addCommand(command: new Command(
name: 'nameserver',
callback: function () {
$this->checkNameserver();
},
description: 'Validate setting for this panel'))
->addCommand(command: new Command( ->addCommand(command: new Command(
name: 'domains', name: 'domains',
callback: function () { callback: function () {
@ -168,7 +177,7 @@ class CLIController
$this->panelsCreate(); $this->panelsCreate();
}, },
mandatoryParameters: ['name'], mandatoryParameters: ['name'],
optionalParameters: ['A=<IPv4>', 'AAAA=<IPv6>', 'apikey=<API-Key>'])) optionalParameters: ['A=<IPv4>', 'AAAA=<IPv6>', 'apikey=<API-Key>', 'self=<yes|no>']))
->addCommand(command: new Command( ->addCommand(command: new Command(
name: 'update', name: 'update',
callback: function () { callback: function () {
@ -348,7 +357,6 @@ class CLIController
$this->logger->debug(message: "showUsage()"); $this->logger->debug(message: "showUsage()");
$debug = $this->configController->getConfig(configKey: 'debug'); $debug = $this->configController->getConfig(configKey: 'debug');
echo COLOR_DEFAULT . ')' . PHP_EOL;
echo COLOR_YELLOW . 'Usage:' . PHP_EOL; echo COLOR_YELLOW . 'Usage:' . PHP_EOL;
echo COLOR_DEFAULT . "\t./bin/console {options} {arguments}" . PHP_EOL . PHP_EOL; echo COLOR_DEFAULT . "\t./bin/console {options} {arguments}" . PHP_EOL . PHP_EOL;
@ -952,6 +960,7 @@ class CLIController
} }
// FIXME check validation state of panel and nameserver keys
var_dump($prefix, $key); var_dump($prefix, $key);
echo 'Length of prefix: ' . strlen($prefix) . PHP_EOL; echo 'Length of prefix: ' . strlen($prefix) . PHP_EOL;
echo 'Length of key: ' . strlen($key) . PHP_EOL; echo 'Length of key: ' . strlen($key) . PHP_EOL;
@ -1132,8 +1141,6 @@ class CLIController
if ($result['data'] == 'pong') { if ($result['data'] == 'pong') {
echo ' ' . COLOR_GREEN . $result['data']; echo ' ' . COLOR_GREEN . $result['data'];
} else { } else {
var_dump($result);
die;
echo COLOR_BLUE . ' xxskip' . COLOR_DEFAULT; echo COLOR_BLUE . ' xxskip' . COLOR_DEFAULT;
if (!$this->configController->getConfig(configKey: 'quiet')) { if (!$this->configController->getConfig(configKey: 'quiet')) {
echo ' ' . $result['data']; echo ' ' . $result['data'];
@ -1549,28 +1556,72 @@ class CLIController
exit(0); exit(0);
} }
$self = $this->arguments['self'] ?? '';
if ($this->nameserverRepository->findByName(name: $name)) { if ($this->nameserverRepository->findByName(name: $name)) {
echo "Nameserver: $name already exists." . PHP_EOL; echo "Nameserver: $name already exists." . PHP_EOL;
exit(1); exit(1);
} else { } else {
$nameserver = new Nameserver(name: $name, a: $a, aaaa: $aaaa, passphrase: $apikey); $nameserver = new Nameserver(name: $name, a: $a, aaaa: $aaaa, passphrase: $apikey, self: $self);
$result = $this->nameserverRepository->insert(nameserver: $nameserver); $result = $this->nameserverRepository->insert(nameserver: $nameserver);
echo 'Nameserver ' . COLOR_YELLOW . $name . COLOR_DEFAULT . ' has been created with id ' . COLOR_YELLOW . $result . COLOR_DEFAULT . PHP_EOL; echo 'Nameserver ' . COLOR_YELLOW . $name . COLOR_DEFAULT . ' has been created with id ' . COLOR_YELLOW . $result . COLOR_DEFAULT . PHP_EOL;
$this->createOpenAPIBootstrap();
exit(0); exit(0);
} }
} }
// FIXME add method create bootstrap php, add it to create, delete and update nameservers
public function createOpenAPIBootstrap()
{
$basePath = $this->baseDir . '/public/openapi/';
$bootStrapFile = $basePath . 'bootstrap.php';
$allNameservers = $this->nameserverRepository->findAll();
$nameservers = [];
$defaultNS = '';
foreach ($allNameservers as $ns) {
$nameservers[] = $ns->getName();
if ($ns->getSelf() === 'yes') {
$defaultNS = $ns->getName();
}
}
// Improvement in generating file content
$nameserverList = implode(separator: "', '", array: $nameservers);
$currentDBVersion = $this->settingsRepository->findByName(name: 'version');
$dbVersion = json_decode(json: $currentDBVersion);
$versionSting = $dbVersion->version->major . '.' . $dbVersion->version->minor . '.' . $dbVersion->version->patch;
$fileContent = "<?php
const DEFAULT_NS = '{$defaultNS}';
const NAMESERVERS = ['{$nameserverList}'];
const VERSION = '{$versionSting}';
" . PHP_EOL;
try {
file_put_contents(filename: $bootStrapFile, data: $fileContent);
} catch (Exception $e) {
if (!$this->quiet) {
echo 'Error: ' . $e->getMessage() . PHP_EOL;
}
}
shell_exec(command: $this->baseDir . 'vendor/bin/openapi src/Controller/RequestController.php -b public/openapi/bootstrap.php -o public/openapi/bindapi.json');
}
/**
* @return void
*/
function nameserversList(): void function nameserversList(): void
{ {
$nameservers = $this->nameserverRepository->findAll(); $nameservers = $this->nameserverRepository->findAll();
if (!empty($nameservers)) { if (!empty($nameservers)) {
echo 'All available nameservers:' . PHP_EOL; echo 'All available nameservers:' . PHP_EOL;
$table = new ConsoleTable(); $table = new ConsoleTable();
$table->setHeaders(content: ['ID', 'Name', 'A', 'AAAA', 'API Key']); $table->setHeaders(content: ['ID', 'Name', 'A', 'AAAA', 'API Key', 'self']);
foreach ($nameservers as $nameserver) { foreach ($nameservers as $nameserver) {
$row = []; $row = [];
$row[] = $nameserver->getId(); $row[] = $nameserver->getId();
@ -1578,6 +1629,7 @@ class CLIController
$row[] = $nameserver->getA(); $row[] = $nameserver->getA();
$row[] = $nameserver->getAaaa(); $row[] = $nameserver->getAaaa();
$row[] = $nameserver->getApikeyPrefix(); $row[] = $nameserver->getApikeyPrefix();
$row[] = $nameserver->getSelf();
$table->addRow(data: $row); $table->addRow(data: $row);
} }
$table->setPadding(value: 2); $table->setPadding(value: 2);
@ -1599,6 +1651,8 @@ class CLIController
$a = $this->arguments['a'] ?? ''; $a = $this->arguments['a'] ?? '';
$aaaa = $this->arguments['aaaa'] ?? ''; $aaaa = $this->arguments['aaaa'] ?? '';
$apikey = $this->arguments['apikey'] ?? ''; $apikey = $this->arguments['apikey'] ?? '';
$self = $this->arguments['self'] ?? '';
if ($id == 0) { if ($id == 0) {
echo 'An ID is required.' . PHP_EOL; echo 'An ID is required.' . PHP_EOL;
@ -1610,17 +1664,22 @@ class CLIController
} }
if ($apikey) { if ($apikey) {
$nameserver = new Nameserver(name: $name, id: intval(value: $id), a: $a, aaaa: $aaaa, passphrase: $apikey); $nameserver = new Nameserver(name: $name, id: intval(value: $id), a: $a, aaaa: $aaaa, passphrase: $apikey, self: $self);
} else { } else {
$nameserver = new Nameserver(name: $name, id: intval(value: $id), a: $a, aaaa: $aaaa); $nameserver = new Nameserver(name: $name, id: intval(value: $id), a: $a, aaaa: $aaaa, self: $self);
} }
if ($this->nameserverRepository->update(nameserver: $nameserver) !== false) { if ($this->nameserverRepository->update(nameserver: $nameserver) !== false) {
$this->createOpenAPIBootstrap();
if (!$this->quiet) {
echo 'Nameserver ' . COLOR_YELLOW . $id . COLOR_DEFAULT . ' has been updated.' . PHP_EOL; echo 'Nameserver ' . COLOR_YELLOW . $id . COLOR_DEFAULT . ' has been updated.' . PHP_EOL;
}
} else { } else {
if (!$this->quiet) {
echo 'Error while updating nameserver ' . COLOR_YELLOW . $id . '.' . PHP_EOL; echo 'Error while updating nameserver ' . COLOR_YELLOW . $id . '.' . PHP_EOL;
} }
} }
}
/** /**
@ -1628,22 +1687,32 @@ class CLIController
function nameserversDelete(): void function nameserversDelete(): void
{ {
if (empty($this->arguments[1])) { if (empty($this->arguments[1])) {
if (!$this->quiet) {
echo "You need to supply an ID." . PHP_EOL; echo "You need to supply an ID." . PHP_EOL;
}
exit(1); exit(1);
} }
$id = intval(value: $this->arguments[1] ?? 0); $id = intval(value: $this->arguments[1] ?? 0);
if ($id == 0) { if ($id == 0) {
if (!$this->quiet) {
echo 'Nameserver with ID ' . COLOR_YELLOW . $id . COLOR_DEFAULT . ' not found.' . PHP_EOL; echo 'Nameserver with ID ' . COLOR_YELLOW . $id . COLOR_DEFAULT . ' not found.' . PHP_EOL;
}
exit(1); exit(1);
} }
if (!$this->nameserverRepository->findByID(id: $id)) { if (!$this->nameserverRepository->findByID(id: $id)) {
if (!$this->quiet) {
echo 'There is no nameserver with ID ' . COLOR_YELLOW . $id . COLOR_DEFAULT . '.' . PHP_EOL; echo 'There is no nameserver with ID ' . COLOR_YELLOW . $id . COLOR_DEFAULT . '.' . PHP_EOL;
}
exit(1); exit(1);
} }
$this->nameserverRepository->delete(id: $id); $this->nameserverRepository->delete(id: $id);
$this->createOpenAPIBootstrap();
if (!$this->quiet) {
echo 'The nameserver with ID ' . COLOR_YELLOW . $id . COLOR_DEFAULT . ' has been deleted.' . PHP_EOL; echo 'The nameserver with ID ' . COLOR_YELLOW . $id . COLOR_DEFAULT . ' has been deleted.' . PHP_EOL;
} }
}
/** /**
@ -2066,7 +2135,7 @@ class CLIController
$update = true; $update = true;
} }
$composerFile = dirname(path: __DIR__, levels: 2) . DIRECTORY_SEPARATOR . 'composer.json'; $composerFile = $this->baseDir . DIRECTORY_SEPARATOR . 'composer.json';
$composerJson = json_decode(json: file_get_contents(filename: $composerFile), associative: false); $composerJson = json_decode(json: file_get_contents(filename: $composerFile), associative: false);
$fileVersion = $composerJson->version; $fileVersion = $composerJson->version;
@ -2087,7 +2156,7 @@ class CLIController
$this->settingsRepository->set(name: 'buildnumber', value: $fileBuildNumber); $this->settingsRepository->set(name: 'buildnumber', value: $fileBuildNumber);
} }
$currentDBVersion = $this->settingsRepository->findByName(name: 'version'); $currentDBVersion = $this->settingsRepository->findByName(name: 'version');
$dbVersion = json_decode($currentDBVersion); $dbVersion = json_decode(json: $currentDBVersion);
$currentDBBuildnumber = $this->settingsRepository->findByName(name: 'buildnumber'); $currentDBBuildnumber = $this->settingsRepository->findByName(name: 'buildnumber');
echo "DB version:\t\t"; echo "DB version:\t\t";
@ -2193,6 +2262,34 @@ class CLIController
} }
private function checkNameserver()
{
$self = $this->panelRepository->findSelf();
$nameserverCount = count($self);
if ($nameserverCount != 1) {
if ($nameserverCount == 0) {
if (!$this->quiet) {
echo 'No nameserver marked as this server.' . PHP_EOL;
echo 'The setting is used to generate the default nameserver in SwaggerUI.' . PHP_EOL;
echo 'Use ' . COLOR_YELLOW . 'nameservers:update <ID> self=yes ' . COLOR_DEFAULT . 'to mark this nameserver.' . PHP_EOL;
exit(1);
}
} else {
if (!$this->quiet) {
echo 'Only one nameserver should be marked as self.' . PHP_EOL;
echo 'The setting is used to generate the default nameserver in SwaggerUI.' . PHP_EOL;
echo 'Use ' . COLOR_YELLOW . 'nameservers:update <ID> self=no ' . COLOR_DEFAULT . 'to remove the stale nameserver' . PHP_EOL;
}
}
} else {
if (!$this->quiet) {
echo 'Only one nameserver is designated as our host' . COLOR_GREEN . ' OK' . COLOR_DEFAULT . PHP_EOL;
}
}
}
private function cronRun() private function cronRun()
{ {
$this->logger->info(message: 'cronRun()'); $this->logger->info(message: 'cronRun()');

View File

@ -17,13 +17,9 @@ use OpenApi\Generator;
use UnhandledMatchError; use UnhandledMatchError;
use function Symfony\Component\String\s; use function Symfony\Component\String\s;
// TODO attributes for swaggerUI // TODO attributes for swaggerUI
/** #[OAT\Info(version: VERSION, title: 'bindAPI')]
*
*/
#[OAT\Info(version: '1.0.9', title: 'bindAPI')]
#[OAT\Server( #[OAT\Server(
url: "{schema}://{hostname}/api", url: "{schema}://{hostname}/api",
description: "The bindAPI URL.", description: "The bindAPI URL.",
@ -35,8 +31,8 @@ use function Symfony\Component\String\s;
), ),
new OAT\ServerVariable( new OAT\ServerVariable(
serverVariable: 'hostname', serverVariable: 'hostname',
default: 'ns1.24unix.net', default: DEFAULT_NS,
enum: ['ns1.24unix.net', 'ns2.24unix.net', 'ns3.24unix.net', 'ns4.24unix.net'] enum: NAMESERVERS
) )
] ]
)] )]
@ -104,7 +100,7 @@ class RequestController
responses: [ responses: [
new OAT\Response( new OAT\Response(
response: 200, response: 200,
description: 'x.y.y' description: 'x.y.z, aka major, minor, patch'
), ),
new OAT\Response( new OAT\Response(
response: 401, response: 401,
@ -128,7 +124,7 @@ class RequestController
path: '/domains', path: '/domains',
operationId: 'getAllDomains', operationId: 'getAllDomains',
description: 'Returns a list of all domains on this server.', description: 'Returns a list of all domains on this server.',
summary: 'Listing all domains.', summary: 'List all domains.',
security: [ security: [
['Authorization' => []] ['Authorization' => []]
], ],
@ -635,17 +631,17 @@ class RequestController
return $host; return $host;
} }
private function apiDoc(): void // private function apiDoc(): void
{ // {
$srcDir = dirname(path: __DIR__); // $srcDir = dirname(path: __DIR__);
$requestControllerPath = $srcDir . '/Controller/RequestController.php'; // $requestControllerPath = $srcDir . '/Controller/RequestController.php';
//
$openApi = Generator::scan(sources: [$requestControllerPath]); // $openApi = Generator::scan(sources: [$requestControllerPath]);
header(header: 'Content-Type: application/json'); // header(header: 'Content-Type: application/json');
//
echo $openApi->toJson(); // echo $openApi->toJson();
exit(0); // exit(0);
} // }
public function __construct( public function __construct(
private readonly ApikeyRepository $apikeyRepository, private readonly ApikeyRepository $apikeyRepository,

View File

@ -12,7 +12,6 @@ use SodiumException;
* *
*/ */
#[OAT\Schema(schema: 'nameserver')] #[OAT\Schema(schema: 'nameserver')]
class Nameserver class Nameserver
{ {
/** /**
@ -31,7 +30,9 @@ class Nameserver
private string $aaaa = '', private string $aaaa = '',
private readonly string $passphrase = '', private readonly string $passphrase = '',
private string $apikey = '', private string $apikey = '',
private string $apikeyPrefix = '') private string $apikeyPrefix = '',
private string $self = 'no'
)
{ {
if ($this->passphrase) { if ($this->passphrase) {
$configController = new ConfigController(quiet: false); $configController = new ConfigController(quiet: false);
@ -50,6 +51,16 @@ class Nameserver
} }
public function getSelf(): string
{
return $this->self;
}
public function setSelf(string $self): void
{
$this->self = $self;
}
/** /**
* @return string * @return string
*/ */

View File

@ -26,7 +26,7 @@ class NameserverRepository
{ {
$nameservers = []; $nameservers = [];
$sql = " $sql = "
SELECT id, name, a, aaaa, apikey, apikey_prefix SELECT id, name, a, aaaa, apikey, apikey_prefix, self
FROM " . DatabaseConnection::TABLE_NAMESERVERS . " FROM " . DatabaseConnection::TABLE_NAMESERVERS . "
ORDER BY name"; ORDER BY name";
@ -34,7 +34,7 @@ class NameserverRepository
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql); $statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->execute(); $statement->execute();
while ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) { while ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) {
$nameserver = new Nameserver(name: $result['name'], id: $result['id'], a: $result['a'], aaaa: $result['aaaa'], apikey: $result['apikey'], apikeyPrefix: $result['apikey_prefix']); $nameserver = new Nameserver(name: $result['name'], id: $result['id'], a: $result['a'], aaaa: $result['aaaa'], apikey: $result['apikey'], apikeyPrefix: $result['apikey_prefix'], self: $result['self']);
$nameservers[] = $nameserver; $nameservers[] = $nameserver;
} }
return $nameservers; return $nameservers;
@ -50,7 +50,7 @@ class NameserverRepository
public function findFirst(): ?Nameserver public function findFirst(): ?Nameserver
{ {
$sql = " $sql = "
SELECT id, name, a, aaaa, apikey, apikey_prefix SELECT id, name, a, aaaa, apikey, apikey_prefix, self
FROM " . DatabaseConnection::TABLE_NAMESERVERS . " FROM " . DatabaseConnection::TABLE_NAMESERVERS . "
ORDER BY name"; ORDER BY name";
@ -58,7 +58,7 @@ class NameserverRepository
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql); $statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->execute(); $statement->execute();
$result = $statement->fetch(mode: PDO::FETCH_ASSOC); $result = $statement->fetch(mode: PDO::FETCH_ASSOC);
return new Nameserver(name: $result['name'], id: $result['id'], a: $result['a'], aaaa: $result['aaaa'], apikey: $result['apikey'], apikeyPrefix: $result['apikey_prefix']); return new Nameserver(name: $result['name'], id: $result['id'], a: $result['a'], aaaa: $result['aaaa'], apikey: $result['apikey'], apikeyPrefix: $result['apikey_prefix'], self: $result['self']);
} catch (PDOException $e) { } catch (PDOException $e) {
exit($e->getMessage()); exit($e->getMessage());
} }
@ -73,7 +73,7 @@ class NameserverRepository
public function findByID(int $id): ?Nameserver public function findByID(int $id): ?Nameserver
{ {
$sql = " $sql = "
SELECT id, name, a, aaaa, apikey, apikey_prefix SELECT id, name, a, aaaa, apikey, apikey_prefix, self
FROM . " . DatabaseConnection::TABLE_NAMESERVERS . " FROM . " . DatabaseConnection::TABLE_NAMESERVERS . "
WHERE id = :id"; WHERE id = :id";
@ -82,7 +82,7 @@ class NameserverRepository
$statement->bindParam(param: ':id', var: $id); $statement->bindParam(param: ':id', var: $id);
$statement->execute(); $statement->execute();
if ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) { if ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) {
return new Nameserver(name: $result['name'], a: $result['a'], aaaa: $result['aaaa'], apikey: $result['apikey'], apikeyPrefix: $result['apikey_prefix']); return new Nameserver(name: $result['name'], a: $result['a'], aaaa: $result['aaaa'], apikey: $result['apikey'], apikeyPrefix: $result['apikey_prefix'], self: $result['self']);
} else { } else {
return null; return null;
} }
@ -100,7 +100,7 @@ class NameserverRepository
public function findByName(string $name): ?Nameserver public function findByName(string $name): ?Nameserver
{ {
$sql = " $sql = "
SELECT id, name, a, aaaa, apikey, apikey_prefix SELECT id, name, a, aaaa, apikey, apikey_prefix, self
FROM " . DatabaseConnection::TABLE_NAMESERVERS . " FROM " . DatabaseConnection::TABLE_NAMESERVERS . "
WHERE name = :name"; WHERE name = :name";
@ -109,7 +109,7 @@ class NameserverRepository
$statement->bindParam(param: ':name', var: $name); $statement->bindParam(param: ':name', var: $name);
$statement->execute(); $statement->execute();
if ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) { if ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) {
return new Nameserver(name: $result['name'], a: $result['a'], aaaa: $result['aaaa'], apikey: $result['apikey'], apikeyPrefix: $result['apikey_prefix']); return new Nameserver(name: $result['name'], a: $result['a'], aaaa: $result['aaaa'], apikey: $result['apikey'], apikeyPrefix: $result['apikey_prefix'], self: $result['self']);
} else { } else {
return null; return null;
} }
@ -131,11 +131,12 @@ class NameserverRepository
$aaaa = $nameserver->getAaaa(); $aaaa = $nameserver->getAaaa();
$apikey = $nameserver->getApikey(); $apikey = $nameserver->getApikey();
$apikeyPrefix = $nameserver->getApikeyPrefix(); $apikeyPrefix = $nameserver->getApikeyPrefix();
$self = $nameserver->getSelf();
$sql = " $sql = "
INSERT INTO " . DatabaseConnection::TABLE_NAMESERVERS . " (name, a, aaaa, apikey, apikey_prefix) INSERT INTO " . DatabaseConnection::TABLE_NAMESERVERS . " (name, a, aaaa, apikey, apikey_prefix, self)
VALUES (:name, :a, :aaaa, :apikey, :apikey_prefix)"; VALUES (:name, :a, :aaaa, :apikey, :apikey_prefix, :self)";
try { try {
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql); $statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
@ -144,6 +145,7 @@ class NameserverRepository
$statement->bindParam(param: ':aaaa', var: $aaaa); $statement->bindParam(param: ':aaaa', var: $aaaa);
$statement->bindParam(param: ':apikey', var: $apikey); $statement->bindParam(param: ':apikey', var: $apikey);
$statement->bindParam(param: ':apikey_prefix', var: $apikeyPrefix); $statement->bindParam(param: ':apikey_prefix', var: $apikeyPrefix);
$statement->bindParam(param: ':self', var: $self);
$statement->execute(); $statement->execute();
return intval(value: $this->databaseConnection->getConnection()->lastInsertId()); return intval(value: $this->databaseConnection->getConnection()->lastInsertId());
@ -166,6 +168,7 @@ class NameserverRepository
$apikey = $nameserver->getApikey(); $apikey = $nameserver->getApikey();
$apikeyPrefix = $nameserver->getApikeyPrefix(); $apikeyPrefix = $nameserver->getApikeyPrefix();
$passphrase = $nameserver->getPassphrase(); $passphrase = $nameserver->getPassphrase();
$self =$nameserver->getSelf();
$current = $this->findByID(id: $id); $current = $this->findByID(id: $id);
@ -185,6 +188,10 @@ class NameserverRepository
$apikeyPrefix = $current->getApikeyPrefix(); $apikeyPrefix = $current->getApikeyPrefix();
} }
if (empty($self)) {
$self = $current->getSelf();
}
$sql = " $sql = "
UPDATE " . DatabaseConnection::TABLE_NAMESERVERS . " SET UPDATE " . DatabaseConnection::TABLE_NAMESERVERS . " SET
@ -192,7 +199,8 @@ class NameserverRepository
a = :a, a = :a,
aaaa = :aaaa, aaaa = :aaaa,
apikey = :apikey, apikey = :apikey,
apikey_prefix = :apikey_prefix apikey_prefix = :apikey_prefix,
self = :self
WHERE id = :id"; WHERE id = :id";
try { try {
@ -203,6 +211,7 @@ class NameserverRepository
$statement->bindParam(param: 'aaaa', var: $aaaa); $statement->bindParam(param: 'aaaa', var: $aaaa);
$statement->bindParam(param: 'apikey', var: $apikey); $statement->bindParam(param: 'apikey', var: $apikey);
$statement->bindParam(param: 'apikey_prefix', var: $apikeyPrefix); $statement->bindParam(param: 'apikey_prefix', var: $apikeyPrefix);
$statement->bindParam(param: 'self', var: $self);
$statement->execute(); $statement->execute();
try { try {
sodium_memzero(string: $apikey); sodium_memzero(string: $apikey);

View File

@ -5,7 +5,8 @@ use App\Service\BindAPI;
error_reporting(error_level: E_ALL & ~E_DEPRECATED); error_reporting(error_level: E_ALL & ~E_DEPRECATED);
if (!is_file(filename: dirname(path: __DIR__, levels: 2) . '/vendor/autoload.php')) { if (!is_file(filename: dirname(path: __DIR__, levels: 2) . '/vendor/autoload.php')) {
exit('Required runtime components are missing. Try running "composer install".' . PHP_EOL); echo 'Required runtime components are missing. Try running "' . COLOR_YELLOW . 'composer install' . COLOR_DEFAULT . '".' . PHP_EOL;
exit(1);
} }
require dirname(path: __DIR__, levels: 2) . '/vendor/autoload.php'; require dirname(path: __DIR__, levels: 2) . '/vendor/autoload.php';