websocket

This commit is contained in:
afornerot 2020-11-23 13:08:32 +01:00
parent 85ff851a1a
commit d1a2131e0b
25 changed files with 1323 additions and 43 deletions

View File

@ -16,7 +16,7 @@
<!-- template -->
<file filelist='nineschool' name='/etc/apache2/sites-available/nineschool' source='nineschool-apache.conf' />
<file filelist='nineschool' name='/var/www/html/nineschool/.env.local' source='nineschool-env.local' rm='True'/>
<file filelist='ninegate' name='/etc/cron.d/nineschool' source='nineschool.cron' rm='True'/>
<file filelist='nineschool' name='/etc/cron.d/nineschool' source='nineschool.cron' rm='True'/>
</container>
</containers>

View File

@ -5,6 +5,7 @@
"php": "^7.1.3",
"ext-ctype": "*",
"ext-iconv": "*",
"cboden/ratchet": "^0.4.3",
"doctrine/annotations": "^1.8",
"friendsofsymfony/ckeditor-bundle": "^2.2",
"friendsofsymfony/rest-bundle": "^3.0",
@ -14,6 +15,7 @@
"nategood/httpful": "^0.3.2",
"nelmio/api-doc-bundle": "^3.6",
"oneup/uploader-bundle": "^3.0",
"ramsey/uuid": "^4.1",
"sensio/framework-extra-bundle": "^5.1",
"symfony/apache-pack": "^1.0",
"symfony/asset": "5.1.*",

View File

