diff --git a/.env b/.env index 2d1c753..3a0cfeb 100644 --- a/.env +++ b/.env @@ -24,7 +24,7 @@ APP_SECRET=e95c7f17da15ce1b03d77ad655379c34 # IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml # # DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db" -# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8.0.32&charset=utf8mb4" +#DATABASE_URL="mysql://root:root@127.0.0.1:3336/dimio?serverVersion=8.0.32&charset=utf8mb4" DATABASE_URL="mysql://root:root@ogcore-database:3306/ogcore?serverVersion=10.11.2-MariaDB&charset=utf8mb4" OG_1_DATABASE_URL="mysql://root:root@ogcore-database:3306/ogcore_old_og?serverVersion=10.11.2-MariaDB&charset=utf8mb4" @@ -32,7 +32,7 @@ OG_1_DATABASE_URL="mysql://root:root@ogcore-database:3306/ogcore_old_og?serverVe ###< doctrine/doctrine-bundle ### ###> nelmio/cors-bundle ### -CORS_ALLOW_ORIGIN='^https?://(localhost|127\.0\.0\.1)(:[0-9]+)?$' +CORS_ALLOW_ORIGIN='*' ###< nelmio/cors-bundle ### ###> lexik/jwt-authentication-bundle ### @@ -40,3 +40,13 @@ JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private.pem JWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pem JWT_PASSPHRASE=8b9154df37ffa91ef9186ce095324e39e50ff3b023bb1ed34383abd019ba4515 ###< lexik/jwt-authentication-bundle ### + +OGBOOT_API_URL=http://localhost:8085 +OGDHCP_API_URL=http://localhost:8085 + +###> UDS ### +UDS_AUTH_LOGIN="Usuarios locales" +UDS_AUTH_USERNAME="natiqindel" +UDS_AUTH_PASSWORD="correct horse battery staple" +UDS_URL=https://localhost:8087/uds/rest/ +###< UDS ### diff --git a/Jenkinsfile b/Jenkinsfile index faa778c..c7893df 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,46 +1,109 @@ pipeline { agent { - node { label 'jenkins-slave' - } + } + + environment { + DOCKER_REPO = "opengnsys" + DOCKER_TAG = "${env.BUILD_NUMBER}" + DOCKER_IMAGE_NAME = "ogcore" + BRANCH_NAME = "${env.BRANCH_NAME}" + DOCKER_IDENTITY = "${DOCKER_REPO}/${DOCKER_IMAGE_NAME}-php:${BRANCH_NAME}-${DOCKER_TAG}" + DOCKER_IDENTITY_NGINX = "${DOCKER_REPO}/${DOCKER_IMAGE_NAME}-nginx:${BRANCH_NAME}-${DOCKER_TAG}" + DOCKER_COMPOSE_TEMPLATE = 'docker-compose-ci-template.yaml' + DOCKER_COMPOSE_FILE = 'docker-compose-ci-tmp.yaml' } stages { - stage('Build Environmen') { + stage ("Checkout") { steps { - //Build environment - sh 'docker compose -f docker-compose-ci.yaml up --build -d' + checkout scm + } + } + stage('Build Environment') { + steps { + script { + docker.build("${DOCKER_IDENTITY}", '-f docker/Dockerfile-jenkins-php .') + docker.build("${DOCKER_IDENTITY_NGINX}", '-f docker/Dockerfile-nginx .') + } + } + } + stage(('Prepare Docker Composer')) { + steps { + sh """ + sed 's|ogcore-php:static|${DOCKER_IDENTITY}|g; s|ogcore-nginx:static|${DOCKER_IDENTITY_NGINX}|g' ${DOCKER_COMPOSE_TEMPLATE} > ${DOCKER_COMPOSE_FILE} + cat ${DOCKER_COMPOSE_FILE} + """ + } + } + stage('Run containers') { + steps { + sh "docker compose -f ${DOCKER_COMPOSE_FILE} up -d" } } stage('Install dependencies') { steps { // Install dependencies - sh 'docker exec ogcore-php composer install' - sh 'docker exec ogcore-php php bin/console lexik:jwt:generate-keypair --overwrite' - sh 'docker exec ogcore-php php bin/console doctrine:migrations:migrate --no-interaction' - sh 'docker exec ogcore-php php bin/console doctrine:fixtures:load --no-interaction' - // Create report directory - sh 'docker exec ogcore-php mkdir -p /report' + sh """ + docker compose exec php mkdir -p /report + docker compose exec php composer install + docker compose exec php php bin/console lexik:jwt:generate-keypair --overwrite + docker compose exec php php bin/console doctrine:migrations:migrate --no-interaction + docker compose exec php php bin/console doctrine:fixtures:load --no-interaction + """ } } stage('Tests') { steps { // Run tests - sh 'docker compose exec php bin/phpunit --log-junit /report/phpunit.xml' - sh 'docker cp ogcore-php:/report/phpunit.xml .' + sh """ + docker compose exec php bin/phpunit --log-junit /report/phpunit.xml + """ } } - } + stage ("Publish Image") { + steps { + script { + docker.withRegistry('https://index.docker.io/v1/', 'docker-hub-credentials') { + docker.image("${DOCKER_IDENTITY}").push() + docker.image("${DOCKER_IDENTITY_NGINX}").push() + } + } + } + } + + } post { always { + sh "docker compose -f ${DOCKER_COMPOSE_FILE} cp php:/report/phpunit.xml phpunit.xml" // Publish JUnit test results xunit ( thresholds: [ skipped(failureThreshold: '0') , failed(failureThreshold: '0') ], tools: [ PHPUnit(pattern: 'phpunit.xml') ] ) // Remove containers - sh 'docker compose -f docker-compose-ci.yaml down' - sh 'docker compose -f docker-compose-ci.yaml rm -f' + + sh "docker compose -f ${DOCKER_COMPOSE_FILE} down" + sh "docker compose -f ${DOCKER_COMPOSE_FILE} rm -f" + sh "docker rmi ${DOCKER_IDENTITY}" + sh "docker rmi ${DOCKER_IDENTITY_NGINX}" + script { + def committerEmail = sh ( + script: "git show -s --pretty=%ae", + returnStdout: true + ).trim() + def buildResult = currentBuild.currentResult + mail to: committerEmail, + subject: "Opengnsys CI Build ${env.JOB_NAME} - ${env.BRANCH_NAME} - ${buildResult}", + body: """ +

Opengnsys CI Build ${JOB_NAME} - ${BRANCH_NAME} - ${buildResult}

+

Build Number: ${BUILD_NUMBER}

+

Build URL: ${BUILD_URL}

º + + Saludos cordiales, + Opengnsys CI + """ + } } } } diff --git a/README.md b/README.md index 1539804..31e23ec 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,7 @@ docker exec ogcore-php php bin/console doctrine:migrations:migrate --no-interact ```sh docker exec ogcore-php php bin/console doctrine:fixtures:load --no-interaction docker exec ogcore-php php bin/console app:load-default-user-groups #cargamos los grupos por defecto +docker exec ogcore-php php bin/console app:load-default-commands #cargamos los commands por defecto ``` ## UX Api Platform @@ -129,12 +130,11 @@ Una vez tengamos la base de datos cargada, podremos ejecutar las migraciones de ```sh --- Migraciones de OpenGnsys. --- docker exec ogcore-php php bin/console opengnsys:migration:organizational-unit #cargamos las unidades organizativas -docker exec ogcore-php php bin/console opengnsys:migration:hardware-profiles #cargamos los perfiles de hardware +docker exec ogcore-php php bin/console opengnsys:migration:hardware-profile #cargamos los perfiles de hardware docker exec ogcore-php php bin/console opengnsys:migration:clients #cargamos los clientes docker exec ogcore-php php bin/console opengnsys:migration:os #cargamos los sistemas operativos -docker exec ogcore-php php bin/console opengnsys:migration:partition #cargamos las particiones - - +docker exec ogcore-php php bin/console opengnsys:migration:image #cargamos las imagenes +docker exec ogcore-php php bin/console opengnsys:migration:software-profile #cargamos los software profiles ``` ## Objetos de interés diff --git a/composer.json b/composer.json index 580ef6b..b7550df 100644 --- a/composer.json +++ b/composer.json @@ -2,12 +2,13 @@ "type": "project", "license": "proprietary", "minimum-stability": "stable", + "version": "0.5.0", "prefer-stable": true, "require": { "php": ">=8.1", "ext-ctype": "*", "ext-iconv": "*", - "api-platform/core": "^3.3", + "api-platform/core": "^3.2", "doctrine/dbal": "^3", "doctrine/doctrine-bundle": "^2.12", "doctrine/doctrine-migrations-bundle": "^3.3", @@ -25,6 +26,7 @@ "symfony/expression-language": "6.4.*", "symfony/flex": "^2", "symfony/framework-bundle": "6.4.*", + "symfony/http-client": "6.4.*", "symfony/property-access": "6.4.*", "symfony/property-info": "6.4.*", "symfony/runtime": "6.4.*", @@ -89,7 +91,6 @@ "phpunit/phpunit": "^9.5", "symfony/browser-kit": "6.4.*", "symfony/css-selector": "6.4.*", - "symfony/http-client": "6.4.*", "symfony/maker-bundle": "^1.59", "symfony/phpunit-bridge": "^7.0", "symfony/web-profiler-bundle": "^6.4", diff --git a/composer.lock b/composer.lock index e756ea9..e2c3c61 100644 --- a/composer.lock +++ b/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "bf1165324e27bddd1a412f25e438fc4c", + "content-hash": "696433794f1d706f6d16af7589d2c1ea", "packages": [ { "name": "api-platform/core", - "version": "v3.3.5", + "version": "v3.3.11", "source": { "type": "git", "url": "https://github.com/api-platform/core.git", - "reference": "b5a93fb0bb855273aabb0807505ba61b68813246" + "reference": "ea7d443376dfa1f9a05b53060049e7837d2ec7d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/api-platform/core/zipball/b5a93fb0bb855273aabb0807505ba61b68813246", - "reference": "b5a93fb0bb855273aabb0807505ba61b68813246", + "url": "https://api.github.com/repos/api-platform/core/zipball/ea7d443376dfa1f9a05b53060049e7837d2ec7d4", + "reference": "ea7d443376dfa1f9a05b53060049e7837d2ec7d4", "shasum": "" }, "require": { @@ -190,9 +190,9 @@ ], "support": { "issues": "https://github.com/api-platform/core/issues", - "source": "https://github.com/api-platform/core/tree/v3.3.5" + "source": "https://github.com/api-platform/core/tree/v3.3.11" }, - "time": "2024-05-29T05:48:47+00:00" + "time": "2024-07-20T08:19:33+00:00" }, { "name": "behat/transliterator", @@ -575,16 +575,16 @@ }, { "name": "doctrine/dbal", - "version": "3.8.5", + "version": "3.9.0", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "0e3536ba088a749985c8801105b6b3ac6c1280b6" + "reference": "d8f68ea6cc00912e5313237130b8c8decf4d28c6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/0e3536ba088a749985c8801105b6b3ac6c1280b6", - "reference": "0e3536ba088a749985c8801105b6b3ac6c1280b6", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/d8f68ea6cc00912e5313237130b8c8decf4d28c6", + "reference": "d8f68ea6cc00912e5313237130b8c8decf4d28c6", "shasum": "" }, "require": { @@ -600,12 +600,12 @@ "doctrine/coding-standard": "12.0.0", "fig/log-test": "^1", "jetbrains/phpstorm-stubs": "2023.1", - "phpstan/phpstan": "1.11.1", + "phpstan/phpstan": "1.11.7", "phpstan/phpstan-strict-rules": "^1.6", - "phpunit/phpunit": "9.6.19", + "phpunit/phpunit": "9.6.20", "psalm/plugin-phpunit": "0.18.4", "slevomat/coding-standard": "8.13.1", - "squizlabs/php_codesniffer": "3.9.2", + "squizlabs/php_codesniffer": "3.10.2", "symfony/cache": "^5.4|^6.0|^7.0", "symfony/console": "^4.4|^5.4|^6.0|^7.0", "vimeo/psalm": "4.30.0" @@ -668,7 +668,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/3.8.5" + "source": "https://github.com/doctrine/dbal/tree/3.9.0" }, "funding": [ { @@ -684,7 +684,7 @@ "type": "tidelift" } ], - "time": "2024-06-08T17:49:56+00:00" + "time": "2024-08-15T07:34:42+00:00" }, { "name": "doctrine/deprecations", @@ -1276,21 +1276,21 @@ }, { "name": "doctrine/migrations", - "version": "3.7.4", + "version": "3.8.0", "source": { "type": "git", "url": "https://github.com/doctrine/migrations.git", - "reference": "954e0a314c2f0eb9fb418210445111747de254a6" + "reference": "535a70dcbd88b8c6ba945be050977457f4f4c06c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/migrations/zipball/954e0a314c2f0eb9fb418210445111747de254a6", - "reference": "954e0a314c2f0eb9fb418210445111747de254a6", + "url": "https://api.github.com/repos/doctrine/migrations/zipball/535a70dcbd88b8c6ba945be050977457f4f4c06c", + "reference": "535a70dcbd88b8c6ba945be050977457f4f4c06c", "shasum": "" }, "require": { "composer-runtime-api": "^2", - "doctrine/dbal": "^3.5.1 || ^4", + "doctrine/dbal": "^3.6 || ^4", "doctrine/deprecations": "^0.5.3 || ^1", "doctrine/event-manager": "^1.2 || ^2.0", "php": "^8.1", @@ -1328,7 +1328,7 @@ "type": "library", "autoload": { "psr-4": { - "Doctrine\\Migrations\\": "lib/Doctrine/Migrations" + "Doctrine\\Migrations\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -1358,7 +1358,7 @@ ], "support": { "issues": "https://github.com/doctrine/migrations/issues", - "source": "https://github.com/doctrine/migrations/tree/3.7.4" + "source": "https://github.com/doctrine/migrations/tree/3.8.0" }, "funding": [ { @@ -1374,20 +1374,20 @@ "type": "tidelift" } ], - "time": "2024-03-06T13:41:11+00:00" + "time": "2024-06-26T14:12:46+00:00" }, { "name": "doctrine/orm", - "version": "2.19.5", + "version": "2.19.6", "source": { "type": "git", "url": "https://github.com/doctrine/orm.git", - "reference": "94986af28452da42a46a4489d1c958a2e5d710e5" + "reference": "c1bb2ccf4b19c845f91ff7c4c01dc7cbba7f4073" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/orm/zipball/94986af28452da42a46a4489d1c958a2e5d710e5", - "reference": "94986af28452da42a46a4489d1c958a2e5d710e5", + "url": "https://api.github.com/repos/doctrine/orm/zipball/c1bb2ccf4b19c845f91ff7c4c01dc7cbba7f4073", + "reference": "c1bb2ccf4b19c845f91ff7c4c01dc7cbba7f4073", "shasum": "" }, "require": { @@ -1416,14 +1416,14 @@ "doctrine/annotations": "^1.13 || ^2", "doctrine/coding-standard": "^9.0.2 || ^12.0", "phpbench/phpbench": "^0.16.10 || ^1.0", - "phpstan/phpstan": "~1.4.10 || 1.10.59", + "phpstan/phpstan": "~1.4.10 || 1.11.1", "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6", "psr/log": "^1 || ^2 || ^3", "squizlabs/php_codesniffer": "3.7.2", "symfony/cache": "^4.4 || ^5.4 || ^6.4 || ^7.0", "symfony/var-exporter": "^4.4 || ^5.4 || ^6.2 || ^7.0", "symfony/yaml": "^3.4 || ^4.0 || ^5.0 || ^6.0 || ^7.0", - "vimeo/psalm": "4.30.0 || 5.22.2" + "vimeo/psalm": "4.30.0 || 5.24.0" }, "suggest": { "ext-dom": "Provides support for XSD validation for XML mapping files", @@ -1473,22 +1473,22 @@ ], "support": { "issues": "https://github.com/doctrine/orm/issues", - "source": "https://github.com/doctrine/orm/tree/2.19.5" + "source": "https://github.com/doctrine/orm/tree/2.19.6" }, - "time": "2024-04-30T06:49:54+00:00" + "time": "2024-06-26T17:24:40+00:00" }, { "name": "doctrine/persistence", - "version": "3.3.2", + "version": "3.3.3", "source": { "type": "git", "url": "https://github.com/doctrine/persistence.git", - "reference": "477da35bd0255e032826f440b94b3e37f2d56f42" + "reference": "b337726451f5d530df338fc7f68dee8781b49779" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/persistence/zipball/477da35bd0255e032826f440b94b3e37f2d56f42", - "reference": "477da35bd0255e032826f440b94b3e37f2d56f42", + "url": "https://api.github.com/repos/doctrine/persistence/zipball/b337726451f5d530df338fc7f68dee8781b49779", + "reference": "b337726451f5d530df338fc7f68dee8781b49779", "shasum": "" }, "require": { @@ -1500,15 +1500,14 @@ "doctrine/common": "<2.10" }, "require-dev": { - "composer/package-versions-deprecated": "^1.11", - "doctrine/coding-standard": "^11", + "doctrine/coding-standard": "^12", "doctrine/common": "^3.0", - "phpstan/phpstan": "1.9.4", + "phpstan/phpstan": "1.11.1", "phpstan/phpstan-phpunit": "^1", "phpstan/phpstan-strict-rules": "^1.1", "phpunit/phpunit": "^8.5 || ^9.5", "symfony/cache": "^4.4 || ^5.4 || ^6.0", - "vimeo/psalm": "4.30.0 || 5.3.0" + "vimeo/psalm": "4.30.0 || 5.24.0" }, "type": "library", "autoload": { @@ -1557,7 +1556,7 @@ ], "support": { "issues": "https://github.com/doctrine/persistence/issues", - "source": "https://github.com/doctrine/persistence/tree/3.3.2" + "source": "https://github.com/doctrine/persistence/tree/3.3.3" }, "funding": [ { @@ -1573,20 +1572,20 @@ "type": "tidelift" } ], - "time": "2024-03-12T14:54:36+00:00" + "time": "2024-06-20T10:14:30+00:00" }, { "name": "doctrine/sql-formatter", - "version": "1.4.0", + "version": "1.4.1", "source": { "type": "git", "url": "https://github.com/doctrine/sql-formatter.git", - "reference": "d1ac84aef745c69ea034929eb6d65a6908b675cc" + "reference": "7f83911cc5eba870de7ebb11283972483f7e2891" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/d1ac84aef745c69ea034929eb6d65a6908b675cc", - "reference": "d1ac84aef745c69ea034929eb6d65a6908b675cc", + "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/7f83911cc5eba870de7ebb11283972483f7e2891", + "reference": "7f83911cc5eba870de7ebb11283972483f7e2891", "shasum": "" }, "require": { @@ -1626,22 +1625,22 @@ ], "support": { "issues": "https://github.com/doctrine/sql-formatter/issues", - "source": "https://github.com/doctrine/sql-formatter/tree/1.4.0" + "source": "https://github.com/doctrine/sql-formatter/tree/1.4.1" }, - "time": "2024-05-08T08:12:09+00:00" + "time": "2024-08-05T20:32:22+00:00" }, { "name": "gedmo/doctrine-extensions", - "version": "v3.15.0", + "version": "v3.16.1", "source": { "type": "git", "url": "https://github.com/doctrine-extensions/DoctrineExtensions.git", - "reference": "2a89103f4984d8970f3855284c8c04e6e6a63c0f" + "reference": "e85560ed96f977b8c29428a99222cb2ef2f0e80d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine-extensions/DoctrineExtensions/zipball/2a89103f4984d8970f3855284c8c04e6e6a63c0f", - "reference": "2a89103f4984d8970f3855284c8c04e6e6a63c0f", + "url": "https://api.github.com/repos/doctrine-extensions/DoctrineExtensions/zipball/e85560ed96f977b8c29428a99222cb2ef2f0e80d", + "reference": "e85560ed96f977b8c29428a99222cb2ef2f0e80d", "shasum": "" }, "require": { @@ -1660,7 +1659,7 @@ "doctrine/annotations": "<1.13 || >=3.0", "doctrine/dbal": "<3.2 || >=4.0", "doctrine/mongodb-odm": "<2.3 || >=3.0", - "doctrine/orm": "<2.14.0 || 2.16.0 || 2.16.1 || >=3.0" + "doctrine/orm": "<2.14.0 || 2.16.0 || 2.16.1 || >=4.0" }, "require-dev": { "doctrine/annotations": "^1.13 || ^2.0", @@ -1668,16 +1667,18 @@ "doctrine/dbal": "^3.2", "doctrine/doctrine-bundle": "^2.3", "doctrine/mongodb-odm": "^2.3", - "doctrine/orm": "^2.14.0", + "doctrine/orm": "^2.14.0 || ^3.0", "friendsofphp/php-cs-fixer": "^3.14.0", "nesbot/carbon": "^2.71 || ^3.0", - "phpstan/phpstan": "^1.10.2", - "phpstan/phpstan-doctrine": "^1.0", - "phpstan/phpstan-phpunit": "^1.0", + "phpstan/phpstan": "^1.11", + "phpstan/phpstan-doctrine": "^1.4", + "phpstan/phpstan-phpunit": "^1.4", "phpunit/phpunit": "^9.6", - "rector/rector": "^0.19", + "rector/rector": "^1.1", "symfony/console": "^5.4 || ^6.0 || ^7.0", + "symfony/doctrine-bridge": "^5.4 || ^6.0 || ^7.0", "symfony/phpunit-bridge": "^6.0 || ^7.0", + "symfony/uid": "^5.4 || ^6.0 || ^7.0", "symfony/yaml": "^5.4 || ^6.0 || ^7.0" }, "suggest": { @@ -1687,7 +1688,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.13-dev" + "dev-main": "3.x-dev" } }, "autoload": { @@ -1735,7 +1736,7 @@ "support": { "email": "gediminas.morkevicius@gmail.com", "issues": "https://github.com/doctrine-extensions/DoctrineExtensions/issues", - "source": "https://github.com/doctrine-extensions/DoctrineExtensions/tree/v3.15.0", + "source": "https://github.com/doctrine-extensions/DoctrineExtensions/tree/v3.16.1", "wiki": "https://github.com/Atlantic18/DoctrineExtensions/tree/main/doc" }, "funding": [ @@ -1756,7 +1757,7 @@ "type": "github" } ], - "time": "2024-02-12T15:17:22+00:00" + "time": "2024-06-25T16:22:14+00:00" }, { "name": "gesdinet/jwt-refresh-token-bundle", @@ -1977,16 +1978,16 @@ }, { "name": "lexik/jwt-authentication-bundle", - "version": "v3.0.0", + "version": "v3.1.0", "source": { "type": "git", "url": "https://github.com/lexik/LexikJWTAuthenticationBundle.git", - "reference": "b20c4ae7fdfe1d7422c7099a141cc9eb64627310" + "reference": "4f1a638289cf9282bad1b82b8df56d3bd4e0743c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/lexik/LexikJWTAuthenticationBundle/zipball/b20c4ae7fdfe1d7422c7099a141cc9eb64627310", - "reference": "b20c4ae7fdfe1d7422c7099a141cc9eb64627310", + "url": "https://api.github.com/repos/lexik/LexikJWTAuthenticationBundle/zipball/4f1a638289cf9282bad1b82b8df56d3bd4e0743c", + "reference": "4f1a638289cf9282bad1b82b8df56d3bd4e0743c", "shasum": "" }, "require": { @@ -2076,7 +2077,7 @@ ], "support": { "issues": "https://github.com/lexik/LexikJWTAuthenticationBundle/issues", - "source": "https://github.com/lexik/LexikJWTAuthenticationBundle/tree/v3.0.0" + "source": "https://github.com/lexik/LexikJWTAuthenticationBundle/tree/v3.1.0" }, "funding": [ { @@ -2088,20 +2089,20 @@ "type": "tidelift" } ], - "time": "2024-05-05T17:49:24+00:00" + "time": "2024-07-03T20:49:59+00:00" }, { "name": "nelmio/cors-bundle", - "version": "2.4.0", + "version": "2.5.0", "source": { "type": "git", "url": "https://github.com/nelmio/NelmioCorsBundle.git", - "reference": "78fcdb91f76b080a1008133def9c7f613833933d" + "reference": "3a526fe025cd20e04a6a11370cf5ab28dbb5a544" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nelmio/NelmioCorsBundle/zipball/78fcdb91f76b080a1008133def9c7f613833933d", - "reference": "78fcdb91f76b080a1008133def9c7f613833933d", + "url": "https://api.github.com/repos/nelmio/NelmioCorsBundle/zipball/3a526fe025cd20e04a6a11370cf5ab28dbb5a544", + "reference": "3a526fe025cd20e04a6a11370cf5ab28dbb5a544", "shasum": "" }, "require": { @@ -2148,9 +2149,9 @@ ], "support": { "issues": "https://github.com/nelmio/NelmioCorsBundle/issues", - "source": "https://github.com/nelmio/NelmioCorsBundle/tree/2.4.0" + "source": "https://github.com/nelmio/NelmioCorsBundle/tree/2.5.0" }, - "time": "2023-11-30T16:41:19+00:00" + "time": "2024-06-24T21:25:28+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -2947,16 +2948,16 @@ }, { "name": "stof/doctrine-extensions-bundle", - "version": "v1.11.0", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/stof/StofDoctrineExtensionsBundle.git", - "reference": "9f7023e4c8a1c00a5627d41c1027a3f89e477630" + "reference": "473ae65598fa4160654c350e139e20ee75d9a91a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/stof/StofDoctrineExtensionsBundle/zipball/9f7023e4c8a1c00a5627d41c1027a3f89e477630", - "reference": "9f7023e4c8a1c00a5627d41c1027a3f89e477630", + "url": "https://api.github.com/repos/stof/StofDoctrineExtensionsBundle/zipball/473ae65598fa4160654c350e139e20ee75d9a91a", + "reference": "473ae65598fa4160654c350e139e20ee75d9a91a", "shasum": "" }, "require": { @@ -3021,9 +3022,9 @@ ], "support": { "issues": "https://github.com/stof/StofDoctrineExtensionsBundle/issues", - "source": "https://github.com/stof/StofDoctrineExtensionsBundle/tree/v1.11.0" + "source": "https://github.com/stof/StofDoctrineExtensionsBundle/tree/v1.12.0" }, - "time": "2024-02-13T14:43:20+00:00" + "time": "2024-06-10T12:27:27+00:00" }, { "name": "symfony/asset", @@ -3096,16 +3097,16 @@ }, { "name": "symfony/cache", - "version": "v6.4.8", + "version": "v6.4.10", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "287142df5579ce223c485b3872df3efae8390984" + "reference": "6702d2d777260e6ff3451fee2d7d78ab5f715cdc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/287142df5579ce223c485b3872df3efae8390984", - "reference": "287142df5579ce223c485b3872df3efae8390984", + "url": "https://api.github.com/repos/symfony/cache/zipball/6702d2d777260e6ff3451fee2d7d78ab5f715cdc", + "reference": "6702d2d777260e6ff3451fee2d7d78ab5f715cdc", "shasum": "" }, "require": { @@ -3172,7 +3173,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v6.4.8" + "source": "https://github.com/symfony/cache/tree/v6.4.10" }, "funding": [ { @@ -3188,7 +3189,7 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-07-17T06:05:49+00:00" }, { "name": "symfony/cache-contracts", @@ -3417,16 +3418,16 @@ }, { "name": "symfony/console", - "version": "v6.4.8", + "version": "v6.4.10", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "be5854cee0e8c7b110f00d695d11debdfa1a2a91" + "reference": "504974cbe43d05f83b201d6498c206f16fc0cdbc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/be5854cee0e8c7b110f00d695d11debdfa1a2a91", - "reference": "be5854cee0e8c7b110f00d695d11debdfa1a2a91", + "url": "https://api.github.com/repos/symfony/console/zipball/504974cbe43d05f83b201d6498c206f16fc0cdbc", + "reference": "504974cbe43d05f83b201d6498c206f16fc0cdbc", "shasum": "" }, "require": { @@ -3491,7 +3492,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.8" + "source": "https://github.com/symfony/console/tree/v6.4.10" }, "funding": [ { @@ -3507,20 +3508,20 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-07-26T12:30:32+00:00" }, { "name": "symfony/dependency-injection", - "version": "v6.4.8", + "version": "v6.4.10", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "d3b618176e8c3a9e5772151c51eba0c52a0c771c" + "reference": "5caf9c5f6085f13b27d70a236b776c07e4a1c3eb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/d3b618176e8c3a9e5772151c51eba0c52a0c771c", - "reference": "d3b618176e8c3a9e5772151c51eba0c52a0c771c", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/5caf9c5f6085f13b27d70a236b776c07e4a1c3eb", + "reference": "5caf9c5f6085f13b27d70a236b776c07e4a1c3eb", "shasum": "" }, "require": { @@ -3572,7 +3573,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v6.4.8" + "source": "https://github.com/symfony/dependency-injection/tree/v6.4.10" }, "funding": [ { @@ -3588,7 +3589,7 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-07-26T07:32:07+00:00" }, { "name": "symfony/deprecation-contracts", @@ -3659,16 +3660,16 @@ }, { "name": "symfony/doctrine-bridge", - "version": "v6.4.8", + "version": "v6.4.10", "source": { "type": "git", "url": "https://github.com/symfony/doctrine-bridge.git", - "reference": "afbf291ccaf595c8ff6f4ed3943aa0ea479e4d04" + "reference": "0de9662441bce4670506d0c371cc819a9d0a7607" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/afbf291ccaf595c8ff6f4ed3943aa0ea479e4d04", - "reference": "afbf291ccaf595c8ff6f4ed3943aa0ea479e4d04", + "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/0de9662441bce4670506d0c371cc819a9d0a7607", + "reference": "0de9662441bce4670506d0c371cc819a9d0a7607", "shasum": "" }, "require": { @@ -3747,7 +3748,7 @@ "description": "Provides integration for Doctrine with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/doctrine-bridge/tree/v6.4.8" + "source": "https://github.com/symfony/doctrine-bridge/tree/v6.4.10" }, "funding": [ { @@ -3763,20 +3764,20 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-07-26T12:30:32+00:00" }, { "name": "symfony/dotenv", - "version": "v6.4.8", + "version": "v6.4.10", "source": { "type": "git", "url": "https://github.com/symfony/dotenv.git", - "reference": "55aefa0029adff89ecffdb560820e945c7983f06" + "reference": "2ae0c84cc9be0dc1eeb86016970b63c764d8472e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dotenv/zipball/55aefa0029adff89ecffdb560820e945c7983f06", - "reference": "55aefa0029adff89ecffdb560820e945c7983f06", + "url": "https://api.github.com/repos/symfony/dotenv/zipball/2ae0c84cc9be0dc1eeb86016970b63c764d8472e", + "reference": "2ae0c84cc9be0dc1eeb86016970b63c764d8472e", "shasum": "" }, "require": { @@ -3821,7 +3822,7 @@ "environment" ], "support": { - "source": "https://github.com/symfony/dotenv/tree/v6.4.8" + "source": "https://github.com/symfony/dotenv/tree/v6.4.10" }, "funding": [ { @@ -3837,20 +3838,20 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-07-09T18:29:35+00:00" }, { "name": "symfony/error-handler", - "version": "v6.4.8", + "version": "v6.4.10", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "ef836152bf13472dc5fb5b08b0c0c4cfeddc0fcc" + "reference": "231f1b2ee80f72daa1972f7340297d67439224f0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/ef836152bf13472dc5fb5b08b0c0c4cfeddc0fcc", - "reference": "ef836152bf13472dc5fb5b08b0c0c4cfeddc0fcc", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/231f1b2ee80f72daa1972f7340297d67439224f0", + "reference": "231f1b2ee80f72daa1972f7340297d67439224f0", "shasum": "" }, "require": { @@ -3896,7 +3897,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v6.4.8" + "source": "https://github.com/symfony/error-handler/tree/v6.4.10" }, "funding": [ { @@ -3912,7 +3913,7 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-07-26T12:30:32+00:00" }, { "name": "symfony/event-dispatcher", @@ -4136,16 +4137,16 @@ }, { "name": "symfony/filesystem", - "version": "v6.4.8", + "version": "v6.4.9", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "4d37529150e7081c51b3c5d5718c55a04a9503f3" + "reference": "b51ef8059159330b74a4d52f68e671033c0fe463" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/4d37529150e7081c51b3c5d5718c55a04a9503f3", - "reference": "4d37529150e7081c51b3c5d5718c55a04a9503f3", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/b51ef8059159330b74a4d52f68e671033c0fe463", + "reference": "b51ef8059159330b74a4d52f68e671033c0fe463", "shasum": "" }, "require": { @@ -4182,7 +4183,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.4.8" + "source": "https://github.com/symfony/filesystem/tree/v6.4.9" }, "funding": [ { @@ -4198,20 +4199,20 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-06-28T09:49:33+00:00" }, { "name": "symfony/finder", - "version": "v6.4.8", + "version": "v6.4.10", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "3ef977a43883215d560a2cecb82ec8e62131471c" + "reference": "af29198d87112bebdd397bd7735fbd115997824c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/3ef977a43883215d560a2cecb82ec8e62131471c", - "reference": "3ef977a43883215d560a2cecb82ec8e62131471c", + "url": "https://api.github.com/repos/symfony/finder/zipball/af29198d87112bebdd397bd7735fbd115997824c", + "reference": "af29198d87112bebdd397bd7735fbd115997824c", "shasum": "" }, "require": { @@ -4246,7 +4247,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v6.4.8" + "source": "https://github.com/symfony/finder/tree/v6.4.10" }, "funding": [ { @@ -4262,20 +4263,20 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-07-24T07:06:38+00:00" }, { "name": "symfony/flex", - "version": "v2.4.5", + "version": "v2.4.6", "source": { "type": "git", "url": "https://github.com/symfony/flex.git", - "reference": "b0a405f40614c9f584b489d54f91091817b0e26e" + "reference": "4dc11919791f81d087a12db2ab4c7e044431ef6b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/flex/zipball/b0a405f40614c9f584b489d54f91091817b0e26e", - "reference": "b0a405f40614c9f584b489d54f91091817b0e26e", + "url": "https://api.github.com/repos/symfony/flex/zipball/4dc11919791f81d087a12db2ab4c7e044431ef6b", + "reference": "4dc11919791f81d087a12db2ab4c7e044431ef6b", "shasum": "" }, "require": { @@ -4311,7 +4312,7 @@ "description": "Composer plugin for Symfony", "support": { "issues": "https://github.com/symfony/flex/issues", - "source": "https://github.com/symfony/flex/tree/v2.4.5" + "source": "https://github.com/symfony/flex/tree/v2.4.6" }, "funding": [ { @@ -4327,20 +4328,20 @@ "type": "tidelift" } ], - "time": "2024-03-02T08:16:47+00:00" + "time": "2024-04-27T10:22:22+00:00" }, { "name": "symfony/framework-bundle", - "version": "v6.4.8", + "version": "v6.4.10", "source": { "type": "git", "url": "https://github.com/symfony/framework-bundle.git", - "reference": "7c7739f87f1a8be1c2f5e7d28addfe763a917acb" + "reference": "6cbdb0cc3ddbb63499262cd3036882b08ee2690b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/7c7739f87f1a8be1c2f5e7d28addfe763a917acb", - "reference": "7c7739f87f1a8be1c2f5e7d28addfe763a917acb", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/6cbdb0cc3ddbb63499262cd3036882b08ee2690b", + "reference": "6cbdb0cc3ddbb63499262cd3036882b08ee2690b", "shasum": "" }, "require": { @@ -4459,7 +4460,7 @@ "description": "Provides a tight integration between Symfony components and the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/framework-bundle/tree/v6.4.8" + "source": "https://github.com/symfony/framework-bundle/tree/v6.4.10" }, "funding": [ { @@ -4475,20 +4476,191 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-07-26T13:24:20+00:00" }, { - "name": "symfony/http-foundation", - "version": "v6.4.8", + "name": "symfony/http-client", + "version": "v6.4.10", "source": { "type": "git", - "url": "https://github.com/symfony/http-foundation.git", - "reference": "27de8cc95e11db7a50b027e71caaab9024545947" + "url": "https://github.com/symfony/http-client.git", + "reference": "b5e498f763e0bf5eed8dcd946e50a3b3f71d4ded" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/27de8cc95e11db7a50b027e71caaab9024545947", - "reference": "27de8cc95e11db7a50b027e71caaab9024545947", + "url": "https://api.github.com/repos/symfony/http-client/zipball/b5e498f763e0bf5eed8dcd946e50a3b3f71d4ded", + "reference": "b5e498f763e0bf5eed8dcd946e50a3b3f71d4ded", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/log": "^1|^2|^3", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/http-client-contracts": "^3.4.1", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "php-http/discovery": "<1.15", + "symfony/http-foundation": "<6.3" + }, + "provide": { + "php-http/async-client-implementation": "*", + "php-http/client-implementation": "*", + "psr/http-client-implementation": "1.0", + "symfony/http-client-implementation": "3.0" + }, + "require-dev": { + "amphp/amp": "^2.5", + "amphp/http-client": "^4.2.1", + "amphp/http-tunnel": "^1.0", + "amphp/socket": "^1.1", + "guzzlehttp/promises": "^1.4|^2.0", + "nyholm/psr7": "^1.0", + "php-http/httplug": "^1.0|^2.0", + "psr/http-client": "^1.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/messenger": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/stopwatch": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpClient\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", + "homepage": "https://symfony.com", + "keywords": [ + "http" + ], + "support": { + "source": "https://github.com/symfony/http-client/tree/v6.4.10" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-07-15T09:26:24+00:00" + }, + { + "name": "symfony/http-client-contracts", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-client-contracts.git", + "reference": "20414d96f391677bf80078aa55baece78b82647d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/20414d96f391677bf80078aa55baece78b82647d", + "reference": "20414d96f391677bf80078aa55baece78b82647d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\HttpClient\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to HTTP clients", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:32:20+00:00" + }, + { + "name": "symfony/http-foundation", + "version": "v6.4.10", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "117f1f20a7ade7bcea28b861fb79160a21a1e37b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/117f1f20a7ade7bcea28b861fb79160a21a1e37b", + "reference": "117f1f20a7ade7bcea28b861fb79160a21a1e37b", "shasum": "" }, "require": { @@ -4536,7 +4708,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v6.4.8" + "source": "https://github.com/symfony/http-foundation/tree/v6.4.10" }, "funding": [ { @@ -4552,20 +4724,20 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-07-26T12:36:27+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.4.8", + "version": "v6.4.10", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "6c519aa3f32adcfd1d1f18d923f6b227d9acf3c1" + "reference": "147e0daf618d7575b5007055340d09aece5cf068" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/6c519aa3f32adcfd1d1f18d923f6b227d9acf3c1", - "reference": "6c519aa3f32adcfd1d1f18d923f6b227d9acf3c1", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/147e0daf618d7575b5007055340d09aece5cf068", + "reference": "147e0daf618d7575b5007055340d09aece5cf068", "shasum": "" }, "require": { @@ -4650,7 +4822,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v6.4.8" + "source": "https://github.com/symfony/http-kernel/tree/v6.4.10" }, "funding": [ { @@ -4666,7 +4838,7 @@ "type": "tidelift" } ], - "time": "2024-06-02T16:06:25+00:00" + "time": "2024-07-26T14:52:04+00:00" }, { "name": "symfony/password-hasher", @@ -4742,16 +4914,16 @@ }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f" + "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/32a9da87d7b3245e09ac426c83d334ae9f06f80f", - "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/64647a7c30b2283f5d49b874d84a18fc22054b7a", + "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a", "shasum": "" }, "require": { @@ -4800,7 +4972,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.30.0" }, "funding": [ { @@ -4816,20 +4988,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-05-31T15:07:36+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "bc45c394692b948b4d383a08d7753968bed9a83d" + "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d", - "reference": "bc45c394692b948b4d383a08d7753968bed9a83d", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/a95281b0be0d9ab48050ebd988b967875cdb9fdb", + "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb", "shasum": "" }, "require": { @@ -4881,7 +5053,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.30.0" }, "funding": [ { @@ -4897,20 +5069,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-05-31T15:07:36+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec" + "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec", - "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fd22ab50000ef01661e2a31d850ebaa297f8e03c", + "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c", "shasum": "" }, "require": { @@ -4961,7 +5133,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.30.0" }, "funding": [ { @@ -4977,25 +5149,24 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-06-19T12:30:46+00:00" }, { "name": "symfony/polyfill-php83", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "86fcae159633351e5fd145d1c47de6c528f8caff" + "reference": "dbdcdf1a4dcc2743591f1079d0c35ab1e2dcbbc9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/86fcae159633351e5fd145d1c47de6c528f8caff", - "reference": "86fcae159633351e5fd145d1c47de6c528f8caff", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/dbdcdf1a4dcc2743591f1079d0c35ab1e2dcbbc9", + "reference": "dbdcdf1a4dcc2743591f1079d0c35ab1e2dcbbc9", "shasum": "" }, "require": { - "php": ">=7.1", - "symfony/polyfill-php80": "^1.14" + "php": ">=7.1" }, "type": "library", "extra": { @@ -5038,7 +5209,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.30.0" }, "funding": [ { @@ -5054,7 +5225,7 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-06-19T12:35:24+00:00" }, { "name": "symfony/property-access", @@ -5135,16 +5306,16 @@ }, { "name": "symfony/property-info", - "version": "v6.4.8", + "version": "v6.4.10", "source": { "type": "git", "url": "https://github.com/symfony/property-info.git", - "reference": "7f544bc6ceb1a6a2283c7af8e8621262c43b7ede" + "reference": "edaea9dcc723cb4a0ab6a00f7d6f8c07c0d8ff77" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-info/zipball/7f544bc6ceb1a6a2283c7af8e8621262c43b7ede", - "reference": "7f544bc6ceb1a6a2283c7af8e8621262c43b7ede", + "url": "https://api.github.com/repos/symfony/property-info/zipball/edaea9dcc723cb4a0ab6a00f7d6f8c07c0d8ff77", + "reference": "edaea9dcc723cb4a0ab6a00f7d6f8c07c0d8ff77", "shasum": "" }, "require": { @@ -5198,7 +5369,7 @@ "validator" ], "support": { - "source": "https://github.com/symfony/property-info/tree/v6.4.8" + "source": "https://github.com/symfony/property-info/tree/v6.4.10" }, "funding": [ { @@ -5214,20 +5385,20 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-07-26T07:32:07+00:00" }, { "name": "symfony/routing", - "version": "v6.4.8", + "version": "v6.4.10", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "8a40d0f9b01f0fbb80885d3ce0ad6714fb603a58" + "reference": "aad19fe10753ba842f0d653a8db819c4b3affa87" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/8a40d0f9b01f0fbb80885d3ce0ad6714fb603a58", - "reference": "8a40d0f9b01f0fbb80885d3ce0ad6714fb603a58", + "url": "https://api.github.com/repos/symfony/routing/zipball/aad19fe10753ba842f0d653a8db819c4b3affa87", + "reference": "aad19fe10753ba842f0d653a8db819c4b3affa87", "shasum": "" }, "require": { @@ -5281,7 +5452,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.4.8" + "source": "https://github.com/symfony/routing/tree/v6.4.10" }, "funding": [ { @@ -5297,7 +5468,7 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-07-15T09:26:24+00:00" }, { "name": "symfony/runtime", @@ -5380,16 +5551,16 @@ }, { "name": "symfony/security-bundle", - "version": "v6.4.8", + "version": "v6.4.10", "source": { "type": "git", "url": "https://github.com/symfony/security-bundle.git", - "reference": "dfb286069b0332e1f1c21962133d17c0fbc1e5e7" + "reference": "50007f4f76632741b62fa9604c5f65807f268b72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-bundle/zipball/dfb286069b0332e1f1c21962133d17c0fbc1e5e7", - "reference": "dfb286069b0332e1f1c21962133d17c0fbc1e5e7", + "url": "https://api.github.com/repos/symfony/security-bundle/zipball/50007f4f76632741b62fa9604c5f65807f268b72", + "reference": "50007f4f76632741b62fa9604c5f65807f268b72", "shasum": "" }, "require": { @@ -5472,7 +5643,7 @@ "description": "Provides a tight integration of the Security component into the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-bundle/tree/v6.4.8" + "source": "https://github.com/symfony/security-bundle/tree/v6.4.10" }, "funding": [ { @@ -5488,20 +5659,20 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-07-17T10:49:44+00:00" }, { "name": "symfony/security-core", - "version": "v6.4.8", + "version": "v6.4.10", "source": { "type": "git", "url": "https://github.com/symfony/security-core.git", - "reference": "5fc7850ada5e8e03d78c1739c82c64d5e2f7d495" + "reference": "432dec55da108c471adcf58c351af01372a52164" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-core/zipball/5fc7850ada5e8e03d78c1739c82c64d5e2f7d495", - "reference": "5fc7850ada5e8e03d78c1739c82c64d5e2f7d495", + "url": "https://api.github.com/repos/symfony/security-core/zipball/432dec55da108c471adcf58c351af01372a52164", + "reference": "432dec55da108c471adcf58c351af01372a52164", "shasum": "" }, "require": { @@ -5558,7 +5729,7 @@ "description": "Symfony Security Component - Core Library", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-core/tree/v6.4.8" + "source": "https://github.com/symfony/security-core/tree/v6.4.10" }, "funding": [ { @@ -5574,7 +5745,7 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-07-26T12:30:32+00:00" }, { "name": "symfony/security-csrf", @@ -5646,16 +5817,16 @@ }, { "name": "symfony/security-http", - "version": "v6.4.8", + "version": "v6.4.9", "source": { "type": "git", "url": "https://github.com/symfony/security-http.git", - "reference": "fb82ddec887dc67f3bcf4d6df3cb8efd529be104" + "reference": "8e70f39626ada36c5492c3aff9369c85d2840948" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-http/zipball/fb82ddec887dc67f3bcf4d6df3cb8efd529be104", - "reference": "fb82ddec887dc67f3bcf4d6df3cb8efd529be104", + "url": "https://api.github.com/repos/symfony/security-http/zipball/8e70f39626ada36c5492c3aff9369c85d2840948", + "reference": "8e70f39626ada36c5492c3aff9369c85d2840948", "shasum": "" }, "require": { @@ -5714,7 +5885,7 @@ "description": "Symfony Security Component - HTTP Integration", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-http/tree/v6.4.8" + "source": "https://github.com/symfony/security-http/tree/v6.4.9" }, "funding": [ { @@ -5730,20 +5901,20 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-06-21T16:04:15+00:00" }, { "name": "symfony/serializer", - "version": "v6.4.8", + "version": "v6.4.10", "source": { "type": "git", "url": "https://github.com/symfony/serializer.git", - "reference": "d6eda9966a3e5d1823c1cedf41bf98f8ed969d7c" + "reference": "9a67fcf320561e96f94d62bbe0e169ac534a5718" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/serializer/zipball/d6eda9966a3e5d1823c1cedf41bf98f8ed969d7c", - "reference": "d6eda9966a3e5d1823c1cedf41bf98f8ed969d7c", + "url": "https://api.github.com/repos/symfony/serializer/zipball/9a67fcf320561e96f94d62bbe0e169ac534a5718", + "reference": "9a67fcf320561e96f94d62bbe0e169ac534a5718", "shasum": "" }, "require": { @@ -5812,7 +5983,7 @@ "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/serializer/tree/v6.4.8" + "source": "https://github.com/symfony/serializer/tree/v6.4.10" }, "funding": [ { @@ -5828,7 +5999,7 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-07-26T13:13:26+00:00" }, { "name": "symfony/service-contracts", @@ -5977,16 +6148,16 @@ }, { "name": "symfony/string", - "version": "v6.4.8", + "version": "v6.4.10", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "a147c0f826c4a1f3afb763ab8e009e37c877a44d" + "reference": "ccf9b30251719567bfd46494138327522b9a9446" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/a147c0f826c4a1f3afb763ab8e009e37c877a44d", - "reference": "a147c0f826c4a1f3afb763ab8e009e37c877a44d", + "url": "https://api.github.com/repos/symfony/string/zipball/ccf9b30251719567bfd46494138327522b9a9446", + "reference": "ccf9b30251719567bfd46494138327522b9a9446", "shasum": "" }, "require": { @@ -6043,7 +6214,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.4.8" + "source": "https://github.com/symfony/string/tree/v6.4.10" }, "funding": [ { @@ -6059,20 +6230,20 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-07-22T10:21:14+00:00" }, { "name": "symfony/translation", - "version": "v6.4.8", + "version": "v6.4.10", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "a002933b13989fc4bd0b58e04bf7eec5210e438a" + "reference": "94041203f8ac200ae9e7c6a18fa6137814ccecc9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/a002933b13989fc4bd0b58e04bf7eec5210e438a", - "reference": "a002933b13989fc4bd0b58e04bf7eec5210e438a", + "url": "https://api.github.com/repos/symfony/translation/zipball/94041203f8ac200ae9e7c6a18fa6137814ccecc9", + "reference": "94041203f8ac200ae9e7c6a18fa6137814ccecc9", "shasum": "" }, "require": { @@ -6138,7 +6309,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v6.4.8" + "source": "https://github.com/symfony/translation/tree/v6.4.10" }, "funding": [ { @@ -6154,7 +6325,7 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-07-26T12:30:32+00:00" }, { "name": "symfony/translation-contracts", @@ -6236,16 +6407,16 @@ }, { "name": "symfony/twig-bridge", - "version": "v6.4.8", + "version": "v6.4.9", "source": { "type": "git", "url": "https://github.com/symfony/twig-bridge.git", - "reference": "57de1b7d7499053a2c5beb9344751e8bfd332649" + "reference": "9bcb26445b9d4ef1087c389234bf33fb00e10ea6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/57de1b7d7499053a2c5beb9344751e8bfd332649", - "reference": "57de1b7d7499053a2c5beb9344751e8bfd332649", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/9bcb26445b9d4ef1087c389234bf33fb00e10ea6", + "reference": "9bcb26445b9d4ef1087c389234bf33fb00e10ea6", "shasum": "" }, "require": { @@ -6325,7 +6496,7 @@ "description": "Provides integration for Twig with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bridge/tree/v6.4.8" + "source": "https://github.com/symfony/twig-bridge/tree/v6.4.9" }, "funding": [ { @@ -6341,7 +6512,7 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-06-21T16:04:15+00:00" }, { "name": "symfony/twig-bundle", @@ -6429,16 +6600,16 @@ }, { "name": "symfony/validator", - "version": "v6.4.8", + "version": "v6.4.10", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "dab2781371d54c86f6b25623ab16abb2dde2870c" + "reference": "bcf939a9d1acd7d2912e9474c0c3d7840a03cbcd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/dab2781371d54c86f6b25623ab16abb2dde2870c", - "reference": "dab2781371d54c86f6b25623ab16abb2dde2870c", + "url": "https://api.github.com/repos/symfony/validator/zipball/bcf939a9d1acd7d2912e9474c0c3d7840a03cbcd", + "reference": "bcf939a9d1acd7d2912e9474c0c3d7840a03cbcd", "shasum": "" }, "require": { @@ -6506,7 +6677,7 @@ "description": "Provides tools to validate values", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/validator/tree/v6.4.8" + "source": "https://github.com/symfony/validator/tree/v6.4.10" }, "funding": [ { @@ -6522,20 +6693,20 @@ "type": "tidelift" } ], - "time": "2024-06-02T15:48:50+00:00" + "time": "2024-07-26T12:30:32+00:00" }, { "name": "symfony/var-dumper", - "version": "v6.4.8", + "version": "v6.4.10", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "ad23ca4312395f0a8a8633c831ef4c4ee542ed25" + "reference": "a71cc3374f5fb9759da1961d28c452373b343dd4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/ad23ca4312395f0a8a8633c831ef4c4ee542ed25", - "reference": "ad23ca4312395f0a8a8633c831ef4c4ee542ed25", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/a71cc3374f5fb9759da1961d28c452373b343dd4", + "reference": "a71cc3374f5fb9759da1961d28c452373b343dd4", "shasum": "" }, "require": { @@ -6591,7 +6762,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.4.8" + "source": "https://github.com/symfony/var-dumper/tree/v6.4.10" }, "funding": [ { @@ -6607,20 +6778,20 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-07-26T12:30:32+00:00" }, { "name": "symfony/var-exporter", - "version": "v6.4.8", + "version": "v6.4.9", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "792ca836f99b340f2e9ca9497c7953948c49a504" + "reference": "f9a060622e0d93777b7f8687ec4860191e16802e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/792ca836f99b340f2e9ca9497c7953948c49a504", - "reference": "792ca836f99b340f2e9ca9497c7953948c49a504", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/f9a060622e0d93777b7f8687ec4860191e16802e", + "reference": "f9a060622e0d93777b7f8687ec4860191e16802e", "shasum": "" }, "require": { @@ -6668,7 +6839,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v6.4.8" + "source": "https://github.com/symfony/var-exporter/tree/v6.4.9" }, "funding": [ { @@ -6684,7 +6855,7 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-06-24T15:53:56+00:00" }, { "name": "symfony/web-link", @@ -6843,16 +7014,16 @@ }, { "name": "twig/twig", - "version": "v3.10.3", + "version": "v3.11.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "67f29781ffafa520b0bbfbd8384674b42db04572" + "reference": "e80fb8ebba85c7341a97a9ebf825d7fd4b77708d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/67f29781ffafa520b0bbfbd8384674b42db04572", - "reference": "67f29781ffafa520b0bbfbd8384674b42db04572", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/e80fb8ebba85c7341a97a9ebf825d7fd4b77708d", + "reference": "e80fb8ebba85c7341a97a9ebf825d7fd4b77708d", "shasum": "" }, "require": { @@ -6860,7 +7031,8 @@ "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-ctype": "^1.8", "symfony/polyfill-mbstring": "^1.3", - "symfony/polyfill-php80": "^1.22" + "symfony/polyfill-php80": "^1.22", + "symfony/polyfill-php81": "^1.29" }, "require-dev": { "psr/container": "^1.0|^2.0", @@ -6906,7 +7078,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.10.3" + "source": "https://github.com/twigphp/Twig/tree/v3.11.0" }, "funding": [ { @@ -6918,7 +7090,7 @@ "type": "tidelift" } ], - "time": "2024-05-16T10:04:27+00:00" + "time": "2024-08-08T16:15:16+00:00" }, { "name": "webmozart/assert", @@ -7406,16 +7578,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.11.1", + "version": "1.12.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", "shasum": "" }, "require": { @@ -7423,11 +7595,12 @@ }, "conflict": { "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3,<3.2.2" + "doctrine/common": "<2.13.3 || >=3 <3.2.2" }, "require-dev": { "doctrine/collections": "^1.6.8", "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", @@ -7453,7 +7626,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" + "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" }, "funding": [ { @@ -7461,20 +7634,20 @@ "type": "tidelift" } ], - "time": "2023-03-08T13:26:56+00:00" + "time": "2024-06-12T14:39:25+00:00" }, { "name": "nikic/php-parser", - "version": "v5.0.2", + "version": "v5.1.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13" + "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/139676794dc1e9231bf7bcd123cfc0c99182cb13", - "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/683130c2ff8c2739f4822ff7ac5c873ec529abd1", + "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1", "shasum": "" }, "require": { @@ -7485,7 +7658,7 @@ }, "require-dev": { "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" + "phpunit/phpunit": "^9.0" }, "bin": [ "bin/php-parse" @@ -7517,9 +7690,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.2" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.1.0" }, - "time": "2024-03-05T20:51:40+00:00" + "time": "2024-07-01T20:03:41+00:00" }, { "name": "phar-io/manifest", @@ -7960,45 +8133,45 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.19", + "version": "9.6.20", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "a1a54a473501ef4cdeaae4e06891674114d79db8" + "reference": "49d7820565836236411f5dc002d16dd689cde42f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a1a54a473501ef4cdeaae4e06891674114d79db8", - "reference": "a1a54a473501ef4cdeaae4e06891674114d79db8", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/49d7820565836236411f5dc002d16dd689cde42f", + "reference": "49d7820565836236411f5dc002d16dd689cde42f", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.3.1 || ^2", + "doctrine/instantiator": "^1.5.0 || ^2", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.3", - "phar-io/version": "^3.0.2", + "myclabs/deep-copy": "^1.12.0", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", "php": ">=7.3", - "phpunit/php-code-coverage": "^9.2.28", - "phpunit/php-file-iterator": "^3.0.5", + "phpunit/php-code-coverage": "^9.2.31", + "phpunit/php-file-iterator": "^3.0.6", "phpunit/php-invoker": "^3.1.1", - "phpunit/php-text-template": "^2.0.3", - "phpunit/php-timer": "^5.0.2", - "sebastian/cli-parser": "^1.0.1", - "sebastian/code-unit": "^1.0.6", + "phpunit/php-text-template": "^2.0.4", + "phpunit/php-timer": "^5.0.3", + "sebastian/cli-parser": "^1.0.2", + "sebastian/code-unit": "^1.0.8", "sebastian/comparator": "^4.0.8", - "sebastian/diff": "^4.0.3", - "sebastian/environment": "^5.1.3", - "sebastian/exporter": "^4.0.5", - "sebastian/global-state": "^5.0.1", - "sebastian/object-enumerator": "^4.0.3", - "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^3.2", + "sebastian/diff": "^4.0.6", + "sebastian/environment": "^5.1.5", + "sebastian/exporter": "^4.0.6", + "sebastian/global-state": "^5.0.7", + "sebastian/object-enumerator": "^4.0.4", + "sebastian/resource-operations": "^3.0.4", + "sebastian/type": "^3.2.1", "sebastian/version": "^3.0.2" }, "suggest": { @@ -8043,7 +8216,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.19" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.20" }, "funding": [ { @@ -8059,7 +8232,7 @@ "type": "tidelift" } ], - "time": "2024-04-05T04:35:58+00:00" + "time": "2024-07-10T11:45:39+00:00" }, { "name": "sebastian/cli-parser", @@ -9224,177 +9397,6 @@ ], "time": "2024-05-31T14:49:08+00:00" }, - { - "name": "symfony/http-client", - "version": "v6.4.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-client.git", - "reference": "61faba993e620fc22d4f0ab3b6bcf8fbb0d44b05" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/61faba993e620fc22d4f0ab3b6bcf8fbb0d44b05", - "reference": "61faba993e620fc22d4f0ab3b6bcf8fbb0d44b05", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/log": "^1|^2|^3", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-client-contracts": "^3.4.1", - "symfony/service-contracts": "^2.5|^3" - }, - "conflict": { - "php-http/discovery": "<1.15", - "symfony/http-foundation": "<6.3" - }, - "provide": { - "php-http/async-client-implementation": "*", - "php-http/client-implementation": "*", - "psr/http-client-implementation": "1.0", - "symfony/http-client-implementation": "3.0" - }, - "require-dev": { - "amphp/amp": "^2.5", - "amphp/http-client": "^4.2.1", - "amphp/http-tunnel": "^1.0", - "amphp/socket": "^1.1", - "guzzlehttp/promises": "^1.4|^2.0", - "nyholm/psr7": "^1.0", - "php-http/httplug": "^1.0|^2.0", - "psr/http-client": "^1.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/http-kernel": "^5.4|^6.0|^7.0", - "symfony/messenger": "^5.4|^6.0|^7.0", - "symfony/process": "^5.4|^6.0|^7.0", - "symfony/stopwatch": "^5.4|^6.0|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\HttpClient\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", - "homepage": "https://symfony.com", - "keywords": [ - "http" - ], - "support": { - "source": "https://github.com/symfony/http-client/tree/v6.4.8" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-05-31T14:49:08+00:00" - }, - { - "name": "symfony/http-client-contracts", - "version": "v3.5.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "20414d96f391677bf80078aa55baece78b82647d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/20414d96f391677bf80078aa55baece78b82647d", - "reference": "20414d96f391677bf80078aa55baece78b82647d", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\HttpClient\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to HTTP clients", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-04-18T09:32:20+00:00" - }, { "name": "symfony/maker-bundle", "version": "v1.60.0", @@ -9489,16 +9491,16 @@ }, { "name": "symfony/phpunit-bridge", - "version": "v7.1.1", + "version": "v7.1.3", "source": { "type": "git", "url": "https://github.com/symfony/phpunit-bridge.git", - "reference": "3e1cb8c4dee341cfe96ae9fe29b1acda52a6bb16" + "reference": "e823122d31935eb711e2767c31f3d71cb0b87fb1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/3e1cb8c4dee341cfe96ae9fe29b1acda52a6bb16", - "reference": "3e1cb8c4dee341cfe96ae9fe29b1acda52a6bb16", + "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/e823122d31935eb711e2767c31f3d71cb0b87fb1", + "reference": "e823122d31935eb711e2767c31f3d71cb0b87fb1", "shasum": "" }, "require": { @@ -9551,7 +9553,7 @@ "description": "Provides utilities for PHPUnit, especially user deprecation notices management", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/phpunit-bridge/tree/v7.1.1" + "source": "https://github.com/symfony/phpunit-bridge/tree/v7.1.3" }, "funding": [ { @@ -9567,7 +9569,7 @@ "type": "tidelift" } ], - "time": "2024-06-04T06:50:37+00:00" + "time": "2024-07-26T12:41:01+00:00" }, { "name": "symfony/process", @@ -9632,16 +9634,16 @@ }, { "name": "symfony/web-profiler-bundle", - "version": "v6.4.8", + "version": "v6.4.10", "source": { "type": "git", "url": "https://github.com/symfony/web-profiler-bundle.git", - "reference": "bcc806d1360991de3bf78ac5ca0202db85de9bfc" + "reference": "370c9f1e3567cd4670d44311838e37d16182c3a7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/bcc806d1360991de3bf78ac5ca0202db85de9bfc", - "reference": "bcc806d1360991de3bf78ac5ca0202db85de9bfc", + "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/370c9f1e3567cd4670d44311838e37d16182c3a7", + "reference": "370c9f1e3567cd4670d44311838e37d16182c3a7", "shasum": "" }, "require": { @@ -9694,7 +9696,7 @@ "dev" ], "support": { - "source": "https://github.com/symfony/web-profiler-bundle/tree/v6.4.8" + "source": "https://github.com/symfony/web-profiler-bundle/tree/v6.4.10" }, "funding": [ { @@ -9710,7 +9712,7 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-07-19T07:26:48+00:00" }, { "name": "theseer/tokenizer", @@ -9879,16 +9881,16 @@ }, { "name": "zenstruck/foundry", - "version": "v1.38.0", + "version": "v1.38.3", "source": { "type": "git", "url": "https://github.com/zenstruck/foundry.git", - "reference": "fd3c763de120445878077e54c608d8d75a3cc22d" + "reference": "112e3a6ce1d75627a3fbfd6cd009055994167edb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zenstruck/foundry/zipball/fd3c763de120445878077e54c608d8d75a3cc22d", - "reference": "fd3c763de120445878077e54c608d8d75a3cc22d", + "url": "https://api.github.com/repos/zenstruck/foundry/zipball/112e3a6ce1d75627a3fbfd6cd009055994167edb", + "reference": "112e3a6ce1d75627a3fbfd6cd009055994167edb", "shasum": "" }, "require": { @@ -9961,7 +9963,7 @@ ], "support": { "issues": "https://github.com/zenstruck/foundry/issues", - "source": "https://github.com/zenstruck/foundry/tree/v1.38.0" + "source": "https://github.com/zenstruck/foundry/tree/v1.38.3" }, "funding": [ { @@ -9969,7 +9971,7 @@ "type": "github" } ], - "time": "2024-06-07T23:04:21+00:00" + "time": "2024-07-04T19:59:49+00:00" } ], "aliases": [], diff --git a/config/api_platform/Client.yaml b/config/api_platform/Client.yaml index b61769b..d1e1d84 100644 --- a/config/api_platform/Client.yaml +++ b/config/api_platform/Client.yaml @@ -13,7 +13,8 @@ resources: filters: - 'api_platform.filter.client.order' - 'api_platform.filter.client.search' - - 'api_platform.filter.client.boolean' + - 'api_platform.filter.client.exist' + ApiPlatform\Metadata\Get: provider: App\State\Provider\ClientProvider ApiPlatform\Metadata\Put: @@ -33,6 +34,21 @@ resources: uriTemplate: /clients/change-organizational-units controller: App\Controller\ChangeOrganizationalUnitAction + agent_status: + class: ApiPlatform\Metadata\Post + method: POST + input: false + uriTemplate: /clients/{uuid}/agent/status + controller: App\Controller\OgAgent\StatusAction + + get_pxe: + class: ApiPlatform\Metadata\Post + method: POST + input: false + uriTemplate: /clients/server/{uuid}/get-pxe + controller: App\Controller\OgBoot\PxeBootFile\GetAction + + properties: App\Entity\Client: id: diff --git a/config/api_platform/Command.yaml b/config/api_platform/Command.yaml new file mode 100644 index 0000000..425259b --- /dev/null +++ b/config/api_platform/Command.yaml @@ -0,0 +1,39 @@ +resources: + App\Entity\Command: + processor: App\State\Processor\CommandProcessor + input: App\Dto\Input\CommandInput + output: App\Dto\Output\CommandOutput + normalizationContext: + groups: ['default', 'command:read'] + denormalizationContext: + groups: ['command:write'] + operations: + ApiPlatform\Metadata\GetCollection: + provider: App\State\Provider\CommandProvider + filters: + - 'api_platform.filter.command.order' + - 'api_platform.filter.command.search' + - 'api_platform.filter.command.boolean' + + ApiPlatform\Metadata\Get: + provider: App\State\Provider\CommandProvider + ApiPlatform\Metadata\Put: + provider: App\State\Provider\CommandProvider + ApiPlatform\Metadata\Patch: + provider: App\State\Provider\CommandProvider + ApiPlatform\Metadata\Post: ~ + ApiPlatform\Metadata\Delete: ~ + + command_execute: + class: ApiPlatform\Metadata\Post + method: POST + input: App\Dto\Input\CommandExecuteInput + uriTemplate: /commands/{uuid}/execute + controller: App\Controller\CommandExecuteAction + +properties: + App\Entity\Command: + id: + identifier: false + uuid: + identifier: true \ No newline at end of file diff --git a/config/api_platform/CommandGroup.yaml b/config/api_platform/CommandGroup.yaml new file mode 100644 index 0000000..aa09ccc --- /dev/null +++ b/config/api_platform/CommandGroup.yaml @@ -0,0 +1,46 @@ +resources: + App\Entity\CommandGroup: + processor: App\State\Processor\CommandGroupProcessor + input: App\Dto\Input\CommandGroupInput + output: App\Dto\Output\CommandGroupOutput + normalizationContext: + groups: ['default', 'command-group:read'] + denormalizationContext: + groups: ['command-group:write'] + operations: + ApiPlatform\Metadata\GetCollection: + provider: App\State\Provider\CommandGroupProvider + filters: + - 'api_platform.filter.command.order' + - 'api_platform.filter.command.search' + - 'api_platform.filter.command.boolean' + + ApiPlatform\Metadata\Get: + provider: App\State\Provider\CommandGroupProvider + ApiPlatform\Metadata\Put: + provider: App\State\Provider\CommandGroupProvider + ApiPlatform\Metadata\Patch: + provider: App\State\Provider\CommandGroupProvider + ApiPlatform\Metadata\Post: ~ + ApiPlatform\Metadata\Delete: ~ + + add_commands: + class: ApiPlatform\Metadata\Post + method: POST + input: App\Dto\Input\CommandGroupAddCommandsInput + uriTemplate: /command-groups/{uuid}/add-commands + controller: App\Controller\CommandGroupAddCommandsAction + + command_group_execute: + class: ApiPlatform\Metadata\Post + method: POST + input: App\Dto\Input\CommandGroupExecuteInput + uriTemplate: /command-groups/{uuid}/execute + controller: App\Controller\CommandGroupExecuteAction + +properties: + App\Entity\CommandGroup: + id: + identifier: false + uuid: + identifier: true \ No newline at end of file diff --git a/config/api_platform/CommandTask.yaml b/config/api_platform/CommandTask.yaml new file mode 100644 index 0000000..d008252 --- /dev/null +++ b/config/api_platform/CommandTask.yaml @@ -0,0 +1,32 @@ +resources: + App\Entity\CommandTask: + processor: App\State\Processor\CommandTaskProcessor + input: App\Dto\Input\CommandTaskInput + output: App\Dto\Output\CommandTaskOutput + normalizationContext: + groups: ['default', 'command-task:read'] + denormalizationContext: + groups: ['command-task:write'] + operations: + ApiPlatform\Metadata\GetCollection: + provider: App\State\Provider\CommandTaskProvider + filters: + - 'api_platform.filter.command_task.order' + - 'api_platform.filter.command_task.search' + - 'api_platform.filter.command_task.boolean' + + ApiPlatform\Metadata\Get: + provider: App\State\Provider\CommandTaskProvider + ApiPlatform\Metadata\Put: + provider: App\State\Provider\CommandTaskProvider + ApiPlatform\Metadata\Patch: + provider: App\State\Provider\CommandTaskProvider + ApiPlatform\Metadata\Post: ~ + ApiPlatform\Metadata\Delete: ~ + +properties: + App\Entity\CommandTask: + id: + identifier: false + uuid: + identifier: true \ No newline at end of file diff --git a/config/api_platform/OgLive.yaml b/config/api_platform/OgLive.yaml new file mode 100644 index 0000000..a40fa2a --- /dev/null +++ b/config/api_platform/OgLive.yaml @@ -0,0 +1,102 @@ +resources: + App\Entity\OgLive: + processor: App\State\Processor\OgLiveProcessor + input: App\Dto\Input\OgLiveInput + output: App\Dto\Output\OgLiveOutput + normalizationContext: + groups: ['default', 'og-live:read'] + denormalizationContext: + groups: ['og-live:write'] + operations: + ApiPlatform\Metadata\GetCollection: + provider: App\State\Provider\OgLiveProvider + filters: + - 'api_platform.filter.og_live.order' + - 'api_platform.filter.og_live.search' + - 'api_platform.filter.og_live.boolean' + + ApiPlatform\Metadata\Get: + provider: App\State\Provider\OgLiveProvider + ApiPlatform\Metadata\Put: + provider: App\State\Provider\OgLiveProvider + ApiPlatform\Metadata\Patch: + provider: App\State\Provider\OgLiveProvider + ApiPlatform\Metadata\Post: ~ + ApiPlatform\Metadata\Delete: ~ + + oglives_sync: + class: ApiPlatform\Metadata\Post + method: POST + input: false + uriTemplate: /og-lives/sync + controller: App\Controller\OgBoot\OgLive\SyncAction + + get_collection_oglives: + shortName: OgLive Server + description: Get collection of OgLive + class: ApiPlatform\Metadata\GetCollection + method: GET + input: false + uriTemplate: /og-lives/server/get-collection + controller: App\Controller\OgBoot\OgLive\GetCollectionAction + + get_oglive: + shortName: OgLive Server + description: Get OgLive + class: ApiPlatform\Metadata\Get + method: GET + input: false + uriTemplate: /og-lives/server/{uuid}/get + controller: App\Controller\OgBoot\OgLive\GetAction + + get_isos: + shortName: OgLive Server + description: Get Isos of OgLive + class: ApiPlatform\Metadata\GetCollection + method: GET + input: false + uriTemplate: /og-lives/server/get-isos + controller: App\Controller\OgBoot\OgLive\GetIsosAction + + get_default: + shortName: OgLive Server + description: Get default OgLive + class: ApiPlatform\Metadata\GetCollection + method: GET + input: false + uriTemplate: /og-lives/server/get-default + controller: App\Controller\OgBoot\OgLive\GetDefaultAction + + set_default: + shortName: OgLive Server + description: Set default OgLive + class: ApiPlatform\Metadata\Post + method: POST + input: false + uriTemplate: /og-lives/server/{uuid}/set-default + controller: App\Controller\OgBoot\OgLive\SetDefaultAction + + install: + shortName: OgLive Server + description: Install OgLive + class: ApiPlatform\Metadata\Post + method: POST + input: false + uriTemplate: /og-lives/server/{uuid}/install + controller: App\Controller\OgBoot\OgLive\InstallAction + + uninstall: + shortName: OgLive Server + description: Uninstall OgLive + class: ApiPlatform\Metadata\Post + method: POST + input: false + uriTemplate: /og-lives/server/{uuid}/uninstall + controller: App\Controller\OgBoot\OgLive\UninstallAction + +properties: + App\Entity\OgLive: + id: + identifier: false + uuid: + identifier: true \ No newline at end of file diff --git a/config/api_platform/OrganizationalUnit.yaml b/config/api_platform/OrganizationalUnit.yaml index ac90e14..d3793b0 100644 --- a/config/api_platform/OrganizationalUnit.yaml +++ b/config/api_platform/OrganizationalUnit.yaml @@ -13,6 +13,8 @@ resources: filters: - 'api_platform.filter.organizational_unit.order' - 'api_platform.filter.organizational_unit.search' + - 'api_platform.filter.organizational_unit.group_filter' + ApiPlatform\Metadata\Get: security: 'is_granted("ORGANIZATIONAL_UNIT_VIEW", object)' provider: App\State\Provider\OrganizationalUnitProvider diff --git a/config/api_platform/PxeTemplate.yaml b/config/api_platform/PxeTemplate.yaml new file mode 100644 index 0000000..ce4ae4d --- /dev/null +++ b/config/api_platform/PxeTemplate.yaml @@ -0,0 +1,103 @@ +resources: + App\Entity\PxeTemplate: + processor: App\State\Processor\PxeTemplateProcessor + input: App\Dto\Input\PxeTemplateInput + output: App\Dto\Output\PxeTemplateOutput + normalizationContext: + groups: ['default', 'pxe-template:read'] + denormalizationContext: + groups: ['pxe-template:write'] + operations: + ApiPlatform\Metadata\GetCollection: + provider: App\State\Provider\PxeTemplateProvider + filters: + - 'api_platform.filter.pxe_template.order' + - 'api_platform.filter.pxe_template.search' + - 'api_platform.filter.pxe_template.boolean' + + ApiPlatform\Metadata\Get: + provider: App\State\Provider\PxeTemplateProvider + ApiPlatform\Metadata\Put: + provider: App\State\Provider\PxeTemplateProvider + ApiPlatform\Metadata\Patch: + provider: App\State\Provider\PxeTemplateProvider + ApiPlatform\Metadata\Post: ~ + ApiPlatform\Metadata\Delete: ~ + + pxe_template_sync: + class: ApiPlatform\Metadata\Post + method: POST + input: false + uriTemplate: /pxe-templates/sync + controller: App\Controller\OgBoot\PxeTemplate\SyncAction + + get_collection_templates: + shortName: PxeTemplate Server + description: Get collection of PxeTemplate + class: ApiPlatform\Metadata\GetCollection + method: GET + input: false + uriTemplate: /pxe-templates/server/get-collection + controller: App\Controller\OgBoot\PxeTemplate\GetCollectionAction + + get_template: + shortName: PxeTemplate Server + description: Get PxeTemplate + class: ApiPlatform\Metadata\Get + method: GET + input: false + uriTemplate: /pxe-templates/server/{uuid}/get + controller: App\Controller\OgBoot\PxeTemplate\GetAction + + post_template: + shortName: PxeTemplate Server + description: Create PxeTemplate + class: ApiPlatform\Metadata\Post + method: POST + input: false + uriTemplate: /pxe-templates/server/{uuid}/post + controller: App\Controller\OgBoot\PxeTemplate\PostAction + + delete_template: + shortName: PxeTemplate Server + description: Delete PxeTemplate + class: ApiPlatform\Metadata\Post + method: POST + input: false + uriTemplate: /pxe-templates/server/{uuid}/delete + controller: App\Controller\OgBoot\PxeTemplate\DeleteAction + + template_add_clients: + shortName: PxeTemplate Server + description: Add Client to PxeTemplate + class: ApiPlatform\Metadata\Post + method: POST + input: App\Dto\Input\PxeTemplateAddClientsInput + uriTemplate: /pxe-templates/{uuid}/add-clients + controller: App\Controller\OgBoot\PxeTemplate\AddClientAction + + template_sync_client: + shortName: PxeTemplate Server + description: Sync Client to PxeTemplate + class: ApiPlatform\Metadata\Post + method: POST + input: App\Dto\Input\PxeTemplateSyncClientInput + uriTemplate: /pxe-templates/{uuid}/sync-client + controller: App\Controller\OgBoot\PxeBootFile\PostAction + + template_delete_client: + shortName: PxeTemplate Server + description: Add Client to PxeTemplate + class: ApiPlatform\Metadata\Post + method: POST + input: App\Dto\Input\PxeTemplateDeleteClientInput + uriTemplate: /pxe-templates/{uuid}/delete-client + controller: App\Controller\OgBoot\PxeTemplate\DeleteClientAction + + +properties: + App\Entity\PxeTemplate: + id: + identifier: false + uuid: + identifier: true \ No newline at end of file diff --git a/config/api_platform/RemoteCalendar.yaml b/config/api_platform/RemoteCalendar.yaml new file mode 100644 index 0000000..4bb8e36 --- /dev/null +++ b/config/api_platform/RemoteCalendar.yaml @@ -0,0 +1,37 @@ +resources: + App\Entity\RemoteCalendar: + processor: App\State\Processor\RemoteCalendarProcessor + input: App\Dto\Input\RemoteCalendarInput + output: App\Dto\Output\RemoteCalendarOutput + normalizationContext: + groups: ['default', 'remote-calendar:read'] + denormalizationContext: + groups: ['remote-calendar:write'] + operations: + ApiPlatform\Metadata\GetCollection: + provider: App\State\Provider\RemoteCalendarProvider + filters: + - 'api_platform.filter.remote_calendar.order' + - 'api_platform.filter.remote_calendar.search' + + ApiPlatform\Metadata\Get: + provider: App\State\Provider\RemoteCalendarProvider + ApiPlatform\Metadata\Put: + provider: App\State\Provider\RemoteCalendarProvider + ApiPlatform\Metadata\Patch: + provider: App\State\Provider\RemoteCalendarProvider + ApiPlatform\Metadata\Post: ~ + ApiPlatform\Metadata\Delete: ~ + + sync_uds: + class: ApiPlatform\Metadata\Post + method: POST + uriTemplate: /remote-calendars/{uuid}/sync-uds + controller: App\Controller\UDS\RemoteCalendarSyncUdsAction + +properties: + App\Entity\RemoteCalendar: + id: + identifier: false + uuid: + identifier: true \ No newline at end of file diff --git a/config/api_platform/RemoteCalendarRule.yaml b/config/api_platform/RemoteCalendarRule.yaml new file mode 100644 index 0000000..89f02eb --- /dev/null +++ b/config/api_platform/RemoteCalendarRule.yaml @@ -0,0 +1,31 @@ +resources: + App\Entity\RemoteCalendarRule: + processor: App\State\Processor\RemoteCalendarRuleProcessor + input: App\Dto\Input\RemoteCalendarRuleInput + output: App\Dto\Output\RemoteCalendarRuleOutput + normalizationContext: + groups: ['default', 'remote-calendar-rule:read'] + denormalizationContext: + groups: ['remote-calendar-rule:write'] + operations: + ApiPlatform\Metadata\GetCollection: + provider: App\State\Provider\RemoteCalendarRuleProvider + filters: + - 'api_platform.filter.remote_calendar_rule.order' + - 'api_platform.filter.remote_calendar_rule.search' + + ApiPlatform\Metadata\Get: + provider: App\State\Provider\RemoteCalendarRuleProvider + ApiPlatform\Metadata\Put: + provider: App\State\Provider\RemoteCalendarRuleProvider + ApiPlatform\Metadata\Patch: + provider: App\State\Provider\RemoteCalendarRuleProvider + ApiPlatform\Metadata\Post: ~ + ApiPlatform\Metadata\Delete: ~ + +properties: + App\Entity\RemoteCalendarRule: + id: + identifier: false + uuid: + identifier: true \ No newline at end of file diff --git a/config/api_platform/SoftwareProfile.yaml b/config/api_platform/SoftwareProfile.yaml index f5c544c..899cad8 100644 --- a/config/api_platform/SoftwareProfile.yaml +++ b/config/api_platform/SoftwareProfile.yaml @@ -11,10 +11,13 @@ resources: ApiPlatform\Metadata\GetCollection: provider: App\State\Provider\SoftwareProfileProvider filters: - - 'api_platform.filter.software.order' - - 'api_platform.filter.software.search' + - 'api_platform.filter.software_profile.order' + - 'api_platform.filter.software_profile.search' + ApiPlatform\Metadata\Get: provider: App\State\Provider\SoftwareProfileProvider + normalizationContext: + groups: ['software-profile:item:get', 'software-profile:read:collection:short'] ApiPlatform\Metadata\Put: provider: App\State\Provider\SoftwareProfileProvider ApiPlatform\Metadata\Patch: diff --git a/config/api_platform/Subnet.yaml b/config/api_platform/Subnet.yaml new file mode 100644 index 0000000..72ef541 --- /dev/null +++ b/config/api_platform/Subnet.yaml @@ -0,0 +1,121 @@ +resources: + App\Entity\Subnet: + processor: App\State\Processor\SubnetProcessor + input: App\Dto\Input\SubnetInput + output: App\Dto\Output\SubnetOutput + normalizationContext: + groups: ['default', 'subnet:read'] + denormalizationContext: + groups: ['subnet:write'] + operations: + ApiPlatform\Metadata\GetCollection: + provider: App\State\Provider\SubnetProvider + filters: + - 'api_platform.filter.subnet.order' + - 'api_platform.filter.subnet.search' + + ApiPlatform\Metadata\Get: + provider: App\State\Provider\SubnetProvider + ApiPlatform\Metadata\Put: + provider: App\State\Provider\SubnetProvider + ApiPlatform\Metadata\Patch: + provider: App\State\Provider\SubnetProvider + ApiPlatform\Metadata\Post: ~ + ApiPlatform\Metadata\Delete: ~ + + subnet_sync: + class: ApiPlatform\Metadata\Post + method: POST + input: false + uriTemplate: /subnets/sync + controller: App\Controller\OgDhcp\Subnet\SyncAction + + get_collection_subnets: + shortName: Subnet Server + description: Get collection of Subnet + class: ApiPlatform\Metadata\GetCollection + method: GET + input: false + uriTemplate: /og-dhcp/server/get-collection + controller: App\Controller\OgDhcp\Subnet\GetCollectionAction + + get_subnet: + shortName: Subnet Server + description: Get Subnet + class: ApiPlatform\Metadata\Get + method: GET + input: false + uriTemplate: /og-dhcp/server/{uuid}/get + controller: App\Controller\OgDhcp\Subnet\GetAction + + post_subnet: + shortName: Subnet Server + description: Create Subnet + class: ApiPlatform\Metadata\Post + method: POST + input: false + uriTemplate: /og-dhcp/server/{uuid}/post + controller: App\Controller\OgDhcp\Subnet\PostAction + + put_subnet: + shortName: Subnet Server + description: Create Subnet + class: ApiPlatform\Metadata\Put + method: PUT + input: false + uriTemplate: /og-dhcp/server/{uuid}/put + controller: App\Controller\OgDhcp\Subnet\PutAction + + delete_subnet: + shortName: Subnet Server + description: Delete Subnet + class: ApiPlatform\Metadata\Delete + method: DELETE + input: false + uriTemplate: /og-dhcp/server/{uuid}/delete + controller: App\Controller\OgDhcp\Subnet\DeleteAction + + post_host: + shortName: Subnet Server Hosts + description: Post Host to Subnet + class: ApiPlatform\Metadata\Post + method: POST + input: App\Dto\Input\SubnetAddHostInput + uriTemplate: /og-dhcp/server/{uuid}/post-host + controller: App\Controller\OgDhcp\Subnet\PostHostAction + + get_hosts: + shortName: Subnet Server Hosts + description: Get Hosts of Subnet + class: ApiPlatform\Metadata\Get + method: GET + input: false + uriTemplate: /og-dhcp/server/{uuid}/get-hosts + controller: App\Controller\OgDhcp\Subnet\GetHostsAction + + put_host: + shortName: Subnet Server Hosts + description: Put Host of Subnet + class: ApiPlatform\Metadata\Put + method: PUT + input: false + uriTemplate: /og-dhcp/server/{uuid}/put-host + controller: App\Controller\OgDhcp\Subnet\PutHostAction + + delete_host: + shortName: Subnet Server Hosts + description: Delete Host of Subnet + class: ApiPlatform\Metadata\Delete + method: DELETE + input: false + read: false + uriTemplate: /og-dhcp/server/{uuid}/delete-host/{clientUuid} + controller: App\Controller\OgDhcp\Subnet\DeleteHostAction + + +properties: + App\Entity\Subnet: + id: + identifier: false + uuid: + identifier: true \ No newline at end of file diff --git a/config/api_platform/Trace.yaml b/config/api_platform/Trace.yaml new file mode 100644 index 0000000..115c1f0 --- /dev/null +++ b/config/api_platform/Trace.yaml @@ -0,0 +1,23 @@ +resources: + App\Entity\Trace: + output: App\Dto\Output\TraceOutput + normalizationContext: + groups: ['default', 'trace:read'] + operations: + ApiPlatform\Metadata\GetCollection: + provider: App\State\Provider\TraceProvider + filters: + - 'api_platform.filter.trace.order' + - 'api_platform.filter.trace.search' + ApiPlatform\Metadata\Get: + provider: App\State\Provider\TraceProvider + + order: + createdAt: DESC + +properties: + App\Entity\Trace: + id: + identifier: false + uuid: + identifier: true \ No newline at end of file diff --git a/config/packages/api_platform.yaml b/config/packages/api_platform.yaml index 352abc2..7adc4f3 100644 --- a/config/packages/api_platform.yaml +++ b/config/packages/api_platform.yaml @@ -1,43 +1,26 @@ api_platform: title: 'OgCore Api' description: 'Api Documentation for OgCore' - version: 1.0.0 - path_segment_name_generator: 'api_platform.path_segment_name_generator.dash' + version: 0.5.0 + path_segment_name_generator: api_platform.path_segment_name_generator.dash + defaults: + pagination_client_items_per_page: true + collection: + pagination: + items_per_page_parameter_name: 'itemsPerPage' formats: jsonld: [ 'application/ld+json' ] - jsonhal: [ 'application/hal+json' ] - jsonapi: [ 'application/vnd.api+json' ] - json: [ 'application/json' ] - xml: [ 'application/xml', 'text/xml' ] - yaml: [ 'application/x-yaml' ] - csv: [ 'text/csv' ] - html: [ 'text/html' ] + json: [ 'application/json' ] + csv: [ 'text/csv' ] patch_formats: jsonld: ['application/ld+json', 'application/json'] mapping: paths: ['%kernel.project_dir%/config/api_platform', '%kernel.project_dir%/src/Dto'] - use_symfony_listeners: true - collection: - pagination: - items_per_page_parameter_name: 'itemsPerPage' - defaults: - pagination_client_items_per_page: true - denormalization_context: - allow_extra_attributes: false - cache_headers: - vary: [ 'Content-Type', 'Authorization', 'Origin' ] - extra_properties: - standard_put: true - rfc_7807_compliant_errors: true - event_listeners_backward_compatibility_layer: false - keep_legacy_inflector: true - docs_formats: - jsonld: ['application/ld+json'] - jsonopenapi: ['application/vnd.openapi+json'] - html: ['text/html'] swagger: versions: [3] api_keys: apiKey: name: Authorization - type: header \ No newline at end of file + type: header + exception_to_status: + Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException: 409 \ No newline at end of file diff --git a/config/packages/framework.yaml b/config/packages/framework.yaml index 980ee45..5b303be 100644 --- a/config/packages/framework.yaml +++ b/config/packages/framework.yaml @@ -18,6 +18,11 @@ framework: php_errors: log: true + http_client: + default_options: + verify_host: false + verify_peer: false + when@test: framework: test: true diff --git a/config/packages/security.yaml b/config/packages/security.yaml index e0670c8..568ba93 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -29,7 +29,8 @@ security: - { path: ^/$, roles: PUBLIC_ACCESS } # Allows accessing the Swagger UI - { path: ^/docs, roles: PUBLIC_ACCESS } # Allows accessing the Swagger UI docs - { path: ^/auth/login, roles: PUBLIC_ACCESS } - - { path: ^/opengnsys/rest/, roles: PUBLIC_ACCESS } + - { path: ^/opengnsys/rest, roles: PUBLIC_ACCESS } + - { path: ^/og-lives/install/webhook, roles: PUBLIC_ACCESS } - { path: ^/auth/refresh, roles: PUBLIC_ACCESS } - { path: ^/, roles: IS_AUTHENTICATED_FULLY } diff --git a/config/services.yaml b/config/services.yaml index beee276..294e4b8 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -4,11 +4,18 @@ imports: parameters: services: - # default configuration for services in *this* file _defaults: autowire: true # Automatically injects dependencies in your services. autoconfigure: true # Automatically registers your services as commands, event subscribers, etc. + bind: + $ogBootApiUrl: '%env(OGBOOT_API_URL)%' + $ogDhcpApiUrl: '%env(OGDHCP_API_URL)%' + $udsAPIurl: '%env(UDS_URL)%' + $udsAuthLogin: '%env(UDS_AUTH_LOGIN)%' + $udsAuthUsername: '%env(UDS_AUTH_USERNAME)%' + $udsAuthPassword: '%env(UDS_AUTH_PASSWORD)%' + App\: resource: '../src/' exclude: @@ -101,3 +108,47 @@ services: bind: $collectionProvider: '@api_platform.doctrine.orm.state.collection_provider' $itemProvider: '@api_platform.doctrine.orm.state.item_provider' + + App\State\Provider\OgLiveProvider: + bind: + $collectionProvider: '@api_platform.doctrine.orm.state.collection_provider' + $itemProvider: '@api_platform.doctrine.orm.state.item_provider' + + App\State\Provider\RemoteCalendarProvider: + bind: + $collectionProvider: '@api_platform.doctrine.orm.state.collection_provider' + $itemProvider: '@api_platform.doctrine.orm.state.item_provider' + + App\State\Provider\CommandProvider: + bind: + $collectionProvider: '@api_platform.doctrine.orm.state.collection_provider' + $itemProvider: '@api_platform.doctrine.orm.state.item_provider' + + App\State\Provider\PxeTemplateProvider: + bind: + $collectionProvider: '@api_platform.doctrine.orm.state.collection_provider' + $itemProvider: '@api_platform.doctrine.orm.state.item_provider' + + App\State\Provider\CommandGroupProvider: + bind: + $collectionProvider: '@api_platform.doctrine.orm.state.collection_provider' + $itemProvider: '@api_platform.doctrine.orm.state.item_provider' + + App\State\Provider\CommandTaskProvider: + bind: + $collectionProvider: '@api_platform.doctrine.orm.state.collection_provider' + $itemProvider: '@api_platform.doctrine.orm.state.item_provider' + + App\State\Provider\SubnetProvider: + bind: + $collectionProvider: '@api_platform.doctrine.orm.state.collection_provider' + $itemProvider: '@api_platform.doctrine.orm.state.item_provider' + App\State\Provider\TraceProvider: + bind: + $collectionProvider: '@api_platform.doctrine.orm.state.collection_provider' + $itemProvider: '@api_platform.doctrine.orm.state.item_provider' + + App\State\Provider\RemoteCalendarRuleProvider: + bind: + $collectionProvider: '@api_platform.doctrine.orm.state.collection_provider' + $itemProvider: '@api_platform.doctrine.orm.state.item_provider' diff --git a/config/services/api_platform.yaml b/config/services/api_platform.yaml index d8f0fa4..b5f7b49 100644 --- a/config/services/api_platform.yaml +++ b/config/services/api_platform.yaml @@ -1,4 +1,16 @@ services: + api_platform.filter.calendar.order: + parent: 'api_platform.doctrine.orm.order_filter' + arguments: + $properties: { 'id': ~, 'name': ~,} + $orderParameterName: 'order' + tags: [ 'api_platform.filter' ] + + api_platform.filter.calendar.search: + parent: 'api_platform.doctrine.orm.search_filter' + arguments: [ { 'id': 'exact', 'name': 'exact'} ] + tags: [ 'api_platform.filter' ] + api_platform.filter.client.order: parent: 'api_platform.doctrine.orm.order_filter' arguments: @@ -8,7 +20,29 @@ services: api_platform.filter.client.search: parent: 'api_platform.doctrine.orm.search_filter' - arguments: [ { 'id': 'exact', 'name': 'partial', 'serialNumber': 'exact', organizationalUnit.id: 'exact' } ] + arguments: [ { 'id': 'exact', 'name': 'partial', 'serialNumber': 'exact', 'template.id': 'exact', organizationalUnit.id: 'exact', mac: 'exact', ip: 'exact' } ] + tags: [ 'api_platform.filter' ] + + api_platform.filter.client.exist: + parent: 'api_platform.doctrine.orm.exists_filter' + arguments: [{'subnet': ~, 'template': ~ }] + tags: [ 'api_platform.filter' ] + + api_platform.filter.command.order: + parent: 'api_platform.doctrine.orm.order_filter' + arguments: + $properties: { 'id': ~, 'name': ~ } + $orderParameterName: 'order' + tags: [ 'api_platform.filter' ] + + api_platform.filter.command.search: + parent: 'api_platform.doctrine.orm.search_filter' + arguments: [ { 'id': 'exact', 'name': 'partial'} ] + tags: [ 'api_platform.filter' ] + + api_platform.filter.command.boolean: + parent: 'api_platform.doctrine.orm.boolean_filter' + arguments: [ { 'enabled': ~ } ] tags: [ 'api_platform.filter' ] api_platform.filter.hardware.order: @@ -18,6 +52,35 @@ services: $orderParameterName: 'order' tags: [ 'api_platform.filter' ] + api_platform.filter.image.order: + parent: 'api_platform.doctrine.orm.order_filter' + arguments: + $properties: { 'id': ~, 'name': ~ } + $orderParameterName: 'order' + tags: [ 'api_platform.filter' ] + + api_platform.filter.image.search: + parent: 'api_platform.doctrine.orm.search_filter' + arguments: [ { 'id': 'exact', 'name': 'partial', } ] + tags: [ 'api_platform.filter' ] + + api_platform.filter.og_live.order: + parent: 'api_platform.doctrine.orm.order_filter' + arguments: + $properties: { 'id': ~, 'name': ~ } + $orderParameterName: 'order' + tags: [ 'api_platform.filter' ] + + api_platform.filter.og_live.search: + parent: 'api_platform.doctrine.orm.search_filter' + arguments: [ { 'id': 'exact', 'name': 'partial', } ] + tags: [ 'api_platform.filter' ] + + api_platform.filter.og_live.boolean: + parent: 'api_platform.doctrine.orm.boolean_filter' + arguments: [ { 'isDefault': ~, 'installed': ~ } ] + tags: [ 'api_platform.filter' ] + api_platform.filter.hardware.search: parent: 'api_platform.doctrine.orm.search_filter' arguments: [ { 'id': 'exact', 'name': 'partial' } ] @@ -35,6 +98,18 @@ services: arguments: [ { 'id': 'exact', 'name': 'exact', 'title': 'exact' } ] tags: [ 'api_platform.filter' ] + api_platform.filter.operative_system.order: + parent: 'api_platform.doctrine.orm.order_filter' + arguments: + $properties: { 'id': ~, 'name': ~ } + $orderParameterName: 'order' + tags: [ 'api_platform.filter' ] + + api_platform.filter.operative_system.search: + parent: 'api_platform.doctrine.orm.search_filter' + arguments: [ { 'id': 'exact', 'name': 'partial' } ] + tags: [ 'api_platform.filter' ] + api_platform.filter.organizational_unit.order: parent: 'api_platform.doctrine.orm.order_filter' arguments: @@ -47,6 +122,11 @@ services: arguments: [ { id: 'exact', name: 'partial', type: 'exact', parent.id: 'exact'} ] tags: [ 'api_platform.filter' ] + api_platform.filter.organizational_unit.group_filter: + parent: 'api_platform.serializer.group_filter' + arguments: [ 'groups', true, ['organizational-unit:read:collection:short'] ] + tags: [ 'api_platform.filter' ] + api_platform.filter.partition.order: parent: 'api_platform.doctrine.orm.order_filter' arguments: @@ -56,7 +136,89 @@ services: api_platform.filter.partition.search: parent: 'api_platform.doctrine.orm.search_filter' - arguments: [ { 'id': 'exact', 'usage': 'exact', 'diskNumber': 'exact' } ] + arguments: [ { 'id': 'exact', 'usage': 'exact', 'diskNumber': 'exact', 'client.id': 'exact' } ] + tags: [ 'api_platform.filter' ] + + api_platform.filter.pxe_template.order: + parent: 'api_platform.doctrine.orm.order_filter' + arguments: + $properties: { 'id': ~, 'name': ~ } + $orderParameterName: 'order' + tags: [ 'api_platform.filter' ] + + api_platform.filter.pxe_boot_file.search: + parent: 'api_platform.doctrine.orm.search_filter' + arguments: [ { 'id': 'exact', 'template': exact } ] + tags: [ 'api_platform.filter' ] + + api_platform.filter.pxe_template.search: + parent: 'api_platform.doctrine.orm.search_filter' + arguments: [ { 'id': 'exact', 'name': 'partial', } ] + tags: [ 'api_platform.filter' ] + + api_platform.filter.pxe_template.boolean: + parent: 'api_platform.doctrine.orm.boolean_filter' + arguments: [ { 'synchronized': ~ } ] + tags: [ 'api_platform.filter' ] + + api_platform.filter.remote_calendar.order: + parent: 'api_platform.doctrine.orm.order_filter' + arguments: + $properties: { 'id': ~, 'name': ~ } + $orderParameterName: 'order' + tags: [ 'api_platform.filter' ] + + api_platform.filter.remote_calendar.search: + parent: 'api_platform.doctrine.orm.search_filter' + arguments: [ { 'id': 'exact', 'name': 'partial', } ] + tags: [ 'api_platform.filter' ] + + api_platform.filter.software.order: + parent: 'api_platform.doctrine.orm.order_filter' + arguments: + $properties: { 'id': ~, 'name': ~ } + $orderParameterName: 'order' + tags: [ 'api_platform.filter' ] + + api_platform.filter.software.search: + parent: 'api_platform.doctrine.orm.search_filter' + arguments: [ { 'id': 'exact', 'name': 'partial', type: 'exact'} ] + tags: [ 'api_platform.filter' ] + + api_platform.filter.software_profile.order: + parent: 'api_platform.doctrine.orm.order_filter' + arguments: + $properties: { 'id': ~, 'description': ~ } + $orderParameterName: 'order' + tags: [ 'api_platform.filter' ] + + api_platform.filter.software_profile.search: + parent: 'api_platform.doctrine.orm.search_filter' + arguments: [ { 'id': 'exact', 'description': 'partial' } ] + tags: [ 'api_platform.filter' ] + + api_platform.filter.subnet.order: + parent: 'api_platform.doctrine.orm.order_filter' + arguments: + $properties: { 'id': ~, 'name': ~ } + $orderParameterName: 'order' + tags: [ 'api_platform.filter' ] + + api_platform.filter.subnet.search: + parent: 'api_platform.doctrine.orm.search_filter' + arguments: [ { 'id': 'exact', 'name': 'partial', ip: 'exact', nextServer: 'exact', netmask: 'exact', bootFileName: 'partial'} ] + tags: [ 'api_platform.filter' ] + + api_platform.filter.trace.search: + parent: 'api_platform.doctrine.orm.search_filter' + arguments: [ { 'id': 'exact', 'command.id': 'exact', 'client.id': 'exact' } ] + tags: [ 'api_platform.filter' ] + + api_platform.filter.trace.order: + parent: 'api_platform.doctrine.orm.order_filter' + arguments: + $properties: { 'id': ~, 'command': ~ } + $orderParameterName: 'order' tags: [ 'api_platform.filter' ] api_platform.filter.user.order: diff --git a/docker-compose-ci-template.yaml b/docker-compose-ci-template.yaml new file mode 100644 index 0000000..b407aa8 --- /dev/null +++ b/docker-compose-ci-template.yaml @@ -0,0 +1,51 @@ +services: + database: + container_name: ogcore-database + image: mariadb:10.11 + environment: + MYSQL_ROOT_PASSWORD: root + MYSQL_DATABASE: ogcore + MYSQL_PASSWORD: root + MYSQL_USER: admin + ports: + - 3336:3306 + volumes: + - database_data:/var/lib/mysql + networks: + - ogcore-network + + nginx: + container_name: ogcore-nginx + build: + context: . + dockerfile: ./docker/Dockerfile-nginx + depends_on: + - php + ports: + - 8080:80 + volumes: + - ./public:/var/www/html/public:cached + networks: + - ogcore-network + image: ogcore-nginx:static + + php: + container_name: ogcore-php + build: + context: . + dockerfile: ./docker/Dockerfile-jenkins-php + depends_on: + - database + environment: + XDEBUG_CLIENT_HOST: 127.17.0.1 + XDEBUG_CLIENT_PORT: 9003 + PHP_IDE_CONFIG: serverName=ogcore + networks: + - ogcore-network + image: ogcore-php:static + +volumes: + database_data: + +networks: + ogcore-network: diff --git a/docker-compose.yaml b/docker-compose.yaml index aad1b74..8a5bd62 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -23,8 +23,10 @@ services: - php ports: - 8080:80 + - 8443:443 # Añadir el puerto 443 volumes: - ./public:/var/www/html/public:cached + - ./docker/certs:/etc/nginx/certs # Montar certificados en Nginx networks: - ogcore-network diff --git a/docker/Dockerfile-nginx b/docker/Dockerfile-nginx index d8d753a..7c8881b 100644 --- a/docker/Dockerfile-nginx +++ b/docker/Dockerfile-nginx @@ -1,2 +1,7 @@ FROM nginx:latest -COPY ./docker/default.conf /etc/nginx/conf.d/default.conf \ No newline at end of file + +# Copiar el archivo de configuración de Nginx +COPY ./docker/default.conf /etc/nginx/conf.d/default.conf + +# Copiar los certificados SSL +COPY ./docker/certs /etc/nginx/certs diff --git a/docker/Dockerfile-php b/docker/Dockerfile-php index da6f17e..a4cdcb8 100644 --- a/docker/Dockerfile-php +++ b/docker/Dockerfile-php @@ -28,3 +28,14 @@ RUN apk del -f .build-deps COPY ./docker/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini +# Generate SSH keys +RUN ssh-keygen -t rsa -b 4096 -f /root/.ssh/id_rsa -N "" + +# Optionally, copy public key to a specific location +RUN cp /root/.ssh/id_rsa.pub /root/.ssh/authorized_keys + +# Expose any ports you may need +EXPOSE 9000 + +# Command to run the PHP-FPM server +CMD ["php-fpm"] diff --git a/docker/certs/ogcore.uds-test.net.crt.pem b/docker/certs/ogcore.uds-test.net.crt.pem new file mode 100644 index 0000000..1541b24 --- /dev/null +++ b/docker/certs/ogcore.uds-test.net.crt.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIExTCCAq2gAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwSTELMAkGA1UEBhMCRVMx +DzANBgNVBAgMBk1hZHJpZDEPMA0GA1UEBwwGTWFkcmlkMRgwFgYDVQQDDA9jYS51 +ZHMtdGVzdC5uZXQwHhcNMjQxMDA5MTQyODM3WhcNMjUxMDE5MTQyODM3WjBNMQsw +CQYDVQQGEwJFUzEPMA0GA1UECAwGTWFkcmlkMQ8wDQYDVQQHDAZNYWRyaWQxHDAa +BgNVBAMME29nY29yZS51ZHMtdGVzdC5uZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQDaT0uiHcCwxUtRiJAhMI1VBuUohIzQgBQ1pwOa8gfwJZGn+p5p +T6qVrDb2RGWL8kJyR0tohQ6BxwVirAYTs0Az2EzZrh26gAlMhEsmQdWjQuWeHiRk +tp+6ELfATSd97LwMe5KgJl80JYQDVHxryPxPTgbxB3tjmp8ErcrhQ58Omq2D6bnd +xrKCbgfSoZP+ZyqKY3sNbHIX3632zSwHnu8on2ltZiYbbs1I29onysM4Zj2eAjZP +ot3pTzt4uIYV+i0fyY3+STvBda10bgUsoFWAVcdG310oVsginkFbpnhZPPueUklw +YtsXPq/yPJwn/tIcbEZ7TO7Pvtlh9RqTne9VAgMBAAGjgbIwga8wHgYDVR0RBBcw +FYITb2djb3JlLnVkcy10ZXN0Lm5ldDAdBgNVHQ4EFgQUS+4OUtWxVvTVc1odUFUO +UR3dURswbgYDVR0jBGcwZaFNpEswSTELMAkGA1UEBhMCRVMxDzANBgNVBAgMBk1h +ZHJpZDEPMA0GA1UEBwwGTWFkcmlkMRgwFgYDVQQDDA9jYS51ZHMtdGVzdC5uZXSC +FECd/NYwzaJTHtQ002YnOD3ZKLs0MA0GCSqGSIb3DQEBCwUAA4ICAQAeHA6/lJIv +hQTySWOOLhnuWcej1DmQhbDzyrylLUfJe86qV7QCLpasXabDpOQzTK5yBkjCWtV2 +YiXNx6eT1iGbs70+5fITjj2vhAT9bxi4WH49xU4q+vfxlfxTkA4/ZXTEEmb+B91Q +BVEF/7f13UiGV2yu4xbDptr98v/55OeycBgwLdNN7uw7EP6WK8ryLxlxvF+nqt1n +YHof/QqRJze3FKHlGhGvx1I3SEE+VwWW5hVbde3HkwlORf5ABr4fxbvudL+kwtMi +HmYV2oYvkYQZK0Vfcua0WAn9vKVBgnF6tXdqJTPG7p91dVe7bIbUdFgNBVBdh/md +SdESFWCghPQ6WYoB7/1WfPKVQ/0IBe7l8Yx+piNNl4WW2M7lOGf8mbBWUHNAgJjD +2u3440PfsPJgBniUuV4ILNhRNGbAjdk86oU8w2Vg6WR7xsQIBcukrHEm5wEW2RkW +bZMclPyUOzHh1l4dQZTyOp2LxYNqtfYXQuPDT6tvZV5hLuLMqQfdLVxuoi3KOgo2 +GfaolX2sW/sA4fx1FAvEvEq7zEvchpocL3EYa/aUNySxMrgjKMc3AtyLYF48D8M7 +1LZMj61TaPWUUalM/u32fEHhqOXJ1o0VX3gCY7c+hKhGFee8Aiyk/hrB2ED/Q/vR +cssM+sHHNwSYI/L+bjEkJDQtVZEztcQODQ== +-----END CERTIFICATE----- diff --git a/docker/certs/ogcore.uds-test.net.key.pem b/docker/certs/ogcore.uds-test.net.key.pem new file mode 100644 index 0000000..5aa9d43 --- /dev/null +++ b/docker/certs/ogcore.uds-test.net.key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDaT0uiHcCwxUtR +iJAhMI1VBuUohIzQgBQ1pwOa8gfwJZGn+p5pT6qVrDb2RGWL8kJyR0tohQ6BxwVi +rAYTs0Az2EzZrh26gAlMhEsmQdWjQuWeHiRktp+6ELfATSd97LwMe5KgJl80JYQD +VHxryPxPTgbxB3tjmp8ErcrhQ58Omq2D6bndxrKCbgfSoZP+ZyqKY3sNbHIX3632 +zSwHnu8on2ltZiYbbs1I29onysM4Zj2eAjZPot3pTzt4uIYV+i0fyY3+STvBda10 +bgUsoFWAVcdG310oVsginkFbpnhZPPueUklwYtsXPq/yPJwn/tIcbEZ7TO7Pvtlh +9RqTne9VAgMBAAECggEADthSi9EbH8oiv4YaSu96xNvlrFYrHyh+d1GGmLw5lvZv +C62qpP2iW3AtAp0PDK+qHgxED/TwUhne/2E0PpWzWXMtcqX45ow7VaUvWQgkB2iO +paxmDCUxAl2NqTl15IW7GdwzUcmaMrkUW4ecuFWf9qKXLT+1f8XtZ0uMHrpS8BKr +bDM5oeushD6/ES32ecBIG3eJafSMESUux1fq/frzHEajS0fkYqFxi2uLYJdPLXC/ +YdVan7sIxOU3gxRROFDYLJ1uaksvUMM31oIujuxngdLTrf/K61RJGBFMeu1UIfrO +v6/9tqZgLIPTaC1nYMxjD+AtkwlY4C5vsPa8+jKtcQKBgQDz16/d/YSPxoa1QyPD +Ae/z+l13DGdk2+PdDavoyb1j11qwl4pgSGIA2uR3XeXg/dtmZaFk+KXUC+mHPsiM +TvxjoqjzP8LMXPJkRRzzTAwMjYzI8/ZAmCW+4q4Sxv3Dw4UQd0tCYi9ruMtXhnqp +agMKT2CNAikmbWdIu4S5uR6GDQKBgQDlMbfB5yJQsanW29VEJkUv+JBKZvxC7v59 +2EmZEbW1hqYHR7PA2qvSnNXvsQKRIcJtmrzf3koDhXN3mw59deBgT5FsUQCGxoK8 +ALMYMKiYcCNLp1rpxoz63lFnSzpD+f2dLBj0sac5Ufw17O6Fjs5+ZqND32UaEXFW +CLrjBpPEaQKBgAjXIQEjV9L+l5Oqw3kmcNSflxPh1z3I2xIAlOLzrXIZNKiCVfn3 +pdXyGaZaOSNXEMU9mgRXH2v4opbMp+iuVGgoVYe8IAvYstD/0HThpO4vk5MVhTAC +VBv/i+ASZtDaHdDjAk99z8pQAM9DiN7rgQC2sAFsuqEyBjSU19MD6x9hAoGAOSW1 +cObF2qMB+y3jNlPoinaK29Jj8fiPgids6nrM+Q8y1LvfKSYdE63BdjuHrVJinVuo +3pUZlVkwGlGSQlwi70DHvN9Rp0lWDbSK82wmjaPgWRvIgmPcgSzv1Taft5Vc1FTL +gC/Px24W2gdSzgB2onPLH8BTADX7MX2Jw9O/AokCgYBK7kvg1/cmikj176JFn1AM +MBCwVKS1fvUyh0bctadVyM+RA22cVvLB5PEbPB+LbyK1PnHB3jivEa954bOuYo39 +frRrRYZW4iP+oTqx8arcioaMW2K5urFtsqNrYVgkE5KDBAqFGSAyuKTAjftMxGqy +tORwgZ9jzgbBC0V8td6fqg== +-----END PRIVATE KEY----- diff --git a/docker/default.conf b/docker/default.conf index 654373e..0cb5a45 100644 --- a/docker/default.conf +++ b/docker/default.conf @@ -1,26 +1,45 @@ server { listen 80; server_name localhost; - root /var/www/html/public; - location / { - try_files $uri /index.php?$is_args$args; + # Redirigir todo el tráfico HTTP a HTTPS + return 301 https://$host$request_uri; +} + +server { + listen 443 ssl; + server_name localhost; + root /var/www/html/public; + index index.html index.php; + + ssl_certificate /etc/nginx/certs/ogcore.uds-test.net.crt.pem; + ssl_certificate_key /etc/nginx/certs/ogcore.uds-test.net.key.pem; + + location /opengnsys/rest/ous// { + rewrite ^/opengnsys/rest/ous//([0-9]+)/images /opengnsys/rest/ous/$1/images; + rewrite ^/opengnsys/rest/ous//([0-9]+)/labs /opengnsys/rest/ous/$1/labs; } - location ~ ^/index.php(/|$) { + # Bloque principal para archivos + location / { + try_files $uri $uri/ /index.php?$args; + } + + # Manejo de PHP + location ~ \.php$ { include fastcgi_params; fastcgi_pass php:9000; fastcgi_split_path_info ^(.+\.php)(/.*)$; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; - fastcgi_param PATH_INFO $fastcgi_path_info; - fastcgi_param DOCUMENT_ROOT $document_root; - internal; + fastcgi_param PATH_INFO $request_uri; + fastcgi_param PATH_TRANSLATED $document_root$fastcgi_script_name; } + # Bloque para errores PHP location ~ \.php$ { return 404; } - error_log /var/log/nginx/error.log; + error_log /var/log/nginx/error.log debug; access_log /var/log/nginx/access.log; -} \ No newline at end of file +} diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..51159ab --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +# Instalar certificados CA de Symfony si no existen +if [ ! -f /root/.symfony*/cacert.pem ]; then + symfony server:ca:install +fi diff --git a/migrations/Version20240808140716.php b/migrations/Version20240808140716.php new file mode 100644 index 0000000..b61c4df --- /dev/null +++ b/migrations/Version20240808140716.php @@ -0,0 +1,31 @@ +addSql('CREATE TABLE og_live (id INT AUTO_INCREMENT NOT NULL, uuid CHAR(36) NOT NULL COMMENT \'(DC2Type:uuid)\', migration_id VARCHAR(255) DEFAULT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, created_by VARCHAR(255) DEFAULT NULL, updated_by VARCHAR(255) DEFAULT NULL, download_url VARCHAR(255) DEFAULT NULL, name VARCHAR(255) NOT NULL, UNIQUE INDEX UNIQ_3D6B7739D17F50A6 (uuid), UNIQUE INDEX UNIQ_IDENTIFIER_NAME (name), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('DROP TABLE og_live'); + } +} diff --git a/migrations/Version20240812095940.php b/migrations/Version20240812095940.php new file mode 100644 index 0000000..448e24e --- /dev/null +++ b/migrations/Version20240812095940.php @@ -0,0 +1,43 @@ +addSql('CREATE TABLE pxe_boot_file (id INT AUTO_INCREMENT NOT NULL, template_id INT DEFAULT NULL, uuid CHAR(36) NOT NULL COMMENT \'(DC2Type:uuid)\', migration_id VARCHAR(255) DEFAULT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, created_by VARCHAR(255) DEFAULT NULL, updated_by VARCHAR(255) DEFAULT NULL, UNIQUE INDEX UNIQ_7FD1F34BD17F50A6 (uuid), INDEX IDX_7FD1F34B5DA0FB8 (template_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('CREATE TABLE pxe_template (id INT AUTO_INCREMENT NOT NULL, uuid CHAR(36) NOT NULL COMMENT \'(DC2Type:uuid)\', migration_id VARCHAR(255) DEFAULT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, created_by VARCHAR(255) DEFAULT NULL, updated_by VARCHAR(255) DEFAULT NULL, template_content VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, UNIQUE INDEX UNIQ_73197554D17F50A6 (uuid), UNIQUE INDEX UNIQ_IDENTIFIER_NAME (name), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('ALTER TABLE pxe_boot_file ADD CONSTRAINT FK_7FD1F34B5DA0FB8 FOREIGN KEY (template_id) REFERENCES pxe_template (id)'); + $this->addSql('ALTER TABLE client ADD pxe_boot_file_id INT DEFAULT NULL'); + $this->addSql('ALTER TABLE client ADD CONSTRAINT FK_C7440455D4CBF752 FOREIGN KEY (pxe_boot_file_id) REFERENCES pxe_boot_file (id)'); + $this->addSql('CREATE INDEX IDX_C7440455D4CBF752 ON client (pxe_boot_file_id)'); + $this->addSql('ALTER TABLE og_live ADD checksum VARCHAR(255) DEFAULT NULL, ADD distribution VARCHAR(255) DEFAULT NULL, ADD kernel VARCHAR(255) DEFAULT NULL, ADD architecture VARCHAR(255) DEFAULT NULL, ADD revision VARCHAR(255) DEFAULT NULL, ADD directory VARCHAR(255) DEFAULT NULL, ADD filename VARCHAR(255) DEFAULT NULL, ADD installed TINYINT(1) DEFAULT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE client DROP FOREIGN KEY FK_C7440455D4CBF752'); + $this->addSql('ALTER TABLE pxe_boot_file DROP FOREIGN KEY FK_7FD1F34B5DA0FB8'); + $this->addSql('DROP TABLE pxe_boot_file'); + $this->addSql('DROP TABLE pxe_template'); + $this->addSql('ALTER TABLE og_live DROP checksum, DROP distribution, DROP kernel, DROP architecture, DROP revision, DROP directory, DROP filename, DROP installed'); + $this->addSql('DROP INDEX IDX_C7440455D4CBF752 ON client'); + $this->addSql('ALTER TABLE client DROP pxe_boot_file_id'); + } +} diff --git a/migrations/Version20240812135824.php b/migrations/Version20240812135824.php new file mode 100644 index 0000000..5bd9784 --- /dev/null +++ b/migrations/Version20240812135824.php @@ -0,0 +1,43 @@ +addSql('CREATE TABLE og_repository (id INT AUTO_INCREMENT NOT NULL, uuid CHAR(36) NOT NULL COMMENT \'(DC2Type:uuid)\', migration_id VARCHAR(255) DEFAULT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, created_by VARCHAR(255) DEFAULT NULL, updated_by VARCHAR(255) DEFAULT NULL, ip_address VARCHAR(255) NOT NULL, description VARCHAR(255) DEFAULT NULL, name VARCHAR(255) NOT NULL, UNIQUE INDEX UNIQ_2E0FDA37D17F50A6 (uuid), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('ALTER TABLE client ADD repository_id INT DEFAULT NULL'); + $this->addSql('ALTER TABLE client ADD CONSTRAINT FK_C744045550C9D4F7 FOREIGN KEY (repository_id) REFERENCES og_repository (id)'); + $this->addSql('CREATE INDEX IDX_C744045550C9D4F7 ON client (repository_id)'); + $this->addSql('ALTER TABLE network_settings ADD repository_id INT DEFAULT NULL'); + $this->addSql('ALTER TABLE network_settings ADD CONSTRAINT FK_48869B5450C9D4F7 FOREIGN KEY (repository_id) REFERENCES og_repository (id)'); + $this->addSql('CREATE INDEX IDX_48869B5450C9D4F7 ON network_settings (repository_id)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE client DROP FOREIGN KEY FK_C744045550C9D4F7'); + $this->addSql('ALTER TABLE network_settings DROP FOREIGN KEY FK_48869B5450C9D4F7'); + $this->addSql('DROP TABLE og_repository'); + $this->addSql('DROP INDEX IDX_48869B5450C9D4F7 ON network_settings'); + $this->addSql('ALTER TABLE network_settings DROP repository_id'); + $this->addSql('DROP INDEX IDX_C744045550C9D4F7 ON client'); + $this->addSql('ALTER TABLE client DROP repository_id'); + } +} diff --git a/migrations/Version20240814130427.php b/migrations/Version20240814130427.php new file mode 100644 index 0000000..8e2cabc --- /dev/null +++ b/migrations/Version20240814130427.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE pxe_template CHANGE template_content template_content TINYTEXT NOT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE pxe_template CHANGE template_content template_content VARCHAR(255) NOT NULL'); + } +} diff --git a/migrations/Version20240819062421.php b/migrations/Version20240819062421.php new file mode 100644 index 0000000..79b21f8 --- /dev/null +++ b/migrations/Version20240819062421.php @@ -0,0 +1,33 @@ +addSql('ALTER TABLE og_live ADD synchronized TINYINT(1) DEFAULT NULL'); + $this->addSql('ALTER TABLE pxe_template ADD synchronized TINYINT(1) DEFAULT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE og_live DROP synchronized'); + $this->addSql('ALTER TABLE pxe_template DROP synchronized'); + } +} diff --git a/migrations/Version20240819140045.php b/migrations/Version20240819140045.php new file mode 100644 index 0000000..01a67ef --- /dev/null +++ b/migrations/Version20240819140045.php @@ -0,0 +1,33 @@ +addSql('ALTER TABLE og_live ADD `default` TINYINT(1) DEFAULT NULL'); + $this->addSql('ALTER TABLE pxe_boot_file ADD synchronized TINYINT(1) DEFAULT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE og_live DROP `default`'); + $this->addSql('ALTER TABLE pxe_boot_file DROP synchronized'); + } +} diff --git a/migrations/Version20240820063513.php b/migrations/Version20240820063513.php new file mode 100644 index 0000000..42803dd --- /dev/null +++ b/migrations/Version20240820063513.php @@ -0,0 +1,41 @@ +addSql('ALTER TABLE client ADD og_live_id INT DEFAULT NULL'); + $this->addSql('ALTER TABLE client ADD CONSTRAINT FK_C7440455F7E54CF3 FOREIGN KEY (og_live_id) REFERENCES og_live (id)'); + $this->addSql('CREATE INDEX IDX_C7440455F7E54CF3 ON client (og_live_id)'); + $this->addSql('ALTER TABLE network_settings ADD og_live_id INT DEFAULT NULL'); + $this->addSql('ALTER TABLE network_settings ADD CONSTRAINT FK_48869B54F7E54CF3 FOREIGN KEY (og_live_id) REFERENCES og_live (id)'); + $this->addSql('CREATE INDEX IDX_48869B54F7E54CF3 ON network_settings (og_live_id)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE network_settings DROP FOREIGN KEY FK_48869B54F7E54CF3'); + $this->addSql('DROP INDEX IDX_48869B54F7E54CF3 ON network_settings'); + $this->addSql('ALTER TABLE network_settings DROP og_live_id'); + $this->addSql('ALTER TABLE client DROP FOREIGN KEY FK_C7440455F7E54CF3'); + $this->addSql('DROP INDEX IDX_C7440455F7E54CF3 ON client'); + $this->addSql('ALTER TABLE client DROP og_live_id'); + } +} diff --git a/migrations/Version20240820064106.php b/migrations/Version20240820064106.php new file mode 100644 index 0000000..2e387f6 --- /dev/null +++ b/migrations/Version20240820064106.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE og_live CHANGE `default` is_default TINYINT(1) DEFAULT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE og_live CHANGE is_default `default` TINYINT(1) DEFAULT NULL'); + } +} diff --git a/migrations/Version20240821065158.php b/migrations/Version20240821065158.php new file mode 100644 index 0000000..dfcd85a --- /dev/null +++ b/migrations/Version20240821065158.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE pxe_template CHANGE template_content template_content LONGTEXT NOT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE pxe_template CHANGE template_content template_content TINYTEXT NOT NULL'); + } +} diff --git a/migrations/Version20240827102833.php b/migrations/Version20240827102833.php new file mode 100644 index 0000000..00ab457 --- /dev/null +++ b/migrations/Version20240827102833.php @@ -0,0 +1,31 @@ +addSql('CREATE TABLE subnet (id INT AUTO_INCREMENT NOT NULL, uuid CHAR(36) NOT NULL COMMENT \'(DC2Type:uuid)\', migration_id VARCHAR(255) DEFAULT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, created_by VARCHAR(255) DEFAULT NULL, updated_by VARCHAR(255) DEFAULT NULL, netmask VARCHAR(255) NOT NULL, ip_address VARCHAR(255) NOT NULL, next_server VARCHAR(255) NOT NULL, boot_file_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, UNIQUE INDEX UNIQ_91C24216D17F50A6 (uuid), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('DROP TABLE subnet'); + } +} diff --git a/migrations/Version20240902124157.php b/migrations/Version20240902124157.php new file mode 100644 index 0000000..5c320b9 --- /dev/null +++ b/migrations/Version20240902124157.php @@ -0,0 +1,33 @@ +addSql('ALTER TABLE network_settings ADD next_server VARCHAR(255) DEFAULT NULL, ADD boot_file_name VARCHAR(255) DEFAULT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE network_settings ADD og_live_id INT DEFAULT NULL, DROP next_server, DROP boot_file_name'); + $this->addSql('ALTER TABLE network_settings ADD CONSTRAINT FK_48869B54F7E54CF3 FOREIGN KEY (og_live_id) REFERENCES og_live (id)'); + + } +} diff --git a/migrations/Version20240903081001.php b/migrations/Version20240903081001.php new file mode 100644 index 0000000..9202867 --- /dev/null +++ b/migrations/Version20240903081001.php @@ -0,0 +1,35 @@ +addSql('ALTER TABLE organizational_unit ADD subnet_id INT DEFAULT NULL'); + $this->addSql('ALTER TABLE organizational_unit ADD CONSTRAINT FK_749AEB2DC9CF9478 FOREIGN KEY (subnet_id) REFERENCES subnet (id)'); + $this->addSql('CREATE INDEX IDX_749AEB2DC9CF9478 ON organizational_unit (subnet_id)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE organizational_unit DROP FOREIGN KEY FK_749AEB2DC9CF9478'); + $this->addSql('DROP INDEX IDX_749AEB2DC9CF9478 ON organizational_unit'); + $this->addSql('ALTER TABLE organizational_unit DROP subnet_id'); + } +} diff --git a/migrations/Version20240904134540.php b/migrations/Version20240904134540.php new file mode 100644 index 0000000..df9dd35 --- /dev/null +++ b/migrations/Version20240904134540.php @@ -0,0 +1,35 @@ +addSql('ALTER TABLE client CHANGE og_live_id subnet_id INT DEFAULT NULL'); + $this->addSql('ALTER TABLE client ADD CONSTRAINT FK_C7440455C9CF9478 FOREIGN KEY (subnet_id) REFERENCES subnet (id)'); + $this->addSql('CREATE INDEX IDX_C7440455C9CF9478 ON client (subnet_id)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE client DROP FOREIGN KEY FK_C7440455C9CF9478'); + $this->addSql('DROP INDEX IDX_C7440455C9CF9478 ON client'); + $this->addSql('ALTER TABLE client CHANGE subnet_id og_live_id INT DEFAULT NULL'); + } +} diff --git a/migrations/Version20240905080435.php b/migrations/Version20240905080435.php new file mode 100644 index 0000000..82c72f8 --- /dev/null +++ b/migrations/Version20240905080435.php @@ -0,0 +1,32 @@ +addSql('ALTER TABLE og_live ADD status VARCHAR(255) NOT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE og_live DROP status'); + + } +} diff --git a/migrations/Version20240916073039.php b/migrations/Version20240916073039.php new file mode 100644 index 0000000..ba99c0b --- /dev/null +++ b/migrations/Version20240916073039.php @@ -0,0 +1,31 @@ +addSql('CREATE TABLE command (id INT AUTO_INCREMENT NOT NULL, uuid CHAR(36) NOT NULL COMMENT \'(DC2Type:uuid)\', migration_id VARCHAR(255) DEFAULT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, created_by VARCHAR(255) DEFAULT NULL, updated_by VARCHAR(255) DEFAULT NULL, script VARCHAR(255) NOT NULL, comments VARCHAR(255) DEFAULT NULL, read_only TINYINT(1) NOT NULL, name VARCHAR(255) NOT NULL, enabled TINYINT(1) NOT NULL, UNIQUE INDEX UNIQ_8ECAEAD4D17F50A6 (uuid), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('DROP TABLE command'); + } +} diff --git a/migrations/Version20240916091601.php b/migrations/Version20240916091601.php new file mode 100644 index 0000000..9f3304d --- /dev/null +++ b/migrations/Version20240916091601.php @@ -0,0 +1,37 @@ +addSql('CREATE TABLE command_group (id INT AUTO_INCREMENT NOT NULL, uuid CHAR(36) NOT NULL COMMENT \'(DC2Type:uuid)\', migration_id VARCHAR(255) DEFAULT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, created_by VARCHAR(255) DEFAULT NULL, updated_by VARCHAR(255) DEFAULT NULL, position INT NOT NULL, name VARCHAR(255) NOT NULL, enabled TINYINT(1) NOT NULL, UNIQUE INDEX UNIQ_FE6811F6D17F50A6 (uuid), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('CREATE TABLE command_group_command (command_group_id INT NOT NULL, command_id INT NOT NULL, INDEX IDX_118CE215C7B800D6 (command_group_id), INDEX IDX_118CE21533E1689A (command_id), PRIMARY KEY(command_group_id, command_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('ALTER TABLE command_group_command ADD CONSTRAINT FK_118CE215C7B800D6 FOREIGN KEY (command_group_id) REFERENCES command_group (id) ON DELETE CASCADE'); + $this->addSql('ALTER TABLE command_group_command ADD CONSTRAINT FK_118CE21533E1689A FOREIGN KEY (command_id) REFERENCES command (id) ON DELETE CASCADE'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE command_group_command DROP FOREIGN KEY FK_118CE215C7B800D6'); + $this->addSql('ALTER TABLE command_group_command DROP FOREIGN KEY FK_118CE21533E1689A'); + $this->addSql('DROP TABLE command_group'); + $this->addSql('DROP TABLE command_group_command'); + } +} diff --git a/migrations/Version20240917064754.php b/migrations/Version20240917064754.php new file mode 100644 index 0000000..64f1f9b --- /dev/null +++ b/migrations/Version20240917064754.php @@ -0,0 +1,43 @@ +addSql('CREATE TABLE command_task (id INT AUTO_INCREMENT NOT NULL, uuid CHAR(36) NOT NULL COMMENT \'(DC2Type:uuid)\', migration_id VARCHAR(255) DEFAULT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, created_by VARCHAR(255) DEFAULT NULL, updated_by VARCHAR(255) DEFAULT NULL, datetime DATETIME NOT NULL, notes VARCHAR(255) DEFAULT NULL, status VARCHAR(255) NOT NULL, UNIQUE INDEX UNIQ_F3D475A8D17F50A6 (uuid), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('CREATE TABLE command_task_command (command_task_id INT NOT NULL, command_id INT NOT NULL, INDEX IDX_BB417CA862DC5265 (command_task_id), INDEX IDX_BB417CA833E1689A (command_id), PRIMARY KEY(command_task_id, command_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('CREATE TABLE command_task_command_group (command_task_id INT NOT NULL, command_group_id INT NOT NULL, INDEX IDX_C43618BD62DC5265 (command_task_id), INDEX IDX_C43618BDC7B800D6 (command_group_id), PRIMARY KEY(command_task_id, command_group_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('ALTER TABLE command_task_command ADD CONSTRAINT FK_BB417CA862DC5265 FOREIGN KEY (command_task_id) REFERENCES command_task (id) ON DELETE CASCADE'); + $this->addSql('ALTER TABLE command_task_command ADD CONSTRAINT FK_BB417CA833E1689A FOREIGN KEY (command_id) REFERENCES command (id) ON DELETE CASCADE'); + $this->addSql('ALTER TABLE command_task_command_group ADD CONSTRAINT FK_C43618BD62DC5265 FOREIGN KEY (command_task_id) REFERENCES command_task (id) ON DELETE CASCADE'); + $this->addSql('ALTER TABLE command_task_command_group ADD CONSTRAINT FK_C43618BDC7B800D6 FOREIGN KEY (command_group_id) REFERENCES command_group (id) ON DELETE CASCADE'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE command_task_command DROP FOREIGN KEY FK_BB417CA862DC5265'); + $this->addSql('ALTER TABLE command_task_command DROP FOREIGN KEY FK_BB417CA833E1689A'); + $this->addSql('ALTER TABLE command_task_command_group DROP FOREIGN KEY FK_C43618BD62DC5265'); + $this->addSql('ALTER TABLE command_task_command_group DROP FOREIGN KEY FK_C43618BDC7B800D6'); + $this->addSql('DROP TABLE command_task'); + $this->addSql('DROP TABLE command_task_command'); + $this->addSql('DROP TABLE command_task_command_group'); + } +} diff --git a/migrations/Version20240917091950.php b/migrations/Version20240917091950.php new file mode 100644 index 0000000..7645fa2 --- /dev/null +++ b/migrations/Version20240917091950.php @@ -0,0 +1,35 @@ +addSql('CREATE TABLE trace (id INT AUTO_INCREMENT NOT NULL, client_id INT NOT NULL, command_id INT NOT NULL, uuid CHAR(36) NOT NULL COMMENT \'(DC2Type:uuid)\', migration_id VARCHAR(255) DEFAULT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, created_by VARCHAR(255) DEFAULT NULL, updated_by VARCHAR(255) DEFAULT NULL, status VARCHAR(255) NOT NULL, output VARCHAR(255) DEFAULT NULL, executed_at DATETIME NOT NULL, finished_at DATETIME NOT NULL, UNIQUE INDEX UNIQ_315BD5A1D17F50A6 (uuid), INDEX IDX_315BD5A119EB6921 (client_id), INDEX IDX_315BD5A133E1689A (command_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('ALTER TABLE trace ADD CONSTRAINT FK_315BD5A119EB6921 FOREIGN KEY (client_id) REFERENCES client (id)'); + $this->addSql('ALTER TABLE trace ADD CONSTRAINT FK_315BD5A133E1689A FOREIGN KEY (command_id) REFERENCES command (id)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE trace DROP FOREIGN KEY FK_315BD5A119EB6921'); + $this->addSql('ALTER TABLE trace DROP FOREIGN KEY FK_315BD5A133E1689A'); + $this->addSql('DROP TABLE trace'); + } +} diff --git a/migrations/Version20240917092207.php b/migrations/Version20240917092207.php new file mode 100644 index 0000000..f291bd8 --- /dev/null +++ b/migrations/Version20240917092207.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE trace CHANGE finished_at finished_at DATETIME DEFAULT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE trace CHANGE finished_at finished_at DATETIME NOT NULL'); + } +} diff --git a/migrations/Version20240924071858.php b/migrations/Version20240924071858.php new file mode 100644 index 0000000..d758402 --- /dev/null +++ b/migrations/Version20240924071858.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE command CHANGE script script LONGTEXT NOT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE command CHANGE script script VARCHAR(255) NOT NULL'); + } +} diff --git a/migrations/Version20240924090429.php b/migrations/Version20240924090429.php new file mode 100644 index 0000000..ba9563c --- /dev/null +++ b/migrations/Version20240924090429.php @@ -0,0 +1,41 @@ +addSql('CREATE TABLE remote_calendar (id INT AUTO_INCREMENT NOT NULL, uuid CHAR(36) NOT NULL COMMENT \'(DC2Type:uuid)\', migration_id VARCHAR(255) DEFAULT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, created_by VARCHAR(255) DEFAULT NULL, updated_by VARCHAR(255) DEFAULT NULL, name VARCHAR(255) NOT NULL, UNIQUE INDEX UNIQ_BD3BDE0AD17F50A6 (uuid), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('CREATE TABLE remote_calendar_rule (id INT AUTO_INCREMENT NOT NULL, remote_calendar_id INT DEFAULT NULL, uuid CHAR(36) NOT NULL COMMENT \'(DC2Type:uuid)\', migration_id VARCHAR(255) DEFAULT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, created_by VARCHAR(255) DEFAULT NULL, updated_by VARCHAR(255) DEFAULT NULL, busy_weekdays JSON NOT NULL COMMENT \'(DC2Type:json)\', busy_from_hour DATETIME NOT NULL, busy_to_hour DATETIME NOT NULL, is_remote_available TINYINT(1) NOT NULL, available_from_date DATE NOT NULL, available_to_date DATE NOT NULL, available_reason VARCHAR(255) NOT NULL, UNIQUE INDEX UNIQ_EE93D058D17F50A6 (uuid), INDEX IDX_EE93D058C56641EE (remote_calendar_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('ALTER TABLE remote_calendar_rule ADD CONSTRAINT FK_EE93D058C56641EE FOREIGN KEY (remote_calendar_id) REFERENCES remote_calendar (id)'); + $this->addSql('ALTER TABLE organizational_unit ADD remote_calendar_id INT DEFAULT NULL'); + $this->addSql('ALTER TABLE organizational_unit ADD CONSTRAINT FK_749AEB2DC56641EE FOREIGN KEY (remote_calendar_id) REFERENCES remote_calendar (id)'); + $this->addSql('CREATE INDEX IDX_749AEB2DC56641EE ON organizational_unit (remote_calendar_id)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE organizational_unit DROP FOREIGN KEY FK_749AEB2DC56641EE'); + $this->addSql('ALTER TABLE remote_calendar_rule DROP FOREIGN KEY FK_EE93D058C56641EE'); + $this->addSql('DROP TABLE remote_calendar'); + $this->addSql('DROP TABLE remote_calendar_rule'); + $this->addSql('DROP INDEX IDX_749AEB2DC56641EE ON organizational_unit'); + $this->addSql('ALTER TABLE organizational_unit DROP remote_calendar_id'); + } +} diff --git a/migrations/Version20240924095558.php b/migrations/Version20240924095558.php new file mode 100644 index 0000000..b8b2d3b --- /dev/null +++ b/migrations/Version20240924095558.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE remote_calendar_rule CHANGE busy_from_hour busy_from_hour TIME NOT NULL, CHANGE busy_to_hour busy_to_hour TIME NOT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE remote_calendar_rule CHANGE busy_from_hour busy_from_hour DATETIME NOT NULL, CHANGE busy_to_hour busy_to_hour DATETIME NOT NULL'); + } +} diff --git a/migrations/Version20240924100335.php b/migrations/Version20240924100335.php new file mode 100644 index 0000000..9edf05f --- /dev/null +++ b/migrations/Version20240924100335.php @@ -0,0 +1,31 @@ +addSql('CREATE UNIQUE INDEX UNIQ_IDENTIFIER_NAME ON remote_calendar (name)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('DROP INDEX UNIQ_IDENTIFIER_NAME ON remote_calendar'); + } +} diff --git a/migrations/Version20240924102357.php b/migrations/Version20240924102357.php new file mode 100644 index 0000000..069d3d3 --- /dev/null +++ b/migrations/Version20240924102357.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE remote_calendar_rule CHANGE busy_weekdays busy_weekdays JSON DEFAULT NULL COMMENT \'(DC2Type:json)\', CHANGE busy_from_hour busy_from_hour TIME DEFAULT NULL, CHANGE busy_to_hour busy_to_hour TIME DEFAULT NULL, CHANGE available_from_date available_from_date DATE DEFAULT NULL, CHANGE available_to_date available_to_date DATE DEFAULT NULL, CHANGE available_reason available_reason VARCHAR(255) DEFAULT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE remote_calendar_rule CHANGE busy_weekdays busy_weekdays JSON NOT NULL COMMENT \'(DC2Type:json)\', CHANGE busy_from_hour busy_from_hour TIME NOT NULL, CHANGE busy_to_hour busy_to_hour TIME NOT NULL, CHANGE available_from_date available_from_date DATE NOT NULL, CHANGE available_to_date available_to_date DATE NOT NULL, CHANGE available_reason available_reason VARCHAR(255) NOT NULL'); + } +} diff --git a/migrations/Version20240926085224.php b/migrations/Version20240926085224.php new file mode 100644 index 0000000..b05ce37 --- /dev/null +++ b/migrations/Version20240926085224.php @@ -0,0 +1,35 @@ +addSql('ALTER TABLE remote_calendar_rule DROP FOREIGN KEY FK_EE93D058C56641EE'); + $this->addSql('ALTER TABLE remote_calendar_rule CHANGE remote_calendar_id remote_calendar_id INT NOT NULL'); + $this->addSql('ALTER TABLE remote_calendar_rule ADD CONSTRAINT FK_EE93D058C56641EE FOREIGN KEY (remote_calendar_id) REFERENCES remote_calendar (id) ON DELETE CASCADE'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE remote_calendar_rule DROP FOREIGN KEY FK_EE93D058C56641EE'); + $this->addSql('ALTER TABLE remote_calendar_rule CHANGE remote_calendar_id remote_calendar_id INT DEFAULT NULL'); + $this->addSql('ALTER TABLE remote_calendar_rule ADD CONSTRAINT FK_EE93D058C56641EE FOREIGN KEY (remote_calendar_id) REFERENCES remote_calendar (id)'); + } +} diff --git a/migrations/Version20240926104532.php b/migrations/Version20240926104532.php new file mode 100644 index 0000000..125bc93 --- /dev/null +++ b/migrations/Version20240926104532.php @@ -0,0 +1,32 @@ +addSql('ALTER TABLE command_group DROP position'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE organizational_unit ADD FK_749AEB2DC56641EE FOREIGN KEY (remote_calendar_id) REFERENCES remote_calendar (id)'); + $this->addSql('ALTER TABLE command_group ADD position INT NOT NULL'); + } +} diff --git a/migrations/Version20240930131003.php b/migrations/Version20240930131003.php new file mode 100644 index 0000000..68b2308 --- /dev/null +++ b/migrations/Version20240930131003.php @@ -0,0 +1,45 @@ +addSql('CREATE TABLE command_task_client (command_task_id INT NOT NULL, client_id INT NOT NULL, INDEX IDX_F97A827D62DC5265 (command_task_id), INDEX IDX_F97A827D19EB6921 (client_id), PRIMARY KEY(command_task_id, client_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('ALTER TABLE command_task_client ADD CONSTRAINT FK_F97A827D62DC5265 FOREIGN KEY (command_task_id) REFERENCES command_task (id) ON DELETE CASCADE'); + $this->addSql('ALTER TABLE command_task_client ADD CONSTRAINT FK_F97A827D19EB6921 FOREIGN KEY (client_id) REFERENCES client (id) ON DELETE CASCADE'); + $this->addSql('ALTER TABLE client DROP FOREIGN KEY FK_C7440455F7E54CF3'); + $this->addSql('DROP INDEX IDX_C7440455F7E54CF3 ON client'); + $this->addSql('ALTER TABLE client ADD og_live_id INT DEFAULT NULL'); + $this->addSql('ALTER TABLE client ADD CONSTRAINT FK_C7440455F7E54CF3 FOREIGN KEY (og_live_id) REFERENCES og_live (id)'); + $this->addSql('CREATE INDEX IDX_C7440455F7E54CF3 ON client (og_live_id)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE command_task_client DROP FOREIGN KEY FK_F97A827D62DC5265'); + $this->addSql('ALTER TABLE command_task_client DROP FOREIGN KEY FK_F97A827D19EB6921'); + $this->addSql('DROP TABLE command_task_client'); + $this->addSql('ALTER TABLE client DROP FOREIGN KEY FK_C7440455F7E54CF3'); + $this->addSql('DROP INDEX IDX_C7440455F7E54CF3 ON client'); + $this->addSql('ALTER TABLE client DROP og_live_id'); + $this->addSql('ALTER TABLE client ADD CONSTRAINT FK_C7440455F7E54CF3 FOREIGN KEY (subnet_id) REFERENCES og_live (id)'); + $this->addSql('CREATE INDEX IDX_C7440455F7E54CF3 ON client (subnet_id)'); + } +} diff --git a/migrations/Version20241002062742.php b/migrations/Version20241002062742.php new file mode 100644 index 0000000..d867007 --- /dev/null +++ b/migrations/Version20241002062742.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE organizational_unit ADD remote_pc TINYINT(1) NOT NULL, ADD reserved TINYINT(1) NOT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE organizational_unit DROP remote_pc, DROP reserved'); + } +} diff --git a/migrations/Version20241008080902.php b/migrations/Version20241008080902.php new file mode 100644 index 0000000..dc61c00 --- /dev/null +++ b/migrations/Version20241008080902.php @@ -0,0 +1,35 @@ +addSql('ALTER TABLE `partition` ADD image_id INT NOT NULL'); + $this->addSql('ALTER TABLE `partition` ADD CONSTRAINT FK_9EB910E43DA5256D FOREIGN KEY (image_id) REFERENCES image (id)'); + $this->addSql('CREATE INDEX IDX_9EB910E43DA5256D ON `partition` (image_id)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE `partition` DROP FOREIGN KEY FK_9EB910E43DA5256D'); + $this->addSql('DROP INDEX IDX_9EB910E43DA5256D ON `partition`'); + $this->addSql('ALTER TABLE `partition` DROP image_id'); + } +} diff --git a/migrations/Version20241008081013.php b/migrations/Version20241008081013.php new file mode 100644 index 0000000..87b726c --- /dev/null +++ b/migrations/Version20241008081013.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE client ADD maintenance TINYINT(1) NOT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE client DROP maintenance'); + } +} diff --git a/migrations/Version20241008092247.php b/migrations/Version20241008092247.php new file mode 100644 index 0000000..033c6bc --- /dev/null +++ b/migrations/Version20241008092247.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE image CHANGE software_profile_id software_profile_id INT DEFAULT NULL, CHANGE path path VARCHAR(255) DEFAULT NULL, CHANGE type type VARCHAR(255) DEFAULT NULL, CHANGE size size INT DEFAULT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE image CHANGE software_profile_id software_profile_id INT NOT NULL, CHANGE path path VARCHAR(255) NOT NULL, CHANGE type type VARCHAR(255) NOT NULL, CHANGE size size INT NOT NULL'); + } +} diff --git a/migrations/Version20241008092849.php b/migrations/Version20241008092849.php new file mode 100644 index 0000000..5c39be2 --- /dev/null +++ b/migrations/Version20241008092849.php @@ -0,0 +1,35 @@ +addSql('ALTER TABLE image ADD organizational_unit_id INT NOT NULL'); + $this->addSql('ALTER TABLE image ADD CONSTRAINT FK_C53D045FFB84408A FOREIGN KEY (organizational_unit_id) REFERENCES organizational_unit (id)'); + $this->addSql('CREATE INDEX IDX_C53D045FFB84408A ON image (organizational_unit_id)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE image DROP FOREIGN KEY FK_C53D045FFB84408A'); + $this->addSql('DROP INDEX IDX_C53D045FFB84408A ON image'); + $this->addSql('ALTER TABLE image DROP organizational_unit_id'); + } +} diff --git a/migrations/Version20241014053130.php b/migrations/Version20241014053130.php new file mode 100644 index 0000000..5abd23e --- /dev/null +++ b/migrations/Version20241014053130.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE subnet ADD server_id INT DEFAULT NULL, ADD synchronized TINYINT(1) DEFAULT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE subnet DROP server_id, DROP synchronized'); + } +} diff --git a/migrations/Version20241014082029.php b/migrations/Version20241014082029.php new file mode 100644 index 0000000..7777645 --- /dev/null +++ b/migrations/Version20241014082029.php @@ -0,0 +1,33 @@ +addSql('ALTER TABLE client DROP FOREIGN KEY FK_C7440455C9CF9478'); + $this->addSql('ALTER TABLE client ADD CONSTRAINT FK_C7440455C9CF9478 FOREIGN KEY (subnet_id) REFERENCES subnet (id) ON DELETE CASCADE'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE client DROP FOREIGN KEY FK_C7440455C9CF9478'); + $this->addSql('ALTER TABLE client ADD CONSTRAINT FK_C7440455C9CF9478 FOREIGN KEY (subnet_id) REFERENCES subnet (id)'); + } +} diff --git a/migrations/Version20241014102105.php b/migrations/Version20241014102105.php new file mode 100644 index 0000000..6015cff --- /dev/null +++ b/migrations/Version20241014102105.php @@ -0,0 +1,33 @@ +addSql('ALTER TABLE client DROP FOREIGN KEY FK_C7440455C9CF9478'); + $this->addSql('ALTER TABLE client ADD CONSTRAINT FK_C7440455C9CF9478 FOREIGN KEY (subnet_id) REFERENCES subnet (id) ON DELETE SET NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE client DROP FOREIGN KEY FK_C7440455C9CF9478'); + $this->addSql('ALTER TABLE client ADD CONSTRAINT FK_C7440455C9CF9478 FOREIGN KEY (subnet_id) REFERENCES subnet (id) ON DELETE CASCADE'); + } +} diff --git a/migrations/Version20241015154123.php b/migrations/Version20241015154123.php new file mode 100644 index 0000000..8a87c52 --- /dev/null +++ b/migrations/Version20241015154123.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE `partition` CHANGE image_id image_id INT DEFAULT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE `partition` CHANGE image_id image_id INT NOT NULL'); + } +} diff --git a/migrations/Version20241016063657.php b/migrations/Version20241016063657.php new file mode 100644 index 0000000..340af96 --- /dev/null +++ b/migrations/Version20241016063657.php @@ -0,0 +1,37 @@ +addSql('ALTER TABLE software ADD type VARCHAR(255) NOT NULL'); + $this->addSql('ALTER TABLE software_profile ADD operative_system_id INT NOT NULL'); + $this->addSql('ALTER TABLE software_profile ADD CONSTRAINT FK_B70C3C9BF1E9F66E FOREIGN KEY (operative_system_id) REFERENCES operative_system (id)'); + $this->addSql('CREATE INDEX IDX_B70C3C9BF1E9F66E ON software_profile (operative_system_id)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE software DROP type'); + $this->addSql('ALTER TABLE software_profile DROP FOREIGN KEY FK_B70C3C9BF1E9F66E'); + $this->addSql('DROP INDEX IDX_B70C3C9BF1E9F66E ON software_profile'); + $this->addSql('ALTER TABLE software_profile DROP operative_system_id'); + } +} diff --git a/migrations/Version20241016065729.php b/migrations/Version20241016065729.php new file mode 100644 index 0000000..a33c8e2 --- /dev/null +++ b/migrations/Version20241016065729.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE software_profile CHANGE operative_system_id operative_system_id INT DEFAULT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE software_profile CHANGE operative_system_id operative_system_id INT NOT NULL'); + } +} diff --git a/migrations/Version20241018055534.php b/migrations/Version20241018055534.php new file mode 100644 index 0000000..0c1d5ab --- /dev/null +++ b/migrations/Version20241018055534.php @@ -0,0 +1,39 @@ +addSql('ALTER TABLE image DROP FOREIGN KEY FK_C53D045FFB84408A'); + $this->addSql('ALTER TABLE image DROP FOREIGN KEY FK_C53D045F19EB6921'); + $this->addSql('DROP INDEX IDX_C53D045F19EB6921 ON image'); + $this->addSql('DROP INDEX IDX_C53D045FFB84408A ON image'); + $this->addSql('ALTER TABLE image DROP client_id, DROP organizational_unit_id'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE image ADD client_id INT NOT NULL, ADD organizational_unit_id INT NOT NULL'); + $this->addSql('ALTER TABLE image ADD CONSTRAINT FK_C53D045FFB84408A FOREIGN KEY (organizational_unit_id) REFERENCES organizational_unit (id)'); + $this->addSql('ALTER TABLE image ADD CONSTRAINT FK_C53D045F19EB6921 FOREIGN KEY (client_id) REFERENCES client (id)'); + $this->addSql('CREATE INDEX IDX_C53D045F19EB6921 ON image (client_id)'); + $this->addSql('CREATE INDEX IDX_C53D045FFB84408A ON image (organizational_unit_id)'); + } +} diff --git a/migrations/Version20241018060155.php b/migrations/Version20241018060155.php new file mode 100644 index 0000000..48d75fb --- /dev/null +++ b/migrations/Version20241018060155.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE image ADD remote_pc TINYINT(1) NOT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE image DROP remote_pc'); + } +} diff --git a/migrations/Version20241019073142.php b/migrations/Version20241019073142.php new file mode 100644 index 0000000..645dac2 --- /dev/null +++ b/migrations/Version20241019073142.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE client ADD agent_job_id VARCHAR(255) DEFAULT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE client DROP agent_job_id'); + } +} diff --git a/migrations/Version20241021061008.php b/migrations/Version20241021061008.php new file mode 100644 index 0000000..84ba8f8 --- /dev/null +++ b/migrations/Version20241021061008.php @@ -0,0 +1,33 @@ +addSql('ALTER TABLE client DROP FOREIGN KEY FK_C7440455F7E54CF3'); + $this->addSql('ALTER TABLE client ADD CONSTRAINT FK_C7440455F7E54CF3 FOREIGN KEY (og_live_id) REFERENCES og_live (id) ON DELETE SET NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE client DROP FOREIGN KEY FK_C7440455F7E54CF3'); + $this->addSql('ALTER TABLE client ADD CONSTRAINT FK_C7440455F7E54CF3 FOREIGN KEY (og_live_id) REFERENCES og_live (id)'); + } +} diff --git a/migrations/Version20241021071250.php b/migrations/Version20241021071250.php new file mode 100644 index 0000000..054ddd6 --- /dev/null +++ b/migrations/Version20241021071250.php @@ -0,0 +1,43 @@ +addSql('ALTER TABLE client DROP FOREIGN KEY FK_C7440455D4CBF752'); + $this->addSql('ALTER TABLE pxe_boot_file DROP FOREIGN KEY FK_7FD1F34B5DA0FB8'); + $this->addSql('DROP TABLE pxe_boot_file'); + $this->addSql('DROP INDEX IDX_C7440455D4CBF752 ON client'); + $this->addSql('ALTER TABLE client CHANGE pxe_boot_file_id template_id INT DEFAULT NULL'); + $this->addSql('ALTER TABLE client ADD CONSTRAINT FK_C74404555DA0FB8 FOREIGN KEY (template_id) REFERENCES pxe_template (id)'); + $this->addSql('CREATE INDEX IDX_C74404555DA0FB8 ON client (template_id)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('CREATE TABLE pxe_boot_file (id INT AUTO_INCREMENT NOT NULL, template_id INT DEFAULT NULL, uuid CHAR(36) CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci` COMMENT \'(DC2Type:uuid)\', migration_id VARCHAR(255) CHARACTER SET utf8mb4 DEFAULT NULL COLLATE `utf8mb4_unicode_ci`, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, created_by VARCHAR(255) CHARACTER SET utf8mb4 DEFAULT NULL COLLATE `utf8mb4_unicode_ci`, updated_by VARCHAR(255) CHARACTER SET utf8mb4 DEFAULT NULL COLLATE `utf8mb4_unicode_ci`, synchronized TINYINT(1) DEFAULT NULL, INDEX IDX_7FD1F34B5DA0FB8 (template_id), UNIQUE INDEX UNIQ_7FD1F34BD17F50A6 (uuid), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB COMMENT = \'\' '); + $this->addSql('ALTER TABLE pxe_boot_file ADD CONSTRAINT FK_7FD1F34B5DA0FB8 FOREIGN KEY (template_id) REFERENCES pxe_template (id)'); + $this->addSql('ALTER TABLE client DROP FOREIGN KEY FK_C74404555DA0FB8'); + $this->addSql('DROP INDEX IDX_C74404555DA0FB8 ON client'); + $this->addSql('ALTER TABLE client CHANGE template_id pxe_boot_file_id INT DEFAULT NULL'); + $this->addSql('ALTER TABLE client ADD CONSTRAINT FK_C7440455D4CBF752 FOREIGN KEY (pxe_boot_file_id) REFERENCES pxe_boot_file (id)'); + $this->addSql('CREATE INDEX IDX_C7440455D4CBF752 ON client (pxe_boot_file_id)'); + } +} diff --git a/migrations/Version20241021201438.php b/migrations/Version20241021201438.php new file mode 100644 index 0000000..7c1dc59 --- /dev/null +++ b/migrations/Version20241021201438.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE client ADD pxe_sync TINYINT(1) DEFAULT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE client DROP pxe_sync'); + } +} diff --git a/src/Command/LoadDefaultCommandsCommand.php b/src/Command/LoadDefaultCommandsCommand.php new file mode 100644 index 0000000..e0f8c72 --- /dev/null +++ b/src/Command/LoadDefaultCommandsCommand.php @@ -0,0 +1,95 @@ + 'Encender', + 'enabled' => true, + 'readOnly' => true, + ], + [ + 'name' => 'Apagar', + 'enabled' => true, + 'readOnly' => true, + ], + [ + 'name' => 'Restaurar Imagen', + 'enabled' => true, + 'readOnly' => true, + ], + [ + 'name' => 'Crear Imagen', + 'enabled' => true, + 'readOnly' => true, + ], + [ + 'name' => 'Reiniciar', + 'enabled' => true, + 'readOnly' => true, + ], + [ + 'name' => 'Inventario Hardware', + 'enabled' => true, + 'readOnly' => true, + ], + [ + 'name' => 'Inventario Software', + 'enabled' => true, + 'readOnly' => true, + ], + [ + 'name' => 'Ejecutar Script', + 'enabled' => true, + 'readOnly' => true, + ], + [ + 'name' => 'Iniciar Sesion', + 'enabled' => true, + 'readOnly' => true, + ], + [ + 'name' => 'Particionar y Formatear', + 'enabled' => true, + 'readOnly' => true, + ], + [ + 'name' => 'Eliminar Imagen Cache', + 'enabled' => true, + 'readOnly' => true, + ], + ]; + + foreach ($commands as $command) { + $entity = new \App\Entity\Command(); + $entity->setName($command['name']); + + $entity->setScript(''); + $entity->setEnabled($command['enabled']); + $entity->setReadOnly($command['readOnly']); + + $this->entityManager->persist($entity); + } + + $this->entityManager->flush(); + + return 1; + } + +} \ No newline at end of file diff --git a/src/Command/LoadOrganizationalUnitDefaultCommand.php b/src/Command/LoadOrganizationalUnitDefaultCommand.php new file mode 100644 index 0000000..673e6da --- /dev/null +++ b/src/Command/LoadOrganizationalUnitDefaultCommand.php @@ -0,0 +1,172 @@ + 'Universidad Test', + 'type' => OrganizationalUnitTypes::ORGANIZATIONAL_UNIT + ] + ]; + + $classrooms = [ + [ + 'name' => 'Aula Test 1', + 'type' => OrganizationalUnitTypes::CLASSROOM + ], + [ + 'name' => 'Aula Test 2', + 'type' => OrganizationalUnitTypes::CLASSROOM + ], + [ + 'name' => 'Aula Test 3', + 'type' => OrganizationalUnitTypes::CLASSROOM + ] + ]; + + $clientsA = [ + [ + 'name' => 'Cliente Test 1a', + 'ip' => '1.1.1.1', + 'mac' => '00:1A:2B:3C:4D:5E', + ], + [ + 'name' => 'Cliente Test 1b', + 'ip' => '2.2.2.2', + 'mac' => '00:1B:3C:4D:5E:6F' + ], + [ + 'name' => 'Cliente Test 1c', + 'ip' => '3.3.3.3', + 'mac' => '00:1C:4D:5E:6F:7A' + ] + ]; + + $clientsB = [ + [ + 'name' => 'Cliente Test 2a', + 'ip' => '4.4.4.4', + 'mac' => '00:1D:5E:6F:7A:8B' + ], + [ + 'name' => 'Cliente Test 2b', + 'ip' => '5.5.5.5', + 'mac' => '00:1E:6F:7A:8B:9C' + ], + [ + 'name' => 'Cliente Test 2c', + 'ip' => '6.6.6.6', + 'mac' => '00:1F:7A:8B:9C:AD' + ], + ]; + + $clientsC = [ + [ + 'name' => 'Cliente Test 3a', + 'ip' => '7.7.7.7.', + 'mac' => '00:2A:8B:9C:AD:BE' + ], + [ + 'name' => 'Cliente Test 3b', + 'ip' => '8.8.8.8', + 'mac' => '00:2B:9C:AD:BE:CF' + ], + [ + 'name' => 'Cliente Test 3c', + 'ip' => '9.9.9.9', + 'mac' => '00:2C:AD:BE:CF:D0' + ] + ]; + + $images = [ + [ + 'name' => 'Imagen Test 1', + 'type' => 'ISO', + 'path' => '/path/to/imagen1.iso' + ], + [ + 'name' => 'Imagen Test 2', + 'type' => 'ISO', + 'path' => '/path/to/imagen2.iso' + ], + [ + 'name' => 'Imagen Test 3', + 'type' => 'ISO', + 'path' => '/path/to/imagen3.iso' + ] + ]; + + + foreach ($organizationalUnits as $organizationalUnit) { + $organizationalUnitEntity = new OrganizationalUnit(); + $organizationalUnitEntity->setName($organizationalUnit['name']); + $organizationalUnitEntity->setType($organizationalUnit['type']); + + $this->entityManager->persist($organizationalUnitEntity); + + foreach ($classrooms as $classroom) { + $classroomEntity = new OrganizationalUnit(); + $classroomEntity->setName($classroom['name']); + $classroomEntity->setType($classroom['type']); + $classroomEntity->setParent($organizationalUnitEntity); + $this->entityManager->persist($classroomEntity); + + + if ($classroomEntity->getName() === 'Aula Test 1') { + $clients = $clientsA; + } elseif ($classroomEntity->getName() === 'Aula Test 2') { + $clients = $clientsB; + } elseif ($classroomEntity->getName() === 'Aula Test 3') { + $clients = $clientsC; + } + + foreach ($clients as $client) { + $clientEntity = new Client(); + $clientEntity->setName($client['name']); + $clientEntity->setIp($client['ip']); + $clientEntity->setMac($client['mac']); + $clientEntity->setMaintenance(false); + $clientEntity->setOrganizationalUnit($classroomEntity); + $this->entityManager->persist($clientEntity); + + foreach ($images as $image) { + $imageEntity = new Image(); + $imageEntity->setName($image['name']); + $imageEntity->setType($image['type']); + $imageEntity->setPath($image['path']); + $imageEntity->setOrganizationalUnit($organizationalUnitEntity); + $imageEntity->setClient($clientEntity); + $this->entityManager->persist($imageEntity); + } + } + } + + $this->entityManager->flush(); + } + + return Command::SUCCESS; + } +} diff --git a/src/Command/Migration/MigrateClientsCommand.php b/src/Command/Migration/MigrateClientsCommand.php index f4c2fc1..cee6b8e 100644 --- a/src/Command/Migration/MigrateClientsCommand.php +++ b/src/Command/Migration/MigrateClientsCommand.php @@ -63,6 +63,7 @@ class MigrateClientsCommand extends Command $clientEntity->setNetdriver($client['netdriver']); $clientEntity->setMac($client['mac']); $clientEntity->setIp($client['ip']); + $clientEntity->setMaintenance(false); $clientEntity->setPosition(['x' => 0, 'y' => 0]); } diff --git a/src/Command/Migration/MigrateHardwareAndHardwareProfileCommand.php b/src/Command/Migration/MigrateHardwareAndHardwareProfileCommand.php index e71b417..7e078ac 100644 --- a/src/Command/Migration/MigrateHardwareAndHardwareProfileCommand.php +++ b/src/Command/Migration/MigrateHardwareAndHardwareProfileCommand.php @@ -6,6 +6,7 @@ use App\Entity\Hardware; use App\Entity\HardwareProfile; use App\Entity\HardwareType; use App\Entity\OrganizationalUnit; +use App\Model\OrganizationalUnitTypes; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Query\ResultSetMapping; use Doctrine\Persistence\ManagerRegistry; @@ -118,7 +119,11 @@ class MigrateHardwareAndHardwareProfileCommand extends Command $hardwareProfileEntity->setComments($hardwareProfile['perfilhard.comentarios']); } - $migrationId = $hardwareProfile['perfilhard.grupoid'] === 0 ? $hardwareProfile['perfilhard.idcentro'] : $hardwareProfile['perfilhard.grupoid']; + $migrationId = match ($hardwareProfile['perfilhard.grupoid']) { + 0 => OrganizationalUnitTypes::ORGANIZATIONAL_UNIT . '-' . $hardwareProfile['perfilhard.idcentro'], + default => OrganizationalUnitTypes::CLASSROOMS_GROUP . '-' . $hardwareProfile['perfilhard.grupoid'], + }; + $organizationalUnit = $organizationalUnitRepository->findOneBy(['migrationId' => $migrationId]); if ($organizationalUnit){ diff --git a/src/Command/Migration/MigrateImagesCommand.php b/src/Command/Migration/MigrateImagesCommand.php new file mode 100644 index 0000000..17de59c --- /dev/null +++ b/src/Command/Migration/MigrateImagesCommand.php @@ -0,0 +1,91 @@ +doctrine->getManager('og_1'); + + $imagesRepository = $this->entityManager->getRepository(Image::class); + $clientRepository = $this->entityManager->getRepository(Client::class); + $ouRepository = $this->entityManager->getRepository(OrganizationalUnit::class); + + /** Obtener las imágenes de la base de datos antigua **/ + $rsmOperativeSystems = new ResultSetMapping(); + $rsmOperativeSystems->addScalarResult('idimagen', 'idimagen'); + $rsmOperativeSystems->addScalarResult('nombreca', 'nombreca'); + $rsmOperativeSystems->addScalarResult('idcentro', 'centros.idcentro'); + $rsmOperativeSystems->addScalarResult('idordenador', 'ordenadores.idordenador'); + $rsmOperativeSystems->addScalarResult('numdisk', 'numdisk'); + $rsmOperativeSystems->addScalarResult('ruta', 'ruta'); + $rsmOperativeSystems->addScalarResult('numpar', 'numpar'); + $rsmOperativeSystems->addScalarResult('revision', 'revision'); + $rsmOperativeSystems->addScalarResult('descripcion', 'descripcion'); + $rsmOperativeSystems->addScalarResult('comentarios', 'comentarios'); + + $imagesQuery = $oldDatabaseEntityManager->createNativeQuery('SELECT idimagen, nombreca, ruta, ordenadores.idordenador, centros.idcentro, numdisk, numpar, revision, descripcion, imagenes.comentarios FROM imagenes LEFT JOIN ordenadores ON imagenes.idordenador = ordenadores.idordenador LEFT JOIN centros ON imagenes.idcentro = imagenes.idcentro', $rsmOperativeSystems); + $images = $imagesQuery->getResult(); + + /** Imágenes **/ + $output->writeln("IMÁGENES TOTAL: ". count($images)); + + foreach ($images as $image){ + $ouEntity = $ouRepository->findOneBy(['migrationId' => OrganizationalUnitTypes::ORGANIZATIONAL_UNIT.'-'.$image['centros.idcentro']]); + + if (!$ouEntity) { + $output->writeln("No se ha encontrado la OU con id: ". $image['centros.idcentro']); + continue; + } + + $clientEntity = $clientRepository->findOneBy(['migrationId' => $image['ordenadores.idordenador']]); + if(!$clientEntity){ + $output->writeln("No se ha encontrado el cliente con id: ". $image['ordenadores.idordenador']); + continue; + } + + $imageEntity = $imagesRepository->findOneBy(['migrationId' => $image['idimagen']]); + if(!$imageEntity) { + $imageEntity = new Image(); + $imageEntity->setMigrationId((string) $image['idimagen']); + $imageEntity->setName($image['nombreca']); + $imageEntity->setClient($clientEntity); + $imageEntity->setOrganizationalUnit($ouEntity); + $imageEntity->setRevision((string) $image['revision']); + $imageEntity->setDescription($image['descripcion']); + $imageEntity->setComments($image['comentarios']); + } + + $this->entityManager->persist($imageEntity); + } + + $this->entityManager->flush(); + + return Command::SUCCESS; + } +} diff --git a/src/Command/Migration/MigrateSoftwareAndSoftwareProfileCommand.php b/src/Command/Migration/MigrateSoftwareAndSoftwareProfileCommand.php index 667de64..8439278 100644 --- a/src/Command/Migration/MigrateSoftwareAndSoftwareProfileCommand.php +++ b/src/Command/Migration/MigrateSoftwareAndSoftwareProfileCommand.php @@ -2,9 +2,12 @@ namespace App\Command\Migration; +use App\Entity\OperativeSystem; use App\Entity\OrganizationalUnit; use App\Entity\Software; use App\Entity\SoftwareProfile; +use App\Model\OrganizationalUnitTypes; +use App\Model\SoftwareTypes; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Query\ResultSetMapping; use Doctrine\Persistence\ManagerRegistry; @@ -24,34 +27,131 @@ class MigrateSoftwareAndSoftwareProfileCommand extends Command parent::__construct(); } - protected function execute(InputInterface $input, OutputInterface $output): void + protected function execute(InputInterface $input, OutputInterface $output): int { + ini_set('memory_limit', '-1'); + + /** @var EntityManagerInterface $oldDatabaseEntityManager */ $oldDatabaseEntityManager = $this->doctrine->getManager('og_1'); $organizationalUnitRepository = $this->entityManager->getRepository(OrganizationalUnit::class); + $operativeSystemRepository = $this->entityManager->getRepository(OperativeSystem::class); $softwareProfileRepository = $this->entityManager->getRepository(SoftwareProfile::class); $softwareRepository = $this->entityManager->getRepository(Software::class); - /** Obtener los perfiles software de la base de datos antigua **/ + /** Obtener los software de la base de datos antigua **/ $rsmSoftware = new ResultSetMapping(); - $rsmSoftware->addScalarResult('idtiposoftware', 'idtiposoftware'); + $rsmSoftware->addScalarResult('idsoftware', 'idsoftware'); $rsmSoftware->addScalarResult('descripcion', 'descripcion'); + $rsmSoftware->addScalarResult('grupoid', 'softwares.grupoid'); + $rsmSoftware->addScalarResult('idcentro', 'softwares.idcentro'); + $rsmSoftware->addScalarResult('idtiposoftware', 'softwares.idtiposoftware'); - $softwareQuery = $oldDatabaseEntityManager->createNativeQuery('SELECT idtiposoftware, descripcion FROM softwares', $rsmSoftware); + $softwareQuery = $oldDatabaseEntityManager->createNativeQuery('SELECT idsoftware, softwares.idtiposoftware, softwares.descripcion, softwares.grupoid, softwares.idcentro FROM softwares ', $rsmSoftware); $softwareCollection = $softwareQuery->getResult(); - foreach ($softwareCollection as $software) { + $output->writeln("SOFTWARE TOTAL: ". count($softwareCollection)); + foreach ($softwareCollection as $software){ $softwareEntity = null; - $softwareEntity = $softwareRepository->findOneBy(['migrationId' => $software['idtiposoftware']]); - if (!$softwareEntity) { + $softwareEntity = $softwareRepository->findOneBy(['migrationId' => $software['idsoftware']]); + if(!$softwareEntity){ + + $type = match ($software['softwares.idtiposoftware']) { + 1 => SoftwareTypes::OPERATIVE_SYSTEM, + 2 => SoftwareTypes::APPLICATION, + 3 => SoftwareTypes::FILE, + default => SoftwareTypes::APPLICATION, + }; + $softwareEntity = new Software(); - $softwareEntity->setMigrationId($software['idtiposoftware']); - $softwareEntity->setName($software['descripcion']); + $softwareEntity->setMigrationId($software['idsoftware']); $softwareEntity->setDescription($software['descripcion']); + $softwareEntity->setName($software['descripcion']); + $softwareEntity->setType($type); } + $migrationId = match ($software['softwares.grupoid']) { + 0 => OrganizationalUnitTypes::ORGANIZATIONAL_UNIT . '-' . $software['softwares.idcentro'], + default => OrganizationalUnitTypes::CLASSROOMS_GROUP . '-' . $software['softwares.grupoid'], + }; + + $organizationalUnit = $organizationalUnitRepository->findOneBy(['migrationId' => $migrationId]); + + /* + if ($organizationalUnit){ + $softwareEntity->setOrganizationalUnit($organizationalUnit); + }*/ + $this->entityManager->persist($softwareEntity); } + + /** Obtener los perfiles software de la base de datos antigua **/ + $rsmSoftwareProfiles = new ResultSetMapping(); + $rsmSoftwareProfiles->addScalarResult('idperfilsoft', 'idperfilsoft'); + $rsmSoftwareProfiles->addScalarResult('descripcion', 'descripcion'); + $rsmSoftwareProfiles->addScalarResult('comentarios', 'perfilessoft.comentarios'); + $rsmSoftwareProfiles->addScalarResult('grupoid', 'perfilessoft.grupoid'); + $rsmSoftwareProfiles->addScalarResult('idcentro', 'perfilessoft.idcentro'); + $rsmSoftwareProfiles->addScalarResult('idnombreso', 'perfilessoft.idnombreso'); + + + $softwareProfilesQuery = $oldDatabaseEntityManager->createNativeQuery('SELECT idperfilsoft, descripcion, grupos.comentarios, perfilessoft.grupoid, perfilessoft.idcentro, perfilessoft.idnombreso FROM perfilessoft LEFT JOIN grupos ON perfilessoft.grupoid = grupos.idgrupo', $rsmSoftwareProfiles); + $softwareProfiles = $softwareProfilesQuery->getResult(); + + /** Perfiles software **/ + $output->writeln("PERFILES SOFTWARE TOTAL: ". count($softwareProfiles)); + foreach ($softwareProfiles as $softwareProfile){ + $softwareProfileEntity = null; + $softwareProfileEntity = $softwareProfileRepository->findOneBy(['migrationId' => $softwareProfile['idperfilsoft']]); + if(!$softwareProfileEntity){ + $softwareProfileEntity = new SoftwareProfile(); + $softwareProfileEntity->setMigrationId($softwareProfile['idperfilsoft']); + $softwareProfileEntity->setDescription($softwareProfile['descripcion']); + $softwareProfileEntity->setComments($softwareProfile['perfilessoft.comentarios']); + } + + $migrationId = match ($softwareProfile['perfilessoft.grupoid']) { + 0 => OrganizationalUnitTypes::ORGANIZATIONAL_UNIT . '-' . $softwareProfile['perfilessoft.idcentro'], + default => OrganizationalUnitTypes::CLASSROOMS_GROUP . '-' . $softwareProfile['perfilessoft.grupoid'], + }; + + $organizationalUnit = $organizationalUnitRepository->findOneBy(['migrationId' => $migrationId]); + + if ($organizationalUnit){ + $softwareProfileEntity->setOrganizationalUnit($organizationalUnit); + } + + $operativeSystem = $operativeSystemRepository->findOneBy(['migrationId' => $softwareProfile['perfilessoft.idnombreso']]); + + if ($operativeSystem){ + $softwareProfileEntity->setOperativeSystem($operativeSystem); + } + + $this->entityManager->persist($softwareProfileEntity); + } + + /** Obtener los software, y asignarselos a los perfiles software **/ + $rsmSoftwareProfilesRelation = new ResultSetMapping(); + $rsmSoftwareProfilesRelation->addScalarResult('idperfilsoft', 'idperfilsoft'); + $rsmSoftwareProfilesRelation->addScalarResult('idsoftware', 'idsoftware'); + + $softwareProfilesQuery = $oldDatabaseEntityManager->createNativeQuery('SELECT idperfilsoft, idsoftware FROM perfilessoft_softwares', $rsmSoftwareProfilesRelation); + $softwareProfileRelations = $softwareProfilesQuery->getResult(); + + $output->writeln("PERFILES SOFTWARE RELACIONES TOTAL: ". count($softwareProfileRelations)); + foreach ($softwareProfileRelations as $softwareProfileRelation){ + $softwareProfileEntity = $softwareProfileRepository->findOneBy(['migrationId' => $softwareProfileRelation['idperfilsoft']]); + $softwareEntity = $softwareRepository->findOneBy(['migrationId' => $softwareProfileRelation['idsoftware']]); + + if ($softwareProfileEntity && $softwareEntity){ + $softwareProfileEntity->addSoftwareCollection($softwareEntity); + $this->entityManager->persist($softwareProfileEntity); + } + } + + $this->entityManager->flush(); + + return Command::SUCCESS; } } \ No newline at end of file diff --git a/src/Controller/CommandExecuteAction.php b/src/Controller/CommandExecuteAction.php new file mode 100644 index 0000000..fbdfda9 --- /dev/null +++ b/src/Controller/CommandExecuteAction.php @@ -0,0 +1,44 @@ +clients; + + /** @var Client $client */ + foreach ($clients as $client) { + $trace = new Trace(); + $trace->setClient($client->getEntity()); + $trace->setCommand($command); + $trace->setStatus(TraceStatus::IN_PROGRESS); + $trace->setExecutedAt(new \DateTimeImmutable()); + + $this->entityManager->persist($trace); + } + + $this->entityManager->flush(); + + return new JsonResponse(data: 'Command executed successfully', status: Response::HTTP_OK); + } +} \ No newline at end of file diff --git a/src/Controller/CommandGroupAddCommandsAction.php b/src/Controller/CommandGroupAddCommandsAction.php new file mode 100644 index 0000000..e779057 --- /dev/null +++ b/src/Controller/CommandGroupAddCommandsAction.php @@ -0,0 +1,35 @@ +commands; + + /** @var Command $command */ + foreach ($commands as $command) { + $commandGroup->addCommand($command->getEntity()); + } + + $this->entityManager->persist($commandGroup); + $this->entityManager->flush(); + + return new JsonResponse(data: 'Commands added to command group successfully', status: Response::HTTP_OK); + } +} \ No newline at end of file diff --git a/src/Controller/CommandGroupExecuteAction.php b/src/Controller/CommandGroupExecuteAction.php new file mode 100644 index 0000000..563a488 --- /dev/null +++ b/src/Controller/CommandGroupExecuteAction.php @@ -0,0 +1,46 @@ +clients; + + foreach ($commandGroup->getCommands() as $command) { + /** @var Client $client */ + foreach ($clients as $client) { + $trace = new Trace(); + $trace->setClient($client->getEntity()); + $trace->setCommand($command); + $trace->setStatus(TraceStatus::IN_PROGRESS); + $trace->setExecutedAt(new \DateTimeImmutable()); + + $this->entityManager->persist($trace); + } + } + + $this->entityManager->flush(); + + return new JsonResponse(data: 'Command group executed successfully', status: Response::HTTP_OK); + } +} \ No newline at end of file diff --git a/src/Controller/OgAgent/OgAdmClientController.php b/src/Controller/OgAgent/OgAdmClientController.php index 0b50352..4ec47f4 100644 --- a/src/Controller/OgAgent/OgAdmClientController.php +++ b/src/Controller/OgAgent/OgAdmClientController.php @@ -4,6 +4,11 @@ declare(strict_types=1); namespace App\Controller\OgAgent; +use App\Entity\Client; +use App\Entity\OrganizationalUnit; +use App\Entity\Partition; +use App\Model\OrganizationalUnitTypes; +use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; @@ -14,8 +19,14 @@ use Symfony\Component\Routing\Attribute\Route; #[AsController] class OgAdmClientController extends AbstractController { - #[Route('/opengnsys/rest/__ogAdmClient/InclusionCliente', methods: ['POST'])] - public function inclusionCliente(Request $request): JsonResponse + public function __construct( + protected readonly EntityManagerInterface $entityManager + ) + { + } + + #[Route('/opengnsys/rest/ogAdmClient/InclusionCliente', methods: ['POST'])] + public function processClient(Request $request): JsonResponse { $data = $request->toArray(); $requiredFields = ['iph', 'cfg']; @@ -26,21 +37,52 @@ class OgAdmClientController extends AbstractController } } + $clientEntity = $this->entityManager->getRepository(Client::class)->findOneBy(['ip' => $data['iph']]); + + if (!$clientEntity) { + return new JsonResponse(['message' => 'Client not found'], Response::HTTP_NOT_FOUND); + } + + foreach ($data['cfg'] as $cfg) { + if (isset($cfg['disk']) && isset($cfg['par'])) { + $partitionEntity = $this->entityManager->getRepository(Partition::class) + ->findOneBy(['client' => $clientEntity, 'diskNumber' => $cfg['disk'], 'partitionNumber' => $cfg['par']]); + + if (!$partitionEntity) { + $partitionEntity = new Partition(); + } + + $partitionEntity->setClient($clientEntity); + $partitionEntity->setDiskNumber((int)$cfg['disk']); + $partitionEntity->setPartitionNumber((int) $cfg['par']); + $partitionEntity->setSize((int) $cfg['tam'] ?? null); + $partitionEntity->setMemoryUsage((int) $cfg['uso'] * 100 ?? null); + $partitionEntity->setFileSystem($cfg['fsi'] ?? null); + + $this->entityManager->persist($partitionEntity); + } + } + + $this->entityManager->flush(); + + $center = $this->entityManager->getRepository(OrganizationalUnit::class)->find($clientEntity->getOrganizationalUnit()->getId()); + $root = $this->entityManager->getRepository(OrganizationalUnit::class)->getRootNodes(); + $responseData = [ 'res' => 1, - 'ido' => $data['ido'] ?? 42, - 'npc' => $data['npc'] ?? 42, - 'che' => 42, + 'ido' => $clientEntity->getId(), + 'npc' => $clientEntity->getName(), + 'che' => 1, 'exe' => 42, - 'ida' => $data['ida'] ?? 42, - 'idc' => $data['idc'] ?? 42, + 'ida' => $clientEntity->getOrganizationalUnit()?->getId(), + 'idc' => $root[0]->getId(), ]; return new JsonResponse($responseData, Response::HTTP_OK); } - #[Route('/opengnsys/rest/__ogAdmClient/AutoexecCliente', methods: ['POST'])] + #[Route('/opengnsys/rest/ogAdmClient/AutoexecCliente', methods: ['POST'])] public function autoexecCliente(Request $request): JsonResponse { $data = $request->toArray(); @@ -71,7 +113,7 @@ class OgAdmClientController extends AbstractController return new JsonResponse($responseData, Response::HTTP_OK); } - #[Route('/opengnsys/rest/__ogAdmClient/enviaArchivo', methods: ['POST'])] + #[Route('/opengnsys/rest/ogAdmClient/enviaArchivo', methods: ['POST'])] public function enviaArchivo(Request $request): JsonResponse { $data = $request->toArray(); @@ -95,7 +137,7 @@ class OgAdmClientController extends AbstractController return new JsonResponse(['contents' => base64_encode($contents)], Response::HTTP_OK); } - #[Route('/opengnsys/rest/__ogAdmClient/ComandosPendientes', methods: ['POST'])] + #[Route('/opengnsys/rest/ogAdmClient/ComandosPendientes', methods: ['POST'])] public function comandosPendientes(Request $request): JsonResponse { $data = $request->toArray(); @@ -122,7 +164,7 @@ class OgAdmClientController extends AbstractController return new JsonResponse($param, Response::HTTP_OK); } - #[Route('/opengnsys/rest/__ogAdmClient/DisponibilidadComandos', methods: ['POST'])] + #[Route('/opengnsys/rest/ogAdmClient/DisponibilidadComandos', methods: ['POST'])] public function disponibilidadComandos(Request $request): JsonResponse { $data = $request->toArray(); diff --git a/src/Controller/OgAgent/StatusAction.php b/src/Controller/OgAgent/StatusAction.php new file mode 100644 index 0000000..d0ff631 --- /dev/null +++ b/src/Controller/OgAgent/StatusAction.php @@ -0,0 +1,89 @@ +getIp()) { + throw new ValidatorException('IP is required'); + } + + try { + $response = $this->httpClient->request('POST', 'https://' . $client->getIp() . ':8000/ogAdmClient/status', [ + 'verify_peer' => false, // Desactivar verificación del certificado + 'verify_host' => false, // Desactivar verificación del nombre del host + 'timeout' => 10, // Tiempo máximo de espera + 'headers' => [ + 'Content-Type' => 'application/json', // Cabecera de tipo de contenido + ], + 'json' => [], // Cuerpo de la solicitud como JSON + ]); + $statusCode = $response->getStatusCode(); + $client->setStatus($statusCode === Response::HTTP_OK ? 'active' : 'off'); + + } catch (TransportExceptionInterface $e) { + $client->setStatus('off'); + + return new JsonResponse( + data: ['error' => $e->getMessage()], + status: Response::HTTP_INTERNAL_SERVER_ERROR + ); + } + + $data = json_decode($response->getContent(), true); + + if (isset($data['cfg'])) { + foreach ($data['cfg'] as $cfg) { + $partitionEntity = $this->entityManager->getRepository(Partition::class) + ->findOneBy(['client' => $client, 'diskNumber' => $cfg['disk'], 'partitionNumber' => $cfg['par']]); + + if (!$partitionEntity) { + $partitionEntity = new Partition(); + } + + $partitionEntity->setClient($client); + $partitionEntity->setDiskNumber($cfg['disk']); + $partitionEntity->setPartitionNumber($cfg['par']); + $partitionEntity->setSize($cfg['tam']); + $partitionEntity->setMemoryUsage($cfg['uso']); + $this->entityManager->persist($partitionEntity); + } + } + + $this->entityManager->persist($client); + $this->entityManager->flush(); + + return new JsonResponse(status: Response::HTTP_OK); + } +} \ No newline at end of file diff --git a/src/Controller/OgAgent/Webhook/GetStatusAction.php b/src/Controller/OgAgent/Webhook/GetStatusAction.php new file mode 100644 index 0000000..fc256f8 --- /dev/null +++ b/src/Controller/OgAgent/Webhook/GetStatusAction.php @@ -0,0 +1,44 @@ +getContent(), true); + + if (!is_array($data)) { + return new JsonResponse(['error' => 'Invalid JSON data'], Response::HTTP_BAD_REQUEST); + } + + + + return new JsonResponse(data: $data, status: Response::HTTP_OK); + } +} \ No newline at end of file diff --git a/src/Controller/OgBoot/AbstractOgBootController.php b/src/Controller/OgBoot/AbstractOgBootController.php new file mode 100644 index 0000000..7e96b1c --- /dev/null +++ b/src/Controller/OgBoot/AbstractOgBootController.php @@ -0,0 +1,56 @@ + [ + 'accept' => 'application/json', + 'Content-Type' => 'application/json' + ], + ]); + + try { + $response = $httpClient->request($method, $url, $params); + + return json_decode($response->getContent(), true); + } catch (ClientExceptionInterface | ServerExceptionInterface $e) { + $response = $e->getResponse(); + $content = json_decode($response->getContent(false), true); + throw new HttpException($response->getStatusCode(), $content['error'] ?? 'An error occurred'); + } catch (TransportExceptionInterface $e) { + throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, $e->getMessage()); + } + } +} diff --git a/src/Controller/OgBoot/OgBootController.php b/src/Controller/OgBoot/OgBootController.php new file mode 100644 index 0000000..eaa71be --- /dev/null +++ b/src/Controller/OgBoot/OgBootController.php @@ -0,0 +1,42 @@ +ogbootStatusService->__invoke(); + + return new JsonResponse( data: $data, status: Response::HTTP_OK); + } +} diff --git a/src/Controller/OgBoot/OgLive/GetAction.php b/src/Controller/OgBoot/OgLive/GetAction.php new file mode 100644 index 0000000..8635aee --- /dev/null +++ b/src/Controller/OgBoot/OgLive/GetAction.php @@ -0,0 +1,36 @@ +getChecksum()) { + throw new ValidatorException('Checksum is required'); + } + + $content = $this->createRequest($httpClient, 'GET', $this->ogBootApiUrl.'/ogboot/v1/oglives/'.$data->getChecksum()); + + return new JsonResponse(data: $content, status: Response::HTTP_OK); + } +} \ No newline at end of file diff --git a/src/Controller/OgBoot/OgLive/GetCollectionAction.php b/src/Controller/OgBoot/OgLive/GetCollectionAction.php new file mode 100644 index 0000000..930b237 --- /dev/null +++ b/src/Controller/OgBoot/OgLive/GetCollectionAction.php @@ -0,0 +1,31 @@ +createRequest($httpClient, 'GET', $this->ogBootApiUrl.'/ogboot/v1/oglives'); + + return new JsonResponse(data: $content, status: Response::HTTP_OK); + } +} \ No newline at end of file diff --git a/src/Controller/OgBoot/OgLive/GetDefaultAction.php b/src/Controller/OgBoot/OgLive/GetDefaultAction.php new file mode 100644 index 0000000..94f3456 --- /dev/null +++ b/src/Controller/OgBoot/OgLive/GetDefaultAction.php @@ -0,0 +1,30 @@ +createRequest($httpClient, 'GET', $this->ogBootApiUrl.'/ogboot/v1/oglives/default'); + + return new JsonResponse(status: Response::HTTP_OK); + } +} \ No newline at end of file diff --git a/src/Controller/OgBoot/OgLive/GetIsosAction.php b/src/Controller/OgBoot/OgLive/GetIsosAction.php new file mode 100644 index 0000000..90ddb19 --- /dev/null +++ b/src/Controller/OgBoot/OgLive/GetIsosAction.php @@ -0,0 +1,31 @@ +createRequest($httpClient, 'GET', $this->ogBootApiUrl.'/ogboot/v1/oglives/isos'); + + return new JsonResponse(data: $content, status: Response::HTTP_OK); + } +} \ No newline at end of file diff --git a/src/Controller/OgBoot/OgLive/InstallAction.php b/src/Controller/OgBoot/OgLive/InstallAction.php new file mode 100644 index 0000000..e2bbe17 --- /dev/null +++ b/src/Controller/OgBoot/OgLive/InstallAction.php @@ -0,0 +1,49 @@ +getDownloadUrl()) { + throw new ValidatorException('Download URL is required'); + } + + $params = [ + 'json' => [ + 'url' => $data->getDownloadUrl(), + 'id' => $data->getUuid() + ] + ]; + + $content = $this->createRequest($httpClient, 'POST', $this->ogBootApiUrl.'/ogboot/v1/oglives/install', $params); + + $data->setStatus(OgLiveStatus::PENDING); + $entityManager->persist($data); + $entityManager->flush(); + + return new JsonResponse(data: $content, status: Response::HTTP_OK); + } +} \ No newline at end of file diff --git a/src/Controller/OgBoot/OgLive/SetDefaultAction.php b/src/Controller/OgBoot/OgLive/SetDefaultAction.php new file mode 100644 index 0000000..3cf7184 --- /dev/null +++ b/src/Controller/OgBoot/OgLive/SetDefaultAction.php @@ -0,0 +1,54 @@ +getChecksum()) { + throw new ValidatorException('Checksum URL is required'); + } + + $params = [ + 'json' => [ + 'checksum' => $data->getChecksum() + ] + ]; + + $content = $this->createRequest($httpClient, 'PUT', $this->ogBootApiUrl.'/ogboot/v1/oglives/default', $params); + + $oldDefaultOgLive = $this->entityManager->getRepository(OgLive::class)->findBy(['isDefault' => true]); + + foreach ($oldDefaultOgLive as $oldOgLive) { + $oldOgLive->setIsDefault(false); + $this->entityManager->persist($oldOgLive); + } + + $data->setIsDefault(true); + $entityManager->persist($data); + $entityManager->flush(); + + return new JsonResponse(status: Response::HTTP_OK); + } +} \ No newline at end of file diff --git a/src/Controller/OgBoot/OgLive/SyncAction.php b/src/Controller/OgBoot/OgLive/SyncAction.php new file mode 100644 index 0000000..0c036a2 --- /dev/null +++ b/src/Controller/OgBoot/OgLive/SyncAction.php @@ -0,0 +1,80 @@ +createRequest($httpClient, 'GET', $this->ogBootApiUrl . '/ogboot/v1/oglives'); + + foreach ($content['message']['installed_ogLives'] as $ogLive) { + $ogLiveEntity = $this->entityManager->getRepository(OgLive::class)->findOneBy(['checksum' => $ogLive['id']]); + if ($ogLiveEntity) { + $this->extracted($ogLiveEntity, $ogLive); + $this->entityManager->persist($ogLiveEntity); + } else { + $ogLiveEntity = new OgLive(); + $this->extracted($ogLiveEntity, $ogLive); + } + $this->entityManager->persist($ogLiveEntity); + } + $this->entityManager->flush(); + //$this->serDefaultOgLive($content['default_oglive']); + + return new JsonResponse(data: $content, status: Response::HTTP_OK); + } + + /** + * @param OgLive|null $ogLiveEntity + * @param mixed $ogLive + * @return void + */ + private function extracted(OgLive|null $ogLiveEntity, mixed $ogLive): void + { + $ogLiveEntity->setName($ogLive['directory']); + $ogLiveEntity->setInstalled(true); + $ogLiveEntity->setArchitecture($ogLive['architecture']); + $ogLiveEntity->setDistribution($ogLive['distribution']); + $ogLiveEntity->setFilename($ogLive['directory']); + $ogLiveEntity->setKernel($ogLive['kernel']); + $ogLiveEntity->setRevision($ogLive['revision']); + $ogLiveEntity->setDirectory($ogLive['directory']); + $ogLiveEntity->setChecksum($ogLive['id']); + $ogLiveEntity->setStatus(OgLiveStatus::ACTIVE); + } + + private function serDefaultOgLive(string $defaultOgLive): void + { + $ogLiveEntity = $this->entityManager->getRepository(OgLive::class)->findOneBy(['name' => $defaultOgLive]); + + if (!$ogLiveEntity) { + return; + } + + $ogLiveEntity->setIsDefault(true); + $this->entityManager->persist($ogLiveEntity); + $this->entityManager->flush(); + } +} \ No newline at end of file diff --git a/src/Controller/OgBoot/OgLive/UninstallAction.php b/src/Controller/OgBoot/OgLive/UninstallAction.php new file mode 100644 index 0000000..d0ea542 --- /dev/null +++ b/src/Controller/OgBoot/OgLive/UninstallAction.php @@ -0,0 +1,41 @@ +getChecksum()) { + throw new ValidatorException('Checksum is required'); + } + + $content = $this->createRequest($httpClient, 'DELETE', $this->ogBootApiUrl.'/ogboot/v1/oglives/'.$data->getChecksum()); + + $entityManager->remove($data); + $entityManager->flush(); + + return new JsonResponse(status: Response::HTTP_OK); + } +} \ No newline at end of file diff --git a/src/Controller/OgBoot/OgLive/Webhook/InstallOgLiveResponseAction.php b/src/Controller/OgBoot/OgLive/Webhook/InstallOgLiveResponseAction.php new file mode 100644 index 0000000..db90e58 --- /dev/null +++ b/src/Controller/OgBoot/OgLive/Webhook/InstallOgLiveResponseAction.php @@ -0,0 +1,98 @@ +getContent(), true); + + if (!is_array($data)) { + return new JsonResponse(['error' => 'Invalid JSON data'], Response::HTTP_BAD_REQUEST); + } + + $data = $data['webhookData']; + + if ($data === null || !isset($data['message'], $data['ogCoreId'], $data['status'])) { + return new JsonResponse(['error' => 'Invalid or incomplete JSON data'], Response::HTTP_BAD_REQUEST); + } + + $message = $data['message']; + $ogCoreId = $data['ogCoreId']; + $status = $data['status']; + + $ogLive = $this->entityManager->getRepository(OgLive::class)->findOneBy(['uuid' => $ogCoreId]); + + if (!$ogLive) { + return new JsonResponse(['error' => 'OgLive not found'], Response::HTTP_NOT_FOUND); + } + + if ($ogLive->getStatus() === OgLiveStatus::ACTIVE) { + return new JsonResponse(['error' => 'OgLive is already active'], Response::HTTP_BAD_REQUEST); + } + + $this->updateOgLive($ogLive, $message, $status); + + return new JsonResponse(data: sprintf('OgLive %s updated successfully', $ogLive->getChecksum()), status: Response::HTTP_OK); + } + + private function updateOgLive (OgLive $ogLive, array $details, string $status): void + { + if ($status === self::OG_LIVE_INSTALL_SUCCESS) { + $ogLive->setInstalled(true); + $ogLive->setSynchronized(true); + $ogLive->setChecksum($details['id']); + $ogLive->setDistribution($details['distribution']); + $ogLive->setKernel($details['kernel']); + $ogLive->setArchitecture($details['architecture']); + $ogLive->setRevision($details['revision']); + $ogLive->setDirectory($details['directory']); + } + + $ogLive->setStatus($status === self::OG_LIVE_INSTALL_SUCCESS ? OgLiveStatus::ACTIVE : OgLiveStatus::FAILED); + $ogLive->setInstalled($status === self::OG_LIVE_INSTALL_SUCCESS); + + $oldDefaultOgLive = $this->entityManager->getRepository(OgLive::class)->findBy(['isDefault' => true]); + + foreach ($oldDefaultOgLive as $oldOgLive) { + $oldOgLive->setIsDefault(false); + $this->entityManager->persist($oldOgLive); + } + + $ogLive->setIsDefault(true); + $this->entityManager->persist($ogLive); + + $this->entityManager->flush(); + } +} \ No newline at end of file diff --git a/src/Controller/OgBoot/PxeBootFile/GetAction.php b/src/Controller/OgBoot/PxeBootFile/GetAction.php new file mode 100644 index 0000000..7f51e2b --- /dev/null +++ b/src/Controller/OgBoot/PxeBootFile/GetAction.php @@ -0,0 +1,43 @@ +request('GET', $this->ogBootApiUrl.'/ogboot/v1/pxes/'.$client->getMac(), [ + 'headers' => [ + 'accept' => 'application/json', + ], + ]); + } catch (TransportExceptionInterface $e) { + return new JsonResponse( data: 'An error occurred', status: Response::HTTP_INTERNAL_SERVER_ERROR); + } + + $data = json_decode($response->getContent(), true); + + return new JsonResponse( data: $data, status: Response::HTTP_OK); + } +} \ No newline at end of file diff --git a/src/Controller/OgBoot/PxeBootFile/GetCollectionAction.php b/src/Controller/OgBoot/PxeBootFile/GetCollectionAction.php new file mode 100644 index 0000000..f870364 --- /dev/null +++ b/src/Controller/OgBoot/PxeBootFile/GetCollectionAction.php @@ -0,0 +1,33 @@ +createRequest($httpClient, 'GET', $this->ogBootApiUrl.'/ogboot/v1/pxes'); + + return new JsonResponse(data: $content, status: Response::HTTP_OK); + } +} \ No newline at end of file diff --git a/src/Controller/OgBoot/PxeBootFile/PostAction.php b/src/Controller/OgBoot/PxeBootFile/PostAction.php new file mode 100644 index 0000000..506b4b9 --- /dev/null +++ b/src/Controller/OgBoot/PxeBootFile/PostAction.php @@ -0,0 +1,80 @@ +client->getEntity(); + + $data = [ + 'template_name' => $pxeTemplate->getName(), + 'mac' => strtolower($client->getMac()), + 'lang' => 'es_ES.UTF_8', + 'ip' => $client->getIp(), + 'server_ip' => '192.168.2.4', + 'router' => $client->getOrganizationalUnit()->getNetworkSettings()->getRouter(), + 'netmask' => $client->getOrganizationalUnit()->getNetworkSettings() ? $client->getOrganizationalUnit()->getNetworkSettings()->getNetmask() : '255.255.255.0', + 'computer_name' => $client->getName(), + 'netiface' => $client->getNetiface(), + 'group' => $client->getOrganizationalUnit()->getName(), + 'ogrepo' => $client->getRepository() ? $client->getRepository()->getIpAddress() : '192.168.2.4', + 'oglive' => '192.168.2.4', + 'oglog' => '192.168.2.4', + 'ogshare' => '192.168.2.4', + 'oglivedir' => 'ogLive', + 'ogprof' => 'false', + 'hardprofile' => $client->getHardwareProfile() ? $client->getHardwareProfile()->getDescription() : 'default', + 'ogntp' => $client->getOrganizationalUnit()->getNetworkSettings()?->getNtp(), + 'ogdns' => $client->getOrganizationalUnit()->getNetworkSettings()?->getDns(), + 'ogProxy' => $client->getOrganizationalUnit()->getNetworkSettings()?->getProxy(), + 'ogunit' => '', + 'resolution' => '788' + ]; + + try { + $response = $httpClient->request('POST', $this->ogBootApiUrl.'/ogboot/v1/pxes', [ + 'headers' => [ + 'accept' => 'application/json', + 'Content-Type' => 'application/json', + ], + 'json' => $data + ]); + } catch (TransportExceptionInterface $e) { + $client->setPxeSync(false); + $this->entityManager->persist($client); + $this->entityManager->flush(); + return new JsonResponse( data: $e->getMessage(), status: Response::HTTP_INTERNAL_SERVER_ERROR); + } + + $client->setPxeSync(true); + $this->entityManager->persist($client); + $this->entityManager->flush(); + + return new JsonResponse(data: json_decode($response->getContent(), true), status: Response::HTTP_OK); + } +} \ No newline at end of file diff --git a/src/Controller/OgBoot/PxeTemplate/AddClientAction.php b/src/Controller/OgBoot/PxeTemplate/AddClientAction.php new file mode 100644 index 0000000..9ebc38c --- /dev/null +++ b/src/Controller/OgBoot/PxeTemplate/AddClientAction.php @@ -0,0 +1,44 @@ +clients; + + foreach ($clients as $client) { + /** @var Client $clientEntity */ + $clientEntity = $client->getEntity(); + $clientEntity->setTemplate($pxeTemplate); + + $this->entityManager->persist($clientEntity); + } + + $this->entityManager->flush(); + + return new JsonResponse(status: Response::HTTP_OK); + } +} \ No newline at end of file diff --git a/src/Controller/OgBoot/PxeTemplate/DeleteAction.php b/src/Controller/OgBoot/PxeTemplate/DeleteAction.php new file mode 100644 index 0000000..ba6c49d --- /dev/null +++ b/src/Controller/OgBoot/PxeTemplate/DeleteAction.php @@ -0,0 +1,46 @@ +request('DELETE', $this->ogBootApiUrl.'/ogboot/v1/pxe-templates/'.$data->getName(), [ + 'headers' => [ + 'accept' => 'application/json', + ], + ]); + } catch (TransportExceptionInterface $e) { + return new JsonResponse( data: 'An error occurred', status: Response::HTTP_INTERNAL_SERVER_ERROR); + } + + if ($response->getStatusCode() === Response::HTTP_OK) { + $entityManager->remove($data); + $entityManager->flush(); + } + + return new JsonResponse(status: Response::HTTP_OK); + } +} \ No newline at end of file diff --git a/src/Controller/OgBoot/PxeTemplate/DeleteClientAction.php b/src/Controller/OgBoot/PxeTemplate/DeleteClientAction.php new file mode 100644 index 0000000..77e07f3 --- /dev/null +++ b/src/Controller/OgBoot/PxeTemplate/DeleteClientAction.php @@ -0,0 +1,43 @@ +client; + + /** @var Client $clientEntity */ + $clientEntity = $client->getEntity(); + + $pxeTemplate->removeClient($clientEntity); + + $this->entityManager->persist($clientEntity); + $this->entityManager->flush(); + + return new JsonResponse(status: Response::HTTP_OK); + } +} \ No newline at end of file diff --git a/src/Controller/OgBoot/PxeTemplate/GetAction.php b/src/Controller/OgBoot/PxeTemplate/GetAction.php new file mode 100644 index 0000000..5bbc2c0 --- /dev/null +++ b/src/Controller/OgBoot/PxeTemplate/GetAction.php @@ -0,0 +1,49 @@ +request('GET', $this->ogBootApiUrl.'/ogboot/v1/pxe-templates/'.$template->getName(), [ + 'headers' => [ + 'accept' => 'application/json', + ], + ]); + } catch (TransportExceptionInterface $e) { + return new JsonResponse( data: 'An error occurred', status: Response::HTTP_INTERNAL_SERVER_ERROR); + } + + $data = json_decode($response->getContent(), true); + + $template->setName($data['template_name']); + $template->setTemplateContent($data['template_content']); + $template->setSynchronized(true); + + $this->entityManager->persist($template); + $this->entityManager->flush(); + + return new JsonResponse( data: $data, status: Response::HTTP_OK); + } +} \ No newline at end of file diff --git a/src/Controller/OgBoot/PxeTemplate/GetCollectionAction.php b/src/Controller/OgBoot/PxeTemplate/GetCollectionAction.php new file mode 100644 index 0000000..c294cae --- /dev/null +++ b/src/Controller/OgBoot/PxeTemplate/GetCollectionAction.php @@ -0,0 +1,41 @@ +request('GET', $this->ogBootApiUrl.'/ogboot/v1/pxe-templates', [ + 'headers' => [ + 'accept' => 'application/json', + ], + ]); + } catch (TransportExceptionInterface $e) { + return new JsonResponse( data: 'An error occurred', status: Response::HTTP_INTERNAL_SERVER_ERROR); + } + + $data = json_decode($response->getContent(), true); + + return new JsonResponse( data: $data, status: Response::HTTP_OK); + } +} \ No newline at end of file diff --git a/src/Controller/OgBoot/PxeTemplate/PostAction.php b/src/Controller/OgBoot/PxeTemplate/PostAction.php new file mode 100644 index 0000000..a448bf1 --- /dev/null +++ b/src/Controller/OgBoot/PxeTemplate/PostAction.php @@ -0,0 +1,62 @@ +request('POST', $this->ogBootApiUrl.'/ogboot/v1/pxe-templates', [ + 'headers' => [ + 'accept' => 'application/json', + 'Content-Type' => 'application/json', + ], + 'json' => [ + 'name_template' => $data->getName(), + 'content_template' => $data->getTemplateContent(), + ], + ]); + + if ($response->getStatusCode() === Response::HTTP_OK) { + $data->setSynchronized(true); + $entityManager->persist($data); + $entityManager->flush(); + } + + $data = json_decode($response->getContent(), true); + return new JsonResponse($data, Response::HTTP_OK); + + } catch (ClientExceptionInterface $e) { + $errorResponse = $e->getResponse(); + $errorContent = $errorResponse ? $errorResponse->getContent(false) : 'Client error occurred'; + return new JsonResponse(['error' => $errorContent], Response::HTTP_BAD_REQUEST); + } catch (ServerExceptionInterface $e) { + $errorResponse = $e->getResponse(); + $errorContent = $errorResponse ? $errorResponse->getContent(false) : 'Server error occurred'; + return new JsonResponse(['error' => $errorContent], Response::HTTP_INTERNAL_SERVER_ERROR); + } catch (TransportExceptionInterface $e) { + return new JsonResponse(['error' => 'Transport error occurred'], Response::HTTP_INTERNAL_SERVER_ERROR); + } + } +} \ No newline at end of file diff --git a/src/Controller/OgBoot/PxeTemplate/SyncAction.php b/src/Controller/OgBoot/PxeTemplate/SyncAction.php new file mode 100644 index 0000000..50746bd --- /dev/null +++ b/src/Controller/OgBoot/PxeTemplate/SyncAction.php @@ -0,0 +1,48 @@ +createRequest($httpClient, 'GET', $this->ogBootApiUrl . '/ogboot/v1/pxe-templates'); + + foreach ($content['message'] as $template) { + $templateEntity = $this->entityManager->getRepository(PxeTemplate::class)->findOneBy(['name' => $template]); + if ($templateEntity) { + $this->entityManager->persist($templateEntity); + } else { + $templateEntity = new PxeTemplate(); + $templateEntity->setName($template); + $templateEntity->setTemplateContent(''); + } + $this->entityManager->persist($templateEntity); + } + $this->entityManager->flush(); + + return new JsonResponse(data: $content, status: Response::HTTP_OK); + } +} \ No newline at end of file diff --git a/src/Controller/OgDhcp/AbstractOgDhcpController.php b/src/Controller/OgDhcp/AbstractOgDhcpController.php new file mode 100644 index 0000000..2e4e6f5 --- /dev/null +++ b/src/Controller/OgDhcp/AbstractOgDhcpController.php @@ -0,0 +1,58 @@ + [ + 'accept' => 'application/json', + 'Content-Type' => 'application/json' + ], + ]); + + try { + $response = $httpClient->request($method, $url, $params); + + return json_decode($response->getContent(), true); + } catch (ClientExceptionInterface | ServerExceptionInterface $e) { + $response = $e->getResponse(); + $content = json_decode($response->getContent(false), true); + throw new HttpException($response->getStatusCode(), $content['error'] ?? 'An error occurred'); + } catch (TransportExceptionInterface $e) { + throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, $e->getMessage()); + } + } +} diff --git a/src/Controller/OgDhcp/OgDhcpController.php b/src/Controller/OgDhcp/OgDhcpController.php new file mode 100644 index 0000000..f67f01f --- /dev/null +++ b/src/Controller/OgDhcp/OgDhcpController.php @@ -0,0 +1,41 @@ +ogdhcpStatusService->__invoke(); + + return new JsonResponse( data: $data, status: Response::HTTP_OK); + } +} diff --git a/src/Controller/OgDhcp/Subnet/DeleteAction.php b/src/Controller/OgDhcp/Subnet/DeleteAction.php new file mode 100644 index 0000000..a00555a --- /dev/null +++ b/src/Controller/OgDhcp/Subnet/DeleteAction.php @@ -0,0 +1,39 @@ +getId()) { + throw new ValidatorException('Data Id is required'); + } + + $content = $this->createRequest($httpClient, 'DELETE', $this->ogDhcpApiUrl.'/ogdhcp/v1/subnets/'.$data->getServerId()); + + $this->entityManager->remove($data); + $this->entityManager->flush(); + + return new JsonResponse(data: $content, status: Response::HTTP_OK); + } +} \ No newline at end of file diff --git a/src/Controller/OgDhcp/Subnet/DeleteHostAction.php b/src/Controller/OgDhcp/Subnet/DeleteHostAction.php new file mode 100644 index 0000000..cf32b80 --- /dev/null +++ b/src/Controller/OgDhcp/Subnet/DeleteHostAction.php @@ -0,0 +1,53 @@ +entityManager->getRepository(Client::class)->findOneBy(['uuid' => $clientUuid]); + + if (!$client || $client->getSubnet() !== $data) { + throw new ValidatorException('Client not found'); + } + + if (!$data->getId()) { + throw new ValidatorException('Data URL is required'); + } + + $params = [ + 'json' => [ + 'macAddress' => strtolower($client->getMac()), + ] + ]; + + $content = $this->createRequest($httpClient, 'DELETE', $this->ogDhcpApiUrl.'/ogdhcp/v1/subnets/'.$data->getServerId().'/hosts', $params); + + $data->removeClient($client); + $this->entityManager->persist($data); + $this->entityManager->flush(); + + return new JsonResponse(data: $content, status: Response::HTTP_OK); + } +} \ No newline at end of file diff --git a/src/Controller/OgDhcp/Subnet/GetAction.php b/src/Controller/OgDhcp/Subnet/GetAction.php new file mode 100644 index 0000000..77f1bce --- /dev/null +++ b/src/Controller/OgDhcp/Subnet/GetAction.php @@ -0,0 +1,36 @@ +getId()) { + throw new ValidatorException('Checksum is required'); + } + + $content = $this->createRequest($httpClient, 'GET', $this->ogDhcpApiUrl.'/ogdhcp/v1/subnets/'.$data->getServerId()); + + return new JsonResponse(data: $content, status: Response::HTTP_OK); + } +} \ No newline at end of file diff --git a/src/Controller/OgDhcp/Subnet/GetCollectionAction.php b/src/Controller/OgDhcp/Subnet/GetCollectionAction.php new file mode 100644 index 0000000..9f9324c --- /dev/null +++ b/src/Controller/OgDhcp/Subnet/GetCollectionAction.php @@ -0,0 +1,31 @@ +createRequest($httpClient, 'GET', $this->ogDhcpApiUrl . '/ogdhcp/v1/subnets'); + + return new JsonResponse(data: $content, status: Response::HTTP_OK); + } +} + diff --git a/src/Controller/OgDhcp/Subnet/GetHostsAction.php b/src/Controller/OgDhcp/Subnet/GetHostsAction.php new file mode 100644 index 0000000..52ca307 --- /dev/null +++ b/src/Controller/OgDhcp/Subnet/GetHostsAction.php @@ -0,0 +1,36 @@ +getId()) { + throw new ValidatorException('Checksum is required'); + } + + $content = $this->createRequest($httpClient, 'GET', $this->ogDhcpApiUrl.'/ogdhcp/v1/subnets/'.$data->getServerId().'/hosts'); + + return new JsonResponse(data: $content, status: Response::HTTP_OK); + } +} \ No newline at end of file diff --git a/src/Controller/OgDhcp/Subnet/PostAction.php b/src/Controller/OgDhcp/Subnet/PostAction.php new file mode 100644 index 0000000..a4824f1 --- /dev/null +++ b/src/Controller/OgDhcp/Subnet/PostAction.php @@ -0,0 +1,47 @@ + [ + 'subnetId' => $data->getId(), + 'mask' => $data->getNetmask(), + 'address' => $data->getIpAddress(), + 'nextServer' => $data->getNextServer(), + 'bootFileName' => $data->getBootFileName(), + ] + ]; + + $content = $this->createRequest($httpClient, 'POST', $this->ogDhcpApiUrl.'/ogdhcp/v1/subnets' , $params); + + $data->setServerId($content['message']['id']); + $data->setSynchronized(true); + $this->entityManager->persist($data); + $this->entityManager->flush(); + + return new JsonResponse(data: $content, status: Response::HTTP_OK); + } +} \ No newline at end of file diff --git a/src/Controller/OgDhcp/Subnet/PostHostAction.php b/src/Controller/OgDhcp/Subnet/PostHostAction.php new file mode 100644 index 0000000..4330f8d --- /dev/null +++ b/src/Controller/OgDhcp/Subnet/PostHostAction.php @@ -0,0 +1,55 @@ +client; + + /** @var Client $clientEntity */ + $clientEntity = $client->getEntity(); + + $data = [ + 'host' => $clientEntity->getName(), + 'macAddress' => strtolower($clientEntity->getMac()), + 'address' => $clientEntity->getIp(), + ]; + + $params = [ + 'json' => $data + ]; + + $content = $this->createRequest($httpClient, 'POST', $this->ogDhcpApiUrl.'/ogdhcp/v1/subnets/'.$subnet->getServerId().'/hosts', $params); + + $subnet->addClient($clientEntity); + $this->entityManager->persist($subnet); + $this->entityManager->flush(); + + return new JsonResponse(data: $content, status: Response::HTTP_OK); + } +} \ No newline at end of file diff --git a/src/Controller/OgDhcp/Subnet/PutAction.php b/src/Controller/OgDhcp/Subnet/PutAction.php new file mode 100644 index 0000000..9e3004c --- /dev/null +++ b/src/Controller/OgDhcp/Subnet/PutAction.php @@ -0,0 +1,48 @@ +getId()) { + throw new ValidatorException('Id is required'); + } + + $params = [ + 'json' => [ + 'mask' => $data->getNetmask(), + 'address' => $data->getIpAddress(), + 'nextServer' => $data->getNextServer(), + 'bootFileName' => $data->getBootFileName(), + ] + ]; + + $content = $this->createRequest($httpClient, 'PUT', $this->ogDhcpApiUrl.'/ogdhcp/v1/subnets/'.$data->getServerId(), $params); + + $this->entityManager->persist($data); + $this->entityManager->flush(); + + return new JsonResponse(data: $content, status: Response::HTTP_OK); + } +} \ No newline at end of file diff --git a/src/Controller/OgDhcp/Subnet/PutHostAction.php b/src/Controller/OgDhcp/Subnet/PutHostAction.php new file mode 100644 index 0000000..3815ca4 --- /dev/null +++ b/src/Controller/OgDhcp/Subnet/PutHostAction.php @@ -0,0 +1,50 @@ +clients; + + foreach ($clients as $client) { + /** @var Client $clientEntity */ + $clientEntity = $client->getEntity(); + $data = [ + 'host' => $clientEntity->getName(), + 'oldMacAddress' => '', + 'macAddress' => '', + 'address' => '', + ]; + + $params = [ + 'json' => $data + ]; + + $content = $this->createRequest($httpClient, 'PUT', $this->ogDhcpApiUrl.'/ogdhcp/v1/subnets/'.$subnet->getId().'/hosts', $params); + } + + return new JsonResponse(status: Response::HTTP_OK); + } +} \ No newline at end of file diff --git a/src/Controller/OgDhcp/Subnet/SyncAction.php b/src/Controller/OgDhcp/Subnet/SyncAction.php new file mode 100644 index 0000000..29c86dc --- /dev/null +++ b/src/Controller/OgDhcp/Subnet/SyncAction.php @@ -0,0 +1,90 @@ +createRequest($httpClient, 'GET', $this->ogDhcpApiUrl . '/ogdhcp/v1/subnets'); + + $arraySync = []; + + foreach ($content['message'] as $subnet) { + $subnetEntity = $this->entityManager->getRepository(Subnet::class)->findOneBy(['serverId' => $subnet['id']]); + if ($subnetEntity) { + $this->extracted($subnetEntity, $subnet); + $this->entityManager->persist($subnetEntity); + } else { + $subnetEntity = new Subnet(); + $this->extracted($subnetEntity, $subnet); + } + + $arraySync[] = $subnet['id']; + + $subnetEntity->setServerId($subnet['id']); + $subnetEntity->setSynchronized(true); + $this->entityManager->persist($subnetEntity); + } + + $this->setSynchronized($arraySync); + + $this->entityManager->flush(); + + return new JsonResponse(data: $content, status: Response::HTTP_OK); + } + + /** + * @param Subnet|null $subnetEntity + * @param mixed $subnet + * @return void + */ + private function extracted(Subnet|null $subnetEntity, mixed $subnet): void + { + $getParsedData = $this->getIpAddressAndNetmaskFromCIDRService->__invoke($subnet['subnet']); + + $subnetEntity->setName($subnet['boot-file-name']); + $subnetEntity->setBootFileName($subnet['boot-file-name']); + $subnetEntity->setIpAddress($getParsedData['ip']); + $subnetEntity->setNetmask($getParsedData['mask']); + $subnetEntity->setNextServer($subnet['next-server']); + + foreach ($subnet['reservations'] as $host) { + $hostEntity = $this->entityManager->getRepository(Client::class)->findOneBy(['mac' => $host['hw-address']]); + if ($hostEntity){ + $subnetEntity->addClient($hostEntity); + } + } + } + + public function setSynchronized(array $array): void + { + $this->entityManager->createQueryBuilder() + ->update(Subnet::class, 's') + ->set('s.synchronized', 'false') + ->where('s.serverId NOT IN (:array)') + ->setParameter('array', array_values($array)) + ->getQuery() + ->getResult(); + } +} \ No newline at end of file diff --git a/src/Controller/UDS/OrganizationalUnitController.php b/src/Controller/UDS/OrganizationalUnitController.php new file mode 100644 index 0000000..5767326 --- /dev/null +++ b/src/Controller/UDS/OrganizationalUnitController.php @@ -0,0 +1,145 @@ + 1, + 'apikey' => bin2hex(random_bytes(16)) + ]; + + return new JsonResponse($data, Response::HTTP_OK); + } + + + #[Route('/opengnsys/rest//ous', methods: ['GET'])] + public function getOUs(Request $request): JsonResponse + { + $organizationalUnits = $this->entityManager + ->getRepository(OrganizationalUnit::class) + ->findBy(['type' => OrganizationalUnitTypes::ORGANIZATIONAL_UNIT], ['name' => 'ASC']); + + $data = []; + foreach ($organizationalUnits as $center) { + $data[] = [ + 'id' => $center->getId(), + 'name' => $center->getName(), + 'description' => $center->getDescription(), + ]; + } + + return new JsonResponse($data, Response::HTTP_OK); + } + + #[Route('/opengnsys/rest/ous/{centerId}/labs', name: 'get_classrooms', methods: ['GET'])] + #[Route('/opengnsys/rest//ous/{centerId}/labs', methods: ['GET'])] + public function getClassrooms(int $centerId): JsonResponse + { + $classrooms = $this->entityManager + ->getRepository(OrganizationalUnit::class) + ->findBy([ + 'type' => OrganizationalUnitTypes::CLASSROOM, + 'parent' => $centerId + ], ['name' => 'ASC']); + + $data = []; + + foreach ($classrooms as $classroom) { + $data[] = [ + 'id' => $classroom->getId(), + 'name' => $classroom->getName(), + 'inremotepc' => true, + 'ou' => [ + 'id' => 1 + ], + 'classroom' => [] + ]; + } + + return new JsonResponse($data, Response::HTTP_OK); + } + + #[Route('/opengnsys/rest/ous/{centerId}/images', name: 'getImages', methods: ['GET'])] + #[Route('/opengnsys/rest//ous/{centerId}/images', methods: ['GET'])] + public function getImages(int $centerId): JsonResponse + { + $parent = $this->entityManager + ->getRepository(OrganizationalUnit::class) + ->find($centerId); + + $images = $this->entityManager + ->getRepository(Image::class) + ->findBy([ + 'organizationalUnit' => $parent, + ], ['name' => 'ASC']); + + $data = []; + + foreach ($images as $image) { + $data[] = [ + 'id' => $image->getId(), + 'name' => $image->getName(), + 'inremotepc' => true, + 'ou' => [ + 'id' => 1 + ] + ]; + } + + return new JsonResponse($data, Response::HTTP_OK); + } + + #[Route('/opengnsys/rest//info', methods: ['GET'])] + public function getOpengnsysInfo(Request $request): JsonResponse + { + $data = [ + "project" => "OpenGnsys", + "version" => "1.1.1d", + "codename" => "Espeto", + "definition" => "http://www.andalucia.com/gastronomy/espeto.htm", + "release" => "", + "ogagent" => "1.1.2", + "services" => [ + "server", + "repository" + ], + "oglive" => + [ + "distribution" => "focal", + "kernel" => "5.13.0-27-beta", + "architecture" => "amd64", + "revision" => "r20210706", + "directory" => "ogLive-5.13.0-r20210706", + "iso" => "ogLive-focal-5.13.0-27-beta-amd64-r20210706.5b4bf5f.iso" + ] + ]; + + return new JsonResponse($data, Response::HTTP_OK); + } +} \ No newline at end of file diff --git a/src/Controller/UDS/RemoteCalendarSyncUdsAction.php b/src/Controller/UDS/RemoteCalendarSyncUdsAction.php new file mode 100644 index 0000000..019534b --- /dev/null +++ b/src/Controller/UDS/RemoteCalendarSyncUdsAction.php @@ -0,0 +1,34 @@ +udsClient->__invoke(); + + return new JsonResponse($data, Response::HTTP_OK); + + } +} \ No newline at end of file diff --git a/src/Dto/Input/ClientInput.php b/src/Dto/Input/ClientInput.php index ec4a2c2..8e78aa0 100644 --- a/src/Dto/Input/ClientInput.php +++ b/src/Dto/Input/ClientInput.php @@ -5,8 +5,11 @@ namespace App\Dto\Input; use ApiPlatform\Metadata\ApiProperty; use App\Dto\Output\HardwareProfileOutput; use App\Dto\Output\MenuOutput; +use App\Dto\Output\OgLiveOutput; use App\Dto\Output\OrganizationalUnitOutput; +use App\Dto\Output\PxeTemplateOutput; use App\Entity\Client; +use App\Entity\OgRepository; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; @@ -56,6 +59,13 @@ final class ClientInput )] public ?string $ip = null; + #[Groups(['client:write'])] + #[ApiProperty( + description: 'El estado del cliente', + example: 'active' + )] + public ?string $status = 'off'; + #[Assert\NotNull(message: 'validators.organizational_unit.not_null')] #[Groups(['client:write', 'client:patch'])] #[ApiProperty( @@ -69,6 +79,12 @@ final class ClientInput )] public ?MenuOutput $menu = null; + #[Groups(['client:write'])] + #[ApiProperty( + description: 'La plantilla PXE del cliente' + )] + public ?PxeTemplateOutput $template = null; + #[Groups(['client:write'])] #[ApiProperty( description: 'El perfil de hardware del cliente' @@ -77,10 +93,29 @@ final class ClientInput #[Groups(['client:write'])] #[ApiProperty( - description: 'descriptions.client.validation' + description: 'OgLive del cliente' + )] + public ?OgLiveOutput $ogLive = null; + + #[Groups(['client:write'])] + #[ApiProperty( + description: 'La posición del cliente dentro del aula' )] public ?array $position = ['x' => 0, 'y' => 0]; + #[Groups(['client:write'])] + #[ApiProperty( + description: 'descriptions.client.validation' + )] + public ?OgRepository $repository = null; + + #[Groups(['client:write'])] + #[ApiProperty( + description: 'descriptions.client.validation' + )] + public ?bool $maintenance = false; + + public function __construct(?Client $client = null) { if (!$client) { @@ -95,11 +130,20 @@ final class ClientInput $this->mac = $client->getMac(); $this->ip = $client->getIp(); $this->position = $client->getPosition(); + $this->status = $client->getStatus(); if ($client->getMenu()) { $this->menu = new MenuOutput($client->getMenu()); } + if ($client->getOgLive()) { + $this->ogLive = new OgLiveOutput($client->getOgLive()); + } + + if ($client->getTemplate()) { + $this->template = new PxeTemplateOutput($client->getTemplate()); + } + if ($client->getHardwareProfile()) { $this->hardwareProfile = new HardwareProfileOutput($client->getHardwareProfile()); } @@ -119,8 +163,12 @@ final class ClientInput $client->setMac($this->mac); $client->setIp($this->ip); $client->setMenu($this->menu?->getEntity()); + $client->setOgLive($this->ogLive?->getEntity()); $client->setHardwareProfile($this->hardwareProfile?->getEntity()); + $client->setTemplate($this->template?->getEntity()); $client->setPosition($this->position); + $client->setStatus($this->status); + $client->setMaintenance($this->maintenance); return $client; } diff --git a/src/Dto/Input/CommandExecuteInput.php b/src/Dto/Input/CommandExecuteInput.php new file mode 100644 index 0000000..4630a47 --- /dev/null +++ b/src/Dto/Input/CommandExecuteInput.php @@ -0,0 +1,17 @@ +name = $commandGroup->getName(); + + if ($commandGroup->getCommands()) { + foreach ($commandGroup->getCommands() as $command) { + $this->commands[] = new CommandOutput($command); + } + } + + $this->enabled = $commandGroup->isEnabled(); + } + + public function createOrUpdateEntity(?CommandGroup $commandGroup = null): CommandGroup + { + if (!$commandGroup) { + $commandGroup = new CommandGroup(); + } + + $commandGroup->setName($this->name); + + foreach ($this->commands as $command) { + $commandsToAdd[] = $command->getEntity(); + } + + $commandGroup->setCommands( $commandsToAdd ?? [] ); + + return $commandGroup; + } +} diff --git a/src/Dto/Input/CommandInput.php b/src/Dto/Input/CommandInput.php new file mode 100644 index 0000000..10697d8 --- /dev/null +++ b/src/Dto/Input/CommandInput.php @@ -0,0 +1,77 @@ +name = $command->getName(); + $this->script = $command->getScript(); + $this->enabled = $command->isEnabled(); + $this->readOnly = $command->isReadOnly(); + $this->comments = $command->getComments(); + } + + public function createOrUpdateEntity(?Command $command = null): Command + { + if (!$command) { + $command = new Command(); + } + + $command->setName($this->name); + $command->setScript($this->script); + $command->setEnabled($this->enabled); + $command->setReadOnly($this->readOnly); + $command->setComments($this->comments); + + return $command; + } +} \ No newline at end of file diff --git a/src/Dto/Input/CommandTaskInput.php b/src/Dto/Input/CommandTaskInput.php new file mode 100644 index 0000000..c7e08e7 --- /dev/null +++ b/src/Dto/Input/CommandTaskInput.php @@ -0,0 +1,120 @@ +getCommands()) { + foreach ($commandTask->getCommands() as $command) { + $this->commands[] = new CommandOutput($command); + } + } + + if ($commandTask->getCommandGroups()) { + foreach ($commandTask->getCommandGroups() as $commandGroup) { + $this->commandGroups[] = new CommandGroupOutput($commandGroup); + } + } + + if ($commandTask->getClients()) { + foreach ($commandTask->getClients() as $client) { + $this->clients[] = new ClientOutput($client); + } + } + + $this->dateTime = $commandTask->getDatetime(); + $this->notes = $commandTask->getNotes(); + } + + public function createOrUpdateEntity(?CommandTask $commandTask = null): CommandTask + { + if (!$commandTask) { + $commandTask = new CommandTask(); + } + + foreach ($this->commands as $command) { + $commandsToAdd[] = $command->getEntity(); + } + + $commandTask->setCommands( $commandsToAdd ?? [] ); + + foreach ($this->commandGroups as $commandGroup) { + $commandGroupsToAdd[] = $commandGroup->getEntity(); + } + + $commandTask->setCommandGroups( $commandGroupsToAdd ?? [] ); + + foreach ($this->clients as $client) { + $clientsToAdd[] = $client->getEntity(); + } + + $commandTask->setClients( $clientsToAdd ?? [] ); + + $commandTask->setDatetime($this->dateTime); + $commandTask->setStatus(CommandTaskStatus::PENDING); + $commandTask->setNotes($this->notes); + + return $commandTask; + } +} diff --git a/src/Dto/Input/ImageInput.php b/src/Dto/Input/ImageInput.php index 10c46a5..c1b2e84 100644 --- a/src/Dto/Input/ImageInput.php +++ b/src/Dto/Input/ImageInput.php @@ -4,8 +4,10 @@ namespace App\Dto\Input; use ApiPlatform\Metadata\ApiProperty; use App\Dto\Output\ClientOutput; +use App\Dto\Output\OrganizationalUnitOutput; use App\Dto\Output\SoftwareProfileOutput; use App\Entity\Image; +use App\Entity\OrganizationalUnit; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; @@ -44,14 +46,13 @@ final class ImageInput #[ApiProperty(description: 'The size of the image', example: 1024)] public ?int $size = null; - #[Groups(['image:write'])] - #[ApiProperty(description: 'The client of the image')] - public ?ClientOutput $client = null; - #[Groups(['image:write'])] #[ApiProperty(description: 'The software profile of the image')] public ?SoftwareProfileOutput $softwareProfile = null; + #[Groups(['image:write'])] + public ?bool $remotePc = false; + public function __construct(?Image $image = null) { if (!$image) { @@ -66,8 +67,11 @@ final class ImageInput $this->revision = $image->getRevision(); $this->info = $image->getInfo(); $this->size = $image->getSize(); - $this->client = new ClientOutput($image->getClient()); - $this->softwareProfile = new SoftwareProfileOutput($image->getSoftwareProfile()); + $this->remotePc = $image->isRemotePc(); + + if ($image->getSoftwareProfile()) { + $this->softwareProfile = new SoftwareProfileOutput($image->getSoftwareProfile()); + } } public function createOrUpdateEntity(?Image $image = null): Image @@ -84,8 +88,8 @@ final class ImageInput $image->setRevision($this->revision); $image->setInfo($this->info); $image->setSize($this->size); - $image->setClient($this->client->getEntity()); $image->setSoftwareProfile($this->softwareProfile->getEntity()); + $image->setRemotePc($this->remotePc); return $image; } diff --git a/src/Dto/Input/NetworkSettingsInput.php b/src/Dto/Input/NetworkSettingsInput.php index e32c732..e4dd125 100644 --- a/src/Dto/Input/NetworkSettingsInput.php +++ b/src/Dto/Input/NetworkSettingsInput.php @@ -2,8 +2,10 @@ namespace App\Dto\Input; +use ApiPlatform\Metadata\ApiProperty; use App\Dto\Output\HardwareProfileOutput; use App\Dto\Output\MenuOutput; +use App\Dto\Output\OgLiveOutput; use App\Entity\HardwareProfile; use App\Entity\Menu; use App\Entity\NetworkSettings; @@ -15,6 +17,12 @@ use Symfony\Component\Validator\Constraints as Assert; class NetworkSettingsInput { + #[Groups(['organizational-unit:write'])] + public ?string $nextServer = null; + + #[Groups(['organizational-unit:write'])] + public ?string $bootFileName = null; + #[Groups(['organizational-unit:write'])] public ?string $proxy = null; @@ -62,6 +70,9 @@ class NetworkSettingsInput #[Groups(['organizational-unit:write'])] public ?HardwareProfileOutput $hardwareProfile = null; + #[Groups(['organizational-unit:write'])] + public ?OgLiveOutput $ogLive = null; + #[Groups(['organizational-unit:write'])] public ?bool $validation = null; @@ -71,6 +82,8 @@ class NetworkSettingsInput return; } + $this->nextServer = $networkSettings->getNextServer(); + $this->bootFileName = $networkSettings->getBootFileName(); $this->proxy = $networkSettings->getProxy(); $this->dns = $networkSettings->getDns(); $this->netmask = $networkSettings->getNetmask(); @@ -91,6 +104,10 @@ class NetworkSettingsInput $this->hardwareProfile = new HardwareProfileOutput($networkSettings->getHardwareProfile()); } + if ($networkSettings->getOgLive()) { + $this->ogLive = new OgLiveOutput($networkSettings->getOgLive()); + } + $this->validation = $networkSettings->getValidation(); } @@ -100,6 +117,8 @@ class NetworkSettingsInput $networkSettings = new NetworkSettings(); } + $networkSettings->setNextServer($this->nextServer); + $networkSettings->setBootFileName($this->bootFileName); $networkSettings->setProxy($this->proxy); $networkSettings->setDns($this->dns); $networkSettings->setNetmask($this->netmask); @@ -120,6 +139,10 @@ class NetworkSettingsInput $networkSettings->setHardwareProfile($this->hardwareProfile->getEntity()); } + if ($this->ogLive) { + $networkSettings->setOgLive($this->ogLive->getEntity()); + } + $networkSettings->setValidation($this->validation); return $networkSettings; diff --git a/src/Dto/Input/OgLiveInput.php b/src/Dto/Input/OgLiveInput.php new file mode 100644 index 0000000..2c86228 --- /dev/null +++ b/src/Dto/Input/OgLiveInput.php @@ -0,0 +1,44 @@ +name = $ogLive->getName(); + $this->downloadUrl = $ogLive->getDownloadUrl(); + } + + public function createOrUpdateEntity(?OgLive $ogLive = null): OgLive + { + if (!$ogLive) { + $ogLive = new OgLive(); + } + + $ogLive->setName($this->name); + $ogLive->setDownloadUrl($this->downloadUrl); + $ogLive->setStatus(OgLiveStatus::INACTIVE); + + return $ogLive; + } +} \ No newline at end of file diff --git a/src/Dto/Input/OrganizationalUnitInput.php b/src/Dto/Input/OrganizationalUnitInput.php index 1b83437..d06e337 100644 --- a/src/Dto/Input/OrganizationalUnitInput.php +++ b/src/Dto/Input/OrganizationalUnitInput.php @@ -4,6 +4,7 @@ namespace App\Dto\Input; use ApiPlatform\Metadata\ApiProperty; use App\Dto\Output\OrganizationalUnitOutput; +use App\Dto\Output\RemoteCalendarOutput; use App\Entity\OrganizationalUnit; use App\Validator\Constraints\OrganizationalUnitMulticastMode; use App\Validator\Constraints\OrganizationalUnitMulticastPort; @@ -50,6 +51,12 @@ class OrganizationalUnitInput #[Assert\Valid()] public ?NetworkSettingsInput $networkSettings = null; + #[Groups(['organizational-unit:write'])] + public ?RemoteCalendarOutput $remoteCalendar = null; + + #[Groups(['organizational-unit:write'])] + public ?bool $remotePc = false; + public function __construct(?OrganizationalUnit $organizationalUnit = null) { if (!$organizationalUnit) { @@ -67,9 +74,14 @@ class OrganizationalUnitInput $this->capacity = $organizationalUnit->getCapacity(); $this->comments = $organizationalUnit->getComments(); $this->type = $organizationalUnit->getType(); + $this->remotePc = $organizationalUnit->isRemotePc(); if ($organizationalUnit->getNetworkSettings()){ $this->networkSettings = new NetworkSettingsInput($organizationalUnit->getNetworkSettings()); } + + if ($organizationalUnit->getRemoteCalendar()) { + $this->remoteCalendar = new RemoteCalendarOutput($organizationalUnit->getRemoteCalendar()); + } } public function createOrUpdateEntity(?OrganizationalUnit $organizationalUnit = null): OrganizationalUnit @@ -89,11 +101,16 @@ class OrganizationalUnitInput $organizationalUnit->setCapacity($this->capacity); $organizationalUnit->setComments($this->comments); $organizationalUnit->setType($this->type); + $organizationalUnit->setRemotePc($this->remotePc); if ($this->networkSettings){ $organizationalUnit->setNetworkSettings($this->networkSettings->createOrUpdateEntity($organizationalUnit->getNetworkSettings())); } + if ($this->remoteCalendar) { + $organizationalUnit->setRemoteCalendar($this->remoteCalendar->getEntity()); + } + return $organizationalUnit; } } \ No newline at end of file diff --git a/src/Dto/Input/PartitionInput.php b/src/Dto/Input/PartitionInput.php index 03d633a..2e7d366 100644 --- a/src/Dto/Input/PartitionInput.php +++ b/src/Dto/Input/PartitionInput.php @@ -4,6 +4,7 @@ namespace App\Dto\Input; use ApiPlatform\Metadata\ApiProperty; use App\Dto\Output\ClientOutput; +use App\Dto\Output\ImageOutput; use App\Dto\Output\OperativeSystemOutput; use App\Dto\Output\OrganizationalUnitOutput; use App\Entity\HardwareProfile; @@ -39,7 +40,6 @@ final class PartitionInput #[ApiProperty(description: 'The filesystem of the partition', example: "filesystem")] public ?string $filesystem = null; - #[Assert\NotNull()] #[Groups(['partition:write'])] #[ApiProperty(description: 'The operative system name of the partition', example: "Ubuntu")] public ?OperativeSystemOutput $operativeSystem = null; @@ -49,11 +49,14 @@ final class PartitionInput #[ApiProperty(description: 'The client of the partition')] public ?ClientOutput $client = null; - #[Assert\NotNull()] #[Groups(['partition:write'])] #[ApiProperty(description: 'The memory usage of the partition', example: 100)] public ?int $memoryUsage = null; + #[Groups(['partition:write'])] + #[ApiProperty(description: 'The image of the partition')] + public ?ImageOutput $image = null; + public function __construct(?Partition $partition = null) { if (!$partition) { @@ -66,9 +69,19 @@ final class PartitionInput $this->size = $partition->getSize(); $this->cacheContent = $partition->getCacheContent(); $this->filesystem = $partition->getFilesystem(); - $this->operativeSystem = new OperativeSystemOutput($partition->getOperativeSystem()); - $this->client = new ClientOutput($partition->getClient()); + + if ($partition->getOperativeSystem()) { + $this->operativeSystem = new OperativeSystemOutput($partition->getOperativeSystem()); + } + + if ($partition->getClient()) { + $this->client = new ClientOutput($partition->getClient()); + } $this->memoryUsage = $partition->getMemoryUsage(); + + if ($partition->getImage()) { + $this->image = new ImageOutput($partition->getImage()); + } } public function createOrUpdateEntity(?Partition $partition = null): Partition @@ -80,12 +93,22 @@ final class PartitionInput $partition->setDiskNumber($this->diskNumber); $partition->setPartitionNumber($this->partitionNumber); $partition->setPartitionCode($this->partitionCode); - $partition->setSize($this->size * 100); + $partition->setSize($this->size * 1024); $partition->setCacheContent($this->cacheContent); $partition->setFilesystem($this->filesystem); - $partition->setOperativeSystem($this->operativeSystem->getEntity()); + + if ($this->operativeSystem) { + $partition->setOperativeSystem($this->operativeSystem->getEntity()); + } $partition->setClient($this->client->getEntity()); - $partition->setMemoryUsage($this->memoryUsage * 100); + + if ($this->memoryUsage) { + $partition->setMemoryUsage($this->memoryUsage * 100); + } + + if ($this->image) { + $partition->setImage($this->image->getEntity()); + } return $partition; } diff --git a/src/Dto/Input/PxeTemplateAddClientsInput.php b/src/Dto/Input/PxeTemplateAddClientsInput.php new file mode 100644 index 0000000..28cf393 --- /dev/null +++ b/src/Dto/Input/PxeTemplateAddClientsInput.php @@ -0,0 +1,20 @@ +name = $pxeTemplate->getName(); + $this->templateContent = $pxeTemplate->getTemplateContent(); + } + + public function createOrUpdateEntity(?PxeTemplate $pxeTemplate = null): PxeTemplate + { + if (!$pxeTemplate) { + $pxeTemplate = new PxeTemplate(); + } + + $pxeTemplate->setName($this->name); + $pxeTemplate->setTemplateContent($this->templateContent); + + return $pxeTemplate; + } +} \ No newline at end of file diff --git a/src/Dto/Input/PxeTemplateSyncClientInput.php b/src/Dto/Input/PxeTemplateSyncClientInput.php new file mode 100644 index 0000000..8dafe1b --- /dev/null +++ b/src/Dto/Input/PxeTemplateSyncClientInput.php @@ -0,0 +1,15 @@ +name = $remoteCalendar->getName(); + + if ($remoteCalendar->getRules()) { + foreach ($remoteCalendar->getRules() as $rule) { + $this->remoteCalendarRules[] = new RemoteCalendarRuleOutput($rule); + } + } + } + + public function createOrUpdateEntity(?RemoteCalendar $remoteCalendar = null): RemoteCalendar + { + if (!$remoteCalendar) { + $remoteCalendar = new RemoteCalendar(); + } + + $remoteCalendar->setName($this->name); + + foreach ($this->remoteCalendarRules as $rule) { + $ruleToAdd[] = $rule->getEntity(); + } + + $remoteCalendar->setRules( $ruleToAdd ?? [] ); + + return $remoteCalendar; + } +} \ No newline at end of file diff --git a/src/Dto/Input/RemoteCalendarRuleInput.php b/src/Dto/Input/RemoteCalendarRuleInput.php new file mode 100644 index 0000000..c0883c4 --- /dev/null +++ b/src/Dto/Input/RemoteCalendarRuleInput.php @@ -0,0 +1,82 @@ +remoteCalendar = new RemoteCalendarOutput($remoteCalendarRule->getRemoteCalendar()); + $this->busyWeekDays = $remoteCalendarRule->getBusyWeekDays(); + $this->busyFromHour = $remoteCalendarRule->getBusyFromHour(); + $this->busyToHour = $remoteCalendarRule->getBusyToHour(); + $this->isRemoteAvailable = $remoteCalendarRule->isRemoteAvailable(); + $this->availableFromDate = $remoteCalendarRule->getAvailableFromDate(); + $this->availableToDate = $remoteCalendarRule->getAvailableToDate(); + $this->availableReason = $remoteCalendarRule->getAvailableReason(); + } + + /** + * @throws \Exception + */ + public function createOrUpdateEntity(?RemoteCalendarRule $remoteCalendarRule = null): RemoteCalendarRule + { + if (!$remoteCalendarRule) { + $remoteCalendarRule = new RemoteCalendarRule(); + } + + $remoteCalendarRule->setRemoteCalendar($this->remoteCalendar->getEntity()); + $remoteCalendarRule->setBusyWeekDays($this->busyWeekDays); + $remoteCalendarRule->setBusyFromHour($this->busyFromHour); + $remoteCalendarRule->setBusyToHour($this->busyToHour); + $remoteCalendarRule->setRemoteAvailable($this->isRemoteAvailable); + $remoteCalendarRule->setAvailableFromDate($this->availableFromDate); + $remoteCalendarRule->setAvailableToDate($this->availableToDate); + $remoteCalendarRule->setAvailableReason($this->availableReason); + + return $remoteCalendarRule; + } +} \ No newline at end of file diff --git a/src/Dto/Input/SoftwareInput.php b/src/Dto/Input/SoftwareInput.php index 624a94c..6835562 100644 --- a/src/Dto/Input/SoftwareInput.php +++ b/src/Dto/Input/SoftwareInput.php @@ -18,6 +18,11 @@ final class SoftwareInput #[ApiProperty(description: 'The description of the software', example: "Software 1 description")] public ?string $description = null; + #[Groups(['software:write'])] + #[ApiProperty(description: 'The type of the software', example: "Software 1 type")] + public ?string $type = null; + + public function __construct(?Software $software = null) { if (!$software) { @@ -26,6 +31,7 @@ final class SoftwareInput $this->name = $software->getName(); $this->description = $software->getDescription(); + $this->type = $software->getType(); } public function createOrUpdateEntity(?Software $software = null): Software @@ -36,6 +42,7 @@ final class SoftwareInput $software->setName($this->name); $software->setDescription($this->description); + $software->setType($this->type); return $software; } diff --git a/src/Dto/Input/SoftwareProfileInput.php b/src/Dto/Input/SoftwareProfileInput.php index c803d82..87ee072 100644 --- a/src/Dto/Input/SoftwareProfileInput.php +++ b/src/Dto/Input/SoftwareProfileInput.php @@ -3,6 +3,7 @@ namespace App\Dto\Input; use ApiPlatform\Metadata\ApiProperty; +use App\Dto\Output\OperativeSystemOutput; use App\Dto\Output\OrganizationalUnitOutput; use App\Entity\SoftwareProfile; use Symfony\Component\Serializer\Annotation\Groups; @@ -21,6 +22,11 @@ final class SoftwareProfileInput #[ApiProperty(description: 'The organizational unit of the software profile')] public ?OrganizationalUnitOutput $organizationalUnit = null; + #[Groups(['software-profile:write'])] + #[ApiProperty(description: 'The operative system of the software profile')] + public ?OperativeSystemOutput $operativeSystem = null; + + public function __construct(?SoftwareProfile $softwareProfile = null) { if (!$softwareProfile) { @@ -32,6 +38,10 @@ final class SoftwareProfileInput if($softwareProfile->getOrganizationalUnit()) { $this->organizationalUnit = new OrganizationalUnitOutput($softwareProfile->getOrganizationalUnit()); } + + if($softwareProfile->getOperativeSystem()) { + $this->operativeSystem = new OperativeSystemOutput($softwareProfile->getOperativeSystem()); + } } public function createOrUpdateEntity(?SoftwareProfile $softwareProfile = null): SoftwareProfile @@ -46,6 +56,10 @@ final class SoftwareProfileInput $softwareProfile->setOrganizationalUnit($this->organizationalUnit->getEntity()); } + if ($this->operativeSystem) { + $softwareProfile->setOperativeSystem($this->operativeSystem->getEntity()); + } + return $softwareProfile; } } \ No newline at end of file diff --git a/src/Dto/Input/SubnetAddHostInput.php b/src/Dto/Input/SubnetAddHostInput.php new file mode 100644 index 0000000..0129a86 --- /dev/null +++ b/src/Dto/Input/SubnetAddHostInput.php @@ -0,0 +1,18 @@ +name = $subnet->getName(); + $this->netmask = $subnet->getNetmask(); + $this->ipAddress = $subnet->getIpAddress(); + $this->nextServer = $subnet->getNextServer(); + $this->bootFileName = $subnet->getBootFileName(); + + if ($subnet->getOrganizationalUnits()) { + foreach ($subnet->getOrganizationalUnits() as $organizationalUnit) { + $this->organizationalUnits[] = new OrganizationalUnitOutput($organizationalUnit); + } + } + } + + public function createOrUpdateEntity(?Subnet $subnet = null): Subnet + { + if (!$subnet) { + $subnet = new Subnet(); + } + + $subnet->setName($this->name); + $subnet->setNetmask($this->netmask); + $subnet->setIpAddress($this->ipAddress); + $subnet->setNextServer($this->nextServer); + $subnet->setBootFileName($this->bootFileName); + + foreach ($this->organizationalUnits as $organizationalUnit) { + $organizationalUnitToAdd[] = $organizationalUnit->getEntity(); + } + $subnet->setOrganizationalUnits($organizationalUnitToAdd ?? [] ); + + return $subnet; + } +} \ No newline at end of file diff --git a/src/Dto/Output/AbstractOutput.php b/src/Dto/Output/AbstractOutput.php index 93f7e50..1992875 100644 --- a/src/Dto/Output/AbstractOutput.php +++ b/src/Dto/Output/AbstractOutput.php @@ -14,7 +14,7 @@ abstract class AbstractOutput public UuidInterface $uuid; #[ApiProperty(identifier: false)] - #[Groups('default')] + #[Groups(groups: ['default', 'organizational-unit:read:collection:short'])] public int $id; public function __construct(private readonly AbstractEntity $entity) diff --git a/src/Dto/Output/ClientOutput.php b/src/Dto/Output/ClientOutput.php index 97c0b5a..3d9399c 100644 --- a/src/Dto/Output/ClientOutput.php +++ b/src/Dto/Output/ClientOutput.php @@ -13,19 +13,19 @@ final class ClientOutput extends AbstractOutput { CONST string TYPE = 'client'; - #[Groups(['client:read', 'organizational-unit:read'])] + #[Groups(['client:read', 'organizational-unit:read', 'pxe-template:read', 'trace:read', 'subnet:read'])] public string $name; #[Groups(['client:read', 'organizational-unit:read'])] public string $type = self::TYPE; - #[Groups(['client:read', 'organizational-unit:read'])] + #[Groups(['client:read', 'organizational-unit:read', 'pxe-template:read', 'trace:read', 'subnet:read'])] public ?string $ip = ''; - #[Groups(['client:read', 'organizational-unit:read'])] + #[Groups(['client:read', 'organizational-unit:read', 'pxe-template:read', 'trace:read', 'subnet:read'])] public ?string $mac = ''; - #[Groups(['client:read', 'organizational-unit:read'])] + #[Groups(['client:read', 'organizational-unit:read', 'trace:read'])] public ?string $serialNumber = ''; #[Groups(['client:read'])] @@ -48,15 +48,35 @@ final class ClientOutput extends AbstractOutput #[ApiProperty(readableLink: true )] public ?HardwareProfileOutput $hardwareProfile = null; + #[Groups(['client:read', 'organizational-unit:read'])] + #[ApiProperty(readableLink: true )] + public ?PxeTemplateOutput $template = null; + #[Groups(['client:read'])] + #[ApiProperty(readableLink: true )] + public ?OgLiveOutput $ogLive = null; + + #[Groups(['client:read'])] + public ?string $subnet = null; + + #[Groups(['client:read', 'organizational-unit:read'])] public ?array $position = ['x' => 0, 'y' => 0]; + #[Groups(['client:read'])] + public ?string $status = ''; + #[Groups(['client:read'])] public \DateTime $createdAt; #[Groups(['client:read'])] public ?string $createdBy = null; + #[Groups(['client:read'])] + public ?bool $maintenance = false; + + #[Groups(['client:read'])] + public ?bool $pxeSync = false; + public function __construct(Client $client) { parent::__construct($client); @@ -78,8 +98,14 @@ final class ClientOutput extends AbstractOutput $this->menu = $client->getMenu() ? new MenuOutput($client->getMenu()) : null; $this->position = $client->getPosition(); + $this->template = $client->getTemplate() ? new PxeTemplateOutput($client->getTemplate()) : null; $this->hardwareProfile = $client->getHardwareProfile() ? new HardwareProfileOutput($client->getHardwareProfile()) : null; + $this->subnet = $client->getSubnet()?->getIpAddress(); + $this->ogLive = $client->getOgLive() ? new OgLiveOutput($client->getOgLive()) : null; + $this->status = $client->getStatus(); $this->createdAt = $client->getCreatedAt(); $this->createdBy = $client->getCreatedBy(); + $this->maintenance = $client->isMaintenance(); + $this->pxeSync = $client->isPxeSync(); } } \ No newline at end of file diff --git a/src/Dto/Output/CommandGroupOutput.php b/src/Dto/Output/CommandGroupOutput.php new file mode 100644 index 0000000..617bf79 --- /dev/null +++ b/src/Dto/Output/CommandGroupOutput.php @@ -0,0 +1,38 @@ +name = $commandGroup->getName(); + + $this->commands = $commandGroup->getCommands()->map( + fn(Command $command) => new CommandOutput($command) + )->toArray(); + + $this->createdAt = $commandGroup->getCreatedAt(); + $this->createdBy = $commandGroup->getCreatedBy(); + } +} \ No newline at end of file diff --git a/src/Dto/Output/CommandOutput.php b/src/Dto/Output/CommandOutput.php new file mode 100644 index 0000000..394a5d1 --- /dev/null +++ b/src/Dto/Output/CommandOutput.php @@ -0,0 +1,45 @@ +name = $command->getName(); + $this->script = $command->getScript(); + $this->readOnly = $command->isReadOnly(); + $this->enabled = $command->isEnabled(); + $this->comments = $command->getComments(); + $this->createdAt = $command->getCreatedAt(); + $this->createdBy = $command->getCreatedBy(); + } +} \ No newline at end of file diff --git a/src/Dto/Output/CommandTaskOutput.php b/src/Dto/Output/CommandTaskOutput.php new file mode 100644 index 0000000..76c519c --- /dev/null +++ b/src/Dto/Output/CommandTaskOutput.php @@ -0,0 +1,62 @@ +commands = $commandTask->getCommands()->map( + fn(Command $command) => new CommandOutput($command) + )->toArray(); + + $this->commandGroups = $commandTask->getCommandGroups()->map( + fn(CommandGroup $commandGroup) => new CommandGroupOutput($commandGroup) + )->toArray(); + + $this->clients = $commandTask->getClients()->map( + fn(Client $client) => new ClientOutput($client) + )->toArray(); + + $this->dateTime = $commandTask->getDateTime(); + $this->notes = $commandTask->getNotes(); + $this->status = $commandTask->getStatus(); + $this->createdAt = $commandTask->getCreatedAt(); + $this->createdBy = $commandTask->getCreatedBy(); + } +} \ No newline at end of file diff --git a/src/Dto/Output/ImageOutput.php b/src/Dto/Output/ImageOutput.php index f14e16a..fe91429 100644 --- a/src/Dto/Output/ImageOutput.php +++ b/src/Dto/Output/ImageOutput.php @@ -19,7 +19,7 @@ final class ImageOutput extends AbstractOutput public ?string $comments = ''; #[Groups(['image:read'])] - public ?string $type = ''; + public ?string $type = null; #[Groups(['image:read'])] public ?string $path = ''; @@ -34,11 +34,17 @@ final class ImageOutput extends AbstractOutput public ?int $size = null; #[Groups(['image:read'])] - public ?ClientOutput $clientOutput = null; + public ?bool $remotePc = null; #[Groups(['image:read'])] public ?SoftwareProfileOutput $softwareProfile = null; + #[Groups(['image:read'])] + public \DateTime $createdAt; + + #[Groups(['image:read'])] + public ?string $createdBy = null; + public function __construct(Image $image) { parent::__construct($image); @@ -51,7 +57,9 @@ final class ImageOutput extends AbstractOutput $this->revision = $image->getRevision(); $this->info = $image->getInfo(); $this->size = $image->getSize(); - $this->clientOutput = new ClientOutput($image->getClient()); - $this->softwareProfile = new SoftwareProfileOutput($image->getSoftwareProfile()); + $this->softwareProfile = $image->getSoftwareProfile() ? new SoftwareProfileOutput($image->getSoftwareProfile()) : null; + $this->remotePc = $image->isRemotePc(); + $this->createdAt = $image->getCreatedAt(); + $this->createdBy = $image->getCreatedBy(); } } \ No newline at end of file diff --git a/src/Dto/Output/NetworkSettingsOutput.php b/src/Dto/Output/NetworkSettingsOutput.php index 9c0b66d..c85361e 100644 --- a/src/Dto/Output/NetworkSettingsOutput.php +++ b/src/Dto/Output/NetworkSettingsOutput.php @@ -9,6 +9,12 @@ use Symfony\Component\Serializer\Annotation\Groups; #[Get(shortName: 'NetworkSettings')] final class NetworkSettingsOutput extends AbstractOutput { + #[Groups(['network-settings:read', "organizational-unit:read", "client:read"])] + public ?string $nextServer = null; + + #[Groups(['network-settings:read', "organizational-unit:read", "client:read"])] + public ?string $bootFileName = null; + #[Groups(['network-settings:read', "organizational-unit:read", "client:read"])] public ?string $proxy = null; @@ -48,6 +54,9 @@ final class NetworkSettingsOutput extends AbstractOutput #[Groups(['network-settings:read', "organizational-unit:read", "client:read"])] public ?HardwareProfileOutput $hardwareProfile = null; + #[Groups(['network-settings:read', "organizational-unit:read", "client:read"])] + public ?OgLiveOutput $ogLive = null; + #[Groups(['network-settings:read', "organizational-unit:read", "client:read"])] public ?bool $validation = null; @@ -61,6 +70,8 @@ final class NetworkSettingsOutput extends AbstractOutput { parent::__construct($networkSettings); + $this->nextServer = $networkSettings->getNextServer(); + $this->bootFileName = $networkSettings->getBootFileName(); $this->proxy = $networkSettings->getProxy(); $this->dns = $networkSettings->getDns(); $this->netmask = $networkSettings->getNetmask(); @@ -81,6 +92,10 @@ final class NetworkSettingsOutput extends AbstractOutput $this->hardwareProfile = new HardwareProfileOutput($networkSettings->getHardwareProfile()); } + if ($networkSettings->getOgLive()) { + $this->ogLive = new OgLiveOutput($networkSettings->getOgLive()); + } + $this->validation = $networkSettings->getValidation(); $this->createdAt = $networkSettings->getCreatedAt(); $this->createdBy = $networkSettings->getCreatedBy(); diff --git a/src/Dto/Output/OgLiveOutput.php b/src/Dto/Output/OgLiveOutput.php new file mode 100644 index 0000000..45a9a57 --- /dev/null +++ b/src/Dto/Output/OgLiveOutput.php @@ -0,0 +1,74 @@ +name = $ogLive->getName(); + $this->synchronized = $ogLive->isSynchronized(); + $this->installed = $ogLive->isInstalled(); + $this->isDefault = $ogLive->getIsDefault(); + $this->downloadUrl = $ogLive->getDownloadUrl(); + $this->distribution = $ogLive->getDistribution(); + $this->revision = $ogLive->getRevision(); + $this->filename = $ogLive->getFilename(); + $this->checksum = $ogLive->getChecksum(); + $this->kernel = $ogLive->getKernel(); + $this->architecture = $ogLive->getArchitecture(); + $this->status = $ogLive->getStatus(); + $this->createdAt = $ogLive->getCreatedAt(); + $this->createdBy = $ogLive->getCreatedBy(); + } +} \ No newline at end of file diff --git a/src/Dto/Output/OperativeSystemOutput.php b/src/Dto/Output/OperativeSystemOutput.php index 39987c2..bac0169 100644 --- a/src/Dto/Output/OperativeSystemOutput.php +++ b/src/Dto/Output/OperativeSystemOutput.php @@ -9,13 +9,21 @@ use Symfony\Component\Serializer\Annotation\Groups; #[Get(shortName: 'OperativeSystem')] final class OperativeSystemOutput extends AbstractOutput { - #[Groups(['operative-system:read', 'partition:read'])] + #[Groups(['operative-system:read', 'partition:read', 'software-profile:read'])] public string $name; + #[Groups(['operative-system:read'])] + public \DateTime $createdAt; + + #[Groups(['operative-system:read'])] + public ?string $createdBy = null; + public function __construct(OperativeSystem $operativeSystem) { parent::__construct($operativeSystem); $this->name = $operativeSystem->getName(); + $this->createdAt = $operativeSystem->getCreatedAt(); + $this->createdBy = $operativeSystem->getCreatedBy(); } } \ No newline at end of file diff --git a/src/Dto/Output/OrganizationalUnitOutput.php b/src/Dto/Output/OrganizationalUnitOutput.php index a51a5c0..9d9ca7c 100644 --- a/src/Dto/Output/OrganizationalUnitOutput.php +++ b/src/Dto/Output/OrganizationalUnitOutput.php @@ -11,7 +11,7 @@ use Symfony\Component\Serializer\Annotation\Groups; #[Get(shortName: 'OrganizationalUnit')] final class OrganizationalUnitOutput extends AbstractOutput { - #[Groups(['organizational-unit:read', "client:read", "user:read"])] + #[Groups(['organizational-unit:read', "client:read", "user:read", 'organizational-unit:read:collection:short'])] public string $name; #[Groups(['organizational-unit:read'])] @@ -38,7 +38,7 @@ final class OrganizationalUnitOutput extends AbstractOutput #[Groups(['organizational-unit:read'])] public ?self $parent = null; - #[Groups(['organizational-unit:read'])] + #[Groups(['organizational-unit:read', 'organizational-unit:read:collection:short'])] public string $path; #[Groups(['organizational-unit:read', "client:read"])] @@ -51,6 +51,16 @@ final class OrganizationalUnitOutput extends AbstractOutput #[Groups(['organizational-unit:read'])] public array $clients = []; + #[Groups(['organizational-unit:read', "client:read"])] + #[ApiProperty(readableLink: true)] + public ?RemoteCalendarOutput $remoteCalendar = null; + + #[Groups(['organizational-unit:read'])] + public ?bool $remotePc = null; + + #[Groups(['organizational-unit:read'])] + public ?bool $available = null; + #[Groups(['organizational-unit:read'])] public \DateTime $createdAt; @@ -69,8 +79,10 @@ final class OrganizationalUnitOutput extends AbstractOutput $this->board = $organizationalUnit->isBoard(); $this->capacity = $organizationalUnit->getCapacity(); $this->type = $organizationalUnit->getType(); + $this->remotePc = $organizationalUnit->isRemotePc(); + $this->available = $organizationalUnit->getRemoteCalendar() && $organizationalUnit->getRemoteCalendar()->isAvailable(); $this->networkSettings = $organizationalUnit->getNetworkSettings() ? new NetworkSettingsOutput($organizationalUnit->getNetworkSettings()) : null; - + $this->remoteCalendar = $organizationalUnit->getRemoteCalendar() ? new RemoteCalendarOutput($organizationalUnit->getRemoteCalendar()) : null; if ($organizationalUnit->getParent()) { $this->parent = new self($organizationalUnit->getParent()); } diff --git a/src/Dto/Output/PartitionOutput.php b/src/Dto/Output/PartitionOutput.php index f6eaadf..a9bb3d7 100644 --- a/src/Dto/Output/PartitionOutput.php +++ b/src/Dto/Output/PartitionOutput.php @@ -12,25 +12,25 @@ class PartitionOutput extends AbstractOutput #[Groups(['partition:read', 'client:read'])] public ?int $diskNumber = null; - #[Groups(['partition:read'])] - public ?string $partitionNumber = null; + #[Groups(['partition:read', 'client:read'])] + public ?int $partitionNumber = null; - #[Groups(['partition:read'])] + #[Groups(['partition:read', 'client:read'])] public ?string $partitionCode = null; #[Groups(['partition:read', 'client:read'])] public ?int $size = null; - #[Groups(['partition:read'])] + #[Groups(['partition:read', 'client:read'])] public ?string $cacheContent = null; - #[Groups(['partition:read'])] + #[Groups(['partition:read', 'client:read'])] public ?string $filesystem = null; #[Groups(['partition:read', 'client:read'])] public ?OperativeSystemOutput $operativeSystem = null; - #[Groups(['partition:read'])] + #[Groups(['partition:read', 'client:read'])] public ?int $memoryUsage = null; public function __construct(Partition $partition) @@ -40,7 +40,7 @@ class PartitionOutput extends AbstractOutput $this->diskNumber = $partition->getDiskNumber(); $this->partitionNumber = $partition->getPartitionNumber(); $this->partitionCode = $partition->getPartitionCode(); - $this->size = $partition->getSize() / 100; + $this->size = $partition->getSize() / 1024 ; $this->cacheContent = $partition->getCacheContent(); $this->filesystem = $partition->getFilesystem(); if ($partition->getOperativeSystem()) { diff --git a/src/Dto/Output/PxeTemplateOutput.php b/src/Dto/Output/PxeTemplateOutput.php new file mode 100644 index 0000000..a625e91 --- /dev/null +++ b/src/Dto/Output/PxeTemplateOutput.php @@ -0,0 +1,43 @@ +name = $pxeTemplate->getName(); + $this->synchronized = $pxeTemplate->isSynchronized(); + $this->templateContent = $pxeTemplate->getTemplateContent(); + $this->clientsLength = $pxeTemplate->getClients()->count(); + $this->createdAt = $pxeTemplate->getCreatedAt(); + $this->createdBy = $pxeTemplate->getCreatedBy(); + } +} \ No newline at end of file diff --git a/src/Dto/Output/RemoteCalendarOutput.php b/src/Dto/Output/RemoteCalendarOutput.php new file mode 100644 index 0000000..b079f8a --- /dev/null +++ b/src/Dto/Output/RemoteCalendarOutput.php @@ -0,0 +1,37 @@ +name = $remoteCalendar->getName(); + + $this->remoteCalendarRules = $remoteCalendar->getRules()->map( + fn(RemoteCalendarRule $rule) => new RemoteCalendarRuleOutput($rule) + )->toArray(); + + $this->createdAt = $remoteCalendar->getCreatedAt(); + } +} \ No newline at end of file diff --git a/src/Dto/Output/RemoteCalendarRuleOutput.php b/src/Dto/Output/RemoteCalendarRuleOutput.php new file mode 100644 index 0000000..9617599 --- /dev/null +++ b/src/Dto/Output/RemoteCalendarRuleOutput.php @@ -0,0 +1,45 @@ +busyWeekDays = $remoteCalendarRule->getBusyWeekDays(); + $this->busyFromHour = $remoteCalendarRule->getBusyFromHour(); + $this->busyToHour = $remoteCalendarRule->getBusyToHour(); + $this->isRemoteAvailable = $remoteCalendarRule->isRemoteAvailable(); + $this->availableFromDate = $remoteCalendarRule->getAvailableFromDate(); + $this->availableToDate = $remoteCalendarRule->getAvailableToDate(); + $this->availableReason = $remoteCalendarRule->getAvailableReason(); + } +} \ No newline at end of file diff --git a/src/Dto/Output/SoftwareOutput.php b/src/Dto/Output/SoftwareOutput.php index 07a4fee..20da642 100644 --- a/src/Dto/Output/SoftwareOutput.php +++ b/src/Dto/Output/SoftwareOutput.php @@ -16,6 +16,9 @@ final class SoftwareOutput extends AbstractOutput #[Groups(['software:read'])] public ?string $description = ''; + #[Groups(['software:read', 'software-profile:read'])] + public ?string $type = ''; + #[Groups(['software:read'])] public \DateTime $createdAt; @@ -28,6 +31,7 @@ final class SoftwareOutput extends AbstractOutput $this->name = $software->getName(); $this->description = $software->getDescription(); + $this->type = $software->getType(); $this->createdAt = $software->getCreatedAt(); $this->createdBy = $software->getCreatedBy(); } diff --git a/src/Dto/Output/SoftwareProfileOutput.php b/src/Dto/Output/SoftwareProfileOutput.php index 5dc21e0..1b2f423 100644 --- a/src/Dto/Output/SoftwareProfileOutput.php +++ b/src/Dto/Output/SoftwareProfileOutput.php @@ -11,7 +11,7 @@ use Symfony\Component\Serializer\Annotation\Groups; #[Get(shortName: 'SoftwareProfile')] final class SoftwareProfileOutput extends AbstractOutput { - #[Groups(['software-profile:read'])] + #[Groups(['software-profile:read', 'image:read'])] public ?string $description = ''; #[Groups(['software-profile:read'])] @@ -21,6 +21,9 @@ final class SoftwareProfileOutput extends AbstractOutput public ?OrganizationalUnitOutput $organizationalUnit = null; #[Groups(['software-profile:read'])] + public ?OperativeSystemOutput $operativeSystem = null; + + #[Groups(['software-profile:item:get'])] public ?array $softwareCollection = []; #[Groups(['software-profile:read'])] @@ -35,10 +38,15 @@ final class SoftwareProfileOutput extends AbstractOutput $this->description = $softwareProfile->getDescription(); $this->comments = $softwareProfile->getComments(); + if($softwareProfile->getOrganizationalUnit()) { $this->organizationalUnit = new OrganizationalUnitOutput($softwareProfile->getOrganizationalUnit()); } + if ($softwareProfile->getOperativeSystem()) { + $this->operativeSystem = new OperativeSystemOutput($softwareProfile->getOperativeSystem()); + } + $this->softwareCollection = $softwareProfile->getSoftwareCollection()->map( fn(Software $hardware) => new SoftwareOutput($hardware) )->toArray(); diff --git a/src/Dto/Output/SubnetOutput.php b/src/Dto/Output/SubnetOutput.php new file mode 100644 index 0000000..e112d82 --- /dev/null +++ b/src/Dto/Output/SubnetOutput.php @@ -0,0 +1,64 @@ +name = $subnet->getName(); + $this->netmask = $subnet->getNetmask(); + $this->ipAddress = $subnet->getIpAddress(); + $this->nextServer = $subnet->getNextServer(); + $this->bootFileName = $subnet->getBootFileName(); + $this->synchronized = $subnet->isSynchronized(); + $this->serverId = $subnet->getServerId(); + + $this->clients = $subnet->getClients()->map( + fn(Client $client) => new ClientOutput($client) + )->toArray(); + + $this->createdAt = $subnet->getCreatedAt(); + $this->createdBy = $subnet->getCreatedBy(); + } +} \ No newline at end of file diff --git a/src/Dto/Output/TraceOutput.php b/src/Dto/Output/TraceOutput.php new file mode 100644 index 0000000..265a9b2 --- /dev/null +++ b/src/Dto/Output/TraceOutput.php @@ -0,0 +1,50 @@ +command = new CommandOutput($trace->getCommand()); + $this->client = new ClientOutput($trace->getClient()); + $this->status = $trace->getStatus(); + $this->executedAt = $trace->getExecutedAt(); + $this->output = $trace->getOutput(); + $this->finishedAt = $trace->getFinishedAt(); + $this->createdAt = $trace->getCreatedAt(); + $this->createdBy = $trace->getCreatedBy(); + } +} \ No newline at end of file diff --git a/src/Entity/Client.php b/src/Entity/Client.php index 638ee48..37546ed 100644 --- a/src/Entity/Client.php +++ b/src/Entity/Client.php @@ -57,6 +57,28 @@ class Client extends AbstractEntity #[ORM\Column(nullable: true)] private ?array $position = ['x' => 0, 'y' => 0]; + #[ORM\ManyToOne(inversedBy: 'clients')] + private ?PxeTemplate $template = null; + + #[ORM\ManyToOne(inversedBy: 'clients')] + private ?OgRepository $repository = null; + + #[ORM\ManyToOne(inversedBy: 'clients')] + #[ORM\JoinColumn( onDelete: 'SET NULL')] + private ?Subnet $subnet = null; + #[ORM\ManyToOne(inversedBy: 'clients')] + #[ORM\JoinColumn( onDelete: 'SET NULL')] + private ?OgLive $ogLive = null; + + #[ORM\Column] + private ?bool $maintenance = null; + + #[ORM\Column(length: 255, nullable: true)] + private ?string $agentJobId = null; + + #[ORM\Column(nullable: true)] + private ?bool $pxeSync = null; + public function __construct() { parent::__construct(); @@ -224,4 +246,89 @@ class Client extends AbstractEntity return $this; } + + public function getTemplate(): ?PxeTemplate + { + return $this->template; + } + + public function setTemplate(?PxeTemplate $template): static + { + $this->template = $template; + + return $this; + } + + + public function getRepository(): ?OgRepository + { + return $this->repository; + } + + public function setRepository(?OgRepository $repository): static + { + $this->repository = $repository; + + return $this; + } + + public function getSubnet(): ?Subnet + { + return $this->subnet; + } + + public function setSubnet(?Subnet $subnet): static + { + $this->subnet = $subnet; + + return $this; + } + + public function getOgLive(): ?OgLive + { + return $this->ogLive; + } + + public function setOgLive(?OgLive $ogLive): static + { + $this->ogLive = $ogLive; + + return $this; + } + + public function isMaintenance(): ?bool + { + return $this->maintenance; + } + + public function setMaintenance(bool $maintenance): static + { + $this->maintenance = $maintenance; + + return $this; + } + + public function getAgentJobId(): ?string + { + return $this->agentJobId; + } + + public function setAgentJobId(?string $agentJobId): static + { + $this->agentJobId = $agentJobId; + + return $this; + } + + public function isPxeSync(): ?bool + { + return $this->pxeSync; + } + + public function setPxeSync(?bool $pxeSync): static + { + $this->pxeSync = $pxeSync; + + return $this; + } } diff --git a/src/Entity/Command.php b/src/Entity/Command.php new file mode 100644 index 0000000..f43aa30 --- /dev/null +++ b/src/Entity/Command.php @@ -0,0 +1,134 @@ + + */ + #[ORM\ManyToMany(targetEntity: CommandGroup::class, mappedBy: 'commands')] + private Collection $commandGroups; + + /** + * @var Collection + */ + #[ORM\ManyToMany(targetEntity: CommandTask::class, mappedBy: 'commands')] + private Collection $commandTasks; + + public function __construct() + { + parent::__construct(); + $this->commandGroups = new ArrayCollection(); + $this->commandTasks = new ArrayCollection(); + } + + public function getScript(): ?string + { + return $this->script; + } + + public function setScript(string $script): static + { + $this->script = $script; + + return $this; + } + + public function getComments(): ?string + { + return $this->comments; + } + + public function setComments(?string $comments): static + { + $this->comments = $comments; + + return $this; + } + + public function isReadOnly(): ?bool + { + return $this->readOnly; + } + + public function setReadOnly(bool $readOnly): static + { + $this->readOnly = $readOnly; + + return $this; + } + + /** + * @return Collection + */ + public function getCommandGroups(): Collection + { + return $this->commandGroups; + } + + public function addCommandGroup(CommandGroup $commandGroup): static + { + if (!$this->commandGroups->contains($commandGroup)) { + $this->commandGroups->add($commandGroup); + $commandGroup->addCommand($this); + } + + return $this; + } + + public function removeCommandGroup(CommandGroup $commandGroup): static + { + if ($this->commandGroups->removeElement($commandGroup)) { + $commandGroup->removeCommand($this); + } + + return $this; + } + + /** + * @return Collection + */ + public function getCommandTasks(): Collection + { + return $this->commandTasks; + } + + public function addCommandTask(CommandTask $commandTask): static + { + if (!$this->commandTasks->contains($commandTask)) { + $this->commandTasks->add($commandTask); + $commandTask->addCommand($this); + } + + return $this; + } + + public function removeCommandTask(CommandTask $commandTask): static + { + if ($this->commandTasks->removeElement($commandTask)) { + $commandTask->removeCommand($this); + } + + return $this; + } +} diff --git a/src/Entity/CommandGroup.php b/src/Entity/CommandGroup.php new file mode 100644 index 0000000..90bec8e --- /dev/null +++ b/src/Entity/CommandGroup.php @@ -0,0 +1,96 @@ + + */ + #[ORM\ManyToMany(targetEntity: Command::class, inversedBy: 'commandGroups')] + private Collection $commands; + + /** + * @var Collection + */ + #[ORM\ManyToMany(targetEntity: CommandTask::class, mappedBy: 'commandGroups')] + private Collection $commandTasks; + + public function __construct() + { + parent::__construct(); + $this->commands = new ArrayCollection(); + $this->commandTasks = new ArrayCollection(); + } + + /** + * @return Collection + */ + public function getCommands(): Collection + { + return $this->commands; + } + + public function setCommands(array $commands): static + { + $this->commands->clear(); + + foreach ($commands as $command){ + $this->addCommand($command); + } + + return $this; + } + + public function addCommand(Command $command): static + { + if (!$this->commands->contains($command)) { + $this->commands->add($command); + } + + return $this; + } + + public function removeCommand(Command $command): static + { + $this->commands->removeElement($command); + + return $this; + } + + /** + * @return Collection + */ + public function getCommandTasks(): Collection + { + return $this->commandTasks; + } + + public function addCommandTask(CommandTask $commandTask): static + { + if (!$this->commandTasks->contains($commandTask)) { + $this->commandTasks->add($commandTask); + $commandTask->addCommandGroup($this); + } + + return $this; + } + + public function removeCommandTask(CommandTask $commandTask): static + { + if ($this->commandTasks->removeElement($commandTask)) { + $commandTask->removeCommandGroup($this); + } + + return $this; + } +} diff --git a/src/Entity/CommandTask.php b/src/Entity/CommandTask.php new file mode 100644 index 0000000..b742212 --- /dev/null +++ b/src/Entity/CommandTask.php @@ -0,0 +1,190 @@ + + */ + #[ORM\ManyToMany(targetEntity: Command::class, inversedBy: 'commandTasks')] + private Collection $commands; + + /** + * @var Collection + */ + #[ORM\ManyToMany(targetEntity: CommandGroup::class, inversedBy: 'commandTasks')] + private Collection $commandGroups; + + #[ORM\Column(type: Types::DATETIME_MUTABLE)] + private ?\DateTimeInterface $datetime = null; + + #[ORM\Column(length: 255, nullable: true)] + private ?string $notes = null; + + #[ORM\Column(length: 255)] + private ?string $status = null; + + /** + * @var Collection + */ + #[ORM\ManyToMany(targetEntity: Client::class)] + private Collection $clients; + + public function __construct() + { + parent::__construct(); + + $this->commands = new ArrayCollection(); + $this->commandGroups = new ArrayCollection(); + $this->clients = new ArrayCollection(); + } + + /** + * @return Collection + */ + public function getCommands(): Collection + { + return $this->commands; + } + + public function setCommands(array $commands): static + { + $this->commands->clear(); + + foreach ($commands as $command){ + $this->addCommand($command); + } + + return $this; + } + + public function addCommand(Command $command): static + { + if (!$this->commands->contains($command)) { + $this->commands->add($command); + } + + return $this; + } + + public function removeCommand(Command $command): static + { + $this->commands->removeElement($command); + + return $this; + } + + /** + * @return Collection + */ + public function getCommandGroups(): Collection + { + return $this->commandGroups; + } + + public function setCommandGroups(array $commandGroups): static + { + $this->commandGroups->clear(); + + foreach ($commandGroups as $commandGroup){ + $this->addCommandGroup($commandGroup); + } + + return $this; + } + + public function addCommandGroup(CommandGroup $commandGroup): static + { + if (!$this->commandGroups->contains($commandGroup)) { + $this->commandGroups->add($commandGroup); + } + + return $this; + } + + public function removeCommandGroup(CommandGroup $commandGroup): static + { + $this->commandGroups->removeElement($commandGroup); + + return $this; + } + + public function getDatetime(): ?\DateTimeInterface + { + return $this->datetime; + } + + public function setDatetime(\DateTimeInterface $datetime): static + { + $this->datetime = $datetime; + + return $this; + } + + public function getNotes(): ?string + { + return $this->notes; + } + + public function setNotes(?string $notes): static + { + $this->notes = $notes; + + return $this; + } + + public function getStatus(): ?string + { + return $this->status; + } + + public function setStatus(string $status): static + { + $this->status = $status; + + return $this; + } + + /** + * @return Collection + */ + public function getClients(): Collection + { + return $this->clients; + } + + public function addClient(Client $client): static + { + if (!$this->clients->contains($client)) { + $this->clients->add($client); + } + + return $this; + } + + public function removeClient(Client $client): static + { + $this->clients->removeElement($client); + + return $this; + } + + public function setClients(array $clients): static + { + $this->clients->clear(); + + foreach ($clients as $client){ + $this->addClient($client); + } + + return $this; + } +} diff --git a/src/Entity/Image.php b/src/Entity/Image.php index 5d41052..7dc8c05 100644 --- a/src/Entity/Image.php +++ b/src/Entity/Image.php @@ -3,6 +3,8 @@ namespace App\Entity; use App\Repository\ImageRepository; +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; #[ORM\Entity(repositoryClass: ImageRepository::class)] @@ -16,10 +18,10 @@ class Image extends AbstractEntity #[ORM\Column(length: 255, nullable: true)] private ?string $comments = null; - #[ORM\Column(length: 255)] + #[ORM\Column(length: 255, nullable: true)] private ?string $path = null; - #[ORM\Column(length: 255)] + #[ORM\Column(length: 255, nullable: true)] private ?string $type = null; #[ORM\Column(length: 255, nullable: true)] @@ -28,17 +30,28 @@ class Image extends AbstractEntity #[ORM\Column(length: 255, nullable: true)] private ?string $info = null; - #[ORM\Column] + #[ORM\Column(length: 255, nullable: true)] private ?int $size = null; #[ORM\ManyToOne] - #[ORM\JoinColumn(nullable: false)] - private ?Client $client = null; - - #[ORM\ManyToOne] - #[ORM\JoinColumn(nullable: false)] + #[ORM\JoinColumn(nullable: true)] private ?SoftwareProfile $softwareProfile = null; + /** + * @var Collection + */ + #[ORM\OneToMany(mappedBy: 'image', targetEntity: Partition::class)] + private Collection $partitions; + + #[ORM\Column] + private ?bool $remotePc = null; + + public function __construct() + { + parent::__construct(); + $this->partitions = new ArrayCollection(); + } + public function getDescription(): ?string { return $this->description; @@ -68,7 +81,7 @@ class Image extends AbstractEntity return $this->path; } - public function setPath(string $path): static + public function setPath(?string $path): static { $this->path = $path; @@ -80,7 +93,7 @@ class Image extends AbstractEntity return $this->type; } - public function setType(string $type): static + public function setType(?string $type): static { $this->type = $type; @@ -116,25 +129,13 @@ class Image extends AbstractEntity return $this->size; } - public function setSize(int $size): static + public function setSize(?int $size): static { $this->size = $size; return $this; } - public function getClient(): ?Client - { - return $this->client; - } - - public function setClient(?Client $client): static - { - $this->client = $client; - - return $this; - } - public function getSoftwareProfile(): ?SoftwareProfile { return $this->softwareProfile; @@ -146,4 +147,46 @@ class Image extends AbstractEntity return $this; } + + /** + * @return Collection + */ + public function getPartitions(): Collection + { + return $this->partitions; + } + + public function addPartition(Partition $partition): static + { + if (!$this->partitions->contains($partition)) { + $this->partitions->add($partition); + $partition->setImage($this); + } + + return $this; + } + + public function removePartition(Partition $partition): static + { + if ($this->partitions->removeElement($partition)) { + // set the owning side to null (unless already changed) + if ($partition->getImage() === $this) { + $partition->setImage(null); + } + } + + return $this; + } + + public function isRemotePc(): ?bool + { + return $this->remotePc; + } + + public function setRemotePc(bool $remotePc): static + { + $this->remotePc = $remotePc; + + return $this; + } } diff --git a/src/Entity/NetworkSettings.php b/src/Entity/NetworkSettings.php index faf7002..bbd2080 100644 --- a/src/Entity/NetworkSettings.php +++ b/src/Entity/NetworkSettings.php @@ -10,6 +10,12 @@ use Doctrine\ORM\Mapping as ORM; #[ORM\Entity(repositoryClass: NetworkSettingsRepository::class)] class NetworkSettings extends AbstractEntity { + #[ORM\Column(length: 255, nullable: true)] + private ?string $nextServer = null; + + #[ORM\Column(length: 255, nullable: true)] + private ?string $bootFileName = null; + #[ORM\Column(length: 255, nullable: true)] private ?string $proxy = null; @@ -60,15 +66,38 @@ class NetworkSettings extends AbstractEntity #[ORM\Column(nullable: true)] private ?bool $validation = null; + #[ORM\ManyToOne] + private ?OgRepository $repository = null; + + #[ORM\ManyToOne] + private ?OgLive $ogLive = null; + public function __construct() { parent::__construct(); $this->organizationalUnits = new ArrayCollection(); } - public function getId(): ?int + public function getNextServer(): ?string { - return $this->id; + return $this->nextServer; + } + + public function setNextServer(?string $nextServer): void + { + $this->nextServer = $nextServer; + } + + public function getBootFileName(): ?string + { + return $this->bootFileName; + } + + public function setBootFileName(?string $bootFileName): static + { + $this->bootFileName = $bootFileName; + + return $this; } public function getProxy(): ?string @@ -268,4 +297,28 @@ class NetworkSettings extends AbstractEntity return $this; } + + public function getRepository(): ?OgRepository + { + return $this->repository; + } + + public function setRepository(?OgRepository $repository): static + { + $this->repository = $repository; + + return $this; + } + + public function getOgLive(): ?OgLive + { + return $this->ogLive; + } + + public function setOgLive(?OgLive $ogLive): static + { + $this->ogLive = $ogLive; + + return $this; + } } diff --git a/src/Entity/OgLive.php b/src/Entity/OgLive.php new file mode 100644 index 0000000..df0f872 --- /dev/null +++ b/src/Entity/OgLive.php @@ -0,0 +1,223 @@ + + */ + #[ORM\OneToMany(mappedBy: 'ogLive', targetEntity: Client::class)] + private Collection $clients; + + #[ORM\Column(length: 255)] + private ?string $status = null; + + public function __construct() + { + parent::__construct(); + $this->clients = new ArrayCollection(); + } + + public function getDownloadUrl(): ?string + { + return $this->downloadUrl; + } + + public function setDownloadUrl(?string $downloadUrl): static + { + $this->downloadUrl = $downloadUrl; + + return $this; + } + + public function getChecksum(): ?string + { + return $this->checksum; + } + + public function setChecksum(?string $checksum): static + { + $this->checksum = $checksum; + + return $this; + } + + public function getDistribution(): ?string + { + return $this->distribution; + } + + public function setDistribution(?string $distribution): static + { + $this->distribution = $distribution; + + return $this; + } + + public function getKernel(): ?string + { + return $this->kernel; + } + + public function setKernel(?string $kernel): static + { + $this->kernel = $kernel; + + return $this; + } + + public function getArchitecture(): ?string + { + return $this->architecture; + } + + public function setArchitecture(?string $architecture): static + { + $this->architecture = $architecture; + + return $this; + } + + public function getRevision(): ?string + { + return $this->revision; + } + + public function setRevision(?string $revision): static + { + $this->revision = $revision; + + return $this; + } + + public function getDirectory(): ?string + { + return $this->directory; + } + + public function setDirectory(?string $directory): static + { + $this->directory = $directory; + + return $this; + } + + public function getFilename(): ?string + { + return $this->filename; + } + + public function setFilename(?string $filename): static + { + $this->filename = $filename; + + return $this; + } + + public function isInstalled(): ?bool + { + return $this->installed; + } + + public function setInstalled(?bool $installed): static + { + $this->installed = $installed; + + return $this; + } + + public function getIsDefault(): ?bool + { + return $this->isDefault; + } + + public function setIsDefault(?bool $isDefault): void + { + $this->isDefault = $isDefault; + } + + /** + * @return Collection + */ + public function getClients(): Collection + { + return $this->clients; + } + + public function addClient(Client $client): static + { + if (!$this->clients->contains($client)) { + $this->clients->add($client); + $client->setOgLive($this); + } + + return $this; + } + + public function removeClient(Client $client): static + { + if ($this->clients->removeElement($client)) { + // set the owning side to null (unless already changed) + if ($client->getOgLive() === $this) { + $client->setOgLive(null); + } + } + + return $this; + } + + public function getStatus(): ?string + { + return $this->status; + } + + public function setStatus(string $status): static + { + $this->status = $status; + + return $this; + } +} diff --git a/src/Entity/OgRepository.php b/src/Entity/OgRepository.php new file mode 100644 index 0000000..9aaaa74 --- /dev/null +++ b/src/Entity/OgRepository.php @@ -0,0 +1,86 @@ + + */ + #[ORM\OneToMany(mappedBy: 'repository', targetEntity: Client::class)] + private Collection $clients; + + public function __construct() + { + parent::__construct(); + $this->clients = new ArrayCollection(); + } + + public function getIpAddress(): ?string + { + return $this->ipAddress; + } + + public function setIpAddress(string $ipAddress): static + { + $this->ipAddress = $ipAddress; + + return $this; + } + + public function getDescription(): ?string + { + return $this->description; + } + + public function setDescription(?string $description): static + { + $this->description = $description; + + return $this; + } + + /** + * @return Collection + */ + public function getClients(): Collection + { + return $this->clients; + } + + public function addClient(Client $client): static + { + if (!$this->clients->contains($client)) { + $this->clients->add($client); + $client->setRepository($this); + } + + return $this; + } + + public function removeClient(Client $client): static + { + if ($this->clients->removeElement($client)) { + // set the owning side to null (unless already changed) + if ($client->getRepository() === $this) { + $client->setRepository(null); + } + } + + return $this; + } +} diff --git a/src/Entity/OrganizationalUnit.php b/src/Entity/OrganizationalUnit.php index 469a9f5..a7d2756 100644 --- a/src/Entity/OrganizationalUnit.php +++ b/src/Entity/OrganizationalUnit.php @@ -84,6 +84,25 @@ class OrganizationalUnit extends AbstractEntity #[ORM\OneToMany(mappedBy: 'organizationalUnit', targetEntity: SoftwareProfile::class)] private Collection $softwareProfiles; + #[ORM\ManyToOne(inversedBy: 'organizationalUnits')] + private ?Subnet $subnet = null; + + #[ORM\ManyToOne(targetEntity: RemoteCalendar::class, cascade: ['persist'], inversedBy: 'organizationalUnits')] + #[ORM\JoinColumn(nullable: true)] + private ?RemoteCalendar $remoteCalendar = null; + + #[ORM\Column] + private ?bool $remotePc = false; + + #[ORM\Column] + private ?bool $reserved = false; + + /** + * @var Collection + */ + #[ORM\OneToMany(mappedBy: 'organizationalUnit', targetEntity: Image::class)] + private Collection $images; + public function __construct() { parent::__construct(); @@ -91,6 +110,7 @@ class OrganizationalUnit extends AbstractEntity $this->users = new ArrayCollection(); $this->clients = new ArrayCollection(); $this->softwareProfiles = new ArrayCollection(); + $this->images = new ArrayCollection(); } public function getDescription(): ?string @@ -368,4 +388,82 @@ class OrganizationalUnit extends AbstractEntity return $this; } + + public function getSubnet(): ?Subnet + { + return $this->subnet; + } + + public function setSubnet(?Subnet $subnet): static + { + $this->subnet = $subnet; + + return $this; + } + + public function getRemoteCalendar(): ?RemoteCalendar + { + return $this->remoteCalendar; + } + + public function setRemoteCalendar(?RemoteCalendar $remoteCalendar): static + { + $this->remoteCalendar = $remoteCalendar; + + return $this; + } + + public function isRemotePc(): ?bool + { + return $this->remotePc; + } + + public function setRemotePc(bool $remotePc): static + { + $this->remotePc = $remotePc; + + return $this; + } + + public function isReserved(): ?bool + { + return $this->reserved; + } + + public function setReserved(bool $reserved): static + { + $this->reserved = $reserved; + + return $this; + } + + /** + * @return Collection + */ + public function getImages(): Collection + { + return $this->images; + } + + public function addImage(Image $image): static + { + if (!$this->images->contains($image)) { + $this->images->add($image); + $image->setOrganizationalUnit($this); + } + + return $this; + } + + public function removeImage(Image $image): static + { + if ($this->images->removeElement($image)) { + // set the owning side to null (unless already changed) + if ($image->getOrganizationalUnit() === $this) { + $image->setOrganizationalUnit(null); + } + } + + return $this; + } } diff --git a/src/Entity/Partition.php b/src/Entity/Partition.php index 7795315..554763d 100644 --- a/src/Entity/Partition.php +++ b/src/Entity/Partition.php @@ -35,8 +35,13 @@ class Partition extends AbstractEntity private ?int $memoryUsage = null; #[ORM\ManyToOne(inversedBy: 'partitions')] + #[ORM\JoinColumn(nullable: true)] private ?OperativeSystem $operativeSystem = null; + #[ORM\ManyToOne(inversedBy: 'partitions')] + #[ORM\JoinColumn(nullable: true)] + private ?Image $image = null; + public function getDiskNumber(): ?int { return $this->diskNumber; @@ -144,4 +149,16 @@ class Partition extends AbstractEntity return $this; } + + public function getImage(): ?Image + { + return $this->image; + } + + public function setImage(?Image $image): static + { + $this->image = $image; + + return $this; + } } diff --git a/src/Entity/PxeTemplate.php b/src/Entity/PxeTemplate.php new file mode 100644 index 0000000..5a3efaa --- /dev/null +++ b/src/Entity/PxeTemplate.php @@ -0,0 +1,85 @@ + + */ + #[ORM\OneToMany(mappedBy: 'template', targetEntity: Client::class)] + private Collection $clients; + + public function __construct() + { + parent::__construct(); + $this->clients = new ArrayCollection(); + } + + public function getTemplateContent(): ?string + { + return $this->templateContent; + } + + public function setTemplateContent(string $templateContent): static + { + $this->templateContent = $templateContent; + + return $this; + } + + /** + * @return Collection + */ + public function getClients(): Collection + { + return $this->clients; + } + + public function setClients(array $clients): static + { + $this->clients->clear(); + + foreach ($clients as $client){ + $this->addClient($client); + } + + return $this; + } + + public function addClient(Client $client): static + { + if (!$this->clients->contains($client)) { + $this->clients->add($client); + } + + return $this; + } + + public function removeClient(Client $client): static + { + if ($this->clients->removeElement($client)) { + if ($client->getTemplate() === $this) { + $client->setTemplate(null); + } + } + + return $this; + } +} diff --git a/src/Entity/RemoteCalendar.php b/src/Entity/RemoteCalendar.php new file mode 100644 index 0000000..66348bc --- /dev/null +++ b/src/Entity/RemoteCalendar.php @@ -0,0 +1,116 @@ + + */ + #[ORM\OneToMany(mappedBy: 'remoteCalendar', targetEntity: OrganizationalUnit::class)] + private Collection $organizationalUnits; + + /** + * @var Collection + */ + #[ORM\OneToMany(mappedBy: 'remoteCalendar', targetEntity: RemoteCalendarRule::class)] + private Collection $rules; + + public function __construct() + { + parent::__construct(); + $this->rules = new ArrayCollection(); + } + + public function getOrganizationalUnits(): Collection + { + return $this->organizationalUnits; + } + + public function setOrganizationalUnits(Collection $organizationalUnits): void + { + $this->organizationalUnits = $organizationalUnits; + } + + /** + * @return Collection + */ + public function getRules(): Collection + { + return $this->rules; + } + + public function setRules(array $rules): static + { + $this->rules->clear(); + + foreach ($rules as $rule){ + $this->addRule($rule); + } + + return $this; + } + + public function addRule(RemoteCalendarRule $rule): static + { + if (!$this->rules->contains($rule)) { + $this->rules->add($rule); + $rule->setRemoteCalendar($this); + } + + return $this; + } + + public function removeRule(RemoteCalendarRule $rule): static + { + if ($this->rules->removeElement($rule)) { + // set the owning side to null (unless already changed) + if ($rule->getRemoteCalendar() === $this) { + $rule->setRemoteCalendar(null); + } + } + + return $this; + } + + public function isAvailable(): bool + { + $now = new \DateTime(); + + foreach ($this->getRules() as $rule) { + if ($rule->isRemoteAvailable()) { + $fromDate = $rule->getAvailableFromDate(); + $toDate = $rule->getAvailableToDate(); + + if ($fromDate && $toDate && $fromDate <= $now && $now <= $toDate) { + return true; + } + } else { + $dayOfWeek = (int) $now->format('w'); + $adjustedDayOfWeek = ($dayOfWeek + 6) % 7; + + if (!in_array($adjustedDayOfWeek, $rule->getBusyWeekdays())) { + return true; + } + + $currentTime = $now->format('H:i'); + if (!($currentTime >= $rule->getBusyFromHour() && $currentTime <= $rule->getBusyToHour())) { + return true; + } + } + } + + return false; + } +} diff --git a/src/Entity/RemoteCalendarRule.php b/src/Entity/RemoteCalendarRule.php new file mode 100644 index 0000000..419fa56 --- /dev/null +++ b/src/Entity/RemoteCalendarRule.php @@ -0,0 +1,138 @@ +busyWeekdays; + } + + public function setBusyWeekdays(?array $busyWeekdays): static + { + $this->busyWeekdays = $busyWeekdays; + + return $this; + } + + public function getBusyFromHour(): string + { + return $this->busyFromHour->format('H:i'); + } + + /** + * @throws \Exception + */ + public function setBusyFromHour(?string $busyFromHour): static + { + $this->busyFromHour = new \DateTimeImmutable($busyFromHour); + + return $this; + } + + public function getBusyToHour(): string + { + return $this->busyToHour->format('H:i'); + } + + /** + * @throws \Exception + */ + public function setBusyToHour(?string $busyToHour): static + { + $this->busyToHour = new \DateTimeImmutable($busyToHour); + + return $this; + } + + public function isRemoteAvailable(): ?bool + { + return $this->isRemoteAvailable; + } + + public function setRemoteAvailable(bool $isRemoteAvailable): static + { + $this->isRemoteAvailable = $isRemoteAvailable; + + return $this; + } + + public function getAvailableFromDate(): ?\DateTimeInterface + { + return $this->availableFromDate; + } + + public function setAvailableFromDate(?\DateTimeInterface $availableFromDate): static + { + $this->availableFromDate = $availableFromDate; + + return $this; + } + + public function getAvailableToDate(): ?\DateTimeInterface + { + return $this->availableToDate; + } + + public function setAvailableToDate(?\DateTimeInterface $availableToDate): static + { + $this->availableToDate = $availableToDate; + + return $this; + } + + public function getAvailableReason(): ?string + { + return $this->availableReason; + } + + public function setAvailableReason(?string $availableReason): static + { + $this->availableReason = $availableReason; + + return $this; + } + + public function getRemoteCalendar(): ?RemoteCalendar + { + return $this->remoteCalendar; + } + + public function setRemoteCalendar(?RemoteCalendar $remoteCalendar): static + { + $this->remoteCalendar = $remoteCalendar; + + return $this; + } +} diff --git a/src/Entity/Software.php b/src/Entity/Software.php index 1723483..891b514 100644 --- a/src/Entity/Software.php +++ b/src/Entity/Software.php @@ -21,6 +21,9 @@ class Software extends AbstractEntity #[ORM\ManyToMany(targetEntity: SoftwareProfile::class, mappedBy: 'softwareCollection')] private Collection $softwareProfiles; + #[ORM\Column(length: 255)] + private ?string $type = null; + public function __construct() { parent::__construct(); @@ -66,4 +69,16 @@ class Software extends AbstractEntity return $this; } + + public function getType(): ?string + { + return $this->type; + } + + public function setType(string $type): static + { + $this->type = $type; + + return $this; + } } diff --git a/src/Entity/SoftwareProfile.php b/src/Entity/SoftwareProfile.php index bc0f968..38eac0f 100644 --- a/src/Entity/SoftwareProfile.php +++ b/src/Entity/SoftwareProfile.php @@ -26,6 +26,10 @@ class SoftwareProfile extends AbstractEntity #[ORM\ManyToMany(targetEntity: Software::class, inversedBy: 'softwareProfiles')] private Collection $softwareCollection; + #[ORM\ManyToOne] + #[ORM\JoinColumn(nullable: true)] + private ?OperativeSystem $operativeSystem = null; + public function __construct() { parent::__construct(); @@ -97,4 +101,16 @@ class SoftwareProfile extends AbstractEntity return $this; } + + public function getOperativeSystem(): ?OperativeSystem + { + return $this->operativeSystem; + } + + public function setOperativeSystem(?OperativeSystem $operativeSystem): static + { + $this->operativeSystem = $operativeSystem; + + return $this; + } } diff --git a/src/Entity/Subnet.php b/src/Entity/Subnet.php new file mode 100644 index 0000000..fe9dd2d --- /dev/null +++ b/src/Entity/Subnet.php @@ -0,0 +1,190 @@ + + */ + #[ORM\OneToMany(mappedBy: 'subnet', targetEntity: OrganizationalUnit::class)] + private Collection $organizationalUnits; + + /** + * @var Collection + */ + #[ORM\OneToMany(mappedBy: 'subnet', targetEntity: Client::class)] + private Collection $clients; + + #[ORM\Column(nullable: true)] + private ?int $serverId = null; + + public function __construct() + { + parent::__construct(); + $this->organizationalUnits = new ArrayCollection(); + $this->clients = new ArrayCollection(); + } + + public function getNetmask(): ?string + { + return $this->netmask; + } + + public function setNetmask(string $netmask): static + { + $this->netmask = $netmask; + + return $this; + } + + public function getIpAddress(): ?string + { + return $this->ipAddress; + } + + public function setIpAddress(string $ipAddress): static + { + $this->ipAddress = $ipAddress; + + return $this; + } + + public function getNextServer(): ?string + { + return $this->nextServer; + } + + public function setNextServer(string $nextServer): static + { + $this->nextServer = $nextServer; + + return $this; + } + + public function getBootFileName(): ?string + { + return $this->bootFileName; + } + + public function setBootFileName(string $bootFileName): static + { + $this->bootFileName = $bootFileName; + + return $this; + } + + /** + * @return Collection + */ + public function getOrganizationalUnits(): Collection + { + return $this->organizationalUnits; + } + + public function setOrganizationalUnits(array $organizationalUnits): static + { + $this->organizationalUnits->clear(); + + foreach ($organizationalUnits as $organizationalUnit){ + $this->addOrganizationalUnit($organizationalUnit); + } + + return $this; + } + + public function addOrganizationalUnit(OrganizationalUnit $organizationalUnit): static + { + if (!$this->organizationalUnits->contains($organizationalUnit)) { + $this->organizationalUnits->add($organizationalUnit); + $organizationalUnit->setSubnet($this); + } + + return $this; + } + + public function removeOrganizationalUnit(OrganizationalUnit $organizationalUnit): static + { + if ($this->organizationalUnits->removeElement($organizationalUnit)) { + // set the owning side to null (unless already changed) + if ($organizationalUnit->getSubnet() === $this) { + $organizationalUnit->setSubnet(null); + } + } + + return $this; + } + + /** + * @return Collection + */ + public function getClients(): Collection + { + return $this->clients; + } + + public function setClients(array $clients): static + { + $this->clients->clear(); + + foreach ($clients as $client){ + $this->addClient($client); + } + + return $this; + } + + public function addClient(Client $client): static + { + if (!$this->clients->contains($client)) { + $this->clients->add($client); + $client->setSubnet($this); + } + + return $this; + } + + public function removeClient(Client $client): static + { + if ($this->clients->removeElement($client)) { + if ($client->getSubnet() === $this) { + $client->setSubnet(null); + } + } + + return $this; + } + + public function getServerId(): ?int + { + return $this->serverId; + } + + public function setServerId(?int $serverId): static + { + $this->serverId = $serverId; + + return $this; + } +} diff --git a/src/Entity/SynchronizedTrait.php b/src/Entity/SynchronizedTrait.php new file mode 100644 index 0000000..f4da200 --- /dev/null +++ b/src/Entity/SynchronizedTrait.php @@ -0,0 +1,23 @@ +synchronized; + } + + public function setSynchronized(?bool $synchronized): self + { + $this->synchronized = $synchronized; + + return $this; + } +} diff --git a/src/Entity/Trace.php b/src/Entity/Trace.php new file mode 100644 index 0000000..1f2f318 --- /dev/null +++ b/src/Entity/Trace.php @@ -0,0 +1,103 @@ +client; + } + + public function setClient(?Client $client): static + { + $this->client = $client; + + return $this; + } + + public function getCommand(): ?Command + { + return $this->command; + } + + public function setCommand(?Command $command): static + { + $this->command = $command; + + return $this; + } + + public function getStatus(): ?string + { + return $this->status; + } + + public function setStatus(string $status): static + { + $this->status = $status; + + return $this; + } + + public function getOutput(): ?string + { + return $this->output; + } + + public function setOutput(?string $output): static + { + $this->output = $output; + + return $this; + } + + public function getExecutedAt(): ?\DateTimeInterface + { + return $this->executedAt; + } + + public function setExecutedAt(\DateTimeInterface $executedAt): static + { + $this->executedAt = $executedAt; + + return $this; + } + + public function getFinishedAt(): ?\DateTimeInterface + { + return $this->finishedAt; + } + + public function setFinishedAt(\DateTimeInterface $finishedAt): static + { + $this->finishedAt = $finishedAt; + + return $this; + } +} diff --git a/src/Factory/ClientFactory.php b/src/Factory/ClientFactory.php index 56e28da..b8f4b89 100644 --- a/src/Factory/ClientFactory.php +++ b/src/Factory/ClientFactory.php @@ -32,6 +32,7 @@ final class ClientFactory extends ModelFactory 'createdAt' => self::faker()->dateTime(), 'name' => self::faker()->text(255), 'updatedAt' => self::faker()->dateTime(), + 'maintenance' => self::faker()->boolean(), ]; } diff --git a/src/Factory/CommandFactory.php b/src/Factory/CommandFactory.php new file mode 100644 index 0000000..2e318ed --- /dev/null +++ b/src/Factory/CommandFactory.php @@ -0,0 +1,59 @@ + + */ +final class CommandFactory extends ModelFactory +{ + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#factories-as-services + * + * @todo inject services if required + */ + public function __construct() + { + parent::__construct(); + } + + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#model-factories + * + * @todo add your default values here + */ + protected function getDefaults(): array + { + return [ + 'createdAt' => self::faker()->dateTime(), + 'enabled' => self::faker()->boolean(), + 'name' => self::faker()->text(255), + 'readOnly' => self::faker()->boolean(), + 'script' => self::faker()->text(255), + 'updatedAt' => self::faker()->dateTime() + ]; + } + + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#initialization + */ + protected function initialize(): self + { + return $this + // ->afterInstantiate(function(Command $command): void {}) + ; + } + + + public static function getClass(): string + { + return Command::class; + } +} diff --git a/src/Factory/CommandGroupFactory.php b/src/Factory/CommandGroupFactory.php new file mode 100644 index 0000000..4608586 --- /dev/null +++ b/src/Factory/CommandGroupFactory.php @@ -0,0 +1,56 @@ + + */ +final class CommandGroupFactory extends ModelFactory +{ + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#factories-as-services + * + * @todo inject services if required + */ + public function __construct() + { + parent::__construct(); + } + + public static function getClass(): string + { + return CommandGroup::class; + } + + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#model-factories + * + * @todo add your default values here + */ + protected function getDefaults(): array + { + return [ + 'createdAt' => self::faker()->dateTime(), + 'enabled' => self::faker()->boolean(), + 'name' => self::faker()->text(255), + 'updatedAt' => self::faker()->dateTime() + ]; + } + + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#initialization + */ + protected function initialize(): self + { + return $this + // ->afterInstantiate(function(CommandGroup $commandGroup): void {}) + ; + } +} diff --git a/src/Factory/CommandTaskFactory.php b/src/Factory/CommandTaskFactory.php new file mode 100644 index 0000000..91d2d09 --- /dev/null +++ b/src/Factory/CommandTaskFactory.php @@ -0,0 +1,56 @@ + + */ +final class CommandTaskFactory extends ModelFactory +{ + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#factories-as-services + * + * @todo inject services if required + */ + public function __construct() + { + parent::__construct(); + } + + public static function getClass(): string + { + return CommandTask::class; + } + + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#model-factories + * + * @todo add your default values here + */ + protected function getDefaults(): array + { + return [ + 'createdAt' => self::faker()->dateTime(), + 'datetime' => self::faker()->dateTime(), + 'status' => self::faker()->text(255), + 'updatedAt' => self::faker()->dateTime() + ]; + } + + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#initialization + */ + protected function initialize(): self + { + return $this + // ->afterInstantiate(function(CommandTask $commandTask): void {}) + ; + } +} diff --git a/src/Factory/ImageFactory.php b/src/Factory/ImageFactory.php index 3a4962d..52822df 100644 --- a/src/Factory/ImageFactory.php +++ b/src/Factory/ImageFactory.php @@ -3,6 +3,7 @@ namespace App\Factory; use App\Entity\Image; +use App\Model\OrganizationalUnitTypes; use App\Repository\ImageRepository; use Zenstruck\Foundry\ModelFactory; use Zenstruck\Foundry\Persistence\PersistentProxyObjectFactory; @@ -32,14 +33,13 @@ final class ImageFactory extends ModelFactory protected function getDefaults(): array { return [ - 'client' => ClientFactory::new(), 'createdAt' => self::faker()->dateTime(), 'name' => self::faker()->text(255), 'path' => self::faker()->text(255), 'size' => self::faker()->randomNumber(), 'softwareProfile' => SoftwareProfileFactory::new(), - 'type' => self::faker()->text(255), 'updatedAt' => self::faker()->dateTime(), + 'remotePc' => self::faker()->boolean(), ]; } diff --git a/src/Factory/OgLiveFactory.php b/src/Factory/OgLiveFactory.php new file mode 100644 index 0000000..bfe05a8 --- /dev/null +++ b/src/Factory/OgLiveFactory.php @@ -0,0 +1,58 @@ + + */ +final class OgLiveFactory extends ModelFactory +{ + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#factories-as-services + * + * @todo inject services if required + */ + public function __construct() + { + parent::__construct(); + } + + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#model-factories + * + * @todo add your default values here + */ + protected function getDefaults(): array + { + return [ + 'createdAt' => self::faker()->dateTime(), + 'name' => self::faker()->text(255), + 'downloadUrl' => self::faker()->text(255), + 'status' => OgLiveStatus::ACTIVE, + 'updatedAt' => self::faker()->dateTime(), + ]; + } + + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#initialization + */ + protected function initialize(): self + { + return $this + // ->afterInstantiate(function(OgLive $ogLive): void {}) + ; + } + + protected static function getClass(): string + { + return OgLive::class; + } +} diff --git a/src/Factory/OrganizationalUnitFactory.php b/src/Factory/OrganizationalUnitFactory.php index c4be743..12bd17b 100644 --- a/src/Factory/OrganizationalUnitFactory.php +++ b/src/Factory/OrganizationalUnitFactory.php @@ -34,6 +34,7 @@ final class OrganizationalUnitFactory extends ModelFactory 'createdAt' => self::faker()->dateTime(), 'name' => self::faker()->text(255), 'updatedAt' => self::faker()->dateTime(), + 'remotePc' => self::faker()->boolean(), ]; } diff --git a/src/Factory/PartitionFactory.php b/src/Factory/PartitionFactory.php index bb3d736..d791b7c 100644 --- a/src/Factory/PartitionFactory.php +++ b/src/Factory/PartitionFactory.php @@ -43,6 +43,7 @@ final class PartitionFactory extends ModelFactory 'updatedAt' => self::faker()->dateTime(), 'operativeSystem' => OperativeSystemFactory::new(), 'client' => ClientFactory::new(), + 'image' => ImageFactory::new(), ]; } diff --git a/src/Factory/PxeTemplateFactory.php b/src/Factory/PxeTemplateFactory.php new file mode 100644 index 0000000..1ae2601 --- /dev/null +++ b/src/Factory/PxeTemplateFactory.php @@ -0,0 +1,56 @@ + + */ +final class PxeTemplateFactory extends ModelFactory +{ + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#factories-as-services + * + * @todo inject services if required + */ + public function __construct() + { + parent::__construct(); + } + + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#model-factories + * + * @todo add your default values here + */ + protected function getDefaults(): array + { + return [ + 'createdAt' => self::faker()->dateTime(), + 'name' => self::faker()->text(255), + 'templateContent' => self::faker()->text(255), + 'updatedAt' => self::faker()->dateTime() + ]; + } + + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#initialization + */ + protected function initialize(): self + { + return $this + // ->afterInstantiate(function(PxeTemplate $pxeTemplate): void {}) + ; + } + + protected static function getClass(): string + { + return PxeTemplate::class; + } +} diff --git a/src/Factory/SoftwareFactory.php b/src/Factory/SoftwareFactory.php index 7d59325..4982727 100644 --- a/src/Factory/SoftwareFactory.php +++ b/src/Factory/SoftwareFactory.php @@ -39,6 +39,7 @@ final class SoftwareFactory extends ModelFactory return [ 'createdAt' => self::faker()->dateTime(), 'name' => self::faker()->text(255), + 'type' => self::faker()->text(255), 'updatedAt' => self::faker()->dateTime(), ]; } diff --git a/src/Factory/SoftwareProfileFactory.php b/src/Factory/SoftwareProfileFactory.php index 5a05ae4..d3d370c 100644 --- a/src/Factory/SoftwareProfileFactory.php +++ b/src/Factory/SoftwareProfileFactory.php @@ -36,6 +36,7 @@ final class SoftwareProfileFactory extends ModelFactory 'createdAt' => self::faker()->dateTime(), 'description' => self::faker()->text(255), 'updatedAt' => self::faker()->dateTime(), + 'operativeSystem' => OperativeSystemFactory::createOne()->_save(), 'organizationalUnit' => OrganizationalUnitFactory::createOne(['type' => OrganizationalUnitTypes::ORGANIZATIONAL_UNIT])->_save(), ]; } diff --git a/src/Factory/SubnetFactory.php b/src/Factory/SubnetFactory.php new file mode 100644 index 0000000..e9e1c66 --- /dev/null +++ b/src/Factory/SubnetFactory.php @@ -0,0 +1,58 @@ + + */ +final class SubnetFactory extends ModelFactory +{ + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#factories-as-services + * + * @todo inject services if required + */ + public function __construct() + { + parent::__construct(); + } + + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#model-factories + * + * @todo add your default values here + */ + protected function getDefaults(): array + { + return [ + 'bootFileName' => self::faker()->text(255), + 'createdAt' => self::faker()->dateTime(), + 'ipAddress' => self::faker()->text(255), + 'netmask' => self::faker()->text(255), + 'nextServer' => self::faker()->text(255), + 'updatedAt' => self::faker()->dateTime() + ]; + } + + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#initialization + */ + protected function initialize(): self + { + return $this + // ->afterInstantiate(function(Subnet $subnet): void {}) + ; + } + + protected static function getClass(): string + { + return Subnet::class; + } +} diff --git a/src/Factory/TraceFactory.php b/src/Factory/TraceFactory.php new file mode 100644 index 0000000..14aec4b --- /dev/null +++ b/src/Factory/TraceFactory.php @@ -0,0 +1,58 @@ + + */ +final class TraceFactory extends ModelFactory +{ + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#factories-as-services + * + * @todo inject services if required + */ + public function __construct() + { + parent::__construct(); + } + + public static function getClass(): string + { + return Trace::class; + } + + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#model-factories + * + * @todo add your default values here + */ + protected function getDefaults(): array + { + return [ + 'client' => ClientFactory::new(), + 'command' => CommandFactory::new(), + 'createdAt' => self::faker()->dateTime(), + 'executedAt' => self::faker()->dateTime(), + 'status' => self::faker()->text(255), + 'updatedAt' => self::faker()->dateTime() + ]; + } + + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#initialization + */ + protected function initialize(): static + { + return $this + // ->afterInstantiate(function(Trace $trace): void {}) + ; + } +} diff --git a/src/Model/CommandTaskStatus.php b/src/Model/CommandTaskStatus.php new file mode 100644 index 0000000..9c1cab1 --- /dev/null +++ b/src/Model/CommandTaskStatus.php @@ -0,0 +1,33 @@ + 'Pendiente', + self::IN_PROGRESS => 'En progreso', + self::COMPLETED => 'Completado', + self::FAILED => 'Fallido', + ]; + + public static function getStatus(): array + { + return self::STATUS; + } + + public static function getCommandTaskStatus(string $status): ?string + { + return self::STATUS[$status] ?? null; + } + + public static function getStatusKeys(): array + { + return array_keys(self::STATUS); + } +} \ No newline at end of file diff --git a/src/Model/OgLiveStatus.php b/src/Model/OgLiveStatus.php new file mode 100644 index 0000000..2b9e744 --- /dev/null +++ b/src/Model/OgLiveStatus.php @@ -0,0 +1,36 @@ + 'Pendiente', + self::ACTIVE => 'Activo', + self::INACTIVE => 'Inactivo', + self::DELETED => 'Eliminado', + self::FAILED => 'Fallido', + ]; + + public static function getOgLiveStatuses(): array + { + return self::OG_LIVE_STATUSES; + } + + public static function getOgLiveStatus(string $ogLiveStatus): ?string + { + return self::OG_LIVE_STATUSES[$ogLiveStatus] ?? null; + } + + public static function getOgLiveStatusKeys(): array + { + return array_keys(self::OG_LIVE_STATUSES); + } +} \ No newline at end of file diff --git a/src/Model/TraceStatus.php b/src/Model/TraceStatus.php new file mode 100644 index 0000000..fc790b2 --- /dev/null +++ b/src/Model/TraceStatus.php @@ -0,0 +1,33 @@ + 'Pendiente', + self::IN_PROGRESS => 'En progreso', + self::COMPLETED => 'Completado', + self::FAILED => 'Fallido', + ]; + + public static function getStatus(): array + { + return self::STATUS; + } + + public static function getTraceStatus(string $status): ?string + { + return self::STATUS[$status] ?? null; + } + + public static function getStatusKeys(): array + { + return array_keys(self::STATUS); + } +} \ No newline at end of file diff --git a/src/OpenApi/OpenApiFactory.php b/src/OpenApi/OpenApiFactory.php index 675a6d6..2f4935e 100644 --- a/src/OpenApi/OpenApiFactory.php +++ b/src/OpenApi/OpenApiFactory.php @@ -19,8 +19,10 @@ final readonly class OpenApiFactory implements OpenApiFactoryInterface $openApi = $this->decorated->__invoke($context); $this->addRefreshToken($openApi); - $this->addSearchEndpoint($openApi); $this->addOgAgentEndpoints($openApi); + $this->addUDsEndpoints($openApi); + $this->addStatusEndpoint($openApi); + $this->addInstallOgLiveWebhookEndpoint($openApi); return $openApi; } @@ -77,55 +79,6 @@ final readonly class OpenApiFactory implements OpenApiFactoryInterface ) )); } - private function addSearchEndpoint(OpenApi $openApi): void - { - $openApi - ->getPaths() - ->addPath('/search', (new Model\PathItem())->withGet( - (new Model\Operation('getSearch')) - ->withTags(['Search']) - ->withResponses([ - Response::HTTP_OK => [ - 'description' => 'Search results', - 'content' => [ - 'application/json' => [ - 'schema' => [ - 'type' => 'object', - 'properties' => [ - 'results' => [ - 'type' => 'array', - 'items' => [ - 'type' => 'object', - 'properties' => [ - 'id' => [ - 'type' => 'integer', - 'example' => 1, - ], - 'name' => [ - 'type' => 'string', - 'example' => 'Item name', - ], - ], - ], - ], - ], - ], - ], - ], - ], - ]) - ->withSummary('Search for items') - ->withParameters([ - new Model\Parameter( - 'query', - 'query', - 'Search query parameter', - true, - false, - ), - ]) - )); - } private function addOgAgentEndpoints(OpenApi $openApi): void { @@ -323,7 +276,7 @@ final readonly class OpenApiFactory implements OpenApiFactoryInterface )); $openApi ->getPaths() - ->addPath('/opengnsys/rest/__ogAdmClient/InclusionCliente', (new Model\PathItem())->withPost( + ->addPath('/opengnsys/rest/ogAdmClient/InclusionCliente', (new Model\PathItem())->withPost( (new Model\Operation('postInclusionCliente')) ->withTags(['OgLive agent']) ->withSummary('Add client to the list of known ones') @@ -363,7 +316,40 @@ final readonly class OpenApiFactory implements OpenApiFactoryInterface 'description' => 'Success', 'content' => [ 'application/json' => [ - 'schema' => ['$ref' => '#/components/schemas/InclusionClienteRes'], + 'schema' => [ + 'type' => 'object', + 'properties' => [ + 'res' => [ + 'type' => 'integer', + 'example' => 1, + ], + 'ido' => [ + 'type' => 'integer', + 'example' => 1, + ], + 'npc' => [ + 'type' => 'string', + 'example' => 'Nombre del cliente', + ], + 'che' => [ + 'type' => 'integer', + 'example' => 1, + ], + 'exe' => [ + 'type' => 'integer', + 'example' => 42, + ], + 'ida' => [ + 'type' => 'integer', + 'example' => 1, + ], + 'idc' => [ + 'type' => 'integer', + 'example' => 1, + ], + ], + 'required' => ['res', 'ido', 'npc', 'che', 'exe', 'ida', 'idc'], + ], ], ], ], @@ -371,7 +357,7 @@ final readonly class OpenApiFactory implements OpenApiFactoryInterface )); $openApi ->getPaths() - ->addPath('/opengnsys/rest/__ogAdmClient/AutoexecCliente', (new Model\PathItem())->withPost( + ->addPath('/opengnsys/rest/ogAdmClient/AutoexecCliente', (new Model\PathItem())->withPost( (new Model\Operation('postAutoexecCliente')) ->withTags(['OgLive agent']) ->withSummary('Create and return autoexec file for client') @@ -450,7 +436,7 @@ final readonly class OpenApiFactory implements OpenApiFactoryInterface )); $openApi ->getPaths() - ->addPath('/opengnsys/rest/__ogAdmClient/enviaArchivo', (new Model\PathItem())->withPost( + ->addPath('/opengnsys/rest/ogAdmClient/enviaArchivo', (new Model\PathItem())->withPost( (new Model\Operation('postEnviaArchivo')) ->withTags(['OgLive agent']) ->withSummary('Send the contents of a file') @@ -536,7 +522,7 @@ final readonly class OpenApiFactory implements OpenApiFactoryInterface )); $openApi ->getPaths() - ->addPath('/opengnsys/rest/__ogAdmClient/ComandosPendientes', (new Model\PathItem())->withPost( + ->addPath('/opengnsys/rest/ogAdmClient/ComandosPendientes', (new Model\PathItem())->withPost( (new Model\Operation('postComandosPendientes')) ->withTags(['OgLive agent']) ->withSummary('Retrieve pending commands for a client') @@ -625,7 +611,7 @@ final readonly class OpenApiFactory implements OpenApiFactoryInterface )); $openApi ->getPaths() - ->addPath('/opengnsys/rest/__ogAdmClient/DisponibilidadComandos', (new Model\PathItem())->withPost( + ->addPath('/opengnsys/rest/ogAdmClient/DisponibilidadComandos', (new Model\PathItem())->withPost( (new Model\Operation('postDisponibilidadComandos')) ->withTags(['OgLive agent']) ->withSummary('Check command availability for a client') @@ -702,4 +688,270 @@ final readonly class OpenApiFactory implements OpenApiFactoryInterface ]) )); } + + private function addStatusEndpoint(OpenApi $openApi): void + { + $openApi + ->getPaths() + ->addPath('/og-boot/status', (new Model\PathItem())->withGet( + (new Model\Operation('getStatus')) + ->withTags(['OgBoot']) + ->withResponses([ + Response::HTTP_OK => [ + 'description' => 'Service status', + 'content' => [ + 'application/json' => [ + 'schema' => [ + 'type' => 'object', + 'properties' => [ + 'status' => [ + 'type' => 'string', + 'example' => 'ok', + ], + 'uptime' => [ + 'type' => 'integer', + 'example' => 12345, + ], + ], + ], + ], + ], + ], + Response::HTTP_SERVICE_UNAVAILABLE => [ + 'description' => 'Service unavailable', + 'content' => [ + 'application/json' => [ + 'schema' => [ + 'type' => 'object', + 'properties' => [ + 'error' => [ + 'type' => 'string', + 'example' => 'Service is down', + ], + ], + ], + ], + ], + ], + ]) + ->withSummary('Get service status') + )); + } + + private function addUDsEndpoints(OpenApi $openApi): void + { + $openApi->getPaths()->addPath('/opengnsys/rest//ous', (new Model\PathItem())->withGet( + (new Model\Operation('getOUs')) + ->withTags(['UDS']) + ->withSummary('Obtener todas las Unidades Organizacionales') + ->withResponses([ + Response::HTTP_OK => [ + 'description' => 'Lista de Unidades Organizacionales', + 'content' => [ + 'application/json' => [ + 'schema' => [ + 'type' => 'array', + 'items' => [ + 'type' => 'object', + 'properties' => [ + 'id' => [ + 'type' => 'integer', + 'example' => 1, + ], + 'name' => [ + 'type' => 'string', + 'example' => 'Nombre de la Unidad Organizacional', + ], + 'description' => [ + 'type' => 'string', + 'example' => 'Descripción de la Unidad Organizacional', + ] + ] + ] + ] + ] + ] + ] + ]) + )); + + $openApi->getPaths()->addPath('/opengnsys/rest/ous/{centerId}/labs', (new Model\PathItem())->withGet( + (new Model\Operation('getClassrooms')) + ->withTags(['UDS']) + ->withSummary('Obtener los laboratorios de una Unidad Organizacional específica') + ->withParameters([ + new Model\Parameter( + 'centerId', + 'path', + 'El ID de la Unidad Organizacional', + true, + false, + ) + ]) + ->withResponses([ + Response::HTTP_OK => [ + 'description' => 'Lista de Laboratorios', + 'content' => [ + 'application/json' => [ + 'schema' => [ + 'type' => 'array', + 'items' => [ + 'type' => 'object', + 'properties' => [ + 'id' => [ + 'type' => 'integer', + 'example' => 1, + ], + 'name' => [ + 'type' => 'string', + 'example' => 'Nombre del Laboratorio', + ], + 'description' => [ + 'type' => 'string', + 'example' => 'Descripción del Laboratorio', + ] + ] + ] + ] + ] + ] + ] + ]) + )); + + $openApi->getPaths()->addPath('/opengnsys/rest/ous/{centerId}/images', (new Model\PathItem())->withGet( + (new Model\Operation('getImages')) + ->withTags(['UDS']) + ->withSummary('Obtener las imágenes de una Unidad Organizacional específica') + ->withParameters([ + new Model\Parameter( + 'centerId', + 'path', + 'El ID de la Unidad Organizacional', + true, + false, + ) + ]) + ->withResponses([ + Response::HTTP_OK => [ + 'description' => 'Lista de Imagenes', + 'content' => [ + 'application/json' => [ + 'schema' => [ + 'type' => 'array', + 'items' => [ + 'type' => 'object', + 'properties' => [ + 'id' => [ + 'type' => 'integer', + 'example' => 1, + ], + 'name' => [ + 'type' => 'string', + 'example' => 'Nombre del Laboratorio', + ], + 'description' => [ + 'type' => 'string', + 'example' => 'Descripción del Laboratorio', + ] + ] + ] + ] + ] + ] + ] + ]) + )); + + $openApi->getPaths()->addPath('/opengnsys/rest//info', (new Model\PathItem())->withGet( + (new Model\Operation('getOpengnsysInfo')) + ->withTags(['UDS']) + ->withSummary('Obtener información general de OpenGnsys') + ->withResponses([ + Response::HTTP_OK => [ + 'description' => 'Información general de OpenGnsys', + 'content' => [ + 'application/json' => [ + 'schema' => [ + 'type' => 'object', + 'properties' => [ + 'project' => [ + 'type' => 'string', + 'example' => 'OpenGnsys', + ], + 'version' => [ + 'type' => 'string', + 'example' => '1.1.1d', + ], + ], + ], + ], + ], + ] + ]) + )); + } + + private function addInstallOgLiveWebhookEndpoint(OpenApi $openApi): void + { + $openApi + ->getPaths() + ->addPath('/og-lives/install/webhook', (new Model\PathItem())->withPost( + (new Model\Operation('postInstallOgLiveWebhook')) + ->withTags(['OgLive']) + ->withResponses([ + Response::HTTP_OK => [ + 'description' => 'Webhook installation successful', + 'content' => [ + 'application/json' => [ + 'schema' => [ + 'type' => 'object', + 'properties' => [ + 'message' => [ + 'type' => 'string', + 'example' => 'Webhook installed successfully', + ], + ], + ], + ], + ], + ], + Response::HTTP_BAD_REQUEST => [ + 'description' => 'Invalid request data', + 'content' => [ + 'application/json' => [ + 'schema' => [ + 'type' => 'object', + 'properties' => [ + 'error' => [ + 'type' => 'string', + 'example' => 'Invalid input data', + ], + ], + ], + ], + ], + ], + ]) + ->withSummary('Install a webhook for OgLive') + ->withRequestBody( + (new Model\RequestBody()) + ->withDescription('Data required for installing the webhook') + ->withContent(new \ArrayObject([ + 'application/json' => new Model\MediaType(new \ArrayObject([ + 'type' => 'object', + 'properties' => [ + 'da' => [ + 'type' => 'string', + 'description' => 'The URL to set for the webhook', + 'example' => 'https://example.com/webhook', + ], + ], + 'required' => ['url'], + ])) + ])) + ->withRequired(true) + ) + )); + } } \ No newline at end of file diff --git a/src/Repository/CommandGroupRepository.php b/src/Repository/CommandGroupRepository.php new file mode 100644 index 0000000..f8cf8b2 --- /dev/null +++ b/src/Repository/CommandGroupRepository.php @@ -0,0 +1,18 @@ + + */ +class CommandGroupRepository extends AbstractRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, CommandGroup::class); + } +} diff --git a/src/Repository/CommandRepository.php b/src/Repository/CommandRepository.php new file mode 100644 index 0000000..544b708 --- /dev/null +++ b/src/Repository/CommandRepository.php @@ -0,0 +1,18 @@ + + */ +class CommandRepository extends AbstractRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Command::class); + } +} diff --git a/src/Repository/CommandTaskRepository.php b/src/Repository/CommandTaskRepository.php new file mode 100644 index 0000000..fc859f8 --- /dev/null +++ b/src/Repository/CommandTaskRepository.php @@ -0,0 +1,18 @@ + + */ +class CommandTaskRepository extends AbstractRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, CommandTask::class); + } +} diff --git a/src/Repository/OgLiveRepository.php b/src/Repository/OgLiveRepository.php new file mode 100644 index 0000000..63e83cc --- /dev/null +++ b/src/Repository/OgLiveRepository.php @@ -0,0 +1,18 @@ + + */ +class OgLiveRepository extends AbstractRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, OgLive::class); + } +} diff --git a/src/Repository/OgRepositoryRepository.php b/src/Repository/OgRepositoryRepository.php new file mode 100644 index 0000000..0db2b01 --- /dev/null +++ b/src/Repository/OgRepositoryRepository.php @@ -0,0 +1,18 @@ + + */ +class OgRepositoryRepository extends AbstractRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, self::class); + } +} diff --git a/src/Repository/PxeTemplateRepository.php b/src/Repository/PxeTemplateRepository.php new file mode 100644 index 0000000..fb569b8 --- /dev/null +++ b/src/Repository/PxeTemplateRepository.php @@ -0,0 +1,18 @@ + + */ +class PxeTemplateRepository extends AbstractRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, PxeTemplate::class); + } +} diff --git a/src/Repository/RemoteCalendarRepository.php b/src/Repository/RemoteCalendarRepository.php new file mode 100644 index 0000000..2401d29 --- /dev/null +++ b/src/Repository/RemoteCalendarRepository.php @@ -0,0 +1,18 @@ + + */ +class RemoteCalendarRepository extends AbstractRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, RemoteCalendar::class); + } +} diff --git a/src/Repository/RemoteCalendarRuleRepository.php b/src/Repository/RemoteCalendarRuleRepository.php new file mode 100644 index 0000000..1238954 --- /dev/null +++ b/src/Repository/RemoteCalendarRuleRepository.php @@ -0,0 +1,18 @@ + + */ +class RemoteCalendarRuleRepository extends AbstractRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, RemoteCalendarRule::class); + } +} diff --git a/src/Repository/SubnetRepository.php b/src/Repository/SubnetRepository.php new file mode 100644 index 0000000..988dd99 --- /dev/null +++ b/src/Repository/SubnetRepository.php @@ -0,0 +1,18 @@ + + */ +class SubnetRepository extends AbstractRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Subnet::class); + } +} diff --git a/src/Repository/TraceRepository.php b/src/Repository/TraceRepository.php new file mode 100644 index 0000000..102fa7b --- /dev/null +++ b/src/Repository/TraceRepository.php @@ -0,0 +1,19 @@ + + */ +class TraceRepository extends AbstractRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Trace::class); + } + +} diff --git a/src/Service/CreateTraceService.php b/src/Service/CreateTraceService.php new file mode 100644 index 0000000..cb747d1 --- /dev/null +++ b/src/Service/CreateTraceService.php @@ -0,0 +1,46 @@ +getCommands() as $command) { + foreach ($commandTask->getClients() as $client) { + $trace = new Trace(); + $trace->setClient($client); + $trace->setCommand($command); + $trace->setStatus(TraceStatus::PENDING); + $trace->setExecutedAt($commandTask->getDatetime()); + $this->entityManager->persist($trace); + } + } + + foreach ($commandTask->getCommandGroups() as $commandGroup) { + foreach ($commandTask->getCommands() as $command) { + foreach ($commandTask->getClients() as $client) { + $trace = new Trace(); + $trace->setClient($client); + $trace->setCommand($command); + $trace->setStatus(TraceStatus::PENDING); + $trace->setExecutedAt($commandTask->getDatetime()); + $this->entityManager->persist($trace); + } + } + } + + $this->entityManager->flush(); + } +} \ No newline at end of file diff --git a/src/Service/OgBoot/StatusService.php b/src/Service/OgBoot/StatusService.php new file mode 100644 index 0000000..c935e28 --- /dev/null +++ b/src/Service/OgBoot/StatusService.php @@ -0,0 +1,48 @@ + false, // Ignorar la verificación del certificado SSL + 'verify_host' => false, // Ignorar la verificación del nombre del host + ]); + + try { + $response = $httpClient->request('GET', $this->ogBootApiUrl.'/ogboot/v1/status', [ + 'headers' => [ + 'accept' => 'application/json', + ], + ]); + } catch (TransportExceptionInterface $e) { + return new JsonResponse( data: 'An error occurred', status: Response::HTTP_INTERNAL_SERVER_ERROR); + } + + return json_decode($response->getContent(), true); + } +} \ No newline at end of file diff --git a/src/Service/OgDhcp/StatusService.php b/src/Service/OgDhcp/StatusService.php new file mode 100644 index 0000000..6e434bf --- /dev/null +++ b/src/Service/OgDhcp/StatusService.php @@ -0,0 +1,46 @@ + false, + 'verify_host' => false, + ]); + + try { + $response = $httpClient->request('GET', $this->ogDhcpApiUrl.'/ogdhcp/v1/status', [ + 'headers' => [ + 'accept' => 'application/json', + ], + ]); + } catch (TransportExceptionInterface $e) { + return new JsonResponse( data: 'An error occurred', status: Response::HTTP_INTERNAL_SERVER_ERROR); + } + + return json_decode($response->getContent(), true); + } +} \ No newline at end of file diff --git a/src/Service/UDS/UDSClient.php b/src/Service/UDS/UDSClient.php new file mode 100644 index 0000000..3d3f161 --- /dev/null +++ b/src/Service/UDS/UDSClient.php @@ -0,0 +1,170 @@ +login(); + $servicePools = $this->getServicePools(); + + foreach ($servicePools as $servicePool) { + $servicePoolInfo = $this->getServicePool($servicePool['provider_id'], $servicePool['service_id']); + + if (!$servicePoolInfo) { + continue; + } + + $classroom = $servicePoolInfo['lab']; + $maxAvailableSeats = $this->getMaxAvailableSeats($classroom); + $servicePool['max_srvs'] = $maxAvailableSeats; + $servicePool['osmanager_id'] = null; + + $response = $this->httpClient->request('PUT', $this->udsAPIurl . 'servicespools/' . $servicePool['id'], [ + 'verify_host' => false, + 'headers' => [ + 'X-Auth-Token' => $this->token, + 'Content-Type' => 'application/json', + 'Scrambler' => $this->scrambler + ], + 'body' => json_encode($servicePool) + ]); + + return json_decode($response->getContent(false), true); + } + } + + /** + * @throws TransportExceptionInterface + */ + public function login(): void + { + try { + $response = $this->httpClient->request('POST', $this->udsAPIurl . 'auth/login', [ + 'verify_host' => false, + 'headers' => [ + 'Content-Type' => 'application/json' + ], + 'json' => [ + 'auth' => $this->udsAuthLogin, + 'username' => $this->udsAuthUsername, + 'password' => $this->udsAuthPassword + ] + ]); + + $data = json_decode($response->getContent(false), true); + + $this->token = $data['token']; + $this->scrambler = $data['scrambler']; + + } catch (TransportExceptionInterface $e) { + throw new TransportException('Error while logging in to UDS'); + } catch (ClientExceptionInterface|ServerExceptionInterface|RedirectionExceptionInterface $e) { + } + } + + /** + * @throws TransportExceptionInterface + */ + public function getServicePools(): array + { + try { + $response = $this->httpClient->request('GET', $this->udsAPIurl . '/servicespools/overview', [ + 'verify_host' => false, + 'headers' => [ + 'X-Auth-Token' => $this->token, + 'Content-Type' => 'application/json', + 'Scrambler' => $this->scrambler + ] + ]); + return json_decode($response->getContent(), true); + } catch (TransportExceptionInterface $e) { + throw new TransportException('Error while fetching service pools'); + } catch (ClientExceptionInterface|ServerExceptionInterface|RedirectionExceptionInterface $e) { + } + } + + /** + * @throws TransportExceptionInterface + */ + public function getServicePool(string $providerId, string $serviceId): ?array + { + try { + $response = $this->httpClient->request('GET', $this->udsAPIurl . 'providers/' . $providerId .'/services/'. $serviceId, [ + 'verify_host' => false, + 'headers' => [ + 'X-Auth-Token' => $this->token, + 'Content-Type' => 'application/json', + 'Scrambler' => $this->scrambler + ] + ]); + + return json_decode($response->getContent(), true); + } catch (TransportExceptionInterface $e) { + throw new TransportException('Error while fetching service pool'); + } catch (ClientExceptionInterface|ServerExceptionInterface|RedirectionExceptionInterface $e) { + } + + return null; + } + + public function getMaxAvailableSeats(int $organizationalUnitId): int + { + $organizationalUnit = $this->entityManager->getRepository(OrganizationalUnit::class)->findOneBy(['id' => $organizationalUnitId]); + + if (!$organizationalUnit) { + return 0; + } + + $remoteCalendar = $organizationalUnit->getRemoteCalendar(); + if (!$remoteCalendar || !$remoteCalendar->isAvailable()) { + return 0; + } + + $totalAvailableClients = 0; + + foreach ($organizationalUnit->getClients() as $client) { + if ($client->isMaintenance()) { + continue; + } + $status = $client->getStatus(); + + $clientAvailable = in_array($status, ['active', 'windows', 'linux']); + $totalAvailableClients += $clientAvailable ? 1 : 0; + } + + return $totalAvailableClients; + } +} \ No newline at end of file diff --git a/src/Service/Utils/GetIpAddressAndNetmaskFromCIDRService.php b/src/Service/Utils/GetIpAddressAndNetmaskFromCIDRService.php new file mode 100644 index 0000000..67e1c37 --- /dev/null +++ b/src/Service/Utils/GetIpAddressAndNetmaskFromCIDRService.php @@ -0,0 +1,18 @@ + $ip, + 'mask' => $mask + ]; + } +} \ No newline at end of file diff --git a/src/State/Processor/CommandGroupProcessor.php b/src/State/Processor/CommandGroupProcessor.php new file mode 100644 index 0000000..65ffacd --- /dev/null +++ b/src/State/Processor/CommandGroupProcessor.php @@ -0,0 +1,69 @@ +processCreateOrUpdate($data, $operation, $uriVariables, $context); + case $operation instanceof Delete: + return $this->processDelete($data, $operation, $uriVariables, $context); + } + } + + /** + * @throws \Exception + */ + private function processCreateOrUpdate($data, Operation $operation, array $uriVariables = [], array $context = []): CommandGroupOutput + { + if (!($data instanceof CommandGroupInput)) { + throw new \Exception(sprintf('data is not instance of %s', CommandGroupInput::class)); + } + + $entity = null; + if (isset($uriVariables['uuid'])) { + $entity = $this->commandGroupRepository->findOneByUuid($uriVariables['uuid']); + } + + $command = $data->createOrUpdateEntity($entity); + $this->validator->validate($command); + $this->commandGroupRepository->save($command); + + return new CommandGroupOutput($command); + } + + private function processDelete($data, Operation $operation, array $uriVariables = [], array $context = []): null + { + $user = $this->commandGroupRepository->findOneByUuid($uriVariables['uuid']); + $this->commandGroupRepository->delete($user); + + return null; + } +} diff --git a/src/State/Processor/CommandProcessor.php b/src/State/Processor/CommandProcessor.php new file mode 100644 index 0000000..fffae4f --- /dev/null +++ b/src/State/Processor/CommandProcessor.php @@ -0,0 +1,68 @@ +processCreateOrUpdate($data, $operation, $uriVariables, $context); + case $operation instanceof Delete: + return $this->processDelete($data, $operation, $uriVariables, $context); + } + } + + /** + * @throws \Exception + */ + private function processCreateOrUpdate($data, Operation $operation, array $uriVariables = [], array $context = []): CommandOutput + { + if (!($data instanceof CommandInput)) { + throw new \Exception(sprintf('data is not instance of %s', CommandInput::class)); + } + + $entity = null; + if (isset($uriVariables['uuid'])) { + $entity = $this->commandRepository->findOneByUuid($uriVariables['uuid']); + } + + $command = $data->createOrUpdateEntity($entity); + $this->validator->validate($command); + $this->commandRepository->save($command); + + return new CommandOutput($command); + } + + private function processDelete($data, Operation $operation, array $uriVariables = [], array $context = []): null + { + $user = $this->commandRepository->findOneByUuid($uriVariables['uuid']); + $this->commandRepository->delete($user); + + return null; + } +} diff --git a/src/State/Processor/CommandTaskProcessor.php b/src/State/Processor/CommandTaskProcessor.php new file mode 100644 index 0000000..fe39109 --- /dev/null +++ b/src/State/Processor/CommandTaskProcessor.php @@ -0,0 +1,71 @@ +processCreateOrUpdate($data, $operation, $uriVariables, $context); + case $operation instanceof Delete: + return $this->processDelete($data, $operation, $uriVariables, $context); + } + } + + /** + * @throws \Exception + */ + private function processCreateOrUpdate($data, Operation $operation, array $uriVariables = [], array $context = []): CommandTaskOutput + { + if (!($data instanceof CommandTaskInput)) { + throw new \Exception(sprintf('data is not instance of %s', CommandTaskInput::class)); + } + + $entity = null; + if (isset($uriVariables['uuid'])) { + $entity = $this->commandTaskRepository->findOneByUuid($uriVariables['uuid']); + } + + $task = $data->createOrUpdateEntity($entity); + $this->validator->validate($task); + $this->commandTaskRepository->save($task); + $this->createTraceService->__invoke($task); + + return new CommandTaskOutput($task); + } + + private function processDelete($data, Operation $operation, array $uriVariables = [], array $context = []): null + { + $user = $this->commandTaskRepository->findOneByUuid($uriVariables['uuid']); + $this->commandTaskRepository->delete($user); + + return null; + } +} diff --git a/src/State/Processor/OgLiveProcessor.php b/src/State/Processor/OgLiveProcessor.php new file mode 100644 index 0000000..0cc9bc3 --- /dev/null +++ b/src/State/Processor/OgLiveProcessor.php @@ -0,0 +1,68 @@ +processCreateOrUpdate($data, $operation, $uriVariables, $context); + case $operation instanceof Delete: + return $this->processDelete($data, $operation, $uriVariables, $context); + } + } + + /** + * @throws \Exception + */ + private function processCreateOrUpdate($data, Operation $operation, array $uriVariables = [], array $context = []): OgLiveOutput + { + if (!($data instanceof OgLiveInput)) { + throw new \Exception(sprintf('data is not instance of %s', OgLiveInput::class)); + } + + $entity = null; + if (isset($uriVariables['uuid'])) { + $entity = $this->ogLiveRepository->findOneByUuid($uriVariables['uuid']); + } + + $ogLive = $data->createOrUpdateEntity($entity); + $this->validator->validate($ogLive); + $this->ogLiveRepository->save($ogLive); + + return new OgLiveOutput($ogLive); + } + + private function processDelete($data, Operation $operation, array $uriVariables = [], array $context = []): null + { + $ogLive = $this->ogLiveRepository->findOneByUuid($uriVariables['uuid']); + $this->ogLiveRepository->delete($ogLive); + + return null; + } +} diff --git a/src/State/Processor/OrganizationalUnitProcessor.php b/src/State/Processor/OrganizationalUnitProcessor.php index 41d3974..e4d2244 100644 --- a/src/State/Processor/OrganizationalUnitProcessor.php +++ b/src/State/Processor/OrganizationalUnitProcessor.php @@ -11,22 +11,18 @@ use ApiPlatform\State\ProcessorInterface; use ApiPlatform\Validator\ValidatorInterface; use App\Dto\Input\ChangeOrganizationalUnitInput; use App\Dto\Input\MenuInput; -use App\Dto\Input\OrganizationalUnitClassroomGroupInput; -use App\Dto\Input\OrganizationalUnitClassroomInput; -use App\Dto\Input\OrganizationalUnitClientGroupInput; use App\Dto\Input\OrganizationalUnitInput; -use App\Dto\Input\OrganizationalUnitRootInput; use App\Dto\Output\OrganizationalUnitOutput; use App\Repository\OrganizationalUnitRepository; use App\Service\ChangeClientNetworkSettingsService; use Doctrine\ORM\EntityManagerInterface; -class OrganizationalUnitProcessor implements ProcessorInterface +readonly class OrganizationalUnitProcessor implements ProcessorInterface { public function __construct( - private readonly OrganizationalUnitRepository $organizationalUnitRepository, - private readonly ValidatorInterface $validator, - private readonly ChangeClientNetworkSettingsService $changeClientNetworkSettingsService, + private OrganizationalUnitRepository $organizationalUnitRepository, + private ValidatorInterface $validator, + private ChangeClientNetworkSettingsService $changeClientNetworkSettingsService, ) { } diff --git a/src/State/Processor/PxeTemplateProcessor.php b/src/State/Processor/PxeTemplateProcessor.php new file mode 100644 index 0000000..637dc30 --- /dev/null +++ b/src/State/Processor/PxeTemplateProcessor.php @@ -0,0 +1,68 @@ +processCreateOrUpdate($data, $operation, $uriVariables, $context); + case $operation instanceof Delete: + return $this->processDelete($data, $operation, $uriVariables, $context); + } + } + + /** + * @throws \Exception + */ + private function processCreateOrUpdate($data, Operation $operation, array $uriVariables = [], array $context = []): PxeTemplateOutput + { + if (!($data instanceof PxeTemplateInput)) { + throw new \Exception(sprintf('data is not instance of %s', PxeTemplateInput::class)); + } + + $entity = null; + if (isset($uriVariables['uuid'])) { + $entity = $this->pxeTemplateRepository->findOneByUuid($uriVariables['uuid']); + } + + $pxeTemplate = $data->createOrUpdateEntity($entity); + $this->validator->validate($pxeTemplate); + $this->pxeTemplateRepository->save($pxeTemplate); + + return new PxeTemplateOutput($pxeTemplate); + } + + private function processDelete($data, Operation $operation, array $uriVariables = [], array $context = []): null + { + $pxeTemplate = $this->pxeTemplateRepository->findOneByUuid($uriVariables['uuid']); + $this->pxeTemplateRepository->delete($pxeTemplate); + + return null; + } +} diff --git a/src/State/Processor/RemoteCalendarProcessor.php b/src/State/Processor/RemoteCalendarProcessor.php new file mode 100644 index 0000000..f5ab68f --- /dev/null +++ b/src/State/Processor/RemoteCalendarProcessor.php @@ -0,0 +1,68 @@ +processCreateOrUpdate($data, $operation, $uriVariables, $context); + case $operation instanceof Delete: + return $this->processDelete($data, $operation, $uriVariables, $context); + } + } + + /** + * @throws \Exception + */ + private function processCreateOrUpdate($data, Operation $operation, array $uriVariables = [], array $context = []): RemoteCalendarOutput + { + if (!($data instanceof RemoteCalendarInput)) { + throw new \Exception(sprintf('data is not instance of %s', RemoteCalendarInput::class)); + } + + $entity = null; + if (isset($uriVariables['uuid'])) { + $entity = $this->remoteCalendarRepository->findOneByUuid($uriVariables['uuid']); + } + + $partition = $data->createOrUpdateEntity($entity); + $this->validator->validate($partition); + $this->remoteCalendarRepository->save($partition); + + return new RemoteCalendarOutput($partition); + } + + private function processDelete($data, Operation $operation, array $uriVariables = [], array $context = []): null + { + $user = $this->remoteCalendarRepository->findOneByUuid($uriVariables['uuid']); + $this->remoteCalendarRepository->delete($user); + + return null; + } +} diff --git a/src/State/Processor/RemoteCalendarRuleProcessor.php b/src/State/Processor/RemoteCalendarRuleProcessor.php new file mode 100644 index 0000000..631c755 --- /dev/null +++ b/src/State/Processor/RemoteCalendarRuleProcessor.php @@ -0,0 +1,68 @@ +processCreateOrUpdate($data, $operation, $uriVariables, $context); + case $operation instanceof Delete: + return $this->processDelete($data, $operation, $uriVariables, $context); + } + } + + /** + * @throws \Exception + */ + private function processCreateOrUpdate($data, Operation $operation, array $uriVariables = [], array $context = []): RemoteCalendarRuleOutput + { + if (!($data instanceof RemoteCalendarRuleInput)) { + throw new \Exception(sprintf('data is not instance of %s', RemoteCalendarRuleInput::class)); + } + + $entity = null; + if (isset($uriVariables['uuid'])) { + $entity = $this->remoteCalendarRuleRepository->findOneByUuid($uriVariables['uuid']); + } + + $partition = $data->createOrUpdateEntity($entity); + $this->validator->validate($partition); + $this->remoteCalendarRuleRepository->save($partition); + + return new RemoteCalendarRuleOutput($partition); + } + + private function processDelete($data, Operation $operation, array $uriVariables = [], array $context = []): null + { + $user = $this->remoteCalendarRuleRepository->findOneByUuid($uriVariables['uuid']); + $this->remoteCalendarRuleRepository->delete($user); + + return null; + } +} diff --git a/src/State/Processor/SubnetProcessor.php b/src/State/Processor/SubnetProcessor.php new file mode 100644 index 0000000..0fef5cf --- /dev/null +++ b/src/State/Processor/SubnetProcessor.php @@ -0,0 +1,69 @@ +processCreateOrUpdate($data, $operation, $uriVariables, $context); + case $operation instanceof Delete: + return $this->processDelete($data, $operation, $uriVariables, $context); + } + } + + /** + * @throws \Exception + */ + private function processCreateOrUpdate($data, Operation $operation, array $uriVariables = [], array $context = []): SubnetOutput + { + if (!($data instanceof SubnetInput)) { + throw new \Exception(sprintf('data is not instance of %s', SubnetInput::class)); + } + + $entity = null; + if (isset($uriVariables['uuid'])) { + $entity = $this->subnetRepository->findOneByUuid($uriVariables['uuid']); + } + + $subnet = $data->createOrUpdateEntity($entity); + $this->validator->validate($subnet); + $this->subnetRepository->save($subnet); + + return new SubnetOutput($subnet); + } + + private function processDelete($data, Operation $operation, array $uriVariables = [], array $context = []): null + { + $bootFile = $this->subnetRepository->findOneByUuid($uriVariables['uuid']); + $this->subnetRepository->delete($bootFile); + + return null; + } +} diff --git a/src/State/Provider/ClientProvider.php b/src/State/Provider/ClientProvider.php index d398a0f..c5dd7d0 100644 --- a/src/State/Provider/ClientProvider.php +++ b/src/State/Provider/ClientProvider.php @@ -13,11 +13,11 @@ use App\Dto\Input\ClientInput; use App\Dto\Output\ClientOutput; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; -class ClientProvider implements ProviderInterface +readonly class ClientProvider implements ProviderInterface { public function __construct( - private readonly ProviderInterface $collectionProvider, - private readonly ProviderInterface $itemProvider + private ProviderInterface $collectionProvider, + private ProviderInterface $itemProvider ) { } diff --git a/src/State/Provider/CommandGroupProvider.php b/src/State/Provider/CommandGroupProvider.php new file mode 100644 index 0000000..767d0cc --- /dev/null +++ b/src/State/Provider/CommandGroupProvider.php @@ -0,0 +1,72 @@ +provideCollection($operation, $uriVariables, $context); + case $operation instanceof Patch: + case $operation instanceof Put: + return $this->provideInput($operation, $uriVariables, $context); + case $operation instanceof Get: + return $this->provideItem($operation, $uriVariables, $context); + } + } + + private function provideCollection(Operation $operation, array $uriVariables = [], array $context = []): object|array|null + { + $paginator = $this->collectionProvider->provide($operation, $uriVariables, $context); + + $items = new \ArrayObject(); + foreach ($paginator->getIterator() as $item){ + $items[] = new CommandGroupOutput($item); + } + + return new TraversablePaginator($items, $paginator->getCurrentPage(), $paginator->getItemsPerPage(), $paginator->getTotalItems()); + } + + public function provideItem(Operation $operation, array $uriVariables = [], array $context = []): object|array|null + { + $item = $this->itemProvider->provide($operation, $uriVariables, $context); + + if (!$item) { + throw new NotFoundHttpException('Command group not found'); + } + + return new CommandGroupOutput($item); + } + + public function provideInput(Operation $operation, array $uriVariables = [], array $context = []): object|array|null + { + if (isset($uriVariables['uuid'])) { + $item = $this->itemProvider->provide($operation, $uriVariables, $context); + + return $item !== null ? new CommandGroupInput($item) : null; + } + + return new CommandGroupInput(); + } +} diff --git a/src/State/Provider/CommandProvider.php b/src/State/Provider/CommandProvider.php new file mode 100644 index 0000000..b5854b1 --- /dev/null +++ b/src/State/Provider/CommandProvider.php @@ -0,0 +1,71 @@ +provideCollection($operation, $uriVariables, $context); + case $operation instanceof Patch: + case $operation instanceof Put: + return $this->provideInput($operation, $uriVariables, $context); + case $operation instanceof Get: + return $this->provideItem($operation, $uriVariables, $context); + } + } + + private function provideCollection(Operation $operation, array $uriVariables = [], array $context = []): object + { + $paginator = $this->collectionProvider->provide($operation, $uriVariables, $context); + + $items = new \ArrayObject(); + foreach ($paginator->getIterator() as $item){ + $items[] = new CommandOutput($item); + } + + return new TraversablePaginator($items, $paginator->getCurrentPage(), $paginator->getItemsPerPage(), $paginator->getTotalItems()); + } + + public function provideItem(Operation $operation, array $uriVariables = [], array $context = []): object|array|null + { + $item = $this->itemProvider->provide($operation, $uriVariables, $context); + + if (!$item) { + throw new NotFoundHttpException('Command not found'); + } + + return new CommandOutput($item); + } + + public function provideInput(Operation $operation, array $uriVariables = [], array $context = []): object|array|null + { + if (isset($uriVariables['uuid'])) { + $item = $this->itemProvider->provide($operation, $uriVariables, $context); + + return $item !== null ? new CommandInput($item) : null; + } + + return new CommandInput(); + } +} diff --git a/src/State/Provider/CommandTaskProvider.php b/src/State/Provider/CommandTaskProvider.php new file mode 100644 index 0000000..49ef3d3 --- /dev/null +++ b/src/State/Provider/CommandTaskProvider.php @@ -0,0 +1,71 @@ +provideCollection($operation, $uriVariables, $context); + case $operation instanceof Patch: + case $operation instanceof Put: + return $this->provideInput($operation, $uriVariables, $context); + case $operation instanceof Get: + return $this->provideItem($operation, $uriVariables, $context); + } + } + + private function provideCollection(Operation $operation, array $uriVariables = [], array $context = []): object|array|null + { + $paginator = $this->collectionProvider->provide($operation, $uriVariables, $context); + + $items = new \ArrayObject(); + foreach ($paginator->getIterator() as $item){ + $items[] = new CommandTaskOutput($item); + } + + return new TraversablePaginator($items, $paginator->getCurrentPage(), $paginator->getItemsPerPage(), $paginator->getTotalItems()); + } + + public function provideItem(Operation $operation, array $uriVariables = [], array $context = []): object|array|null + { + $item = $this->itemProvider->provide($operation, $uriVariables, $context); + + if (!$item) { + throw new NotFoundHttpException('Command task not found'); + } + + return new CommandTaskOutput($item); + } + + public function provideInput(Operation $operation, array $uriVariables = [], array $context = []): object|array|null + { + if (isset($uriVariables['uuid'])) { + $item = $this->itemProvider->provide($operation, $uriVariables, $context); + + return $item !== null ? new CommandTaskInput($item) : null; + } + + return new CommandTaskInput(); + } +} diff --git a/src/State/Provider/ImageProvider.php b/src/State/Provider/ImageProvider.php index d807b4a..be46ddc 100644 --- a/src/State/Provider/ImageProvider.php +++ b/src/State/Provider/ImageProvider.php @@ -52,7 +52,7 @@ readonly class ImageProvider implements ProviderInterface $item = $this->itemProvider->provide($operation, $uriVariables, $context); if (!$item) { - throw new NotFoundHttpException('Menu not found'); + throw new NotFoundHttpException('Image not found'); } return new ImageOutput($item); diff --git a/src/State/Provider/OgLiveProvider.php b/src/State/Provider/OgLiveProvider.php new file mode 100644 index 0000000..cf1bcc5 --- /dev/null +++ b/src/State/Provider/OgLiveProvider.php @@ -0,0 +1,71 @@ +provideCollection($operation, $uriVariables, $context); + case $operation instanceof Patch: + case $operation instanceof Put: + return $this->provideInput($operation, $uriVariables, $context); + case $operation instanceof Get: + return $this->provideItem($operation, $uriVariables, $context); + } + } + + private function provideCollection(Operation $operation, array $uriVariables = [], array $context = []): object + { + $paginator = $this->collectionProvider->provide($operation, $uriVariables, $context); + + $items = new \ArrayObject(); + foreach ($paginator->getIterator() as $item){ + $items[] = new OgLiveOutput($item); + } + + return new TraversablePaginator($items, $paginator->getCurrentPage(), $paginator->getItemsPerPage(), $paginator->getTotalItems()); + } + + public function provideItem(Operation $operation, array $uriVariables = [], array $context = []): object|array|null + { + $item = $this->itemProvider->provide($operation, $uriVariables, $context); + + if (!$item) { + throw new NotFoundHttpException('OgLive not found'); + } + + return new OgLiveOutput($item); + } + + public function provideInput(Operation $operation, array $uriVariables = [], array $context = []): object|array|null + { + if (isset($uriVariables['uuid'])) { + $item = $this->itemProvider->provide($operation, $uriVariables, $context); + + return $item !== null ? new OgLiveInput($item) : null; + } + + return new OgLiveInput(); + } +} diff --git a/src/State/Provider/OrganizationalUnitProvider.php b/src/State/Provider/OrganizationalUnitProvider.php index 7475e68..3aa0349 100644 --- a/src/State/Provider/OrganizationalUnitProvider.php +++ b/src/State/Provider/OrganizationalUnitProvider.php @@ -14,7 +14,7 @@ use App\Dto\Output\OrganizationalUnitOutput; use App\Entity\OrganizationalUnit; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; -readonly class OrganizationalUnitProvider implements ProviderInterface +final readonly class OrganizationalUnitProvider implements ProviderInterface { public function __construct( private ProviderInterface $collectionProvider, diff --git a/src/State/Provider/PxeTemplateProvider.php b/src/State/Provider/PxeTemplateProvider.php new file mode 100644 index 0000000..8704364 --- /dev/null +++ b/src/State/Provider/PxeTemplateProvider.php @@ -0,0 +1,71 @@ +provideCollection($operation, $uriVariables, $context); + case $operation instanceof Patch: + case $operation instanceof Put: + return $this->provideInput($operation, $uriVariables, $context); + case $operation instanceof Get: + return $this->provideItem($operation, $uriVariables, $context); + } + } + + private function provideCollection(Operation $operation, array $uriVariables = [], array $context = []): object + { + $paginator = $this->collectionProvider->provide($operation, $uriVariables, $context); + + $items = new \ArrayObject(); + foreach ($paginator->getIterator() as $item){ + $items[] = new PxeTemplateOutput($item); + } + + return new TraversablePaginator($items, $paginator->getCurrentPage(), $paginator->getItemsPerPage(), $paginator->getTotalItems()); + } + + public function provideItem(Operation $operation, array $uriVariables = [], array $context = []): object|array|null + { + $item = $this->itemProvider->provide($operation, $uriVariables, $context); + + if (!$item) { + throw new NotFoundHttpException('PxeTemplate not found'); + } + + return new PxeTemplateOutput($item); + } + + public function provideInput(Operation $operation, array $uriVariables = [], array $context = []): object|array|null + { + if (isset($uriVariables['uuid'])) { + $item = $this->itemProvider->provide($operation, $uriVariables, $context); + + return $item !== null ? new PxeTemplateInput($item) : null; + } + + return new PxeTemplateInput(); + } +} diff --git a/src/State/Provider/RemoteCalendarProvider.php b/src/State/Provider/RemoteCalendarProvider.php new file mode 100644 index 0000000..1cb9c98 --- /dev/null +++ b/src/State/Provider/RemoteCalendarProvider.php @@ -0,0 +1,71 @@ +provideCollection($operation, $uriVariables, $context); + case $operation instanceof Patch: + case $operation instanceof Put: + return $this->provideInput($operation, $uriVariables, $context); + case $operation instanceof Get: + return $this->provideItem($operation, $uriVariables, $context); + } + } + + private function provideCollection(Operation $operation, array $uriVariables = [], array $context = []): object + { + $paginator = $this->collectionProvider->provide($operation, $uriVariables, $context); + + $items = new \ArrayObject(); + foreach ($paginator->getIterator() as $item){ + $items[] = new RemoteCalendarOutput($item); + } + + return new TraversablePaginator($items, $paginator->getCurrentPage(), $paginator->getItemsPerPage(), $paginator->getTotalItems()); + } + + public function provideItem(Operation $operation, array $uriVariables = [], array $context = []): object|array|null + { + $item = $this->itemProvider->provide($operation, $uriVariables, $context); + + if (!$item) { + throw new NotFoundHttpException('RemoteCalendar not found'); + } + + return new RemoteCalendarOutput($item); + } + + public function provideInput(Operation $operation, array $uriVariables = [], array $context = []): object|array|null + { + if (isset($uriVariables['uuid'])) { + $item = $this->itemProvider->provide($operation, $uriVariables, $context); + + return $item !== null ? new RemoteCalendarInput($item) : null; + } + + return new RemoteCalendarInput(); + } +} diff --git a/src/State/Provider/RemoteCalendarRuleProvider.php b/src/State/Provider/RemoteCalendarRuleProvider.php new file mode 100644 index 0000000..4417635 --- /dev/null +++ b/src/State/Provider/RemoteCalendarRuleProvider.php @@ -0,0 +1,71 @@ +provideCollection($operation, $uriVariables, $context); + case $operation instanceof Patch: + case $operation instanceof Put: + return $this->provideInput($operation, $uriVariables, $context); + case $operation instanceof Get: + return $this->provideItem($operation, $uriVariables, $context); + } + } + + private function provideCollection(Operation $operation, array $uriVariables = [], array $context = []): object + { + $paginator = $this->collectionProvider->provide($operation, $uriVariables, $context); + + $items = new \ArrayObject(); + foreach ($paginator->getIterator() as $item){ + $items[] = new RemoteCalendarRuleOutput($item); + } + + return new TraversablePaginator($items, $paginator->getCurrentPage(), $paginator->getItemsPerPage(), $paginator->getTotalItems()); + } + + public function provideItem(Operation $operation, array $uriVariables = [], array $context = []): object|array|null + { + $item = $this->itemProvider->provide($operation, $uriVariables, $context); + + if (!$item) { + throw new NotFoundHttpException('RemoteCalendarRule not found'); + } + + return new RemoteCalendarRuleOutput($item); + } + + public function provideInput(Operation $operation, array $uriVariables = [], array $context = []): object|array|null + { + if (isset($uriVariables['uuid'])) { + $item = $this->itemProvider->provide($operation, $uriVariables, $context); + + return $item !== null ? new RemoteCalendarRuleInput($item) : null; + } + + return new RemoteCalendarRuleInput(); + } +} diff --git a/src/State/Provider/SoftwareProfileProvider.php b/src/State/Provider/SoftwareProfileProvider.php index 94f9aed..8d34140 100644 --- a/src/State/Provider/SoftwareProfileProvider.php +++ b/src/State/Provider/SoftwareProfileProvider.php @@ -41,7 +41,7 @@ readonly class SoftwareProfileProvider implements ProviderInterface $items = new \ArrayObject(); foreach ($paginator->getIterator() as $item){ - $items[] = new SoftwareProfileInput($item); + $items[] = new SoftwareProfileOutput($item); } return new TraversablePaginator($items, $paginator->getCurrentPage(), $paginator->getItemsPerPage(), $paginator->getTotalItems()); diff --git a/src/State/Provider/SubnetProvider.php b/src/State/Provider/SubnetProvider.php new file mode 100644 index 0000000..919c688 --- /dev/null +++ b/src/State/Provider/SubnetProvider.php @@ -0,0 +1,71 @@ +provideCollection($operation, $uriVariables, $context); + case $operation instanceof Patch: + case $operation instanceof Put: + return $this->provideInput($operation, $uriVariables, $context); + case $operation instanceof Get: + return $this->provideItem($operation, $uriVariables, $context); + } + } + + private function provideCollection(Operation $operation, array $uriVariables = [], array $context = []): object + { + $paginator = $this->collectionProvider->provide($operation, $uriVariables, $context); + + $items = new \ArrayObject(); + foreach ($paginator->getIterator() as $item){ + $items[] = new SubnetOutput($item); + } + + return new TraversablePaginator($items, $paginator->getCurrentPage(), $paginator->getItemsPerPage(), $paginator->getTotalItems()); + } + + public function provideItem(Operation $operation, array $uriVariables = [], array $context = []): object|array|null + { + $item = $this->itemProvider->provide($operation, $uriVariables, $context); + + if (!$item) { + throw new NotFoundHttpException('Subnet not found'); + } + + return new SubnetOutput($item); + } + + public function provideInput(Operation $operation, array $uriVariables = [], array $context = []): object|array|null + { + if (isset($uriVariables['uuid'])) { + $item = $this->itemProvider->provide($operation, $uriVariables, $context); + + return $item !== null ? new SubnetInput($item) : null; + } + + return new SubnetInput(); + } +} diff --git a/src/State/Provider/TraceProvider.php b/src/State/Provider/TraceProvider.php new file mode 100644 index 0000000..aeefd56 --- /dev/null +++ b/src/State/Provider/TraceProvider.php @@ -0,0 +1,56 @@ +provideCollection($operation, $uriVariables, $context); + case $operation instanceof Get: + return $this->provideItem($operation, $uriVariables, $context); + } + } + + private function provideCollection(Operation $operation, array $uriVariables = [], array $context = []): object + { + $paginator = $this->collectionProvider->provide($operation, $uriVariables, $context); + + $items = new \ArrayObject(); + foreach ($paginator->getIterator() as $item){ + $items[] = new TraceOutput($item); + } + + return new TraversablePaginator($items, $paginator->getCurrentPage(), $paginator->getItemsPerPage(), $paginator->getTotalItems()); + } + + public function provideItem(Operation $operation, array $uriVariables = [], array $context = []): object|array|null + { + $item = $this->itemProvider->provide($operation, $uriVariables, $context); + + if (!$item) { + throw new NotFoundHttpException('Trace not found'); + } + + return new TraceOutput($item); + } +} diff --git a/tests/Functional/CommandGroupTest.php b/tests/Functional/CommandGroupTest.php new file mode 100644 index 0000000..de5faef --- /dev/null +++ b/tests/Functional/CommandGroupTest.php @@ -0,0 +1,127 @@ + self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]); + + CommandGroupFactory::createMany(10); + + $this->createClientWithCredentials()->request('GET', '/command-groups'); + $this->assertResponseStatusCodeSame(Response::HTTP_OK); + $this->assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8'); + $this->assertJsonContains([ + '@context' => '/contexts/CommandGroup', + '@id' => '/command-groups', + '@type' => 'hydra:Collection', + 'hydra:totalItems' => 10, + ]); + } + + /** + * @throws RedirectionExceptionInterface + * @throws DecodingExceptionInterface + * @throws ClientExceptionInterface + * @throws TransportExceptionInterface + * @throws ServerExceptionInterface + */ + public function testCreateCommandGroup(): void + { + UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]); + + CommandFactory::createOne(['name' => self::CMD_CREATE]); + $commandIri = $this->findIriBy(Command::class, ['name' => self::CMD_CREATE]); + + $this->createClientWithCredentials()->request('POST', '/command-groups',['json' => [ + 'name' => self::CMD_GROUP_CREATE, + 'commands' => [ + $commandIri + ] + ]]); + + $this->assertResponseStatusCodeSame(201); + $this->assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8'); + $this->assertJsonContains([ + '@context' => '/contexts/CommandGroupOutput', + '@type' => 'CommandGroup', + 'name' => self::CMD_GROUP_CREATE, + ]); + } + + /** + * @throws RedirectionExceptionInterface + * @throws DecodingExceptionInterface + * @throws ClientExceptionInterface + * @throws TransportExceptionInterface + * @throws ServerExceptionInterface + */ + public function testUpdateCommandGroup(): void + { + UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]); + + CommandGroupFactory::createOne(['name' => self::CMD_GROUP_CREATE]); + $iri = $this->findIriBy(CommandGroup::class, ['name' => self::CMD_GROUP_CREATE]); + + $this->createClientWithCredentials()->request('PUT', $iri, ['json' => [ + 'name' => self::CMD_GROUP_UPDATE, + ]]); + + $this->assertResponseIsSuccessful(); + $this->assertJsonContains([ + '@id' => $iri, + 'name' => self::CMD_GROUP_UPDATE + ]); + } + + /** + * @throws TransportExceptionInterface + * @throws ServerExceptionInterface + * @throws RedirectionExceptionInterface + * @throws DecodingExceptionInterface + * @throws ClientExceptionInterface + */ + public function testDeleteCommandGroup(): void + { + UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]); + + CommandGroupFactory::createOne(['name' => self::CMD_GROUP_DELETE]); + $iri = $this->findIriBy(CommandGroup::class, ['name' => self::CMD_GROUP_DELETE]); + + $this->createClientWithCredentials()->request('DELETE', $iri); + $this->assertResponseStatusCodeSame(204); + $this->assertNull( + static::getContainer()->get('doctrine')->getRepository(CommandGroup::class)->findOneBy(['name' => self::CMD_GROUP_DELETE]) + ); + } +} \ No newline at end of file diff --git a/tests/Functional/CommandTaskTest.php b/tests/Functional/CommandTaskTest.php new file mode 100644 index 0000000..49b9555 --- /dev/null +++ b/tests/Functional/CommandTaskTest.php @@ -0,0 +1,129 @@ + self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]); + + CommandTaskFactory::createMany(10); + + $this->createClientWithCredentials()->request('GET', '/command-tasks'); + $this->assertResponseStatusCodeSame(Response::HTTP_OK); + $this->assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8'); + $this->assertJsonContains([ + '@context' => '/contexts/CommandTask', + '@id' => '/command-tasks', + '@type' => 'hydra:Collection', + 'hydra:totalItems' => 10, + ]); + } + + /** + * @throws RedirectionExceptionInterface + * @throws DecodingExceptionInterface + * @throws ClientExceptionInterface + * @throws TransportExceptionInterface + * @throws ServerExceptionInterface + */ + public function testCreateCommandTask(): void + { + UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]); + + CommandFactory::createOne(['name' => self::CMD_CREATE]); + $commandIri = $this->findIriBy(Command::class, ['name' => self::CMD_CREATE]); + + $date = new \DateTimeImmutable(); + + $this->createClientWithCredentials()->request('POST', '/command-tasks',['json' => [ + 'dateTime' => $date->format('Y-m-d H:i:s'), + 'notes' => self::CMD_TASK_CREATE, + 'commands' => [ + $commandIri + ] + ]]); + + $this->assertResponseStatusCodeSame(201); + $this->assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8'); + $this->assertJsonContains([ + '@context' => '/contexts/CommandTaskOutput', + '@type' => 'CommandTask', + 'notes' => self::CMD_TASK_CREATE, + ]); + } + + /** + * @throws RedirectionExceptionInterface + * @throws DecodingExceptionInterface + * @throws ClientExceptionInterface + * @throws TransportExceptionInterface + * @throws ServerExceptionInterface + */ + public function testUpdateCommandTask(): void + { + UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]); + + CommandTaskFactory::createOne(['notes' => self::CMD_TASK_CREATE]); + $iri = $this->findIriBy(CommandTask::class, ['notes' => self::CMD_TASK_CREATE]); + + $this->createClientWithCredentials()->request('PUT', $iri, ['json' => [ + 'notes' => self::CMD_TASK_UPDATE, + ]]); + + $this->assertResponseIsSuccessful(); + $this->assertJsonContains([ + '@id' => $iri, + 'notes' => self::CMD_TASK_UPDATE + ]); + } + + /** + * @throws TransportExceptionInterface + * @throws ServerExceptionInterface + * @throws RedirectionExceptionInterface + * @throws DecodingExceptionInterface + * @throws ClientExceptionInterface + */ + public function testDeleteCommandTask(): void + { + UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]); + + CommandTaskFactory::createOne(['notes' => self::CMD_TASK_DELETE]); + $iri = $this->findIriBy(CommandTask::class, ['notes' => self::CMD_TASK_DELETE]); + + $this->createClientWithCredentials()->request('DELETE', $iri); + $this->assertResponseStatusCodeSame(204); + $this->assertNull( + static::getContainer()->get('doctrine')->getRepository(CommandTask::class)->findOneBy(['notes' => self::CMD_TASK_DELETE]) + ); + } +} \ No newline at end of file diff --git a/tests/Functional/CommandTest.php b/tests/Functional/CommandTest.php new file mode 100644 index 0000000..68a55ad --- /dev/null +++ b/tests/Functional/CommandTest.php @@ -0,0 +1,122 @@ + self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]); + + CommandFactory::createMany(10); + + $this->createClientWithCredentials()->request('GET', '/commands'); + $this->assertResponseStatusCodeSame(Response::HTTP_OK); + $this->assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8'); + $this->assertJsonContains([ + '@context' => '/contexts/Command', + '@id' => '/commands', + '@type' => 'hydra:Collection', + 'hydra:totalItems' => 10, + ]); + } + + /** + * @throws RedirectionExceptionInterface + * @throws DecodingExceptionInterface + * @throws ClientExceptionInterface + * @throws TransportExceptionInterface + * @throws ServerExceptionInterface + */ + public function testCreateCommand(): void + { + UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]); + + $this->createClientWithCredentials()->request('POST', '/commands',['json' => [ + 'name' => self::CMD_CREATE, + 'script' => 'echo "Hello World!"', + ]]); + + $this->assertResponseStatusCodeSame(201); + $this->assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8'); + $this->assertJsonContains([ + '@context' => '/contexts/CommandOutput', + '@type' => 'Command', + 'name' => self::CMD_CREATE, + 'script' => 'echo "Hello World!"' + ]); + } + + /** + * @throws RedirectionExceptionInterface + * @throws DecodingExceptionInterface + * @throws ClientExceptionInterface + * @throws TransportExceptionInterface + * @throws ServerExceptionInterface + */ + public function testUpdateCommand(): void + { + UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]); + + CommandFactory::createOne(['name' => self::CMD_CREATE]); + $iri = $this->findIriBy(Command::class, ['name' => self::CMD_CREATE]); + + $this->createClientWithCredentials()->request('PUT', $iri, ['json' => [ + 'name' => self::CMD_UPDATE, + 'readOnly' => true + ]]); + + $this->assertResponseIsSuccessful(); + $this->assertJsonContains([ + '@id' => $iri, + 'name' => self::CMD_UPDATE, + 'readOnly' => true + ]); + } + + /** + * @throws TransportExceptionInterface + * @throws ServerExceptionInterface + * @throws RedirectionExceptionInterface + * @throws DecodingExceptionInterface + * @throws ClientExceptionInterface + */ + public function testDeleteCommand(): void + { + UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]); + + CommandFactory::createOne(['name' => self::CMD_DELETE]); + $iri = $this->findIriBy(Command::class, ['name' => self::CMD_DELETE]); + + $this->createClientWithCredentials()->request('DELETE', $iri); + $this->assertResponseStatusCodeSame(204); + $this->assertNull( + static::getContainer()->get('doctrine')->getRepository(Command::class)->findOneBy(['name' => self::CMD_DELETE]) + ); + } +} \ No newline at end of file diff --git a/tests/Functional/ImageTest.php b/tests/Functional/ImageTest.php index b4e95fc..eee855f 100644 --- a/tests/Functional/ImageTest.php +++ b/tests/Functional/ImageTest.php @@ -8,8 +8,10 @@ use App\Entity\OrganizationalUnit; use App\Entity\SoftwareProfile; use App\Factory\ClientFactory; use App\Factory\ImageFactory; +use App\Factory\OrganizationalUnitFactory; use App\Factory\SoftwareProfileFactory; use App\Factory\UserFactory; +use App\Model\OrganizationalUnitTypes; use App\Model\UserGroupPermissions; use Symfony\Component\HttpFoundation\Response; use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface; @@ -62,9 +64,6 @@ class ImageTest extends AbstractTest { UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]); - ClientFactory::createOne(['name' => self::CLIENT]); - $clientIri = $this->findIriBy(Client::class, ['name' => self::CLIENT]); - SoftwareProfileFactory::createOne(['description' => self::SOFTWARE_PROFILE]); $swPIri = $this->findIriBy(SoftwareProfile::class, ['description' => self::SOFTWARE_PROFILE]); @@ -72,9 +71,7 @@ class ImageTest extends AbstractTest 'name' => self::IMAGE_CREATE, 'size' => 123, 'path' => '/path/to/image', - 'type' => 'type', - 'client' => $clientIri, - 'softwareProfile' => $swPIri + 'softwareProfile' => $swPIri, ]]); $this->assertResponseStatusCodeSame(201); diff --git a/tests/Functional/OgLiveTest.php b/tests/Functional/OgLiveTest.php new file mode 100644 index 0000000..95b2490 --- /dev/null +++ b/tests/Functional/OgLiveTest.php @@ -0,0 +1,126 @@ + self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]); + + OgLiveFactory::createMany(10); + + $this->createClientWithCredentials()->request('GET', '/og-lives'); + $this->assertResponseStatusCodeSame(Response::HTTP_OK); + $this->assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8'); + $this->assertJsonContains([ + '@context' => '/contexts/OgLive', + '@id' => '/og-lives', + '@type' => 'hydra:Collection', + 'hydra:totalItems' => 10, + ]); + } + + /** + * @throws RedirectionExceptionInterface + * @throws DecodingExceptionInterface + * @throws ClientExceptionInterface + * @throws TransportExceptionInterface + * @throws ServerExceptionInterface + */ + public function testCreateOgLive(): void + { + UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]); + + $this->createClientWithCredentials()->request('POST', '/og-lives',['json' => [ + 'name' => self::OGLIVE_CREATE, + 'downloadUrl' => 'http://example.com', + ]]); + + $this->assertResponseStatusCodeSame(201); + $this->assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8'); + $this->assertJsonContains([ + '@context' => '/contexts/OgLiveOutput', + '@type' => 'OgLive', + 'name' => self::OGLIVE_CREATE, + 'downloadUrl' => 'http://example.com', + 'status' => OgLiveStatus::INACTIVE + ]); + } + + /** + * @throws RedirectionExceptionInterface + * @throws DecodingExceptionInterface + * @throws ClientExceptionInterface + * @throws TransportExceptionInterface + * @throws ServerExceptionInterface + */ + public function testUpdateOgLive(): void + { + UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]); + + OgLiveFactory::createOne(['name' => self::OGLIVE_CREATE, 'downloadUrl' => 'http://example.com']); + $iri = $this->findIriBy(OgLive::class, ['name' => self::OGLIVE_CREATE]); + + $this->createClientWithCredentials()->request('PUT', $iri, ['json' => [ + 'name' => self::OGLIVE_UPDATE, + 'downloadUrl' => 'http://example-2.com', + ]]); + + $this->assertResponseIsSuccessful(); + $this->assertJsonContains([ + '@id' => $iri, + 'name' => self::OGLIVE_UPDATE, + 'downloadUrl' => 'http://example-2.com', + ]); + } + + /** + * @throws TransportExceptionInterface + * @throws ServerExceptionInterface + * @throws RedirectionExceptionInterface + * @throws DecodingExceptionInterface + * @throws ClientExceptionInterface + */ + public function testDeleteOgLive(): void + { + UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]); + + OgLiveFactory::createOne(['name' => self::OGLIVE_CREATE, 'downloadUrl' => 'http://example.com']); + $iri = $this->findIriBy(OgLive::class, ['name' => self::OGLIVE_CREATE]); + + $this->createClientWithCredentials()->request('DELETE', $iri); + $this->assertResponseStatusCodeSame(204); + $this->assertNull( + static::getContainer()->get('doctrine')->getRepository(OgLive::class)->findOneBy(['name' => self::OGLIVE_CREATE]) + ); + } +} \ No newline at end of file diff --git a/tests/Functional/OrganizationalUnitTest.php b/tests/Functional/OrganizationalUnitTest.php index 899093b..bcb4a97 100644 --- a/tests/Functional/OrganizationalUnitTest.php +++ b/tests/Functional/OrganizationalUnitTest.php @@ -63,6 +63,7 @@ class OrganizationalUnitTest extends AbstractTest $this->createClientWithCredentials()->request('POST', '/organizational-units',['json' => [ 'name' => self::ORGANIZATIONAL_UNIT_CREATE, 'type' => OrganizationalUnitTypes::ORGANIZATIONAL_UNIT, + 'remotePc' => true, ]]); $this->assertResponseStatusCodeSame(201); @@ -72,6 +73,7 @@ class OrganizationalUnitTest extends AbstractTest '@type' => 'OrganizationalUnit', 'name' => self::ORGANIZATIONAL_UNIT_CREATE, 'type' => OrganizationalUnitTypes::ORGANIZATIONAL_UNIT, + 'remotePc' => true, ]); } diff --git a/tests/Functional/PartitionTest.php b/tests/Functional/PartitionTest.php index 39debe4..e587484 100644 --- a/tests/Functional/PartitionTest.php +++ b/tests/Functional/PartitionTest.php @@ -3,11 +3,13 @@ namespace Functional; use App\Entity\Client; +use App\Entity\Image; use App\Entity\Menu; use App\Entity\OperativeSystem; use App\Entity\Partition; use App\Factory\ClientFactory; use App\Factory\HardwareProfileFactory; +use App\Factory\ImageFactory; use App\Factory\MenuFactory; use App\Factory\OperativeSystemFactory; use App\Factory\OrganizationalUnitFactory; @@ -73,9 +75,13 @@ class PartitionTest extends AbstractTest OperativeSystemFactory::createOne(['name' => 'Ubuntu']); $osIri = $this->findIriBy(OperativeSystem::class, ['name' => 'Ubuntu']); + ImageFactory::createOne(['name' => 'Image 1']); + $imageIri = $this->findIriBy(Image::class, ['name' => 'Image 1']); + $this->createClientWithCredentials()->request('POST', '/partitions',['json' => [ 'size' => 100, 'operativeSystem' => $osIri, + 'image' => $imageIri, 'client' => $iri, 'memoryUsage' => 100 ]]); diff --git a/tests/Functional/PxeTemplateTest.php b/tests/Functional/PxeTemplateTest.php new file mode 100644 index 0000000..d2aafdb --- /dev/null +++ b/tests/Functional/PxeTemplateTest.php @@ -0,0 +1,122 @@ + self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]); + + PxeTemplateFactory::createMany(10); + + $this->createClientWithCredentials()->request('GET', '/pxe-templates'); + $this->assertResponseStatusCodeSame(Response::HTTP_OK); + $this->assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8'); + $this->assertJsonContains([ + '@context' => '/contexts/PxeTemplate', + '@id' => '/pxe-templates', + '@type' => 'hydra:Collection', + 'hydra:totalItems' => 10, + ]); + } + + /** + * @throws RedirectionExceptionInterface + * @throws DecodingExceptionInterface + * @throws ClientExceptionInterface + * @throws TransportExceptionInterface + * @throws ServerExceptionInterface + */ + public function testCreatePxeTemplate(): void + { + UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]); + + $this->createClientWithCredentials()->request('POST', '/pxe-templates',['json' => [ + 'name' => self::PXE_TEMPLATE_CREATE, + 'templateContent' => 'content' + ]]); + + $this->assertResponseStatusCodeSame(201); + $this->assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8'); + $this->assertJsonContains([ + '@context' => '/contexts/PxeTemplateOutput', + '@type' => 'PxeTemplate', + 'name' => self::PXE_TEMPLATE_CREATE, + 'templateContent' => 'content' + ]); + } + + /** + * @throws RedirectionExceptionInterface + * @throws DecodingExceptionInterface + * @throws ClientExceptionInterface + * @throws TransportExceptionInterface + * @throws ServerExceptionInterface + */ + public function testUpdatePxeTemplate(): void + { + UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]); + + PxeTemplateFactory::createOne(['name' => self::PXE_TEMPLATE_CREATE, 'templateContent' => 'content']); + $iri = $this->findIriBy(PxeTemplate::class, ['name' => self::PXE_TEMPLATE_CREATE]); + + $this->createClientWithCredentials()->request('PUT', $iri, ['json' => [ + 'name' => self::PXE_TEMPLATE_UPDATE, + 'templateContent' => 'updated-content', + ]]); + + $this->assertResponseIsSuccessful(); + $this->assertJsonContains([ + '@id' => $iri, + 'name' => self::PXE_TEMPLATE_UPDATE, + 'templateContent' => 'updated-content', + ]); + } + + /** + * @throws TransportExceptionInterface + * @throws ServerExceptionInterface + * @throws RedirectionExceptionInterface + * @throws DecodingExceptionInterface + * @throws ClientExceptionInterface + */ + public function testDeletePxeTemplate(): void + { + UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]); + + PxeTemplateFactory::createOne(['name' => self::PXE_TEMPLATE_DELETE, 'templateContent' => 'content']); + $iri = $this->findIriBy(PxeTemplate::class, ['name' => self::PXE_TEMPLATE_DELETE]); + + $this->createClientWithCredentials()->request('DELETE', $iri); + $this->assertResponseStatusCodeSame(204); + $this->assertNull( + static::getContainer()->get('doctrine')->getRepository(PxeTemplate::class)->findOneBy(['name' => self::PXE_TEMPLATE_DELETE]) + ); + } +} \ No newline at end of file diff --git a/tests/Functional/SoftwareTest.php b/tests/Functional/SoftwareTest.php index 07f41dd..f48a299 100644 --- a/tests/Functional/SoftwareTest.php +++ b/tests/Functional/SoftwareTest.php @@ -7,6 +7,7 @@ use App\Entity\Software; use App\Factory\OrganizationalUnitFactory; use App\Factory\SoftwareFactory; use App\Factory\UserFactory; +use App\Model\SoftwareTypes; use App\Model\UserGroupPermissions; use Symfony\Component\HttpFoundation\Response; use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface; @@ -59,6 +60,7 @@ class SoftwareTest extends AbstractTest $this->createClientWithCredentials()->request('POST', '/software',['json' => [ 'name' => self::SW_CREATE, + 'type' => SoftwareTypes::FILE ]]); $this->assertResponseStatusCodeSame(201); @@ -66,7 +68,8 @@ class SoftwareTest extends AbstractTest $this->assertJsonContains([ '@context' => '/contexts/SoftwareOutput', '@type' => 'Software', - 'name' => self::SW_CREATE + 'name' => self::SW_CREATE, + 'type' => SoftwareTypes::FILE ]); } diff --git a/translations/validators.en.yaml b/translations/validators.en.yaml index e5b6e69..7881069 100644 --- a/translations/validators.en.yaml +++ b/translations/validators.en.yaml @@ -8,6 +8,18 @@ validators: organizational_unit: not_null: 'The organizational unit should not be null.' + command: + name: + not_blank: 'The name should not be blank.' + script: + not_blank: 'The script should not be blank.' + + command_group: + name: + not_blank: 'The name should not be blank.' + position: + not_blank: 'The position should not be blank.' + view: name: not_blank: 'The name should not be blank.' @@ -36,4 +48,21 @@ validators: operative_system: name: - not_blank: 'The name should not be blank.' \ No newline at end of file + not_blank: 'The name should not be blank.' + + og_live: + name: + not_blank: 'The name should not be blank.' + unique: 'The name should be unique.' + + subnet: + name: + not_blank: 'The name should not be blank.' + ip_address: + not_blank: 'The IP should not be blank.' + netmask: + not_blank: 'The netmask should not be blank.' + boot_file_name: + not_blank: 'The boot file name should not be blank.' + next_server: + not_blank: 'The next server should not be blank.' \ No newline at end of file diff --git a/translations/validators.es.yaml b/translations/validators.es.yaml index 9bf6d15..9f11c35 100644 --- a/translations/validators.es.yaml +++ b/translations/validators.es.yaml @@ -8,6 +8,18 @@ validators: organizational_unit: not_null: 'La unidad organizativa no debería estar vacía.' + command: + name: + not_blank: 'El nombre no debería estar vacío.' + script: + not_blank: 'El script no debería estar vacío.' + + command_group: + name: + not_blank: 'El nombre no debería estar vacío.' + position: + not_blank: 'La posición no debería estar vacía.' + view: name: not_blank: 'El nombre no debería estar vacío.' @@ -36,4 +48,16 @@ validators: operative_system: name: - not_blank: 'El nombre no debería estar vacío.' \ No newline at end of file + not_blank: 'El nombre no debería estar vacío.' + + subnet: + name: + not_blank: 'El nombre no debería estar vacío.' + ip_address: + not_blank: 'La dirección IP no debería estar vacía.' + netmask: + not_blank: 'La máscara de red no debería estar vacía.' + boot_file_name: + not_blank: 'El nombre del archivo de arranque no debería estar vacío.' + next_server: + not_blank: 'El servidor no debería estar vacío.' \ No newline at end of file