From 85a926e5bbb7c0134c32ee46df70618bbd9eb67c Mon Sep 17 00:00:00 2001 From: Vladimir Svacko Date: Wed, 28 Jan 2026 15:01:28 +0100 Subject: [PATCH] fix: README enhancement --- README.md | 546 ++++++++++++++++++++++++++++++++++++++++++++++++++ README_old.md | 300 --------------------------- 2 files changed, 546 insertions(+), 300 deletions(-) create mode 100644 README.md delete mode 100644 README_old.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..2bb2500 --- /dev/null +++ b/README.md @@ -0,0 +1,546 @@ +# Zabbix GraphQL API + +A GraphQL wrapper for the Zabbix API that provides enhanced mass import/export operations, hierarchical host group management, and dynamic schema extensibility. Built with Apollo Server, TypeScript, and ES modules. + +## ๐Ÿš€ Features + +- **GraphQL Interface**: Modern GraphQL API wrapping Zabbix functionality + - *Reference*: `schema/queries.graphql`, `schema/mutations.graphql`, `src/api/start.ts` + +- **Hierarchical Data Mapping**: Automatic mapping of Zabbix items/tags to nested GraphQL objects + - *Reference*: `src/api/resolver_helpers.ts`, `schema/device_value_commons.graphql`, `docs/sample_all_devices_query.graphql` + +- **Mass Operations**: Import/export capabilities for hosts, templates, and user rights + - *Reference*: `schema/mutations.graphql` (importHosts, importTemplates, importUserRights, etc.), `docs/sample_import_*.graphql` + +- **Dynamic Schema Extension**: Extend the schema without code changes using environment variables + - *Reference*: `src/api/schema.ts`, `schema/extensions/`, `src/common_utils.ts` (ADDITIONAL_SCHEMAS, ADDITIONAL_RESOLVERS) + +- **Permission System**: Role-based access control using Zabbix template groups + - *Reference*: `schema/api_commons.graphql` (Permission enum, PermissionRequest), `src/api/resolvers.ts` (hasPermissions, userPermissions), `docs/sample_import_permissions_template_groups_mutation.graphql` + +- **Real-time Subscriptions**: WebSocket support for GraphQL subscriptions (infrastructure implemented) + - *Reference*: `src/api/start.ts` (WebSocketServer integration with `graphql-ws`), `AGENTS.md` (mentions WebSocket support), `package.json` (graphql-ws, subscriptions dependencies) + +- **Type Safety**: Full TypeScript support with generated types + - *Reference*: `codegen.ts`, `src/schema/generated/graphql.ts`, `tsconfig.json`, `package.json` (devDependencies for GraphQL Codegen) + +## ๐Ÿ“‹ Prerequisites + +Before you begin, ensure you have met the following requirements: + +- **Node.js** >= 18.x (tested with v21.5.0) +- **NPM** >= 8.x +- **Zabbix Server** with API access +- **Zabbix Super Admin Token** (for full functionality) + +## ๐Ÿ› ๏ธ Installation + +### Clone the repository + +```bash +git clone https://github.com/your-repo/zabbix-graphql-api.git +cd zabbix-graphql-api +``` + +### Install dependencies + +```bash +npm install +``` + +## โš™๏ธ Configuration + +### Environment Variables + +Create a `.env` file in the project root with the following variables: + +```bash +# Zabbix connection +ZABBIX_BASE_URL=http://your-zabbix-server/zabbix +ZABBIX_AUTH_TOKEN=your-super-admin-token +ZABBIX_AUTH_TOKEN_FOR_REQUESTS=your-super-admin-token + +# Optional configuration +ZABBIX_EDGE_DEVICE_BASE_GROUP=Roadwork +ZABBIX_ROADWORK_BASE_GROUP=Roadwork +ZABBIX_PERMISSION_TEMPLATE_GROUP_NAME_PREFIX=Permissions +SCHEMA_PATH=./schema/ + +# Dynamic schema extension (optional) +ADDITIONAL_SCHEMAS=./schema/extensions/display_devices.graphql,./schema/extensions/location_tracker_devices.graphql +ADDITIONAL_RESOLVERS=SinglePanelDevice,FourPanelDevice,DistanceTrackerDevice + +# Logging +LOG_LEVELS=info +``` + +### Environment Variable Details + +| Variable | Description | Default | +|----------|-------------|---------| +| `ZABBIX_BASE_URL` | URL to your Zabbix server (include `/zabbix` path) | - | +| `ZABBIX_AUTH_TOKEN` | Zabbix Super Admin API token | - | +| `ZABBIX_AUTH_TOKEN_FOR_REQUESTS` | Token used for automated requests | - | +| `ZABBIX_EDGE_DEVICE_BASE_GROUP` | Base group for edge devices | - | +| `ZABBIX_ROADWORK_BASE_GROUP` | Base group for roadwork devices | - | +| `ZABBIX_PERMISSION_TEMPLATE_GROUP_NAME_PREFIX` | Prefix for permission template groups | `Permissions` | +| `SCHEMA_PATH` | Path to schema files | `./schema/` | +| `ADDITIONAL_SCHEMAS` | Comma-separated list of additional schema files | - | +| `ADDITIONAL_RESOLVERS` | Comma-separated list of resolver types to generate | - | +| `LOG_LEVELS` | Log level configuration | - | + +## โ–ถ๏ธ Running the Application + +### Development Mode + +```bash +# Start with hot reloading +npm run start +``` + +The GraphQL API will be available at `http://localhost:4000/` + +### Production Build + +```bash +# Compile TypeScript +npm run compile + +# Run production build +npm run prod +``` + +### Available Scripts + +| Script | Description | +|--------|-------------| +| `npm run start` | Start development server with hot reload | +| `npm run compile` | Compile TypeScript to JavaScript | +| `npm run prod` | Run production build | +| `npm run test` | Run tests | +| `npm run codegen` | Generate TypeScript types from GraphQL schema | +| `npm run nodemon` | Alternative development runner | + +## ๐Ÿณ Docker Deployment + +### Using Pre-built Images + +The application can be deployed using Docker: + +```bash +# Build the image +docker build -t zabbix-graphql-api . + +# Run the container +docker run -d \ + --name zabbix-graphql \ + -p 4000:4000 \ + -e ZABBIX_BASE_URL=http://your-zabbix-server/zabbix \ + -e ZABBIX_AUTH_TOKEN=your-super-admin-token \ + zabbix-graphql-api +``` + +### Building Your Own Image + +```bash +# Build with custom API version +docker build --build-arg API_VERSION=v1.0.0 -t zabbix-graphql-api . + +# Run with environment file +docker run -d \ + --name zabbix-graphql \ + -p 4000:4000 \ + --env-file .env \ + zabbix-graphql-api +``` + +## ๐Ÿ” Roles and Permissions Extension + +The API implements a permission system using Zabbix template groups: + +### Permission Template Groups + +- Template groups with prefix `Permissions/` (configurable via `ZABBIX_PERMISSION_TEMPLATE_GROUP_NAME_PREFIX`) are used for permissions +- Users gain permissions by being assigned to user groups that have access to these permission template groups + +### Available Permissions + +The system supports three permission levels defined in `schema/api_commons.graphql`: + +- `DENY`: Explicitly denies access (supersedes other permissions) +- `READ`: Allows viewing/reading access +- `READ_WRITE`: Allows both reading and writing (implies READ permission) + +### Permission Object Names + +Permission object names map to Zabbix template group paths: `Permissions/{objectName}` + +### GraphQL Permission Queries + +```graphql +# Check if current user has specific permissions +query HasPermissions { + hasPermissions(permissions: [ + { objectName: "hosts", permission: READ }, + { objectName: "templates", permission: READ_WRITE } + ]) +} + +# Get all user permissions +query GetUserPermissions { + userPermissions(objectNames: ["hosts", "templates"]) +} +``` + +### Setting Up Permissions + +1. Create template groups with the prefix `Permissions/` (e.g., `Permissions/hosts`, `Permissions/templates`) +2. Assign these template groups to user groups in Zabbix with appropriate permission levels +3. Users in those user groups will inherit the permissions + +### Detailed Permission Usage Examples + +For comprehensive examples of permission usage patterns, see `schema/api_commons.graphql` which contains detailed documentation in the `PermissionRequest` input type comments, including real-world examples of how to model permissions for buttons, status controls, and application features. + +See also `docs/sample_import_permissions_template_groups_mutation.graphql` for examples of importing permission template groups. + +## ๐Ÿ“Š Schema and Schema Extension + +### Main Schema Structure + +The GraphQL schema is located in the `schema/` directory and consists of: + +- `queries.graphql` - Query definitions (see detailed documentation in file comments) +- `mutations.graphql` - Mutation definitions (see detailed documentation in file comments) +- `devices.graphql` - Device-related types (see detailed documentation in file comments) +- `zabbix.graphql` - Zabbix-specific types (see detailed documentation in file comments) +- `device_value_commons.graphql` - Common value types (see detailed documentation in file comments) +- `api_commons.graphql` - Common API types and permission system (see detailed documentation in file comments) +- `extensions/` - Custom device type extensions + +For comprehensive understanding of each operation, read the detailed comments in the respective schema files. + +### Dynamic Schema Extension + +Extend the schema without code changes using environment variables: + +```bash +ADDITIONAL_SCHEMAS=./schema/extensions/display_devices.graphql,./schema/extensions/location_tracker_devices.graphql +ADDITIONAL_RESOLVERS=SinglePanelDevice,FourPanelDevice,DistanceTrackerDevice +``` + +This enables runtime schema extension for custom device types without modifying the core code. + +### Sample Operations + +For practical examples of schema usage, see the sample files in the `docs/` directory: +- `docs/sample_all_devices_query.graphql` - Example of querying all devices +- `docs/sample_import_templates_mutation.graphql` - Example of importing templates +- `docs/sample_import_host_groups_mutation.graphql` - Example of importing host groups + +## ๐Ÿ—‚๏ธ Hierarchical Data Mapping + +The API automatically maps Zabbix items to nested GraphQL objects using the `createHierarchicalValueFieldResolver` function: + +- Zabbix item key `state.current.values.temperature` โ†’ GraphQL `{ state: { current: { values: { temperature } } } }` +- Type hints: `json_`, `str_`, `bool_`, `float_` prefixes for value conversion +- Automatic resolution of hierarchical structures from flat Zabbix item keys + +The `createHierarchicalValueFieldResolver` function (found in `src/api/resolver_helpers.ts`) dynamically creates resolvers that map Zabbix items or tags to hierarchical GraphQL structures. It uses field names and Zabbix item keys (dot-separated) to automatically resolve nested objects, eliminating the need for manual resolver definitions for each hierarchical field. + +For detailed information about the mapping mechanism and type hinting, see the comments in `schema/device_value_commons.graphql` and `src/api/resolver_helpers.ts`. + +See `docs/sample_all_devices_query.graphql` for examples of how hierarchical data appears in query results. + +## ๐Ÿท๏ธ Zabbix Tags Usage + +Zabbix tags are used for: + +- Device classification (`deviceType` tag) +- Host categorization (`hostType` tag) +- Custom metadata storage +- Permission assignment through template groups + +For detailed information about tag usage and available tag types, see the comments in `schema/devices.graphql` and `schema/zabbix.graphql`. + +See `docs/sample_all_hosts_query.graphql` and `docs/sample_all_devices_query.graphql` for examples of how tags appear in query results. + +## ๐Ÿงช Testing + +Run the test suite: + +```bash +npm test +``` + +The testing strategy includes: +- Unit tests with mocked Zabbix API responses +- Integration tests with real GraphQL operations +- Permission system validation +- Import/export functionality testing + +## ๐Ÿ“– Detailed Documentation Through Comments + +This project uses extensive inline documentation in the form of comments within the GraphQL schema files and documentation samples. For the most comprehensive understanding of the API, its capabilities, and usage patterns, read the detailed comments in: + +- `schema/queries.graphql` - Complete documentation of all query operations +- `schema/mutations.graphql` - Complete documentation of all mutation operations with usage examples +- `schema/api_commons.graphql` - Detailed explanation of the permission system with real-world usage examples +- `docs/*.graphql` - Practical examples of all operations with sample variables and expected outcomes + +The comments in these files contain real-world usage examples, implementation notes, and detailed explanations that go beyond what's covered in this README. + +## ๐Ÿ“– Example: Extending Schema with Distance Tracker Device + +### Zabbix-Side Configuration + +Before extending the schema, you need to configure Zabbix appropriately: + +#### 1. Host Configuration in Zabbix +- Create a host in Zabbix with the tag `deviceType` set to `distance-tracker` +- Add items to the host with hierarchical keys that match your GraphQL fields: + - `distance.current` (for the `distance` field) + - `battery.level` (for the `batteryLevel` field) + - `status.lastSeen` (for the `lastSeen` field) + - `location.latitude` and `location.longitude` (for the `location` object) + +#### 2. Item Key Naming Convention +The API automatically maps dotted item keys to nested GraphQL objects: +- Zabbix item key `distance.current` โ†’ GraphQL `{ distance }` +- Zabbix item key `battery.level` โ†’ GraphQL `{ batteryLevel }` +- Zabbix item key `location.latitude` โ†’ GraphQL `{ location: { location_lat } }` + +### Schema Extension Steps + +#### 1. Create Schema Extension + +Create `schema/extensions/distance_tracker_device.graphql`: + +```graphql +type DistanceTrackerDevice { + id: String + name: String + location: Location + distance: Float + batteryLevel: Float + lastSeen: DateTime +} +``` + +#### 2. Configure Environment Variables + +```bash +ADDITIONAL_SCHEMAS=./schema/extensions/distance_tracker_device.graphql +ADDITIONAL_RESOLVERS=DistanceTrackerDevice +``` + +#### 3. Import Template via GraphQL Mutation + +Instead of manually creating items in Zabbix, you can import a complete template using the GraphQL API: + +```graphql +mutation ImportDistanceTrackerTemplate($templates: [CreateTemplate!]!) { + importTemplates(templates: $templates) { + host + templateid + message + error { + message + code + data + } + } +} +``` + +Variables: +```json +{ + "templates": [ + { + "host": "DISTANCE_TRACKER", + "name": "Distance Tracker Device Template", + "groupNames": ["Templates/Roadwork/Devices"], + "tags": [ + { "tag": "deviceType", "value": "DistanceTrackerDevice" } + ], + "items": [ + { + "name": "Distance Current Value", + "type": 0, + "key": "distance.current", + "value_type": 0, + "history": "7d", + "units": "m" + }, + { + "name": "Battery Level", + "type": 0, + "key": "battery.level", + "value_type": 0, + "history": "7d", + "units": "%" + }, + { + "name": "Last Seen Timestamp", + "type": 0, + "key": "status.lastSeen", + "value_type": 4, + "history": "30d" + }, + { + "name": "Location Latitude", + "type": 0, + "key": "location.latitude", + "value_type": 0, + "history": "30d", + "units": "deg" + }, + { + "name": "Location Longitude", + "type": 0, + "key": "location.longitude", + "value_type": 0, + "history": "30d", + "units": "deg" + } + ] + } + ] +} +``` + +This creates a template in Zabbix with all the required items that map to your GraphQL fields. + +#### 4. Link Hosts to the Template + +After importing the template, link your hosts to it in Zabbix or via the importHosts mutation: + +```graphql +mutation ImportHosts($hosts: [CreateHost!]!) { + importHosts(hosts: $hosts) { + deviceKey + hostid + message + error { + message + code + data + } + } +} +``` + +Variables: +```json +{ + "hosts": [ + { + "deviceKey": "DistanceTracker001", + "name": "Distance Tracker 001", + "deviceType": "distance-tracker", + "groupNames": ["Roadwork/Devices"], + "templateids": [12345] // Use the templateid returned from importTemplates + } + ] +} +``` + +#### 5. Use in Queries + +Once the template and host are set up in Zabbix, query the data via GraphQL: + +```graphql +query GetDistanceTrackers { + allDevices(tag_deviceType: ["distance-tracker"]) { + ... on DistanceTrackerDevice { + id + name + location { + name + location_lat + location_lon + } + distance + batteryLevel + lastSeen + } + } +} +``` + +#### 6. Expected Response Structure + +Based on the Zabbix configuration above, the API will return: +```json +{ + "data": { + "allDevices": [ + { + "id": "12345", + "name": "Distance Tracker 001", + "location": { + "name": "Main Office", + "location_lat": "37.7749", + "location_lon": "-122.4194" + }, + "distance": 42.5, + "batteryLevel": 87.2, + "lastSeen": "2023-10-15T10:30:00Z" + } + ] + } +} +``` + +## ๐Ÿค Contributing + +1. Fork the repository +2. Create a feature branch (`git checkout -b feature/amazing-feature`) +3. Commit your changes (`git commit -m 'Add amazing feature'`) +4. Push to the branch (`git push origin feature/amazing-feature`) +5. Open a Pull Request + +## ๐Ÿ“„ License + +This project is licensed under the AGPL-3.0 License - see the [LICENSE](LICENSE) file for details. + +## ๐Ÿ“š Schema and Documentation + +### Schema Files as Documentation + +The schema files in the `schema/` directory serve as both API definition and documentation. Each type, field, and operation includes detailed comments explaining usage, parameters, and examples. For comprehensive understanding of the API, read the comments in: + +- `schema/queries.graphql` - Query operations with detailed parameter descriptions +- `schema/mutations.graphql` - Mutation operations with input type documentation +- `schema/api_commons.graphql` - Common types and permission system documentation +- `schema/devices.graphql` - Device-related types and hierarchies +- `schema/zabbix.graphql` - Zabbix-specific mappings and types + +### Documentation Files + +The `docs/` directory contains sample GraphQL queries and mutations that demonstrate how to use the API: + +- `sample_all_*.graphql` - Sample queries for retrieving hosts, devices, templates, and groups +- `sample_import_*.graphql` - Sample mutations for importing various Zabbix entities +- `sample_delete_*.graphql` - Sample mutations for deleting templates and template groups +- `sample_export_*.graphql` - Sample queries for exporting user rights and other data +- `VCR - Technical product information.pdf` - Technical documentation for specific implementations + +Of particular interest: +- `sample_import_distance_tracker_template.graphql` - Complete example of importing a template for distance tracker devices +- `sample_import_user_rights_mutation.graphql` - Example of importing user permissions +- `sample_import_permissions_template_groups_mutation.graphql` - Example of importing permission template groups + +### Reading Comments for Detailed Documentation + +For detailed documentation with usage examples and implementation notes, read the comments in the schema and documentation files. The project creator has embedded extensive documentation as comments in the GraphQL schema files, which provide real-world usage examples and implementation guidance that complement this README. + +## ๐Ÿ†˜ Support + +For support, please open an issue in the GitHub repository. + +## ๐Ÿ”„ API Version + +Current API version: ${API_VERSION:-"Not set"} \ No newline at end of file diff --git a/README_old.md b/README_old.md deleted file mode 100644 index ea8e536..0000000 --- a/README_old.md +++ /dev/null @@ -1,300 +0,0 @@ -# Zabbix GraphQL API - -A modern GraphQL interface for Zabbix, providing enhanced features and easier integration for automation and management. - -## Purpose - -The Zabbix GraphQL API acts as a wrapper and enhancer for the native Zabbix JSON-RPC API. It simplifies complex operations, provides a strongly-typed schema, and adds advanced logic for importing, querying, and managing Zabbix entities like hosts, templates, and user rights. - -## Key Features & Enhancements - -Compared to the original Zabbix API, this GraphQL API provides several key enhancements: - -* **Mass Import/Export**: Robust support for importing and exporting templates, template groups, hosts, and host groups in bulk. -* **Hierarchical Host Groups**: Automatically handles the creation and resolution of nested host group hierarchies (e.g., `Parent/Child/Leaf`). -* **Template Management**: - * Full support for template items, including complex preprocessing steps and tags. - * **Dependent Item Support**: Intelligent deferred creation logic to handle item dependencies within a template. - * Linked template resolution by name. -* **Advanced Deletion**: Ability to delete templates and template groups not only by ID but also by **name patterns** (supporting Zabbix wildcards like `%`). -* **User Rights & Permissions**: - * Integrated management of user roles and user groups. - * Support for importing/exporting user rights with UUID-based matching for cross-instance consistency. - * On-the-fly permission checks (`hasPermissions`, `userPermissions`). -* **Improved Error Reporting**: Detailed error data from Zabbix is appended to GraphQL error messages, making debugging significantly easier. -* **Strongly Typed Schema**: Leverages GraphQL's type system for clear API documentation and client-side code generation. -* **Dynamic Schema Extensibility**: Easily extend the API with custom schema snippets and dynamic resolvers for specialized device types without modifying the core code. -* **CI/CD Integration**: Includes a ready-to-use Forgejo/Gitea/GitHub Actions workflow for automated building, testing, and deployment. -* **Sample Application (VCR)**: Designed to power the **Virtual Control Room**, a professional cockpit for managing thousands of IoT/Edge devices. - -## How to Install and Start - -### Prerequisites - -* **Node.js**: Version 18 or higher recommended. -* **Zabbix**: A running Zabbix instance (compatible with Zabbix 6.0+). - -### Installation - -1. Clone the repository: - ```bash - git clone - cd zabbix-graphql-api - ``` - -2. Install dependencies: - ```bash - npm install - ``` - -### Configuration - -The API is configured via environment variables. Create a `.env` file or set them in your environment: - -| Variable | Description | Default | -| :--- | :--- | :--- | -| `ZABBIX_BASE_URL` | URL to your Zabbix API (e.g., `http://zabbix.example.com/zabbix`) | | -| `ZABBIX_AUTH_TOKEN` | Zabbix Super Admin API token for administrative tasks | | -| `ZABBIX_EDGE_DEVICE_BASE_GROUP` | Base host group for devices | `Roadwork` | -| `ZABBIX_PERMISSION_TEMPLATE_GROUP_NAME_PREFIX` | Prefix for template groups used as permissions | `Permissions` | -| `SCHEMA_PATH` | Path to the directory containing `.graphql` schema files | `./schema/` | -| `HOST_GROUP_FILTER_DEFAULT` | Default search pattern for `allHostGroups` query | | -| `HOST_TYPE_FILTER_DEFAULT` | Default value for `tag_hostType` filter in `allHosts` and `allDevices` queries | | - -### Starting the API - -#### Development Mode -Starts the server with `nodemon` and `tsx` for automatic reloading: -```bash -npm run start -``` - -#### Production Mode -Builds the project and runs the compiled code: -```bash -npm run prod -``` - -The API will be available at `http://localhost:4000/`. - -#### Running with Docker - -### Using the Pre-built Image - -You can run the API without building it locally by pulling the latest image from the Hilbig IT Forgejo infrastructure: - -```bash -docker pull forgejo.tooling.hilbigit.com/zabbix/zabbix-graphql-api:latest -``` - -Start the container by passing the required environment variables: - -```bash -docker run -d \ - --name zabbix-graphql-api \ - -p 4000:4000 \ - -e ZABBIX_BASE_URL=http://your-zabbix-instance/zabbix \ - -e ZABBIX_AUTH_TOKEN=your-super-admin-token \ - forgejo.tooling.hilbigit.com/zabbix/zabbix-graphql-api:latest -``` - -#### Building Locally - -If you prefer to build the image yourself using the provided `Dockerfile`: - -1. Build the image (ensure you provide an `API_VERSION`): - ```bash - docker build -t zabbix-graphql-api --build-arg API_VERSION=1.0.0 . - ``` - -2. Run the container: - ```bash - docker run -d \ - --name zabbix-graphql-api \ - -p 4000:4000 \ - -e ZABBIX_BASE_URL=http://your-zabbix-instance/zabbix \ - -e ZABBIX_AUTH_TOKEN=your-super-admin-token \ - zabbix-graphql-api - ``` - -## Extending the Schema - -The Zabbix GraphQL API is designed to be highly extensible. You can add your own GraphQL schema snippets and have resolvers dynamically created for them. - -### Dynamic Resolvers with `createHierarchicalValueFieldResolver` - -The function `createHierarchicalValueFieldResolver` (found in `src/api/resolver_helpers.ts`) allows for the automatic creation of resolvers that map Zabbix items or tags to a hierarchical GraphQL structure. It uses field names and Zabbix item keys (dot-separated) to automatically resolve nested objects. - -### Zabbix Preconditions for Hierarchical Mapping - -In order for the dynamic resolvers to correctly map Zabbix data to your GraphQL schema, the following preconditions must be met in your Zabbix templates: - -* **Key Naming**: Zabbix item keys (or tags) must match the GraphQL field names. -* **Dot Separation**: Use a dot (`.`) as a separator to represent nested object structures. For example, a Zabbix item with the key `state.current.values.temperature` will be automatically mapped to the `temperature` field within the nested structure: `state` -> `current` -> `values` -> `temperature`. -* **Type Hinting**: You can guide the type conversion by prepending a type hint and an underscore to the last token of the key: - * `json_`: Parses the value as a JSON object (useful for complex types). - * `str_`: Forces the value to be treated as a string. - * `bool_`: Forces the value to be treated as a boolean. - * `float_`: Forces the value to be treated as a number. - -For a complete example of a Zabbix template designed for schema extension, see the [Distance Tracker Import Sample](docs/sample_import_distance_tracker_template.graphql). - -### No-Code Extension via Environment Variables - -You can extend the schema and add resolvers without writing any TypeScript code by using the following environment variables: - -* **`ADDITIONAL_SCHEMAS`**: A comma-separated list of paths to additional `.graphql` files. -* **`ADDITIONAL_RESOLVERS`**: A comma-separated list of GraphQL Type names for which dynamic hierarchical resolvers should be created. - -#### Example - -Suppose you have custom device definitions in `schema/extensions/`. You can load them and enable dynamic resolution by setting: - -```bash -ADDITIONAL_SCHEMAS=./schema/extensions/display_devices.graphql,./schema/extensions/location_tracker_devices.graphql,./schema/extensions/location_tracker_commons.graphql -ADDITIONAL_RESOLVERS=SinglePanelDevice,FourPanelDevice,DistanceTrackerDevice -``` - -The API will: -1. Load all provided schema files. -2. For each type listed in `ADDITIONAL_RESOLVERS`, it will automatically create a resolver that maps Zabbix items (e.g., an item with key `state.current.values.temperature`) to the corresponding GraphQL fields. - -## User Permissions & `hasPermission` - -The Zabbix GraphQL API provides a sophisticated way to manage and check application-level permissions using Zabbix's built-in user group and template group mechanisms. - -### Modeling Permissions with Template Groups - -Permissions can be modeled as **empty template groups** (groups with no templates or hosts attached) organized in a hierarchical structure. By convention, these groups start with a configurable prefix (default: `Permissions/`). - -#### Example Hierarchy: -* `Permissions/ConstructionSite`: General access to construction site data. -* `Permissions/Automatism`: Access to automation features. -* `Permissions/Automatism/Status`: Permission to view automation status. - -### Zabbix Preconditions - -1. **Template Groups**: Create template groups for each permission you want to manage (e.g., `Permissions/App1/FeatureA`). -2. **User Groups**: In Zabbix, assign these template groups to Zabbix User Groups with specific permission levels (`READ`, `READ_WRITE`, or `DENY`). -3. **Authentication**: The GraphQL API will check the permissions of the authenticated user (via token or session cookie) against these Zabbix assignments. - -### Using `hasPermission` and `userPermissions` - -The API provides two main queries for permission checking: - -* **`userPermissions`**: Returns a list of all permissions assigned to the current user. -* **`hasPermissions`**: Checks if the user has a specific set of required permissions (e.g., "Does the user have `READ_WRITE` access to `Automatism/Status`?"). - -This allows for fine-grained access control in your frontend or external applications, using Zabbix as the central authorization authority. - -For a complete example of how to import these permission groups, see the [Permissions Template Groups Import Sample](docs/sample_import_permissions_template_groups_mutation.graphql). - -## Host Classification & Filtering - -The API leverages Zabbix tags to classify hosts and devices, enabling efficient filtering and multi-tenancy support. - -### The `hostType` Tag - -The `hostType` tag is used to categorize hosts and templates. This allows the API to provide default filters for specific application domains or device categories. - -#### How to set the Host Type in Zabbix: - -To classify a host or a template, simply add a tag in the Zabbix UI or via the API: -* **Tag Name**: `hostType` -* **Tag Value**: A string representing the category (e.g., `Roadwork/Devices`, `SmartCity/Sensors`). - -This tag can be defined: -1. **Directly on the Host**: Specific to that individual device. -2. **On a Template**: All hosts linked to this template will inherit the classification. - -### Default Filtering with `HOST_TYPE_FILTER_DEFAULT` - -By configuring the `HOST_TYPE_FILTER_DEFAULT` environment variable, you can set a global default for the `allHosts` and `allDevices` queries. - -* If `HOST_TYPE_FILTER_DEFAULT=Roadwork/Devices` is set, a query like `allHosts { host }` will only return hosts that have the `hostType` tag set to `Roadwork/Devices`. -* This default can always be overridden in the GraphQL query by explicitly passing the `tag_hostType` argument. - -### Search Filtering with `HOST_GROUP_FILTER_DEFAULT` - -The `HOST_GROUP_FILTER_DEFAULT` variable provides a default search pattern for the `allHostGroups` query. This is particularly useful for restricting the visible host group hierarchy to a specific subtree by default. - -#### Overriding the Default Filter - -The default filter can be overridden by explicitly providing the `search_name` argument in the `allHostGroups` query. When `search_name` is present, the environment variable is ignored. - -#### Using Wildcards - -The `search_name` parameter supports the `*` wildcard (enabled via the Zabbix API's `searchWildcardsEnabled` feature). This allows you to search for all subgroups within a specific path. - -**Example**: To find all subgroups of `Roadwork/Devices/`, use the following query: - -```graphql -query { - allHostGroups(search_name: "Roadwork/Devices/*") { - groupid - name - } -} -``` - -## Sample Application: Virtual Control Room (VCR) - -The **Virtual Control Room (VCR)** is a professional cockpit and control center application designed for monitoring and managing large-scale deployments of IoT and Edge devices, such as traffic management systems, roadwork safety equipment, and environmental sensors. - -### How VCR uses the GraphQL API: - -* **Unified Cockpit**: VCR utilizes the API's **hierarchical mapping** to provide a unified view of diverse device types. It maps Zabbix items and tags directly to structured GraphQL objects (e.g., `operational` telemetry and `current` business state). -* **Dynamic Authorization**: The `hasPermissions` query is used to implement a **Dynamic UI**. Buttons, controls, and status indicators are shown or enabled only if the user has the required `READ` or `READ_WRITE` permissions for that specific object. -* **Mass Provisioning**: VCR leverages the **mass import** capabilities to provision thousands of devices and templates in a single operation, significantly reducing manual configuration effort in Zabbix. -* **Data Visualization**: It uses the `exportHostValueHistory` endpoint to power dashboards showing historical trends, such as traffic density, battery levels, or sensor readings over time. - -For more detailed information about the VCR product, please refer to the technical presentation: -[VCR - Technical product information](docs/VCR%20-%20Technical%20product%20information.pdf) - -## Sample Environment File - -Below is a complete example of a `.env` file showing all available configuration options: - -```env -# Zabbix Connection -ZABBIX_BASE_URL=http://your-zabbix-instance/zabbix -ZABBIX_AUTH_TOKEN=your-super-admin-token-here - -# General Configuration -ZABBIX_EDGE_DEVICE_BASE_GROUP=Roadwork -API_VERSION=1.0.0 -SCHEMA_PATH=./schema/ -HOST_GROUP_FILTER_DEFAULT=Roadwork/Devices/* -HOST_TYPE_FILTER_DEFAULT=Roadwork/Devices - -# Schema Extensions (No-Code) -ADDITIONAL_SCHEMAS=./schema/extensions/display_devices.graphql,./schema/extensions/location_tracker_devices.graphql,./schema/extensions/location_tracker_commons.graphql -ADDITIONAL_RESOLVERS=SinglePanelDevice,FourPanelDevice,DistanceTrackerDevice - -# Logging -# LOG_LEVEL=debug -``` - -## Usage Samples - -The `docs` directory contains several sample GraphQL queries and mutations to help you get started: - -* **Hosts**: - * [Query All Hosts](docs/sample_all_hosts_query.graphql) - * [Import Hosts](docs/sample_import_hosts_mutation.graphql) -* **Templates**: - * [Query Templates](docs/sample_templates_query.graphql) - * [Import Templates](docs/sample_import_templates_mutation.graphql) - * [Import Distance Tracker Template](docs/sample_import_distance_tracker_template.graphql) (Schema Extension Example) - * [Delete Templates](docs/sample_delete_templates_mutation.graphql) -* **Template Groups**: - * [Import Host Template Groups](docs/sample_import_host_template_groups_mutation.graphql) - * [Import Permissions Template Groups](docs/sample_import_permissions_template_groups_mutation.graphql) - * [Delete Template Groups](docs/sample_delete_template_groups_mutation.graphql) -* **User Rights**: - * [Export User Rights](docs/sample_export_user_rights_query.graphql) - * [Import User Rights](docs/sample_import_user_rights_mutation.graphql) - -## License - -This project is licensed under the **GNU Affero General Public License v3.0**. See the [LICENSE](LICENSE) file for details.