@ -4,8 +4,111 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"content-hash": "dcf29a3826720301ab52c6fe3543f7bd",
"content-hash": "6e17c24e8ecdd92e1fa9b4738c5c94f3",
"packages": [
{
"name": "brick/math",
"version": "0.9.1",
"source": {
"type": "git",
"url": "https://github.com/brick/math.git",
"reference": "283a40c901101e66de7061bd359252c013dcc43c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/brick/math/zipball/283a40c901101e66de7061bd359252c013dcc43c",
"reference": "283a40c901101e66de7061bd359252c013dcc43c",
"shasum": ""
},
"require": {
"ext-json": "*",
"php": "^7.1|^8.0"
},
"require-dev": {
"php-coveralls/php-coveralls": "^2.2",
"phpunit/phpunit": "^7.5.15|^8.5",
"vimeo/psalm": "^3.5"
},
"type": "library",
"autoload": {
"psr-4": {
"Brick\\Math\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Arbitrary-precision arithmetic library",
"keywords": [
"Arbitrary-precision",
"BigInteger",
"BigRational",
"arithmetic",
"bigdecimal",
"bignum",
"brick",
"math"
],
"time": "2020-08-18T23:57:15+00:00"
},
{
"name": "cboden/ratchet",
"version": "v0.4.3",
"source": {
"type": "git",
"url": "https://github.com/ratchetphp/Ratchet.git",
"reference": "466a0ecc83209c75b76645eb823401b5c52e5f21"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ratchetphp/Ratchet/zipball/466a0ecc83209c75b76645eb823401b5c52e5f21",
"reference": "466a0ecc83209c75b76645eb823401b5c52e5f21",
"shasum": ""
},
"require": {
"guzzlehttp/psr7": "^1.0",
"php": ">=5.4.2",
"ratchet/rfc6455": "^0.3",
"react/socket": "^1.0 || ^0.8 || ^0.7 || ^0.6 || ^0.5",
"symfony/http-foundation": "^2.6|^3.0|^4.0|^5.0",
"symfony/routing": "^2.6|^3.0|^4.0|^5.0"
},
"require-dev": {
"phpunit/phpunit": "~4.8"
},
"type": "library",
"autoload": {
"psr-4": {
"Ratchet\\": "src/Ratchet"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Chris Boden",
"email": "cboden@gmail.com",
"role": "Developer"
},
{
"name": "Matt Bonneau",
"role": "Developer"
}
],
"description": "PHP WebSocket library",
"homepage": "http://socketo.me",
"keywords": [
"Ratchet",
"WebSockets",
"server",
"sockets",
"websocket"
],
"time": "2020-07-07T15:50:14+00:00"
},
{
"name": "doctrine/annotations",
"version": "1.10.3",
@ -1165,6 +1268,7 @@
"reflection",
"static"
],
"abandoned": "roave/better-reflection",
"time": "2020-03-27T11:06:43+00:00"
},
{
@ -1278,6 +1382,49 @@
],
"time": "2020-06-16T20:11:17+00:00"
},
{
"name": "evenement/evenement",
"version": "v3.0.1",
"source": {
"type": "git",
"url": "https://github.com/igorw/evenement.git",
"reference": "531bfb9d15f8aa57454f5f0285b18bec903b8fb7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/igorw/evenement/zipball/531bfb9d15f8aa57454f5f0285b18bec903b8fb7",
"reference": "531bfb9d15f8aa57454f5f0285b18bec903b8fb7",
"shasum": ""
},
"require": {
"php": ">=7.0"
},
"require-dev": {
"phpunit/phpunit": "^6.0"
},
"type": "library",
"autoload": {
"psr-0": {
"Evenement": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Igor Wiedler",
"email": "igor@wiedler.ch"
}
],
"description": "Événement is a very simple event dispatching library for PHP",
"keywords": [
"event-dispatcher",
"event-emitter"
],
"time": "2017-07-23T21:35:13+00:00"
},
{
"name": "exsyst/swagger",
"version": "v0.4.1",
@ -1496,6 +1643,77 @@
],
"time": "2020-06-29T11:19:01+00:00"
},
{
"name": "guzzlehttp/psr7",
"version": "1.7.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "53330f47520498c0ae1f61f7e2c90f55690c06a3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/53330f47520498c0ae1f61f7e2c90f55690c06a3",
"reference": "53330f47520498c0ae1f61f7e2c90f55690c06a3",
"shasum": ""
},
"require": {
"php": ">=5.4.0",
"psr/http-message": "~1.0",
"ralouphie/getallheaders": "^2.0.5 || ^3.0.0"
},
"provide": {
"psr/http-message-implementation": "1.0"
},
"require-dev": {
"ext-zlib": "*",
"phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.10"
},
"suggest": {
"laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.7-dev"
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Psr7\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "Tobias Schultze",
"homepage": "https://github.com/Tobion"
}
],
"description": "PSR-7 message implementation that also provides common utility methods",
"keywords": [
"http",
"message",
"psr-7",
"request",
"response",
"stream",
"uri",
"url"
],
"time": "2020-09-30T07:37:11+00:00"
},
{
"name": "jasig/phpcas",
"version": "1.3.8",
@ -2495,6 +2713,56 @@
],
"time": "2019-01-08T18:20:26+00:00"
},
{
"name": "psr/http-message",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-message.git",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for HTTP messages",
"homepage": "https://github.com/php-fig/http-message",
"keywords": [
"http",
"http-message",
"psr",
"psr-7",
"request",
"response"
],
"time": "2016-08-06T14:39:51+00:00"
},
{
"name": "psr/link",
"version": "1.0.0",
@ -2591,6 +2859,627 @@
],
"time": "2020-03-23T09:12:05+00:00"
},
{
"name": "ralouphie/getallheaders",
"version": "3.0.3",
"source": {
"type": "git",
"url": "https://github.com/ralouphie/getallheaders.git",
"reference": "120b605dfeb996808c31b6477290a714d356e822"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
"reference": "120b605dfeb996808c31b6477290a714d356e822",
"shasum": ""
},
"require": {
"php": ">=5.6"
},
"require-dev": {
"php-coveralls/php-coveralls": "^2.1",
"phpunit/phpunit": "^5 || ^6.5"
},
"type": "library",
"autoload": {
"files": [
"src/getallheaders.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ralph Khattar",
"email": "ralph.khattar@gmail.com"
}
],
"description": "A polyfill for getallheaders.",
"time": "2019-03-08T08:55:37+00:00"
},
{
"name": "ramsey/collection",
"version": "1.1.1",
"source": {
"type": "git",
"url": "https://github.com/ramsey/collection.git",
"reference": "24d93aefb2cd786b7edd9f45b554aea20b28b9b1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ramsey/collection/zipball/24d93aefb2cd786b7edd9f45b554aea20b28b9b1",
"reference": "24d93aefb2cd786b7edd9f45b554aea20b28b9b1",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8"
},
"require-dev": {
"captainhook/captainhook": "^5.3",
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
"ergebnis/composer-normalize": "^2.6",
"fzaninotto/faker": "^1.5",
"hamcrest/hamcrest-php": "^2",
"jangregor/phpstan-prophecy": "^0.6",
"mockery/mockery": "^1.3",
"phpstan/extension-installer": "^1",
"phpstan/phpstan": "^0.12.32",
"phpstan/phpstan-mockery": "^0.12.5",
"phpstan/phpstan-phpunit": "^0.12.11",
"phpunit/phpunit": "^8.5",
"psy/psysh": "^0.10.4",
"slevomat/coding-standard": "^6.3",
"squizlabs/php_codesniffer": "^3.5",
"vimeo/psalm": "^3.12.2"
},
"type": "library",
"autoload": {
"psr-4": {
"Ramsey\\Collection\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ben Ramsey",
"email": "ben@benramsey.com",
"homepage": "https://benramsey.com"
}
],
"description": "A PHP 7.2+ library for representing and manipulating collections.",
"keywords": [
"array",
"collection",
"hash",
"map",
"queue",
"set"
],
"time": "2020-09-10T20:58:17+00:00"
},
{
"name": "ramsey/uuid",
"version": "4.1.1",
"source": {
"type": "git",
"url": "https://github.com/ramsey/uuid.git",
"reference": "cd4032040a750077205918c86049aa0f43d22947"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ramsey/uuid/zipball/cd4032040a750077205918c86049aa0f43d22947",
"reference": "cd4032040a750077205918c86049aa0f43d22947",
"shasum": ""
},
"require": {
"brick/math": "^0.8 || ^0.9",
"ext-json": "*",
"php": "^7.2 || ^8",
"ramsey/collection": "^1.0",
"symfony/polyfill-ctype": "^1.8"
},
"replace": {
"rhumsaa/uuid": "self.version"
},
"require-dev": {
"codeception/aspect-mock": "^3",
"dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7.0",
"doctrine/annotations": "^1.8",
"goaop/framework": "^2",
"mockery/mockery": "^1.3",
"moontoast/math": "^1.1",
"paragonie/random-lib": "^2",
"php-mock/php-mock-mockery": "^1.3",
"php-mock/php-mock-phpunit": "^2.5",
"php-parallel-lint/php-parallel-lint": "^1.1",
"phpbench/phpbench": "^0.17.1",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^0.12",
"phpstan/phpstan-mockery": "^0.12",
"phpstan/phpstan-phpunit": "^0.12",
"phpunit/phpunit": "^8.5",
"psy/psysh": "^0.10.0",
"slevomat/coding-standard": "^6.0",
"squizlabs/php_codesniffer": "^3.5",
"vimeo/psalm": "3.9.4"
},
"suggest": {
"ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.",
"ext-ctype": "Enables faster processing of character classification using ctype functions.",
"ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.",
"ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.",
"paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter",
"ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type."
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.x-dev"
}
},
"autoload": {
"psr-4": {
"Ramsey\\Uuid\\": "src/"
},
"files": [
"src/functions.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "A PHP library for generating and working with universally unique identifiers (UUIDs).",
"homepage": "https://github.com/ramsey/uuid",
"keywords": [
"guid",
"identifier",
"uuid"
],
"time": "2020-08-18T17:17:46+00:00"
},
{
"name": "ratchet/rfc6455",
"version": "v0.3",
"source": {
"type": "git",
"url": "https://github.com/ratchetphp/RFC6455.git",
"reference": "c8651c7938651c2d55f5d8c2422ac5e57a183341"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ratchetphp/RFC6455/zipball/c8651c7938651c2d55f5d8c2422ac5e57a183341",
"reference": "c8651c7938651c2d55f5d8c2422ac5e57a183341",
"shasum": ""
},
"require": {
"guzzlehttp/psr7": "^1.0",
"php": ">=5.4.2"
},
"require-dev": {
"phpunit/phpunit": "5.7.*",
"react/socket": "^1.3"
},
"type": "library",
"autoload": {
"psr-4": {
"Ratchet\\RFC6455\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Chris Boden",
"email": "cboden@gmail.com",
"role": "Developer"
},
{
"name": "Matt Bonneau",
"role": "Developer"
}
],
"description": "RFC6455 WebSocket protocol handler",
"homepage": "http://socketo.me",
"keywords": [
"WebSockets",
"rfc6455",
"websocket"
],
"time": "2020-05-15T18:31:24+00:00"
},
{
"name": "react/cache",
"version": "v1.1.0",
"source": {
"type": "git",
"url": "https://github.com/reactphp/cache.git",
"reference": "44a568925556b0bd8cacc7b49fb0f1cf0d706a0c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/reactphp/cache/zipball/44a568925556b0bd8cacc7b49fb0f1cf0d706a0c",
"reference": "44a568925556b0bd8cacc7b49fb0f1cf0d706a0c",
"shasum": ""
},
"require": {
"php": ">=5.3.0",
"react/promise": "^3.0 || ^2.0 || ^1.1"
},
"require-dev": {
"phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35"
},
"type": "library",
"autoload": {
"psr-4": {
"React\\Cache\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Christian Lück",
"email": "christian@clue.engineering",
"homepage": "https://clue.engineering/"
},
{
"name": "Cees-Jan Kiewiet",
"email": "reactphp@ceesjankiewiet.nl",
"homepage": "https://wyrihaximus.net/"
},
{
"name": "Jan Sorgalla",
"email": "jsorgalla@gmail.com",
"homepage": "https://sorgalla.com/"
},
{
"name": "Chris Boden",
"email": "cboden@gmail.com",
"homepage": "https://cboden.dev/"
}
],
"description": "Async, Promise-based cache interface for ReactPHP",
"keywords": [
"cache",
"caching",
"promise",
"reactphp"
],
"time": "2020-09-18T12:12:35+00:00"
},
{
"name": "react/dns",
"version": "v1.4.0",
"source": {
"type": "git",
"url": "https://github.com/reactphp/dns.git",
"reference": "665260757171e2ab17485b44e7ffffa7acb6ca1f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/reactphp/dns/zipball/665260757171e2ab17485b44e7ffffa7acb6ca1f",
"reference": "665260757171e2ab17485b44e7ffffa7acb6ca1f",
"shasum": ""
},
"require": {
"php": ">=5.3.0",
"react/cache": "^1.0 || ^0.6 || ^0.5",
"react/event-loop": "^1.0 || ^0.5",
"react/promise": "^3.0 || ^2.7 || ^1.2.1",
"react/promise-timer": "^1.2"
},
"require-dev": {
"clue/block-react": "^1.2",
"phpunit/phpunit": "^9.3 || ^4.8.35"
},
"type": "library",
"autoload": {
"psr-4": {
"React\\Dns\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Christian Lück",
"email": "christian@clue.engineering",
"homepage": "https://clue.engineering/"
},
{
"name": "Cees-Jan Kiewiet",
"email": "reactphp@ceesjankiewiet.nl",
"homepage": "https://wyrihaximus.net/"
},
{
"name": "Jan Sorgalla",
"email": "jsorgalla@gmail.com",
"homepage": "https://sorgalla.com/"
},
{
"name": "Chris Boden",
"email": "cboden@gmail.com",
"homepage": "https://cboden.dev/"
}
],
"description": "Async DNS resolver for ReactPHP",
"keywords": [
"async",
"dns",
"dns-resolver",
"reactphp"
],
"time": "2020-09-18T12:12:55+00:00"
},
{
"name": "react/event-loop",
"version": "v1.1.1",
"source": {
"type": "git",
"url": "https://github.com/reactphp/event-loop.git",
"reference": "6d24de090cd59cfc830263cfba965be77b563c13"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/reactphp/event-loop/zipball/6d24de090cd59cfc830263cfba965be77b563c13",
"reference": "6d24de090cd59cfc830263cfba965be77b563c13",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"require-dev": {
"phpunit/phpunit": "^7.0 || ^6.4 || ^5.7 || ^4.8.35"
},
"suggest": {
"ext-event": "~1.0 for ExtEventLoop",
"ext-pcntl": "For signal handling support when using the StreamSelectLoop",
"ext-uv": "* for ExtUvLoop"
},
"type": "library",
"autoload": {
"psr-4": {
"React\\EventLoop\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "ReactPHP's core reactor event loop that libraries can use for evented I/O.",
"keywords": [
"asynchronous",
"event-loop"
],
"time": "2020-01-01T18:39:52+00:00"
},
{
"name": "react/promise",
"version": "v2.8.0",
"source": {
"type": "git",
"url": "https://github.com/reactphp/promise.git",
"reference": "f3cff96a19736714524ca0dd1d4130de73dbbbc4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/reactphp/promise/zipball/f3cff96a19736714524ca0dd1d4130de73dbbbc4",
"reference": "f3cff96a19736714524ca0dd1d4130de73dbbbc4",
"shasum": ""
},
"require": {
"php": ">=5.4.0"
},
"require-dev": {
"phpunit/phpunit": "^7.0 || ^6.5 || ^5.7 || ^4.8.36"
},
"type": "library",
"autoload": {
"psr-4": {
"React\\Promise\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jan Sorgalla",
"email": "jsorgalla@gmail.com"
}
],
"description": "A lightweight implementation of CommonJS Promises/A for PHP",
"keywords": [
"promise",
"promises"
],
"time": "2020-05-12T15:16:56+00:00"
},
{
"name": "react/promise-timer",
"version": "v1.6.0",
"source": {
"type": "git",
"url": "https://github.com/reactphp/promise-timer.git",
"reference": "daee9baf6ef30c43ea4c86399f828bb5f558f6e6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/reactphp/promise-timer/zipball/daee9baf6ef30c43ea4c86399f828bb5f558f6e6",
"reference": "daee9baf6ef30c43ea4c86399f828bb5f558f6e6",
"shasum": ""
},
"require": {
"php": ">=5.3",
"react/event-loop": "^1.0 || ^0.5 || ^0.4 || ^0.3.5",
"react/promise": "^3.0 || ^2.7.0 || ^1.2.1"
},
"require-dev": {
"phpunit/phpunit": "^9.0 || ^5.7 || ^4.8.35"
},
"type": "library",
"autoload": {
"psr-4": {
"React\\Promise\\Timer\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Christian Lück",
"email": "christian@lueck.tv"
}
],
"description": "A trivial implementation of timeouts for Promises, built on top of ReactPHP.",
"homepage": "https://github.com/reactphp/promise-timer",
"keywords": [
"async",
"event-loop",
"promise",
"reactphp",
"timeout",
"timer"
],
"time": "2020-07-10T12:18:06+00:00"
},
{
"name": "react/socket",
"version": "v1.6.0",
"source": {
"type": "git",
"url": "https://github.com/reactphp/socket.git",
"reference": "e2b96b23a13ca9b41ab343268dbce3f8ef4d524a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/reactphp/socket/zipball/e2b96b23a13ca9b41ab343268dbce3f8ef4d524a",
"reference": "e2b96b23a13ca9b41ab343268dbce3f8ef4d524a",
"shasum": ""
},
"require": {
"evenement/evenement": "^3.0 || ^2.0 || ^1.0",
"php": ">=5.3.0",
"react/dns": "^1.1",
"react/event-loop": "^1.0 || ^0.5",
"react/promise": "^2.6.0 || ^1.2.1",
"react/promise-timer": "^1.4.0",
"react/stream": "^1.1"
},
"require-dev": {
"clue/block-react": "^1.2",
"phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35",
"react/promise-stream": "^1.2"
},
"type": "library",
"autoload": {
"psr-4": {
"React\\Socket\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Christian Lück",
"email": "christian@clue.engineering",
"homepage": "https://clue.engineering/"
},
{
"name": "Cees-Jan Kiewiet",
"email": "reactphp@ceesjankiewiet.nl",
"homepage": "https://wyrihaximus.net/"
},
{
"name": "Jan Sorgalla",
"email": "jsorgalla@gmail.com",
"homepage": "https://sorgalla.com/"
},
{
"name": "Chris Boden",
"email": "cboden@gmail.com",
"homepage": "https://cboden.dev/"
}
],
"description": "Async, streaming plaintext TCP/IP and secure TLS socket server and client connections for ReactPHP",
"keywords": [
"Connection",
"Socket",
"async",
"reactphp",
"stream"
],
"time": "2020-08-28T12:49:05+00:00"
},
{
"name": "react/stream",
"version": "v1.1.1",
"source": {
"type": "git",
"url": "https://github.com/reactphp/stream.git",
"reference": "7c02b510ee3f582c810aeccd3a197b9c2f52ff1a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/reactphp/stream/zipball/7c02b510ee3f582c810aeccd3a197b9c2f52ff1a",
"reference": "7c02b510ee3f582c810aeccd3a197b9c2f52ff1a",
"shasum": ""
},
"require": {
"evenement/evenement": "^3.0 || ^2.0 || ^1.0",
"php": ">=5.3.8",
"react/event-loop": "^1.0 || ^0.5 || ^0.4 || ^0.3.5"
},
"require-dev": {
"clue/stream-filter": "~1.2",
"phpunit/phpunit": "^7.0 || ^6.4 || ^5.7 || ^4.8.35"
},
"type": "library",
"autoload": {
"psr-4": {
"React\\Stream\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Event-driven readable and writable streams for non-blocking I/O in ReactPHP",
"keywords": [
"event-driven",
"io",
"non-blocking",
"pipe",
"reactphp",
"readable",
"stream",
"writable"
],
"time": "2020-05-04T10:17:57+00:00"
},
{
"name": "sensio/framework-extra-bundle",
"version": "v5.5.6",

View File

@ -12,6 +12,8 @@ twig:
appName: '%appName%'
appCron: '%appCron%'
appMasteridentity: '%appMasteridentity%'
wssuse: '%wssuse%'
wssurl: '%wssurl%'
sondeUse: '%sondeUse%'
sondeUrl: '%sondeUrl%'

View File

@ -62,6 +62,11 @@ app_theme_select:
path: /admin/theme/select/{name}
defaults: { _controller: App\Controller\ThemeController:select, name: "" }
#== Wss ==================================================================================================================
app_wss_sample:
path: /user/wss/sampble
defaults: { _controller: App\Controller\WebsocketController:sample }
#== Sonde ================================================================================================================
app_sonde:
path: /sonde

View File

@ -46,6 +46,10 @@ parameters:
casEmail: '%env(resolve:CAS_EMAIL)%'
casLastname: '%env(resolve:CAS_LASTNAME)%'
casFirstname: '%env(resolve:CAS_FIRSTNAME)%'
wssuse: '%env(resolve:WSS_USE)%'
wssport: '%env(resolve:WSS_PORT)%'
wssurl: 'wss://%env(resolve:APP_WEBURL)%/wss%env(resolve:APP_ALIAS)%'
proxyUse: '%env(resolve:PROXY_USE)%'
proxyHost: '%env(resolve:PROXY_HOST)%'

View File

@ -12,6 +12,11 @@ h1{
}
.page-maxed {
max-width:1200px;
margin:auto !important;
}
/* Sidebar Styles */
.contentsidebar {
margin-left:250px;

View File

@ -52,6 +52,11 @@ CAS_LASTNAME=lastname
CAS_FIRSTNAME=firstname
# WEBSOCKET
WSS_USE=0
WSS_PORT=5586
# Proxy
PROXY_USE=0
PROXY_HOST=

View File

@ -6,12 +6,15 @@ cd ${DIR}
cd ..
DIR=$(pwd)
# Mise en place du fichier d'environnement model
yes 2>/dev/null | cp $DIR/scripts/.env.model $DIR/.env
# Import des env
. $DIR/.env
. $DIR/.env.local
# Déclaration d'un proxy
if [[ "$PROXY_USE"=="1" ]]
if [[ "$PROXY_USE" == "1" ]]
then
export HTTP_PROXY="$PROXY_HOST:$PROXY_PORT"
export HTTPS_PROXY="$PROXY_HOST:$PROXY_PORT"
@ -23,9 +26,6 @@ then
find $DIR/var/log -mindepth 1 -mtime +7 -delete
fi
# Mise en place du fichier d'environnement model
yes 2>/dev/null | cp $DIR/scripts/.env.model $DIR/.env
# Installation des dépendances composer
echo COMPOSER = Install
composer install --quiet
@ -34,6 +34,12 @@ php bin/console app:AppInit --env=prod
php bin/console app:CronInit --env=prod
php bin/console app:Script --env=prod
# Websocket
if [[ "$WSS_USE" == "1" ]]
then
$DIR/scripts/websocket.sh restart
fi
# Permissions
echo PERMISSIONS
./scripts/perm.sh www-data

View File

@ -0,0 +1,37 @@
#!/bin/bash
# Se positionner sur la racine du projet
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
cd ${DIR}
cd ..
DIR=$(pwd)
# Import des env
. $DIR/.env
. $DIR/.env.local
# Déclaration d'un proxy
if [[ "$WSS_USE" == "1" ]]
then
# Server Websocket
if [[ "$1" != "restartifdown" ]]; then
echo WEBSOCKET = STOP
pid="$(pgrep -a -f app:Websocket| grep $APP_ALIAS)"
if [ -n "${pid}" ]; then
IFS=' ' read -r -a array <<< "$pid"
kill -9 ${array[0]};
fi
fi
# Port LISTEN ?
pid="$(pgrep -a -f app:Websocket| grep $APP_ALIAS)"
restart="yes"
if [ "$1" == "restartifdown" ] && [ -n "${pid}" ] ; then
restart="no"
fi
if [ "$restart" == "yes" ] && [ "$1" != "stop" ] ; then
echo WEBSOCKET = START
bin/console app:Websocket --name $APP_ALIAS & disown
fi
fi

View File

@ -9,6 +9,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Console\Input\ArrayInput;
use Ramsey\Uuid\Uuid;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Id\AssignedGenerator;
@ -354,6 +355,8 @@ class AppInitCommand extends Command
if(!$entity) {
$this->writelnred('Création du compte admin par défaut avec password admin - Veuillez modifier votre password admin après connexion');
$entity = new User;
$key = Uuid::uuid4();
$entity->setId(0);
$entity->setUsername("admin");
$entity->setPassword("admin");
@ -362,6 +365,7 @@ class AppInitCommand extends Command
$entity->setEmail($this->appmailnoreply);
$entity->setRoles(["ROLE_ADMIN"]);
$entity->setAvatar("admin.jpg");
$entity->setApiKey($key);
$this->em->persist($entity);
}

View File

@ -3,15 +3,11 @@
namespace App\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Console\Input\ArrayInput;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Id\AssignedGenerator;
use Ramsey\Uuid\Uuid;
use App\Entity\Script;
@ -49,7 +45,7 @@ class ScriptCommand extends Command
$output->writeln('APP = Scripts');
//$this->callscript("test");
$this->callscript("addapikey");
$output->writeln('');
@ -61,7 +57,7 @@ class ScriptCommand extends Command
private function callscript($name) {
$script=$this->em->getRepository("App:Script")->findOneBy(["name"=>$name]);
if(!$script) {
$this->writelnred("== SCRIPT = ".$name);
//$this->writelnred("== SCRIPT = ".$name);
$this->$name();
$script=new Script();
@ -72,8 +68,14 @@ class ScriptCommand extends Command
}
}
private function test() {
$this->writeln("TEST");
private function addapikey() {
$users=$this->em->getRepository("App:User")->findBy(["apikey"=>null]);
foreach($users as $user) {
$key = Uuid::uuid4();
$user->setApikey($key);
$this->em->persist($user);
$this->em->flush();
}
}

View File

@ -10,6 +10,7 @@ use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Ramsey\Uuid\Uuid;
use App\Entity\Group as Group;
use App\Entity\User as User;
@ -525,9 +526,11 @@ class SynchroUsersCommand extends Command
if(!$simulate) {
if(!$user) {
$user = new User();
$key = Uuid::uuid4();
$user->setUsername($apiuser->username);
$user->setPassword("NOPASSWORD");
$user->setApiKey($key);
}
$user->setLastname($apiuser->lastname);

View File

@ -0,0 +1,53 @@
<?php
namespace App\Command;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Doctrine\ORM\EntityManagerInterface;
use Ratchet\Http\HttpServer;
use Ratchet\Server\IoServer;
use Ratchet\WebSocket\WsServer;
use App\Websocket\MessageHandler;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputOption;
class WebsocketServerCommand extends Command
{
private $container;
private $em;
public function __construct(ContainerInterface $container,EntityManagerInterface $em)
{
parent::__construct();
$this->container = $container;
$this->em = $em;
}
protected function configure()
{
$this
->setName('app:Websocket')
->setDescription('Lauch Websocket server')
->setHelp('Lauch Websocket server')
->addOption('name',null,InputOption::VALUE_REQUIRED,'Websocket server name',null)
;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$port = $this->container->getParameter('wssport');
$output->writeln("Starting server on port " . $port);
$server = IoServer::factory(
new HttpServer(
new WsServer(
new MessageHandler($this->container,$this->em)
)
),
$port
);
$server->run();
return 0;
}
}

View File

@ -12,6 +12,7 @@ use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Ramsey\Uuid\Uuid;
class SecurityController extends AbstractController
{
@ -37,9 +38,6 @@ class SecurityController extends AbstractController
}
public function loginMYSQL(Request $request, AuthenticationUtils $authenticationUtils) {
// activer les activités par défaut
$this->get('session')->set('activeactivity',true);
return $this->render('Home/login.html.twig', array(
'last_username' => $authenticationUtils->getLastUsername(),
'error' => $authenticationUtils->getLastAuthenticationError(),
@ -87,11 +85,13 @@ class SecurityController extends AbstractController
if (!$exists) {
$user = new User();
$key = Uuid::uuid4();
$user->setUsername($username);
$user->setLastname($lastname);
$user->setFirstname($firstname);
$user->setEmail($email);
$user->setApiKey($key);
$user->setPassword("CASPWD-".$username);
$user->setSalt("CASPWD-".$username);
@ -120,8 +120,6 @@ class SecurityController extends AbstractController
$this->updateLDAP($user);
}
// activer les activités par défaut
$this->get('session')->set('activeactivity',true);
// Autoconnexion
// Récupérer le token de l'utilisateur

View File

@ -5,7 +5,7 @@ namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Form\FormError;
use Ramsey\Uuid\Uuid;
use App\Entity\User as Entity;
use App\Form\UserType as Form;
@ -37,7 +37,9 @@ class UserController extends AbstractController
// Initialisation de l'enregistrement
$em = $this->getDoctrine()->getManager();
$data = new Entity();
$key = Uuid::uuid4();
$data->setAvatar("noavatar.png");
$data->setApiKey($key);
// Création du formulaire
$form = $this->createForm(Form::class,$data,array("mode"=>"submit","appAuth"=>$this->getParameter("appAuth"),"appMasteridentity"=>$this->getParameter("appMasteridentity")));

View File

@ -0,0 +1,13 @@
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class WebsocketController extends AbstractController
{
public function sample()
{
return $this->render('Websocket/sample.html.twig');
}
}

View File

@ -103,7 +103,8 @@ class UserType extends AbstractType
$builder->add('apikey',
TextType::class, [
"label" =>"Clé Accès",
"required" => false
"required" => true,
"disabled" => true,
]
);

View File

@ -0,0 +1,114 @@
<?php
namespace App\Websocket;
use Exception;
use Ratchet\ConnectionInterface;
use Ratchet\MessageComponentInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Doctrine\ORM\EntityManagerInterface;
use SplObjectStorage;
class MessageHandler implements MessageComponentInterface
{
protected $container;
protected $em;
protected $clients;
private $subscriptions;
private $users;
public function __construct(ContainerInterface $container, EntityManagerInterface $em)
{
$this->container = $container;
$this->em = $em;
$this->clients = new SplObjectStorage;
$this->subscriptions = [];
$this->users = [];
$this->keys = [];
}
public function onOpen(ConnectionInterface $conn)
{
$this->clients->attach($conn);
$this->users[$conn->resourceId] = $conn;
}
public function onClose(ConnectionInterface $conn)
{
$data= new \stdClass;
$data->command = "adead";
$this->sendMessage($conn,$data,false);
$this->clients->detach($conn);
unset($this->users[$conn->resourceId]);
unset($this->keys[$conn->resourceId]);
unset($this->subscriptions[$conn->resourceId]);
}
public function onError(ConnectionInterface $conn, Exception $e)
{
$conn->close();
}
public function onMessage(ConnectionInterface $conn, $msg)
{
$data = json_decode($msg);
switch ($data->command) {
case "subscribe":
$this->subscriptions[$conn->resourceId] = $data->channel;
$this->keys[$conn->resourceId] = $data->key;
break;
case "meto":
if (isset($this->subscriptions[$conn->resourceId])) {
$this->sendMessage($conn,$data,false);
}
break;
case "alive":
default:
if (isset($this->subscriptions[$conn->resourceId])) {
$this->sendMessage($conn,$data);
}
break;
}
}
private function sendMessage(ConnectionInterface $conn, $data, $tome=true) {
$target = $this->subscriptions[$conn->resourceId];
foreach ($this->subscriptions as $id=>$channel) {
if ($channel == $target) {
if($tome||(!$tome&&$id!=$conn->resourceId)) {
// From
$key= $this->keys[$conn->resourceId];
$from=$this->em->getRepository("App:User")->findOneBy(["apikey"=>$key]);
// To
$key= $this->keys[$id];
$to=$this->em->getRepository("App:User")->findOneBy(["apikey"=>$key]);
// Send
if($from && $to) {
$data->from= new \stdClass;
$data->from->id = $from->getId();
$data->from->username = $from->getUsername();
$data->from->displayname = $from->getDisplayname();
$data->from->avatar = $this->getAvatar($from->getAvatar());
$data->log="== GET MSG from ".$data->from->username." to ".$to->getUsername()." = ".$data->command;
$this->users[$id]->send(json_encode($data));
}
}
}
}
}
private function getAvatar($avatar) {
if(stripos($avatar,"http")===0)
return $avatar;
else
return "/".$this->container->getParameter("appAlias")."/uploads/avatar/".$avatar;
}
}

View File

@ -1,4 +1,10 @@
{
"brick/math": {
"version": "0.9.1"
},
"cboden/ratchet": {
"version": "v0.4.3"
},
"doctrine/annotations": {
"version": "1.0",
"recipe": {
@ -81,6 +87,9 @@
"egulias/email-validator": {
"version": "2.1.17"
},
"evenement/evenement": {
"version": "v3.0.1"
},
"exsyst/swagger": {
"version": "v0.4.1"
},
@ -108,6 +117,9 @@
"config/packages/fos_rest.yaml"
]
},
"guzzlehttp/psr7": {
"version": "1.7.0"
},
"jasig/phpcas": {
"version": "1.3.8"
},
@ -194,12 +206,48 @@
"psr/event-dispatcher": {
"version": "1.0.0"
},
"psr/http-message": {
"version": "1.0.1"
},
"psr/link": {
"version": "1.0.0"
},
"psr/log": {
"version": "1.1.2"
},
"ralouphie/getallheaders": {
"version": "3.0.3"
},
"ramsey/collection": {
"version": "1.1.1"
},
"ramsey/uuid": {
"version": "4.1.1"
},
"ratchet/rfc6455": {
"version": "v0.3"
},
"react/cache": {
"version": "v1.1.0"
},
"react/dns": {
"version": "v1.4.0"
},
"react/event-loop": {
"version": "v1.1.1"
},
"react/promise": {
"version": "v2.8.0"
},
"react/promise-timer": {
"version": "v1.6.0"
},
"react/socket": {
"version": "v1.6.0"
},
"react/stream": {
"version": "v1.1.1"
},
"sensio/framework-extra-bundle": {
"version": "5.2",
"recipe": {

View File

@ -1,6 +1,9 @@
{% extends "base.html.twig" %}
{% block body %}
{% if wssuse and app.user %}
{{ render(path("app_wss_sample")) }}
{% endif %}
{% endblock %}

View File

@ -1,4 +1,12 @@
$(document).ready(function() {
$(".pick-a-color").spectrum(
{
type: "text",
showAlpha: false
}
);
var doit = true;
$("a[data-method]").on('click',function(){
@ -20,4 +28,24 @@ function ModalLoad(idmodal,title,path) {
$("#"+idmodal+" .modal-header h4").text(title);
$("#"+idmodal+" iframe").attr("src",path);
$("#"+idmodal).modal("show");
}
}
{% if wssuse %}
function subscribe(channeltype,channelkey,userkey) {
console.log("== SUBSCRIBE "+channeltype+"-"+channelkey+" with userkey "+userkey);
conn.send(JSON.stringify({
command: "subscribe",
log: "",
channel: channeltype+"-"+channelkey,
channeltype: channeltype,
channelkey: channelkey,
userkey: userkey
}));
}
function sendMessage(msg) {
json=JSON.stringify(msg);
console.log("== SEND MSG = "+json);
conn.send(json);
}
{% endif %}

View File

@ -0,0 +1,61 @@
<div id="chat" class="text-center mt-5">
<div class="mb-2">online</div>
<div id="online" style="mt-2"></div>
</div>
{% if wssuse %}
<script>
var conn;
function connect() {
conn = new WebSocket("{{wssurl}}");
conn.onopen = function(e) {
console.log("== CONNECT");
{% set userkey = "" %}
{% if app.user %}
{% set userkey = app.user.apikey %}
{%endif%}
subscribe("home",1,"{{userkey}}");
sendMessage({command: "alive"});
};
conn.onmessage = function(e) {
ret=JSON.parse(e.data);
console.log(ret.log);
switch(ret.command) {
case "alive" :
if(!$('#online'+ret.from.id).length) {
html='<img id="online'+ret.from.id+'" src="'+ret.from.avatar+'" class="avatar ml-2 mr-2" title="'+ret.from.displayname+'">';
$("#online").append(html);
}
if(ret.from.id!={{app.user.id}})
sendMessage({command: "meto"});
break;
case "adead" :
$('#online'+ret.from.id).remove();
break;
case "meto" :
if(!$('#online'+ret.from.id).length) {
html='<img id="online'+ret.from.id+'" src="'+ret.from.avatar+'" class="avatar ml-2 mr-2" title="'+ret.from.displayname+'">';
$("#online").append(html);
}
break;
}
};
conn.onclose = function(e) {
console.log("== DISCONNECT");
$('#online img').remove();
console.log('Socket is closed. Reconnect will be attempted in 1 second.', e.reason);
setTimeout(function() { connect(); }, 1000);
};
}
connect();
</script>
{% endif %}

View File

@ -34,6 +34,15 @@
{% endblock %}
</style>
{{ encore_entry_script_tags('app') }}
{% block encorescripttags %}
{% endblock %}
<script>
{{ include('Include/javascript.js.twig') }}
</script>
{% set class="" %}
{% if usemonocolor is defined and usemonocolor %}
@ -93,7 +102,7 @@
</nav>
{% endif %}
<main id="main" class="container-fluid">
<main id="main" class="container-fluid {% if maxwidth is defined and maxwidth %} page-maxed {% endif %}">
{% set contentsidebar="" %}
{% if usesidebar is defined and usesidebar %}
{% set contentsidebar="contentsidebar" %}
@ -111,19 +120,20 @@
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Modification Evènement</h5>
<h4 class="modal-title"></h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<iframe id="framemodal" frameborder=0 width="100%" height="600px"></iframe>
<iframe frameborder=0 width="100%" height="600px"></iframe>
</div>
</div>
</div>
</div>
<div id="mymodallarge" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog modal-xl">
<div class="modal-content">
@ -138,28 +148,12 @@
</div>
</div>
{{ encore_entry_script_tags('app') }}
{% block encorescripttags %}
{% endblock %}
{% block localexternalscript %}
{% endblock %}
<script>
{{ include('Include/javascript.js.twig') }}
</script>
<script>
$(".pick-a-color").spectrum(
{
type: "text",
showAlpha: false
}
);
{% block localjavascript %}
{% endblock %}

View File

@ -1 +1,2 @@
* * * * * root /var/www/html/nineschool/scripts/cron.sh &>/dev/null
* * * * * root /var/www/html/nineschool/scripts/websocket.sh restartifdown &>/dev/null