├── .env.dist ├── .gitignore ├── .php-version ├── .php_cs.cache ├── README.md ├── bin └── console ├── composer.json ├── composer.lock ├── config ├── bootstrap.php ├── bundles.php ├── jwt │ ├── private.pem │ └── public.pem ├── packages │ ├── cache.yaml │ ├── dev │ │ ├── routing.yaml │ │ └── web_profiler.yaml │ ├── doctrine.yaml │ ├── doctrine_migrations.yaml │ ├── fos_rest.yaml │ ├── framework.yaml │ ├── lexik_jwt_authentication.yaml │ ├── nelmio_api_doc.yaml │ ├── prod │ │ ├── doctrine.yaml │ │ └── routing.yaml │ ├── routing.yaml │ ├── security.yaml │ ├── test │ │ ├── framework.yaml │ │ ├── routing.yaml │ │ ├── twig.yaml │ │ ├── validator.yaml │ │ └── web_profiler.yaml │ ├── twig.yaml │ └── validator.yaml ├── preload.php ├── routes.yaml ├── routes │ ├── annotations.yaml │ ├── dev │ │ ├── framework.yaml │ │ └── web_profiler.yaml │ └── nelmio_api_doc.yaml ├── services.yaml └── services_test.yaml ├── depfile.yml ├── migrations └── .gitignore ├── psalm.xml ├── public └── index.php ├── sample.png ├── src ├── Command │ └── MeetingCommand.php ├── Controller │ ├── .gitignore │ ├── MeetingController.php │ ├── MeetingRegistrationController.php │ ├── MeetingTagController.php │ ├── UserController.php │ └── UserDeviceController.php ├── DataFixtures │ ├── .gitignore │ └── UserFixtures.php ├── Doctrine │ └── RefreshTokenManager.php ├── Entity │ ├── .UserDevice.php.swp │ ├── .gitignore │ ├── Meeting.php │ ├── Tag.php │ ├── User.php │ └── UserDevice.php ├── Event │ ├── MeetingModifiedEvent.php │ ├── MeetingRegisteredEvent.php │ ├── MeetingUnRegisteredEvent.php │ ├── MeetingUserRegisteredEvent.php │ ├── MeetingUserUnRegisteredEvent.php │ ├── UserDeviceRegisteredEvent.php │ └── UserDeviceRemovedEvent.php ├── EventListener │ └── MeetingRegisteredListener.php ├── EventSubscriber │ └── MeetingRegisteredSubscriber.php ├── Exception │ └── MyException.php ├── Form │ ├── MeetingType.php │ └── UserType.php ├── Kernel.php ├── MeetingEvents.php ├── Message │ └── MeetingMessage.php ├── MessageHandler │ └── MeetingMessageHandler.php ├── Migrations │ ├── Version20200125074328.php │ ├── Version20201222071711.php │ └── Version20201222132851.php ├── Repository │ ├── .gitignore │ ├── MeetingRepository.php │ ├── TagRepository.php │ ├── UserDeviceRepository.php │ └── UserRepository.php └── Security │ └── Voter │ └── MeetingVoter.php ├── symfony.lock ├── templates ├── base.html.twig ├── default │ └── index.html.twig ├── emails │ └── registration.html.twig ├── meeting_registration │ └── index.html.twig └── user │ └── index.html.twig ├── tests └── Util │ └── CalculatorTest.php └── ts └── index.php /.env.dist: -------------------------------------------------------------------------------- 1 | 2 | # This file is a "template" of which env vars needs to be defined in your configuration or in an .env file 3 | # Set variables here that may be different on each deployment target of the app, e.g. development, staging, production. 4 | # https://symfony.com/doc/current/best_practices/configuration.html#infrastructure-related-configuration 5 | 6 | ###> symfony/framework-bundle ### 7 | APP_ENV=dev 8 | APP_DEBUG=1 9 | APP_SECRET=67d829bf61dc5f87a73fd814e2c9f629 10 | ###< symfony/framework-bundle ### 11 | 12 | ###> doctrine/doctrine-bundle ### 13 | # Format described at http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url 14 | # For a sqlite database, use: "sqlite:///%kernel.project_dir%/var/data.db" 15 | # Set "serverVersion" to your server version to avoid edge-case exceptions and extra database calls 16 | DATABASE_URL=mysql://root:root@127.0.0.1:3306/api?charset=utf8mb4&serverVersion=mariadb-10.2.14 17 | ###< doctrine/doctrine-bundle ### 18 | 19 | ###> nelmio/cors-bundle ### 20 | CORS_ALLOW_ORIGIN=^https?://(localhost|127\.0\.0\.1)(:[0-9]+)?$ 21 | ###< nelmio/cors-bundle ### 22 | 23 | ###> symfony/messenger ### 24 | # Choose one of the transports below 25 | # MESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/messages 26 | # MESSENGER_TRANSPORT_DSN=doctrine://default 27 | # MESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages 28 | ###< symfony/messenger ### 29 | 30 | ###> lexik/jwt-authentication-bundle ### 31 | JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private.pem 32 | JWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pem 33 | JWT_PASSPHRASE=1714faf6bd29f8bd1a02d69a0d136984 34 | ###< lexik/jwt-authentication-bundle ### 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ###> symfony/framework-bundle ### 2 | /.env 3 | /public/bundles/ 4 | /var/ 5 | /vendor/ 6 | ###< symfony/framework-bundle ### 7 | tags 8 | .ctags 9 | 10 | ###> lexik/jwt-authentication-bundle ### 11 | /config/jwt/*.pem 12 | ###< lexik/jwt-authentication-bundle ### 13 | 14 | -------------------------------------------------------------------------------- /.php-version: -------------------------------------------------------------------------------- 1 | 7.4 2 | -------------------------------------------------------------------------------- /.php_cs.cache: -------------------------------------------------------------------------------- 1 | {"php":"7.2.5-1+ubuntu16.04.1+deb.sury.org+1","version":"2.12.2","rules":{"blank_line_after_namespace":true,"braces":true,"class_definition":true,"elseif":true,"function_declaration":true,"indentation_type":true,"line_ending":true,"lowercase_constants":true,"lowercase_keywords":true,"method_argument_space":{"on_multiline":"ensure_fully_multiline"},"no_break_comment":true,"no_closing_tag":true,"no_spaces_after_function_name":true,"no_spaces_inside_parenthesis":true,"no_trailing_whitespace":true,"no_trailing_whitespace_in_comment":true,"single_blank_line_at_eof":true,"single_class_element_per_statement":{"elements":["property"]},"single_import_per_statement":true,"single_line_after_imports":true,"switch_case_semicolon_to_colon":true,"switch_case_space":true,"visibility_required":true,"encoding":true,"full_opening_tag":true},"hashes":{"src\/Event\/MeetingModifiedEvent.php":3291987488,"src\/Event\/UserDeviceRegisteredEvent.php":599758648,"src\/Event\/MeetingRegisteredEvent.php":2196285934,"src\/Event\/MeetingUserRegisteredEvent.php":1234027932,"src\/Event\/MeetingUserUnRegisteredEvent.php":2033796812,"src\/Event\/MeetingUnRegisteredEvent.php":3236709851,"src\/Event\/UserDeviceRemovedEvent.php":3668399556,"src\/MeetingEvents.php":3394194698,"src\/Services\/Interfaces\/MeetingInterface.php":4170378143,"src\/Services\/MeetingService.php":3942900065,"src\/Serializer\/Normalizer\/ExceptionHandler.php":1271418393,"src\/Serializer\/Normalizer\/UserNormalizer.php":2417151589,"src\/EventSubscriber\/MeetingRegisteredSubscriber.php":16862354,"src\/Exception\/MyException.php":2670735671,"src\/Util\/Calculator.php":51273867,"src\/DependencyInjection\/RuleManagerCompilerPass.php":2661132051,"src\/DataFixtures\/UserFixtures.php":486183908,"src\/DataFixtures\/MeetingFixtures.php":1106745876,"src\/Kernel.php":1569315419,"src\/EventListener\/MeetingRegisteredListener.php":1965350084,"src\/Controller\/MeetingTagController.php":2690697174,"src\/Controller\/DefaultController.php":3224857040,"src\/Controller\/UserDeviceController.php":1827808311,"src\/Controller\/MeetingRegistrationController.php":2573131551,"src\/Controller\/MeetingController.php":207569449,"src\/Controller\/MeetingUserController.php":1563735223,"src\/Normalizer\/ExceptionNormalizer.php":2670216402,"src\/Repository\/UserRepository.php":2371032551,"src\/Repository\/TagRepository.php":3447230577,"src\/Repository\/UserDeviceRepository.php":3343829094,"src\/Repository\/MeetingRepository.php":2476684908,"src\/Service\/RuleManager.php":3268426555,"src\/Service\/RuleInterface.php":1620116641,"src\/Service\/IsNumericRule.php":877526536,"src\/Service\/GreaterThanRule.php":561809094,"src\/Entity\/Meeting.php":3051859627,"src\/Entity\/User.php":565099987,"src\/Entity\/Tag.php":1521624089,"src\/Entity\/UserDevice.php":2294109357}} -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Symfony 5 Rest API Using FOSBundle 3 with JWT 2 | =========================================== 3 | 4 | Rest API for Meetings 5 | 6 | $ cp .env.dist .env 7 | 8 | $ composer install 9 | 10 | $ php -S localhost:9100 -t public 11 | 12 | 13 | ![Api Flow](https://github.com/shambhu384/symfony5-jwt-restapi/raw/master/sample.png) 14 | 15 | # RabbitMQ Installation 16 | https://www.linuxhelp.com/how-to-install-rabbitmq-on-linuxmint-18-3/ 17 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | load(__DIR__.'/../.env'); 23 | } 24 | 25 | $input = new ArgvInput(); 26 | $env = $input->getParameterOption(['--env', '-e'], $_SERVER['APP_ENV'] ?? 'dev', true); 27 | $debug = (bool) ($_SERVER['APP_DEBUG'] ?? ('prod' !== $env)) && !$input->hasParameterOption('--no-debug', true); 28 | 29 | if ($debug) { 30 | umask(0000); 31 | 32 | if (class_exists(Debug::class)) { 33 | Debug::enable(); 34 | } 35 | } 36 | 37 | $kernel = new Kernel($env, $debug); 38 | $application = new Application($kernel); 39 | $application->run($input); 40 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "project", 3 | "license": "proprietary", 4 | "require": { 5 | "php": "^7.2.5", 6 | "ext-ctype": "*", 7 | "ext-iconv": "*", 8 | "doctrine/doctrine-migrations-bundle": "^2.1", 9 | "friendsofsymfony/rest-bundle": "^3.0", 10 | "gesdinet/jwt-refresh-token-bundle": "^0.9.1", 11 | "lexik/jwt-authentication-bundle": "^2.10", 12 | "nelmio/api-doc-bundle": "^4.0", 13 | "predis/predis": "^1.1", 14 | "symfony/asset": "5.2.*", 15 | "symfony/console": "5.2.*", 16 | "symfony/dotenv": "5.2.*", 17 | "symfony/flex": "^1.3.1", 18 | "symfony/framework-bundle": "5.2.*", 19 | "symfony/security-bundle": "5.2.*", 20 | "symfony/serializer-pack": "^1.0", 21 | "symfony/validator": "5.2.*", 22 | "symfony/yaml": "5.2.*" 23 | }, 24 | "require-dev": { 25 | "doctrine/doctrine-fixtures-bundle": "^3.4", 26 | "symfony/maker-bundle": "^1.14", 27 | "symfony/profiler-pack": "^1.0" 28 | }, 29 | "config": { 30 | "preferred-install": { 31 | "*": "dist" 32 | }, 33 | "sort-packages": true 34 | }, 35 | "autoload": { 36 | "psr-4": { 37 | "App\\": "src/" 38 | } 39 | }, 40 | "autoload-dev": { 41 | "psr-4": { 42 | "App\\Tests\\": "tests/" 43 | } 44 | }, 45 | "replace": { 46 | "paragonie/random_compat": "2.*", 47 | "symfony/polyfill-ctype": "*", 48 | "symfony/polyfill-iconv": "*", 49 | "symfony/polyfill-php72": "*", 50 | "symfony/polyfill-php71": "*", 51 | "symfony/polyfill-php70": "*", 52 | "symfony/polyfill-php56": "*" 53 | }, 54 | "scripts": { 55 | "auto-scripts": { 56 | "cache:clear": "symfony-cmd", 57 | "assets:install %PUBLIC_DIR%": "symfony-cmd" 58 | }, 59 | "post-install-cmd": [ 60 | "@auto-scripts" 61 | ], 62 | "post-update-cmd": [ 63 | "@auto-scripts" 64 | ] 65 | }, 66 | "conflict": { 67 | "symfony/symfony": "*" 68 | }, 69 | "extra": { 70 | "symfony": { 71 | "allow-contrib": false, 72 | "require": "5.2.*" 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /config/bootstrap.php: -------------------------------------------------------------------------------- 1 | =1.2) 9 | if (is_array($env = @include dirname(__DIR__).'/.env.local.php')) { 10 | $_ENV += $env; 11 | } elseif (!class_exists(Dotenv::class)) { 12 | throw new RuntimeException('Please run "composer require symfony/dotenv" to load the ".env" files configuring the application.'); 13 | } else { 14 | $path = dirname(__DIR__).'/.env'; 15 | $dotenv = new Dotenv(false); 16 | 17 | // load all the .env files 18 | if (method_exists($dotenv, 'loadEnv')) { 19 | $dotenv->loadEnv($path); 20 | } else { 21 | // fallback code in case your Dotenv component is not 4.2 or higher (when loadEnv() was added) 22 | 23 | if (file_exists($path) || !file_exists($p = "$path.dist")) { 24 | $dotenv->load($path); 25 | } else { 26 | $dotenv->load($p); 27 | } 28 | 29 | if (null === $env = $_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? null) { 30 | $dotenv->populate(array('APP_ENV' => $env = 'dev')); 31 | } 32 | 33 | if ('test' !== $env && file_exists($p = "$path.local")) { 34 | $dotenv->load($p); 35 | $env = $_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? $env; 36 | } 37 | 38 | if (file_exists($p = "$path.$env")) { 39 | $dotenv->load($p); 40 | } 41 | 42 | if (file_exists($p = "$path.$env.local")) { 43 | $dotenv->load($p); 44 | } 45 | } 46 | } 47 | 48 | $_SERVER += $_ENV; 49 | $_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? null) ?: 'dev'; 50 | $_SERVER['APP_DEBUG'] = $_SERVER['APP_DEBUG'] ?? $_ENV['APP_DEBUG'] ?? 'prod' !== $_SERVER['APP_ENV']; 51 | $_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = (int) $_SERVER['APP_DEBUG'] || filter_var($_SERVER['APP_DEBUG'], FILTER_VALIDATE_BOOLEAN) ? '1' : '0'; 52 | -------------------------------------------------------------------------------- /config/bundles.php: -------------------------------------------------------------------------------- 1 | ['all' => true], 5 | Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true], 6 | Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], 7 | Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true], 8 | Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], 9 | Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true], 10 | Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true], 11 | Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], 12 | Nelmio\ApiDocBundle\NelmioApiDocBundle::class => ['all' => true], 13 | FOS\RestBundle\FOSRestBundle::class => ['all' => true], 14 | Lexik\Bundle\JWTAuthenticationBundle\LexikJWTAuthenticationBundle::class => ['all' => true], 15 | Gesdinet\JWTRefreshTokenBundle\GesdinetJWTRefreshTokenBundle::class => ['all' => true], 16 | ]; 17 | -------------------------------------------------------------------------------- /config/jwt/private.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN ENCRYPTED PRIVATE KEY----- 2 | MIIJnzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQISrxe8Wcc7A4CAggA 3 | MB0GCWCGSAFlAwQBKgQQXVjsXKp92jfhA24bWc10bASCCVCQY7jTq2GojScQKeUr 4 | FiiwrlLdPKiGKetLoCmLiID2FkMX05AyyIrTP1qt/z6G7m0lB4wPs0yvAGQgScDb 5 | l/gfjT6ZLiOuEDH59mEoBSnISWZYhSelwqWplP5cHdAhv6+UcweVYK3pPhwvYgch 6 | oI+ER8OK2KGcK6fBFJMetSFEctcpngiZm89y7eCqc/JRENLv4ebH9TnHef1Y9nR9 7 | bHLphNw5FMZ3NfpMws2M47uM0W7Vm9k8FHwDTyzzQ+6zBJ5fh+oGL0A4p0tpbCFQ 8 | Xb+GasVCvtqs1sNasi1rOj4b/gGIN1DhgrbUI32GBgqd/qJYuQEukIX1A09jetLI 9 | S9BAXEupOfGytUdZffhb7kENOvYzb+SyplR7uALxzFHGJU45DjjQDvhTxKPz7f91 10 | /j50FrX1EOhhVhvmZ8VRgs1WkDeohDfykY7ncbHjPfX0UdeYbfrwXg+6o809I56U 11 | Rwf7HehSm41Gtx3D+ne48oXhNFCDgaqAKwK1oEiWdVXg/v/wUUteup+AB8dxD7Hy 12 | W3OuQTThWg2wr5gClvwdWsJ4aQMLTLKe4JbDxovRXG2Za1D1X52Mwl289I+9cFjt 13 | 21mMRWVrLrLvDu2gXcqHphSUATDwdQCQCqjTcoWtNn5V1x3aFX4i90FKqnoS0dYu 14 | E9VQCyn2YqqOuoIemj+6GGo8/vOrELZQ/7g3Qqsd7IwXViVrqHHMupwGkhBjhV2b 15 | sLwOnFtc3hcpBE2qVprgoOFhNaaVSlzlFBcEQoB0Je6Bfdsg9PZ3ri5iiBha4Bok 16 | wedPEEVL9MFdLZOFTqwAL9FKwnmjlp+8pYTnngmm5u+0Cm4dIKVrr2e30NMpqFeH 17 | AVb5ljKPzlGHOv85oqWDx+K/MA34GCSxke5lyUip4+djS03Sq/oVYICMDogQ8Ieo 18 | YDlvsTTCERXOzr6mrKOK63iAlSRL59cKcqBhrXcgy4Ksi9c08Q3rI1NxXGps8g30 19 | qSRCAr2mrqnU8QAWftLfhH9SOJi+A3nxg+RUgSUKgGX/QnJD8CfDpZ9wLOhHGWZq 20 | 3yYcnE89cJpol/RHmt2NAW3hm9E3iSJJakN09hsCublX2qmF33IAz2TzqB0gXWTq 21 | W43QZxLpAzC9wuvw2HWqliQf+N/uQi0yrm+aKcSXxHBf4RSiaKiS1retI/R3bnsk 22 | 2HX9o1bD0tH9+oB+459JwoDPP8wlLLkl89gldfUWYyAdduMxLvrTcd6ny5EvQYu+ 23 | 7Qnx5W7Yh7d6D2knC6hShNkqSQHEiM0haIkGkXLrjULZTPUtxLE+jFqIRi8DddNB 24 | qlfDriCP01OKwFKTnXKI5TN1WzG8j0UxtkkZeDDXrPNg7+KAMHUPp7lH8a04RsJ3 25 | xoGExMa4fM6aDU0Nz0Q6lEKpiMCrHS3y6pEwDWQhYktTyVB2t4eS/v9YpSvyi4Kn 26 | CSJwTvn1oMo8ZHsd+S96xGsRk1VOC/OBnlFSdC72d19r4g5qVT9Ack3dOcLI/HUB 27 | ED6Av8f5Vq4PBmDJrr54WQz3PdkM+9niOerzb9Xy+8hNFE9OXV7oYfnGb3hwmKxc 28 | /QBg63tEir7KQqZax+W8VV8b69a0R/u5EvXFDsUApMyG608/8awmYFlxa5JNmoLc 29 | 6rrv2FpS8zsXOQCcHyx8NhK2GVuxNW+UZlFATWEes11GSY20w4H6qK0SCu4PbLvx 30 | i/M3am9WfKfyaK0iInCbFsoywxwnUeNqYrqK8Im9DqbH5nrLrswwUuL8WHNwBETy 31 | 4vfM5h0+DL+5EXiSKcgaeVLlg6h01rxGT+3dDDX0d3cx8IpHvzWyihSocW0+UOQx 32 | lCpFAz5m0npbvcf9SOhnDD0Y8fe/UHDoNHR0uLPou2EJsZeJjPZPgSAdAXTU3iT+ 33 | ggfN1R5CG0HsPFveWwnNurYgdgGUFw51IQ2BWx6khKLANCN0VrYyElmKbP3Y85Vn 34 | ALV4g2x6KqYDUChzy9hdPxpks4v9KWdXFEJS2aJC58L68Nwt7GXbVxzYNH/HWkDK 35 | f8+MyQiZz/i/VquzBJzG5E1ZyecyLsmBdGpsYaGhH1ewEIvrOelvTgRsLra/1GF5 36 | nIMoTrejQPt0uVKAL+KGSuTQr1L3Gu/pf1mZx88EzNwzJbZygkb7PHVgpSPsessQ 37 | vjQmVuyzq84/mJ3rreLrrSiT6xf9rFWPVyexNKHLDK1hFUwKGy8dXH9/zZ2HYU4q 38 | Cn8T7UqvWNpCfS4jpjg+4NVxVUKJ5o3qSpENm4JCk2qhRToN/s3e0u6LO7MkO5K2 39 | MR7XOlBCNI3LSq47aFphr9gB8CCIY3n1v1esK5KNptTYyVw7JEdnXsUbn9mvZ+A9 40 | JLG1F9yCnrYcRUbjbTvT3v5lsGkf0GyQH6UOY/EzV+6+4k27e9pIng55U7xDBUWF 41 | 7gSarFhy6l86vp4SowYQy5tH9q1NaUZf0K3qr88xM1XDi7EToxDbL+6gS4sc8fr3 42 | EXEkH/4CzFRDXcmBiwWRq4myhKtDLgmonsDWovB4oVY2XqNPneONE7UobblT0Woi 43 | pZ5D1MThE0OQeFwV4CCcIxViJuEEutBR7khzBlTxLbPTgeLCSJ1xrSHBzvh66mmj 44 | qBBmc9VW36lRKeM+u6JXTvgIC312GwIts1ZtGE3na5FJr0Gufq9TovmEp8lrfIDi 45 | ZM4p8r6qiuVU7MpQjuL+430CIhvEay3dbNstz6BzUOiE+cR5cru/wnkydFVErPz/ 46 | qLDwaaczn38w36+YxbMKpNkEML0mOSOsL8UHrgUwdUO5sglhvLoXonWuqrWMZgG4 47 | ilgtdeOWkUDCDYJ/SMDUWnSKaduZKtF9+REwFkNeTqUb+zxwQxPoqGB8GeqyfQ/9 48 | xZfvkFPujHQWaWa99qv87dxIXIb9V+J4nB/iiz9H3FVJfQLgoaI0VNgZVBHh74+b 49 | Ab/Vfj6cwlXnq0U80qdtUhsuHQ/1z6z0bgHq3P+Wesi+kTiAmcDPqqGFDlRgy2kd 50 | 3f4cjrptn5qiOsyypq/AWtBJ/spENED46XvnKL6vprOanbuZ2ZZJmO8T99Yw9yhz 51 | sLz+3D0DPoEXlRzWxokteaxCrDo8Zi7OYOZEYtmmiEbsfwoaN2yt+EqDBlMDHOgX 52 | iuKK4nteirmxWpuX7nBoWRDUlEf30sdVvAVTyFhK4WSZxjxCKLra5EF1Xshd/psO 53 | vIfGzjPHkCPpMYuWBRBOOpoAPA== 54 | -----END ENCRYPTED PRIVATE KEY----- 55 | -------------------------------------------------------------------------------- /config/jwt/public.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxMO73KjldnfgHSHcyyr7 3 | ikgUkAML30nTuPiZB4zoCd9BorkK3t9JEh61HYpHHC9CpqMjjr3uwnWKeCl9bCmU 4 | 3biYkxoqwZh+MXQpmcQ2hJEa1bWlxmDcLQUvk7SPEs6hxbyG2aiLbLcOm9D5LwSm 5 | bIo5jRrdxBPBazt3rPJJTSBn4MqKnLhoMgvGYTqOfL3QN/3e5vDZN1qLEYO2hpRW 6 | 3vdCXEJxU8UxihftEcd0nyOHGxlKftKdFrrZSGEqYwBaEdvoMKDIX5TdtydGRHhH 7 | 26EJ3HvuF2jClmUGkaHQhrQ93qzBQ+RZzjsTXs+UYB1c77IdB2uRkIrNxxpwMHhh 8 | dIZFS1Ah+dLYI8PCmZHhYYYf7feiszWP06Qzx44ElMbCe/MTzbksSPWqljWXldSb 9 | QpuGOFCRv9SJvfVFKqRqR5MWdWrqcrfpIVsPtjp1Ln+U8d5HAexX84yD5P2XEnDa 10 | C/iA0/JHEyTFRZoJYx9LIOXHtWwSvXi2LUXvzUyUV5MRdaXxgMeqgnfJHzuzDTRg 11 | YtkQwK46Ku/vBtxG5raOPJZpmzU0yhxFSRgQCC3cb8ddWNuIQSURz7IR5at6WBLW 12 | 4EIRXlzyDKWl27l/rteRpnkQoNXpnW+i/zHf4DO5EtY6CxNDH+qLfjKe/Kz0nEFP 13 | pj3MxctGbWUxGVRMUTUTeDMCAwEAAQ== 14 | -----END PUBLIC KEY----- 15 | -------------------------------------------------------------------------------- /config/packages/cache.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | cache: 3 | # Put the unique name of your app here: the prefix seed 4 | # is used to compute stable namespaces for cache keys. 5 | #prefix_seed: your_vendor_name/app_name 6 | 7 | # The app cache caches to the filesystem by default. 8 | # Other options include: 9 | 10 | # Redis 11 | #app: cache.adapter.redis 12 | #default_redis_provider: redis://localhost 13 | 14 | # APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues) 15 | #app: cache.adapter.apcu 16 | 17 | # Namespaced pools use the above "app" backend by default 18 | pools: 19 | 20 | redis.cache: 21 | adapter: cache.adapter.redis 22 | provider: app.my_custom_redis_provider 23 | -------------------------------------------------------------------------------- /config/packages/dev/routing.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | router: 3 | strict_requirements: true 4 | -------------------------------------------------------------------------------- /config/packages/dev/web_profiler.yaml: -------------------------------------------------------------------------------- 1 | web_profiler: 2 | toolbar: true 3 | intercept_redirects: false 4 | 5 | framework: 6 | profiler: { only_exceptions: false } 7 | -------------------------------------------------------------------------------- /config/packages/doctrine.yaml: -------------------------------------------------------------------------------- 1 | doctrine: 2 | dbal: 3 | url: '%env(resolve:DATABASE_URL)%' 4 | 5 | # IMPORTANT: You MUST configure your server version, 6 | # either here or in the DATABASE_URL env var (see .env file) 7 | #server_version: '5.7' 8 | orm: 9 | auto_generate_proxy_classes: true 10 | naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware 11 | auto_mapping: true 12 | mappings: 13 | App: 14 | is_bundle: false 15 | type: annotation 16 | dir: '%kernel.project_dir%/src/Entity' 17 | prefix: 'App\Entity' 18 | alias: App 19 | -------------------------------------------------------------------------------- /config/packages/doctrine_migrations.yaml: -------------------------------------------------------------------------------- 1 | doctrine_migrations: 2 | dir_name: '%kernel.project_dir%/src/Migrations' 3 | # namespace is arbitrary but should be different from App\Migrations 4 | # as migrations classes should NOT be autoloaded 5 | namespace: DoctrineMigrations 6 | -------------------------------------------------------------------------------- /config/packages/fos_rest.yaml: -------------------------------------------------------------------------------- 1 | # Read the documentation: https://symfony.com/doc/master/bundles/FOSRestBundle/index.html 2 | fos_rest: 3 | param_fetcher_listener: true 4 | allowed_methods_listener: true 5 | view: 6 | view_response_listener: true 7 | format_listener: 8 | rules: 9 | - { path: ^/api, prefer_extension: true, fallback_format: json, priorities: [ json] } 10 | 11 | service: 12 | serializer: fos_rest.serializer.symfony 13 | -------------------------------------------------------------------------------- /config/packages/framework.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | secret: '%env(APP_SECRET)%' 3 | #default_locale: en 4 | #http_method_override: true 5 | 6 | # Enables session support. Note that the session will ONLY be started if you read or write from it. 7 | # Remove or comment this section to explicitly disable session support. 8 | session: 9 | handler_id: ~ 10 | 11 | #esi: true 12 | #fragments: true 13 | php_errors: 14 | log: true 15 | -------------------------------------------------------------------------------- /config/packages/lexik_jwt_authentication.yaml: -------------------------------------------------------------------------------- 1 | lexik_jwt_authentication: 2 | secret_key: '%env(resolve:JWT_SECRET_KEY)%' 3 | public_key: '%env(resolve:JWT_PUBLIC_KEY)%' 4 | pass_phrase: '%env(JWT_PASSPHRASE)%' 5 | user_identity_field: email 6 | -------------------------------------------------------------------------------- /config/packages/nelmio_api_doc.yaml: -------------------------------------------------------------------------------- 1 | nelmio_api_doc: 2 | models: { use_jms: false } 3 | 4 | media_types: 5 | # Default: 6 | - json 7 | - xml 8 | documentation: 9 | info: 10 | title: Meetings API 11 | description: A RestAPI for Manage Meetings 12 | version: 1.0.0 13 | 14 | components: 15 | securitySchemes: 16 | Bearer: 17 | type: http 18 | scheme: bearer 19 | bearerFormat: JWT 20 | 21 | security: 22 | - Bearer: [] 23 | paths: 24 | /api/login_check: 25 | post: 26 | tags: 27 | - Authentication 28 | summary: Login into the api. 29 | requestBody: 30 | content: 31 | application/json: 32 | schema: 33 | properties: 34 | username: 35 | type: string 36 | password: 37 | type: string 38 | type: object 39 | responses: 40 | '200': 41 | description: OK 42 | content: 43 | application/json: 44 | schema: 45 | type: object 46 | properties: 47 | token: 48 | type: string 49 | refresh_token: 50 | type: string 51 | '401': 52 | description: Invalid credentials 53 | '400': 54 | description: Invalid JSON. 55 | security: [] 56 | /api/token/refresh: 57 | post: 58 | tags: 59 | - Authentication 60 | summary: Login into the api by refresh token. 61 | requestBody: 62 | content: 63 | application/json: 64 | schema: 65 | properties: 66 | refresh_token: 67 | type: string 68 | type: object 69 | responses: 70 | '200': 71 | description: OK 72 | content: 73 | application/json: 74 | schema: 75 | type: object 76 | properties: 77 | token: 78 | type: string 79 | refresh_token: 80 | type: string 81 | '401': 82 | description: An authentication exception occurred. 83 | security: [] 84 | 85 | areas: # to filter documented areas 86 | path_patterns: 87 | - ^/api(?!(/doc|/doc.json|/token/refresh)$) 88 | 89 | 90 | -------------------------------------------------------------------------------- /config/packages/prod/doctrine.yaml: -------------------------------------------------------------------------------- 1 | doctrine: 2 | orm: 3 | auto_generate_proxy_classes: false 4 | metadata_cache_driver: 5 | type: pool 6 | pool: doctrine.system_cache_pool 7 | query_cache_driver: 8 | type: pool 9 | pool: doctrine.system_cache_pool 10 | result_cache_driver: 11 | type: pool 12 | pool: doctrine.result_cache_pool 13 | 14 | framework: 15 | cache: 16 | pools: 17 | doctrine.result_cache_pool: 18 | adapter: cache.app 19 | doctrine.system_cache_pool: 20 | adapter: cache.system 21 | -------------------------------------------------------------------------------- /config/packages/prod/routing.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | router: 3 | strict_requirements: null 4 | -------------------------------------------------------------------------------- /config/packages/routing.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | router: 3 | strict_requirements: ~ 4 | -------------------------------------------------------------------------------- /config/packages/security.yaml: -------------------------------------------------------------------------------- 1 | security: 2 | encoders: 3 | App\Entity\User: 4 | algorithm: auto 5 | 6 | # https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers 7 | providers: 8 | # used to reload user from session & other features (e.g. switch_user) 9 | app_user_provider: 10 | entity: 11 | class: App\Entity\User 12 | property: email 13 | 14 | firewalls: 15 | 16 | apidoc: 17 | pattern: ^/api/doc 18 | anonymous: true 19 | 20 | 21 | login: 22 | pattern: ^/api/login 23 | stateless: true 24 | anonymous: true 25 | json_login: 26 | check_path: /api/login_check 27 | success_handler: lexik_jwt_authentication.handler.authentication_success 28 | failure_handler: lexik_jwt_authentication.handler.authentication_failure 29 | refresh: 30 | pattern: ^/api/token/refresh 31 | stateless: true 32 | anonymous: true 33 | 34 | api: 35 | pattern: ^/api 36 | stateless: true 37 | guard: 38 | authenticators: 39 | - lexik_jwt_authentication.jwt_token_authenticator 40 | 41 | access_control: 42 | - { path: ^/api/doc, roles: IS_AUTHENTICATED_ANONYMOUSLY } 43 | - { path: ^/api/login, roles: IS_AUTHENTICATED_ANONYMOUSLY } 44 | - { path: ^/api/token/refresh, roles: IS_AUTHENTICATED_ANONYMOUSLY } 45 | - { path: ^/api, roles: IS_AUTHENTICATED_FULLY } 46 | -------------------------------------------------------------------------------- /config/packages/test/framework.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | test: true 3 | session: 4 | storage_id: session.storage.mock_file 5 | -------------------------------------------------------------------------------- /config/packages/test/routing.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | router: 3 | strict_requirements: true 4 | -------------------------------------------------------------------------------- /config/packages/test/twig.yaml: -------------------------------------------------------------------------------- 1 | twig: 2 | strict_variables: true 3 | -------------------------------------------------------------------------------- /config/packages/test/validator.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | validation: 3 | not_compromised_password: false 4 | -------------------------------------------------------------------------------- /config/packages/test/web_profiler.yaml: -------------------------------------------------------------------------------- 1 | web_profiler: 2 | toolbar: false 3 | intercept_redirects: false 4 | 5 | framework: 6 | profiler: { collect: false } 7 | -------------------------------------------------------------------------------- /config/packages/twig.yaml: -------------------------------------------------------------------------------- 1 | twig: 2 | default_path: '%kernel.project_dir%/templates' 3 | -------------------------------------------------------------------------------- /config/packages/validator.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | validation: 3 | email_validation_mode: html5 4 | 5 | # Enables validator auto-mapping support. 6 | # For instance, basic validation constraints will be inferred from Doctrine's metadata. 7 | #auto_mapping: 8 | # App\Entity\: [] 9 | -------------------------------------------------------------------------------- /config/preload.php: -------------------------------------------------------------------------------- 1 | get() won't work. 13 | # The best practice is to be explicit about your dependencies anyway. 14 | 15 | # makes classes in src/ available to be used as services 16 | # this creates a service per class whose id is the fully-qualified class name 17 | App\: 18 | resource: '../src/*' 19 | exclude: '../src/{Entity,Migrations,Tests,Kernel.php}' 20 | 21 | # controllers are imported separately to make sure services can be injected 22 | # as action arguments even if you don't extend any base controller class 23 | App\Controller\: 24 | resource: '../src/Controller' 25 | tags: ['controller.service_arguments'] 26 | 27 | # add more service definitions when explicit configuration is needed 28 | # please note that last definitions always *replace* previous ones 29 | sensio_framework_extra.view.listener: 30 | alias: Sensio\Bundle\FrameworkExtraBundle\EventListener\TemplateListener 31 | 32 | 33 | App\MessageHandler\: 34 | resource: '../src/MessageHandler' 35 | tags: ['messenger.message_handler'] 36 | 37 | app.my_custom_redis_provider: 38 | class: \Redis 39 | factory: ['Symfony\Component\Cache\Adapter\RedisAdapter', 'createConnection'] 40 | arguments: 41 | - 'redis://localhost' 42 | - { retry_interval: 2, timeout: 10 } 43 | 44 | gesdinet.jwtrefreshtoken.refresh_token_manager: 45 | class: App\Doctrine\RefreshTokenManager 46 | public: true 47 | arguments: [ '@doctrine.orm.default_entity_manager', 'Gesdinet\JWTRefreshTokenBundle\Entity\RefreshToken'] 48 | 49 | -------------------------------------------------------------------------------- /config/services_test.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | _defaults: 3 | public: true 4 | 5 | # If you need to access services in a test, create an alias 6 | # and then fetch that alias from the container. As a convention, 7 | # aliases are prefixed with test. For example: 8 | # 9 | # test.App\Service\MyService: '@App\Service\MyService' 10 | -------------------------------------------------------------------------------- /depfile.yml: -------------------------------------------------------------------------------- 1 | # depfile.yml 2 | paths: 3 | - ./src 4 | exclude_files: 5 | - .*test.* 6 | layers: 7 | - name: Controller 8 | collectors: 9 | - type: className 10 | regex: .*Controller.* 11 | - name: Repository 12 | collectors: 13 | - type: className 14 | regex: .*Repository.* 15 | - name: Service 16 | collectors: 17 | - type: className 18 | regex: .*Service.* 19 | ruleset: 20 | Controller: 21 | - Service 22 | Service: 23 | - Repository 24 | Repository: ~ -------------------------------------------------------------------------------- /migrations/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shambhu384/symfony5-jwt-restapi/0264a7be4cad4516d89235a6b3ad692e1e6bdf79/migrations/.gitignore -------------------------------------------------------------------------------- /psalm.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | load(__DIR__.'/../.env'); 16 | } 17 | 18 | $env = $_SERVER['APP_ENV'] ?? 'dev'; 19 | $debug = (bool) ($_SERVER['APP_DEBUG'] ?? ('prod' !== $env)); 20 | 21 | if ($debug) { 22 | umask(0000); 23 | 24 | Debug::enable(); 25 | } 26 | 27 | if ($trustedProxies = $_SERVER['TRUSTED_PROXIES'] ?? false) { 28 | Request::setTrustedProxies(explode(',', $trustedProxies), Request::HEADER_X_FORWARDED_ALL ^ Request::HEADER_X_FORWARDED_HOST); 29 | } 30 | 31 | if ($trustedHosts = $_SERVER['TRUSTED_HOSTS'] ?? false) { 32 | Request::setTrustedHosts(explode(',', $trustedHosts)); 33 | } 34 | 35 | $kernel = new Kernel($env, $debug); 36 | $request = Request::createFromGlobals(); 37 | $response = $kernel->handle($request); 38 | $response->send(); 39 | $kernel->terminate($request, $response); 40 | -------------------------------------------------------------------------------- /sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shambhu384/symfony5-jwt-restapi/0264a7be4cad4516d89235a6b3ad692e1e6bdf79/sample.png -------------------------------------------------------------------------------- /src/Command/MeetingCommand.php: -------------------------------------------------------------------------------- 1 | setDescription('Add a short description for your command') 20 | ->addArgument('arg1', InputArgument::OPTIONAL, 'Argument description') 21 | ->addOption('option1', null, InputOption::VALUE_NONE, 'Option description') 22 | ; 23 | } 24 | 25 | protected function execute(InputInterface $input, OutputInterface $output) 26 | { 27 | $io = new SymfonyStyle($input, $output); 28 | $arg1 = $input->getArgument('arg1'); 29 | 30 | if ($arg1) { 31 | $io->note(sprintf('You passed an argument: %s', $arg1)); 32 | } 33 | 34 | if ($input->getOption('option1')) { 35 | // ... 36 | } 37 | 38 | $io->success('You have a new command! Now make it your own! Pass --help to see your options.'); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Controller/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shambhu384/symfony5-jwt-restapi/0264a7be4cad4516d89235a6b3ad692e1e6bdf79/src/Controller/.gitignore -------------------------------------------------------------------------------- /src/Controller/MeetingController.php: -------------------------------------------------------------------------------- 1 | deserialize($request->getContent(), Meeting::class, 'json'); 79 | } catch (NotEncodableValueException $exception) { 80 | throw new HttpException(Response::HTTP_BAD_REQUEST, 'Invalid Json'); 81 | } 82 | 83 | $errors = $validator->validate($meeting); 84 | 85 | if (count($errors) > 0) { 86 | /* 87 | * Uses a __toString method on the $errors variable which is a 88 | * ConstraintViolationList object. This gives us a nice string 89 | * for debugging. 90 | */ 91 | $json = $serializer->serialize($errors, 'json', array_merge([ 92 | 'json_encode_options' => JsonResponse::DEFAULT_ENCODING_OPTIONS, 93 | ], [])); 94 | 95 | return new JsonResponse($json, Response::HTTP_BAD_REQUEST, [], true); 96 | } 97 | 98 | $meeting->setOrganiser($this->getUser()->getId()); 99 | 100 | $em->persist($meeting); 101 | $em->flush(); 102 | 103 | $dispatcher->dispatch(new MeetingRegisteredEvent($meeting)); 104 | return new Response(null, Response::HTTP_CREATED); 105 | } 106 | 107 | /** 108 | * Lists all Meetings. 109 | * @Route("/meetings", name="get_all", methods={"GET"}) 110 | * 111 | * @OA\Response( 112 | * response=200, 113 | * description="Returns the meetings of an user", 114 | * @OA\JsonContent( 115 | * type="array", 116 | * @OA\Items(ref=@Model(type=Meeting::class, groups={"full"})) 117 | * ) 118 | * ) 119 | * @OA\Parameter( 120 | * name="order", 121 | * in="query", 122 | * description="The field used to order meetings", 123 | * @OA\Schema(type="string") 124 | * ) 125 | * @OA\Tag(name="Meetings") 126 | * @Security(name="Bearer") 127 | 128 | */ 129 | public function getMeetings(CacheInterface $redisCache, MeetingRepository $meetingRepository, SerializerInterface $serializer) { 130 | // add pagination on data using ParamFetcherInterface 131 | 132 | $meetings = $redisCache->get('meetings', function (ItemInterface $item) use ($meetingRepository) { 133 | return $meetingRepository->findAll(); 134 | }); 135 | 136 | $context = new Context(); 137 | $context->setVersion('1.0'); 138 | $context->addGroup('user'); 139 | 140 | $view = $this->view($meetings, 200); 141 | $view->setContext($context); 142 | 143 | 144 | return $this->handleView($view); 145 | } 146 | 147 | /** 148 | * Get Meeting. 149 | * 150 | * @OA\Response( 151 | * response=200, 152 | * description="Returns the meetings of an user", 153 | * @OA\JsonContent( 154 | * type="array", 155 | * @OA\Items(ref=@Model(type=Meeting::class, groups={"full"})) 156 | * ) 157 | * ) 158 | * @OA\Parameter( 159 | * name="order", 160 | * in="query", 161 | * description="The field used to order meetings", 162 | * @OA\Schema(type="string") 163 | * ) 164 | * @OA\Tag(name="Meetings") 165 | * @Security(name="Bearer") 166 | * @Route("/meetings/{id<\d+>?1}", name="meeting_index", methods={"GET"}) 167 | */ 168 | public function getMeeting($id, MeetingRepository $meetingRepository): Response 169 | { 170 | // query for a single Product by its primary key (usually "id") 171 | $meeting = $meetingRepository->find($id); 172 | if (!$meeting) { 173 | throw new HttpException(404, 'Meeting not found'); 174 | } 175 | 176 | $context = new Context(); 177 | $context->setVersion('1.0'); 178 | $context->addGroup('user'); 179 | 180 | $view = $this->view($meeting, 200); 181 | $view->setContext($context); 182 | 183 | // Move this in Meeting normalizer 184 | return $this->handleView($view); 185 | } 186 | 187 | /** 188 | * Update an Meeting. 189 | * 190 | * @OA\Response( 191 | * response=200, 192 | * description="Returns the meetings of an user", 193 | * @OA\JsonContent( 194 | * type="array", 195 | * @OA\Items(ref=@Model(type=Meeting::class, groups={"full"})) 196 | * ) 197 | * ) 198 | * @OA\Parameter( 199 | * name="order", 200 | * in="query", 201 | * description="The field used to order meetings", 202 | * @OA\Schema(type="string") 203 | * ) 204 | * @OA\Tag(name="Meetings") 205 | * @Security(name="Bearer") 206 | * 207 | * @Route("/meetings/{id<\d+>?1}", name="meeting_put", methods={"PUT"}) 208 | * @return View 209 | */ 210 | public function putMeeting($id, Request $request, MeetingRepository $meetingRepository, EntityManagerInterface $em): View 211 | { 212 | $meeting = $meetingRepository->find($id); 213 | if (!$meeting) { 214 | throw new HttpException(404, 'Meeting not found'); 215 | } 216 | $postdata = json_decode($request->getContent()); 217 | $meeting->setDescription($postdata->description); 218 | $meeting->setDateTime(new \DateTime($postdata->datetime)); 219 | $em->persist($meeting); 220 | $em->flush(); 221 | return View::create($meeting, Response::HTTP_OK, []); 222 | } 223 | 224 | /** 225 | * Delete an Meeting. 226 | * 227 | * @OA\Parameter( 228 | * name="order", 229 | * in="query", 230 | * description="The field used to order meetings", 231 | * @OA\Schema(type="string") 232 | * ) 233 | * @OA\Tag(name="Meetings") 234 | * @Security(name="Bearer") 235 | * 236 | * @Route("/meetings/{id<\d+>?1}", name="meeting_delete", methods={"DELETE"}) 237 | * @return View 238 | */ 239 | public function deleteMeeting($id, Request $request, MeetingRepository $meetingRepository, EntityManagerInterface $em): View 240 | { 241 | $meeting = $meetingRepository->find($id); 242 | if (!$meeting) { 243 | throw new HttpException(404, 'Meeting not found'); 244 | } 245 | $em->remove($meeting); 246 | $em->flush(); 247 | return View::create(null, Response::HTTP_NO_CONTENT); 248 | } 249 | } 250 | -------------------------------------------------------------------------------- /src/Controller/MeetingRegistrationController.php: -------------------------------------------------------------------------------- 1 | findBy(array('id' => $request->get('user_id'))); 38 | if (!$user) { 39 | throw new HttpException(400, 'Userid invalid.'); 40 | } 41 | 42 | $meeting = $meetingRepository->find(array('id' => $request->get('meeting_id'))); 43 | if (!$meeting) { 44 | throw new HttpException(400, 'Meetingid invalid.'); 45 | } 46 | 47 | $user->setMeeting($meeting); 48 | $meeting->setUser($user); 49 | 50 | $em->persist($user); 51 | $em->persist($meeting); 52 | $em->flush(); 53 | return new Response('', Response::HTTP_NO_CONTENT, []); 54 | } 55 | 56 | /** 57 | * Unregister 58 | * 59 | * @Route("/meetings/{id}/unregister/{user}", name="meeting_user_unregister", methods={"POST"}) 60 | * @OA\Tag(name="Meetings") 61 | */ 62 | public function unregisterUserMeeting( 63 | EntityManagerInterface $em, 64 | MeetingRepository $meetingRepository, 65 | Request $request, 66 | UserRepository $userRepository 67 | ): Response 68 | { 69 | // Check user already exists 70 | $user = $userRepository->findBy(array('id' => $request->get('user_id'))); 71 | if (!$user) { 72 | throw new HttpException(400, 'Userid invalid.'); 73 | } 74 | 75 | $meeting = $meetingRepository->find(array('id' => $request->get('meeting_id'))); 76 | if (!$meeting) { 77 | throw new HttpException(400, 'Meetingid invalid.'); 78 | } 79 | 80 | $user->removeMeeting($meeting); 81 | //$meeting->removeUser($user); 82 | $em->remove($meeting); 83 | //$em->remove($user); 84 | $em->flush(); 85 | return new Response('', Response::HTTP_NO_CONTENT, []); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/Controller/MeetingTagController.php: -------------------------------------------------------------------------------- 1 | 1], Response::HTTP_CREATED, []); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Controller/UserController.php: -------------------------------------------------------------------------------- 1 | deserialize($request->getContent(), User::class, 'json'); 65 | } catch (NotEncodableValueException $exception) { 66 | throw new HttpException(Response::HTTP_BAD_REQUEST, 'Invalid Json'); 67 | } 68 | 69 | $errors = $validator->validate($user); 70 | 71 | if (count($errors) > 0) { 72 | /* 73 | * Uses a __toString method on the $errors variable which is a 74 | * ConstraintViolationList object. This gives us a nice string 75 | * for debugging. 76 | */ 77 | $json = $serializer->serialize($errors, 'json', array_merge([ 78 | 'json_encode_options' => JsonResponse::DEFAULT_ENCODING_OPTIONS, 79 | ], [])); 80 | 81 | return new JsonResponse($json, Response::HTTP_BAD_REQUEST, [], true); 82 | } 83 | 84 | $em->persist($user); 85 | $em->flush(); 86 | 87 | return new Response(null, Response::HTTP_CREATED); 88 | } 89 | 90 | /** 91 | */ 92 | public function getUsers(AdapterInterface $cache, EntityManagerInterface $em, UserRepository $userRepository): Response 93 | { 94 | // add pagination on data using ParamFetcherInterface 95 | $limit = $paramFetcher->get('limit'); 96 | $page = $limit * ($paramFetcher->get('page') - 1); 97 | $users = $userRepository->findAll(array(), array('id' => $paramFetcher->get('sort')), $limit, $page); 98 | // Move this in User normalizer 99 | $response = array(); 100 | if (count($users) > 0) { 101 | foreach ($users as $user) { 102 | // find users 103 | $response[] = array( 104 | 'id' => $user->getId(), 105 | 'name' => $user->getFullName(), 106 | 'email' => $user->getEmail() 107 | ); 108 | } 109 | } 110 | 111 | return new Response(array( 112 | "metadata" => array("limit" => (int)$limit, "start"=> $page), 113 | 'collections' => $response 114 | ), Response::HTTP_OK, []); 115 | } 116 | 117 | /** 118 | * Get User 119 | * 120 | * @Route("/users/{id}", name="users_get", methods={"GET"}) 121 | * @OA\Tag(name="Users") 122 | * @return Response 123 | */ 124 | public function getApiUser($id, UserRepository $userRepository): View 125 | { 126 | // query for a single Product by its primary key (usually "id") 127 | $user = $userRepository->find($id); 128 | if (!$user) { 129 | throw new HttpException(404, 'User not found'); 130 | } 131 | 132 | $context = new Context(); 133 | $context->setVersion('1.0'); 134 | $context->addGroup('user'); 135 | 136 | $view = $this->view($user, 200); 137 | $view->setContext($context); 138 | 139 | return $this->handleView($view); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/Controller/UserDeviceController.php: -------------------------------------------------------------------------------- 1 | 1], Response::HTTP_CREATED, []); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/DataFixtures/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shambhu384/symfony5-jwt-restapi/0264a7be4cad4516d89235a6b3ad692e1e6bdf79/src/DataFixtures/.gitignore -------------------------------------------------------------------------------- /src/DataFixtures/UserFixtures.php: -------------------------------------------------------------------------------- 1 | encoder = $encoder; 18 | } 19 | 20 | // ... 21 | public function load(ObjectManager $manager) 22 | { 23 | $user = new User(); 24 | $user->setEmail('admin@lp.com'); 25 | 26 | $password = $this->encoder->encodePassword($user, 'pass_1234'); 27 | $user->setPassword($password); 28 | 29 | $manager->persist($user); 30 | $manager->flush(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Doctrine/RefreshTokenManager.php: -------------------------------------------------------------------------------- 1 | objectManager = $om; 12 | $this->repository = $om->getRepository($class); 13 | $metadata = $om->getClassMetadata($class); 14 | $this->class = $metadata->getName(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Entity/.UserDevice.php.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shambhu384/symfony5-jwt-restapi/0264a7be4cad4516d89235a6b3ad692e1e6bdf79/src/Entity/.UserDevice.php.swp -------------------------------------------------------------------------------- /src/Entity/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shambhu384/symfony5-jwt-restapi/0264a7be4cad4516d89235a6b3ad692e1e6bdf79/src/Entity/.gitignore -------------------------------------------------------------------------------- /src/Entity/Meeting.php: -------------------------------------------------------------------------------- 1 | users = new ArrayCollection(); 98 | $this->tags = new ArrayCollection(); 99 | } 100 | 101 | 102 | /** 103 | * Get id. 104 | * 105 | * @return int 106 | */ 107 | public function getId(): int 108 | { 109 | return $this->id; 110 | } 111 | 112 | /** 113 | * Set id. 114 | * 115 | * @param int $id 116 | * 117 | * @return self 118 | */ 119 | public function setId(int $id) 120 | { 121 | $this->id = $id; 122 | 123 | } 124 | 125 | /** 126 | * Get name. 127 | * 128 | * @return string 129 | */ 130 | public function getName(): ?string 131 | { 132 | return $this->name; 133 | } 134 | 135 | /** 136 | * Set name. 137 | * 138 | * @param string $name 139 | */ 140 | public function setName($name) 141 | { 142 | $this->name = $name; 143 | } 144 | 145 | /** 146 | * Get description. 147 | * 148 | * @return string 149 | */ 150 | public function getDescription(): ?string 151 | { 152 | return $this->description; 153 | } 154 | 155 | /** 156 | * Set description. 157 | * 158 | * @param string $description 159 | */ 160 | public function setDescription($description) 161 | { 162 | $this->description = $description; 163 | } 164 | 165 | /** 166 | * @param User $user 167 | */ 168 | public function setUser(User $user) 169 | { 170 | if ($this->users->contains($user)) { 171 | return; 172 | } 173 | $this->users->add($user); 174 | $user->setMeeting($this); 175 | } 176 | 177 | /** 178 | * @param User $user 179 | */ 180 | public function removeUser(User $user) 181 | { 182 | if (!$this->users->contains($user)) { 183 | return; 184 | } 185 | $this->users->removeElement($user); 186 | $user->removeMeeting($this); 187 | } 188 | 189 | /** 190 | * @param Tag $tag 191 | */ 192 | public function setTag(Tag $tag) 193 | { 194 | if ($this->tags->contains($tag)) { 195 | return; 196 | } 197 | $this->tags->add($tag); 198 | } 199 | 200 | /** 201 | * @param Tag $tag 202 | */ 203 | public function removeTag(Tag $tag) 204 | { 205 | if (!$this->tags->contains($tag)) { 206 | return; 207 | } 208 | $this->tags->removeElement($tag); 209 | $tag->removeMeeting($this); 210 | } 211 | 212 | /** 213 | * Get users. 214 | * 215 | * @return Collection 216 | */ 217 | public function getUsers(): Collection 218 | { 219 | return $this->users; 220 | } 221 | 222 | /** 223 | * @return Collection 224 | */ 225 | public function getTags(): Collection 226 | { 227 | return $this->tags; 228 | } 229 | 230 | public function addTag(Tag $tag): self 231 | { 232 | if (!$this->tags->contains($tag)) { 233 | $this->tags[] = $tag; 234 | $tag->addMeeting($this); 235 | } 236 | 237 | return $this; 238 | } 239 | 240 | public function getOrganiser(): ?int 241 | { 242 | return $this->organiser; 243 | } 244 | 245 | public function setOrganiser(int $organiser): self 246 | { 247 | $this->organiser = $organiser; 248 | 249 | return $this; 250 | } 251 | 252 | /** 253 | * Pre persist event listener 254 | * 255 | * @ORM\PrePersist 256 | * 257 | * @return void 258 | */ 259 | public function beforeSave() 260 | { 261 | $this->createdAt = new DateTime('now', new \DateTimeZone('UTC')); 262 | $this->updatedAt = new DateTime('now', new \DateTimeZone('UTC')); 263 | } 264 | 265 | /** 266 | * Pre update event handler 267 | * 268 | * @ORM\PreUpdate 269 | * 270 | * @return void 271 | */ 272 | public function doPreUpdate() 273 | { 274 | $this->updatedAt = new DateTime('now', new \DateTimeZone('UTC')); 275 | } 276 | 277 | /** 278 | * Get created date/time 279 | * 280 | * @return \DateTime 281 | */ 282 | public function getCreatedAt() 283 | { 284 | return $this->createdAt; 285 | } 286 | /** 287 | * Set created at 288 | * 289 | * @param DateTime $created timestamp 290 | * 291 | * @return self 292 | */ 293 | public function setCreatedAt($created) 294 | { 295 | $this->createdAt = $created; 296 | return $this; 297 | } 298 | /** 299 | * Get last update date/time 300 | * 301 | * @return \DateTime 302 | */ 303 | public function getUpdatedAt() 304 | { 305 | return $this->updatedAt; 306 | } 307 | 308 | /** 309 | * Set updated at 310 | * 311 | * @param DateTime $updated timestamp 312 | * 313 | * @return self 314 | */ 315 | public function setUpdatedAt($updated) 316 | { 317 | $this->updatedAt = $updated; 318 | return $this; 319 | } 320 | 321 | /** 322 | * {@inherit} 323 | * 324 | * @return string 325 | */ 326 | public function __toString(): string 327 | { 328 | return (string) $this->getName(); 329 | } 330 | 331 | public function getMeetingAt(): ?\DateTimeInterface 332 | { 333 | return $this->meetingAt; 334 | } 335 | 336 | public function setMeetingAt(\DateTimeInterface $meetingAt): self 337 | { 338 | $this->meetingAt = $meetingAt; 339 | 340 | return $this; 341 | } 342 | } 343 | -------------------------------------------------------------------------------- /src/Entity/Tag.php: -------------------------------------------------------------------------------- 1 | meetings = new ArrayCollection(); 50 | } 51 | 52 | public function getId() 53 | { 54 | return $this->id; 55 | } 56 | 57 | public function getName(): ?string 58 | { 59 | return $this->name; 60 | } 61 | 62 | public function setName(string $name): self 63 | { 64 | $this->name = $name; 65 | 66 | return $this; 67 | } 68 | 69 | /** 70 | * @return Collection|Meeting[] 71 | */ 72 | public function getMeetings(): Collection 73 | { 74 | return $this->meetings; 75 | } 76 | 77 | public function addMeeting(Meeting $meeting): self 78 | { 79 | if (!$this->meetings->contains($meeting)) { 80 | $this->meetings[] = $meeting; 81 | } 82 | 83 | return $this; 84 | } 85 | 86 | public function removeMeeting(Meeting $meeting): self 87 | { 88 | if ($this->meetings->contains($meeting)) { 89 | $this->meetings->removeElement($meeting); 90 | } 91 | 92 | return $this; 93 | } 94 | 95 | /** 96 | * Pre persist event listener 97 | * 98 | * @ORM\PrePersist 99 | */ 100 | public function beforeSave() 101 | { 102 | $this->createdAt = new \DateTime('now', new \DateTimeZone('UTC')); 103 | $this->updatedAt = new \DateTime('now', new \DateTimeZone('UTC')); 104 | } 105 | /** 106 | * Pre update event handler 107 | * 108 | * @ORM\PreUpdate 109 | */ 110 | public function doPreUpdate() 111 | { 112 | $this->updatedAt = new \DateTime('now', new \DateTimeZone('UTC')); 113 | } 114 | 115 | /** 116 | * Get created date/time 117 | * 118 | * @return \DateTime 119 | */ 120 | public function getCreatedAt() 121 | { 122 | return $this->createdAt; 123 | } 124 | /** 125 | * @param \DateTime 126 | * 127 | * @return Account 128 | */ 129 | public function setCreatedAt($created) 130 | { 131 | $this->createdAt = $created; 132 | return $this; 133 | } 134 | /** 135 | * Get last update date/time 136 | * 137 | * @return \DateTime 138 | */ 139 | public function getUpdatedAt() 140 | { 141 | return $this->updatedAt; 142 | } 143 | /** 144 | * @param \DateTime 145 | * 146 | * @return Account 147 | */ 148 | public function setUpdatedAt($updated) 149 | { 150 | $this->updatedAt = $updated; 151 | return $this; 152 | } 153 | 154 | public function __toString() 155 | { 156 | return (string) $this->getName(); 157 | } 158 | 159 | } 160 | -------------------------------------------------------------------------------- /src/Entity/User.php: -------------------------------------------------------------------------------- 1 | id; 43 | } 44 | 45 | public function getEmail(): ?string 46 | { 47 | return $this->email; 48 | } 49 | 50 | public function setEmail(string $email): self 51 | { 52 | $this->email = $email; 53 | 54 | return $this; 55 | } 56 | 57 | /** 58 | * A visual identifier that represents this user. 59 | * 60 | * @see UserInterface 61 | */ 62 | public function getUsername(): string 63 | { 64 | return (string) $this->email; 65 | } 66 | 67 | /** 68 | * @see UserInterface 69 | */ 70 | public function getRoles(): array 71 | { 72 | $roles = $this->roles; 73 | // guarantee every user at least has ROLE_USER 74 | $roles[] = 'ROLE_USER'; 75 | 76 | return array_unique($roles); 77 | } 78 | 79 | public function setRoles(array $roles): self 80 | { 81 | $this->roles = $roles; 82 | 83 | return $this; 84 | } 85 | 86 | /** 87 | * @see UserInterface 88 | */ 89 | public function getPassword(): string 90 | { 91 | return (string) $this->password; 92 | } 93 | 94 | public function setPassword(string $password): self 95 | { 96 | $this->password = $password; 97 | 98 | return $this; 99 | } 100 | 101 | /** 102 | * @see UserInterface 103 | */ 104 | public function getSalt() 105 | { 106 | // not needed when using the "bcrypt" algorithm in security.yaml 107 | } 108 | 109 | /** 110 | * @see UserInterface 111 | */ 112 | public function eraseCredentials() 113 | { 114 | // If you store any temporary, sensitive data on the user, clear it here 115 | // $this->plainPassword = null; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/Entity/UserDevice.php: -------------------------------------------------------------------------------- 1 | id; 76 | } 77 | 78 | public function getAppid(): ?string 79 | { 80 | return $this->appid; 81 | } 82 | 83 | public function setAppid(string $appid): self 84 | { 85 | $this->appid = $appid; 86 | 87 | return $this; 88 | } 89 | 90 | public function getName(): ?string 91 | { 92 | return $this->name; 93 | } 94 | 95 | public function setName(string $name): self 96 | { 97 | $this->name = $name; 98 | 99 | return $this; 100 | } 101 | 102 | public function getModel(): ?string 103 | { 104 | return $this->model; 105 | } 106 | 107 | public function setModel(?string $model): self 108 | { 109 | $this->model = $model; 110 | 111 | return $this; 112 | } 113 | 114 | public function getPlatform(): ?string 115 | { 116 | return $this->platform; 117 | } 118 | 119 | public function setPlatform(?string $platform): self 120 | { 121 | $this->platform = $platform; 122 | 123 | return $this; 124 | } 125 | 126 | public function getVersion(): ?string 127 | { 128 | return $this->version; 129 | } 130 | 131 | public function setVersion(?string $version): self 132 | { 133 | $this->version = $version; 134 | 135 | return $this; 136 | } 137 | 138 | public function getPushid(): ?string 139 | { 140 | return $this->pushid; 141 | } 142 | 143 | public function setPushid(?string $pushid): self 144 | { 145 | $this->pushid = $pushid; 146 | 147 | return $this; 148 | } 149 | 150 | public function getUuid(): ?string 151 | { 152 | return $this->uuid; 153 | } 154 | 155 | public function setUuid(?string $uuid): self 156 | { 157 | $this->uuid = $uuid; 158 | 159 | return $this; 160 | } 161 | 162 | public function getUserid(): ?User 163 | { 164 | return $this->userid; 165 | } 166 | 167 | public function setUserid(?User $userid): self 168 | { 169 | $this->userid = $userid; 170 | 171 | return $this; 172 | } 173 | 174 | /** 175 | * Pre persist event listener 176 | * 177 | * @ORM\PrePersist 178 | */ 179 | public function beforeSave() 180 | { 181 | $this->createdAt = new \DateTime('now', new \DateTimeZone('UTC')); 182 | $this->updatedAt = new \DateTime('now', new \DateTimeZone('UTC')); 183 | } 184 | /** 185 | * Pre update event handler 186 | * 187 | * @ORM\PreUpdate 188 | */ 189 | public function doPreUpdate() 190 | { 191 | $this->updatedAt = new \DateTime('now', new \DateTimeZone('UTC')); 192 | } 193 | 194 | /** 195 | * Get created date/time 196 | * 197 | * @return \DateTime 198 | */ 199 | public function getCreatedAt() 200 | { 201 | return $this->createdAt; 202 | } 203 | /** 204 | * @param \DateTime 205 | * 206 | * @return Account 207 | */ 208 | public function setCreatedAt($created) 209 | { 210 | $this->createdAt = $created; 211 | return $this; 212 | } 213 | /** 214 | * Get last update date/time 215 | * 216 | * @return \DateTime 217 | */ 218 | public function getUpdatedAt() 219 | { 220 | return $this->updatedAt; 221 | } 222 | /** 223 | * @param \DateTime 224 | * 225 | * @return Account 226 | */ 227 | public function setUpdatedAt($updated) 228 | { 229 | $this->updatedAt = $updated; 230 | return $this; 231 | } 232 | 233 | public function __toString() 234 | { 235 | return (string) $this->getName(); 236 | } 237 | 238 | } 239 | -------------------------------------------------------------------------------- /src/Event/MeetingModifiedEvent.php: -------------------------------------------------------------------------------- 1 | meeting = $meeting; 18 | } 19 | 20 | /** 21 | * Get meeting. 22 | * 23 | * @return Meeting 24 | */ 25 | public function getMeeting(): Meeting 26 | { 27 | return $this->meeting; 28 | } 29 | 30 | /** 31 | * Set meeting. 32 | * 33 | * @param Meeting $meeting 34 | */ 35 | public function setMeeting(Meeting $meeting) 36 | { 37 | $this->meeting = $meeting; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Event/MeetingRegisteredEvent.php: -------------------------------------------------------------------------------- 1 | meeting = $meeting; 18 | } 19 | 20 | /** 21 | * Get meeting. 22 | * 23 | * @return Meeting 24 | */ 25 | public function getMeeting(): Meeting 26 | { 27 | return $this->meeting; 28 | } 29 | 30 | /** 31 | * Set meeting. 32 | * 33 | * @param Meeting $meeting 34 | */ 35 | public function setMeeting(Meeting $meeting) 36 | { 37 | $this->meeting = $meeting; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Event/MeetingUnRegisteredEvent.php: -------------------------------------------------------------------------------- 1 | meeting = $meeting; 17 | } 18 | 19 | /** 20 | * Get meeting. 21 | * 22 | * @return Meeting 23 | */ 24 | public function getMeeting(): Meeting 25 | { 26 | return $this->meeting; 27 | } 28 | 29 | /** 30 | * Set meeting. 31 | * 32 | * @param Meeting $meeting 33 | */ 34 | public function setMeeting(Meeting $meeting) 35 | { 36 | $this->meeting = $meeting; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Event/MeetingUserRegisteredEvent.php: -------------------------------------------------------------------------------- 1 | meeting = $meeting; 18 | } 19 | 20 | /** 21 | * Get meeting. 22 | * 23 | * @return Meeting 24 | */ 25 | public function getMeeting(): Meeting 26 | { 27 | return $this->meeting; 28 | } 29 | 30 | /** 31 | * Set meeting. 32 | * 33 | * @param Meeting $meeting 34 | */ 35 | public function setMeeting(Meeting $meeting) 36 | { 37 | $this->meeting = $meeting; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Event/MeetingUserUnRegisteredEvent.php: -------------------------------------------------------------------------------- 1 | meeting = $meeting; 17 | } 18 | 19 | /** 20 | * Get meeting. 21 | * 22 | * @return Meeting 23 | */ 24 | public function getMeeting(): Meeting 25 | { 26 | return $this->meeting; 27 | } 28 | 29 | /** 30 | * Set meeting. 31 | * 32 | * @param Meeting $meeting 33 | */ 34 | public function setMeeting(Meeting $meeting) 35 | { 36 | $this->meeting = $meeting; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Event/UserDeviceRegisteredEvent.php: -------------------------------------------------------------------------------- 1 | meeting = $meeting; 18 | } 19 | 20 | /** 21 | * Get meeting. 22 | * 23 | * @return Meeting 24 | */ 25 | public function getMeeting() 26 | { 27 | return $this->meeting; 28 | } 29 | 30 | /** 31 | * Set meeting. 32 | * 33 | * @param Meeting $meeting 34 | */ 35 | public function setMeeting(Meeting $meeting) 36 | { 37 | $this->meeting = $meeting; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Event/UserDeviceRemovedEvent.php: -------------------------------------------------------------------------------- 1 | meeting = $meeting; 18 | } 19 | 20 | /** 21 | * Get meeting. 22 | * 23 | * @return meeting. 24 | */ 25 | public function getMeeting() 26 | { 27 | return $this->meeting; 28 | } 29 | 30 | /** 31 | * Set meeting. 32 | * 33 | * @param Meeting $meeting 34 | */ 35 | public function setMeeting(Meeting $meeting) 36 | { 37 | $this->meeting = $meeting; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/EventListener/MeetingRegisteredListener.php: -------------------------------------------------------------------------------- 1 | setLogger($logger); 20 | } 21 | 22 | public static function getSubscribedEvents() 23 | { 24 | // return the subscribed events, their methods and priorities 25 | return array( 26 | 'meeting.registered' => array( 27 | array('processMeeting', 10), 28 | array('logMeeting', 0), 29 | array('notifyMeeting', -10), 30 | ) 31 | ); 32 | } 33 | 34 | public function processMeeting(MeetingRegisteredEvent $event) 35 | { 36 | $this->logger->info(sprintf('Metting initilise : %s', $event->getMeeting()->getName())); 37 | } 38 | 39 | public function logMeeting(MeetingRegisteredEvent $event) 40 | { 41 | $this->logger->info(sprintf('Meeting created: %s', $event->getMeeting()->getName())); 42 | } 43 | 44 | public function notifyMeeting(MeetingRegisteredEvent $event) 45 | { 46 | $this->logger->info(sprintf('Notify users about new : %s', $event->getMeeting()->getName())); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Exception/MyException.php: -------------------------------------------------------------------------------- 1 | add('name') 18 | ->add('description') 19 | ->add('datetime') 20 | ->add('organiser', UserType::class) 21 | ->add('tags'); 22 | } 23 | 24 | public function configureOptions(OptionsResolver $resolver) 25 | { 26 | $resolver->setDefaults([ 27 | 'data_class' => Meeting::class, 28 | 'csrf_protection' => false, 29 | ]); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Form/UserType.php: -------------------------------------------------------------------------------- 1 | add('username') 16 | ->add('email') 17 | ; 18 | } 19 | 20 | public function configureOptions(OptionsResolver $resolver) 21 | { 22 | $resolver->setDefaults([ 23 | 'data_class' => User::class, 24 | ]); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Kernel.php: -------------------------------------------------------------------------------- 1 | getProjectDir().'/var/cache/'.$this->environment; 22 | } 23 | 24 | public function getLogDir() 25 | { 26 | return $this->getProjectDir().'/var/log'; 27 | } 28 | 29 | public function registerBundles() 30 | { 31 | $contents = require $this->getProjectDir().'/config/bundles.php'; 32 | foreach ($contents as $class => $envs) { 33 | if (isset($envs['all']) || isset($envs[$this->environment])) { 34 | yield new $class(); 35 | } 36 | } 37 | } 38 | 39 | protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader) 40 | { 41 | $container->addResource(new FileResource($this->getProjectDir().'/config/bundles.php')); 42 | // Feel free to remove the "container.autowiring.strict_mode" parameter 43 | // if you are using symfony/dependency-injection 4.0+ as it's the default behavior 44 | $container->setParameter('container.autowiring.strict_mode', true); 45 | $container->setParameter('container.dumper.inline_class_loader', true); 46 | $confDir = $this->getProjectDir().'/config'; 47 | 48 | $loader->load($confDir.'/{packages}/*'.self::CONFIG_EXTS, 'glob'); 49 | $loader->load($confDir.'/{packages}/'.$this->environment.'/**/*'.self::CONFIG_EXTS, 'glob'); 50 | $loader->load($confDir.'/{services}'.self::CONFIG_EXTS, 'glob'); 51 | $loader->load($confDir.'/{services}_'.$this->environment.self::CONFIG_EXTS, 'glob'); 52 | } 53 | 54 | protected function configureRoutes(RouteCollectionBuilder $routes) 55 | { 56 | $confDir = $this->getProjectDir().'/config'; 57 | 58 | $routes->import($confDir.'/{routes}/*'.self::CONFIG_EXTS, '/', 'glob'); 59 | $routes->import($confDir.'/{routes}/'.$this->environment.'/**/*'.self::CONFIG_EXTS, '/', 'glob'); 60 | $routes->import($confDir.'/{routes}'.self::CONFIG_EXTS, '/', 'glob'); 61 | } 62 | 63 | protected function build(ContainerBuilder $container): void 64 | { 65 | parent::build($container); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/MeetingEvents.php: -------------------------------------------------------------------------------- 1 | abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 24 | 25 | $this->addSql('CREATE TABLE user (id INT AUTO_INCREMENT NOT NULL, fullname VARCHAR(100) NOT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, email VARCHAR(255) NOT NULL, password VARCHAR(255) NOT NULL, username VARCHAR(255) NOT NULL, roles LONGTEXT NOT NULL COMMENT \'(DC2Type:array)\', PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); 26 | $this->addSql('CREATE TABLE user_meeting (user_id INT NOT NULL, meeting_id INT NOT NULL, INDEX IDX_AD18FF33A76ED395 (user_id), INDEX IDX_AD18FF3367433D9C (meeting_id), PRIMARY KEY(user_id, meeting_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); 27 | $this->addSql('CREATE TABLE user_device (id INT AUTO_INCREMENT NOT NULL, userid_id INT NOT NULL, appid VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, model VARCHAR(255) DEFAULT NULL, platform VARCHAR(255) DEFAULT NULL, version VARCHAR(255) DEFAULT NULL, pushid VARCHAR(255) DEFAULT NULL, uuid VARCHAR(255) DEFAULT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, INDEX IDX_6C7DADB358E0A285 (userid_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); 28 | $this->addSql('CREATE TABLE tag (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(255) NOT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); 29 | $this->addSql('CREATE TABLE tag_meeting (tag_id INT NOT NULL, meeting_id INT NOT NULL, INDEX IDX_C724CC93BAD26311 (tag_id), INDEX IDX_C724CC9367433D9C (meeting_id), PRIMARY KEY(tag_id, meeting_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); 30 | $this->addSql('CREATE TABLE meeting (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(100) NOT NULL, description LONGTEXT NOT NULL, datetime DATETIME NOT NULL, organiser INT NOT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); 31 | $this->addSql('ALTER TABLE user_meeting ADD CONSTRAINT FK_AD18FF33A76ED395 FOREIGN KEY (user_id) REFERENCES user (id)'); 32 | $this->addSql('ALTER TABLE user_meeting ADD CONSTRAINT FK_AD18FF3367433D9C FOREIGN KEY (meeting_id) REFERENCES meeting (id)'); 33 | $this->addSql('ALTER TABLE user_device ADD CONSTRAINT FK_6C7DADB358E0A285 FOREIGN KEY (userid_id) REFERENCES user (id)'); 34 | $this->addSql('ALTER TABLE tag_meeting ADD CONSTRAINT FK_C724CC93BAD26311 FOREIGN KEY (tag_id) REFERENCES tag (id) ON DELETE CASCADE'); 35 | $this->addSql('ALTER TABLE tag_meeting ADD CONSTRAINT FK_C724CC9367433D9C FOREIGN KEY (meeting_id) REFERENCES meeting (id) ON DELETE CASCADE'); 36 | } 37 | 38 | public function down(Schema $schema) : void 39 | { 40 | // this down() migration is auto-generated, please modify it to your needs 41 | $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 42 | 43 | $this->addSql('ALTER TABLE user_meeting DROP FOREIGN KEY FK_AD18FF33A76ED395'); 44 | $this->addSql('ALTER TABLE user_device DROP FOREIGN KEY FK_6C7DADB358E0A285'); 45 | $this->addSql('ALTER TABLE tag_meeting DROP FOREIGN KEY FK_C724CC93BAD26311'); 46 | $this->addSql('ALTER TABLE user_meeting DROP FOREIGN KEY FK_AD18FF3367433D9C'); 47 | $this->addSql('ALTER TABLE tag_meeting DROP FOREIGN KEY FK_C724CC9367433D9C'); 48 | $this->addSql('DROP TABLE user'); 49 | $this->addSql('DROP TABLE user_meeting'); 50 | $this->addSql('DROP TABLE user_device'); 51 | $this->addSql('DROP TABLE tag'); 52 | $this->addSql('DROP TABLE tag_meeting'); 53 | $this->addSql('DROP TABLE meeting'); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Migrations/Version20201222071711.php: -------------------------------------------------------------------------------- 1 | abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 24 | 25 | $this->addSql('DROP TABLE user_meeting'); 26 | $this->addSql('ALTER TABLE user DROP fullname, DROP created_at, DROP updated_at, DROP username, CHANGE email email VARCHAR(180) NOT NULL, CHANGE roles roles LONGTEXT NOT NULL COMMENT \'(DC2Type:json)\''); 27 | $this->addSql('CREATE UNIQUE INDEX UNIQ_8D93D649E7927C74 ON user (email)'); 28 | } 29 | 30 | public function down(Schema $schema) : void 31 | { 32 | // this down() migration is auto-generated, please modify it to your needs 33 | $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 34 | 35 | $this->addSql('CREATE TABLE user_meeting (user_id INT NOT NULL, meeting_id INT NOT NULL, INDEX IDX_AD18FF33A76ED395 (user_id), INDEX IDX_AD18FF3367433D9C (meeting_id), PRIMARY KEY(user_id, meeting_id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB COMMENT = \'\' '); 36 | $this->addSql('ALTER TABLE user_meeting ADD CONSTRAINT FK_AD18FF3367433D9C FOREIGN KEY (meeting_id) REFERENCES meeting (id)'); 37 | $this->addSql('ALTER TABLE user_meeting ADD CONSTRAINT FK_AD18FF33A76ED395 FOREIGN KEY (user_id) REFERENCES user (id)'); 38 | $this->addSql('DROP INDEX UNIQ_8D93D649E7927C74 ON user'); 39 | $this->addSql('ALTER TABLE user ADD fullname VARCHAR(100) CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci`, ADD created_at DATETIME NOT NULL, ADD updated_at DATETIME NOT NULL, ADD username VARCHAR(255) CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci`, CHANGE email email VARCHAR(255) CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci`, CHANGE roles roles LONGTEXT CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci` COMMENT \'(DC2Type:array)\''); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Migrations/Version20201222132851.php: -------------------------------------------------------------------------------- 1 | abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 24 | 25 | $this->addSql('ALTER TABLE meeting CHANGE datetime meeting_at DATETIME NOT NULL'); 26 | } 27 | 28 | public function down(Schema $schema) : void 29 | { 30 | // this down() migration is auto-generated, please modify it to your needs 31 | $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 32 | 33 | $this->addSql('ALTER TABLE meeting CHANGE meeting_at datetime DATETIME NOT NULL'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Repository/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shambhu384/symfony5-jwt-restapi/0264a7be4cad4516d89235a6b3ad692e1e6bdf79/src/Repository/.gitignore -------------------------------------------------------------------------------- /src/Repository/MeetingRepository.php: -------------------------------------------------------------------------------- 1 | createQueryBuilder('u') 31 | ->andWhere('u.exampleField = :val') 32 | ->setParameter('val', $value) 33 | ->orderBy('u.id', 'ASC') 34 | ->setMaxResults(10) 35 | ->getQuery() 36 | ->getResult() 37 | ; 38 | } 39 | */ 40 | 41 | /* 42 | public function findOneBySomeField($value): ?Meeting 43 | { 44 | return $this->createQueryBuilder('u') 45 | ->andWhere('u.exampleField = :val') 46 | ->setParameter('val', $value) 47 | ->getQuery() 48 | ->getOneOrNullResult() 49 | ; 50 | } 51 | */ 52 | } 53 | -------------------------------------------------------------------------------- /src/Repository/TagRepository.php: -------------------------------------------------------------------------------- 1 | createQueryBuilder('t') 33 | ->andWhere('t.exampleField = :val') 34 | ->setParameter('val', $value) 35 | ->orderBy('t.id', 'ASC') 36 | ->setMaxResults(10) 37 | ->getQuery() 38 | ->getResult() 39 | ; 40 | } 41 | */ 42 | 43 | /* 44 | public function findOneBySomeField($value): ?Tag 45 | { 46 | return $this->createQueryBuilder('t') 47 | ->andWhere('t.exampleField = :val') 48 | ->setParameter('val', $value) 49 | ->getQuery() 50 | ->getOneOrNullResult() 51 | ; 52 | } 53 | */ 54 | } 55 | -------------------------------------------------------------------------------- /src/Repository/UserDeviceRepository.php: -------------------------------------------------------------------------------- 1 | createQueryBuilder('u') 34 | ->andWhere('u.exampleField = :val') 35 | ->setParameter('val', $value) 36 | ->orderBy('u.id', 'ASC') 37 | ->setMaxResults(10) 38 | ->getQuery() 39 | ->getResult() 40 | ; 41 | } 42 | */ 43 | 44 | /* 45 | public function findOneBySomeField($value): ?UserDevice 46 | { 47 | return $this->createQueryBuilder('u') 48 | ->andWhere('u.exampleField = :val') 49 | ->setParameter('val', $value) 50 | ->getQuery() 51 | ->getOneOrNullResult() 52 | ; 53 | } 54 | */ 55 | } 56 | -------------------------------------------------------------------------------- /src/Repository/UserRepository.php: -------------------------------------------------------------------------------- 1 | setPassword($newEncodedPassword); 35 | $this->_em->persist($user); 36 | $this->_em->flush(); 37 | } 38 | 39 | // /** 40 | // * @return User[] Returns an array of User objects 41 | // */ 42 | /* 43 | public function findByExampleField($value) 44 | { 45 | return $this->createQueryBuilder('u') 46 | ->andWhere('u.exampleField = :val') 47 | ->setParameter('val', $value) 48 | ->orderBy('u.id', 'ASC') 49 | ->setMaxResults(10) 50 | ->getQuery() 51 | ->getResult() 52 | ; 53 | } 54 | */ 55 | 56 | /* 57 | public function findOneBySomeField($value): ?User 58 | { 59 | return $this->createQueryBuilder('u') 60 | ->andWhere('u.exampleField = :val') 61 | ->setParameter('val', $value) 62 | ->getQuery() 63 | ->getOneOrNullResult() 64 | ; 65 | } 66 | */ 67 | } 68 | -------------------------------------------------------------------------------- /src/Security/Voter/MeetingVoter.php: -------------------------------------------------------------------------------- 1 | getUser(); 31 | // if the user is anonymous, do not grant access 32 | if (!$user instanceof UserInterface) { 33 | return false; 34 | } 35 | 36 | // ... (check conditions and return true to grant permission) ... 37 | switch ($attribute) { 38 | case self::EDIT: 39 | // logic to determine if the user can EDIT 40 | // return true or false 41 | break; 42 | } 43 | 44 | return false; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /symfony.lock: -------------------------------------------------------------------------------- 1 | { 2 | "doctrine/annotations": { 3 | "version": "1.0", 4 | "recipe": { 5 | "repo": "github.com/symfony/recipes", 6 | "branch": "master", 7 | "version": "1.0", 8 | "ref": "a2759dd6123694c8d901d0ec80006e044c2e6457" 9 | }, 10 | "files": [ 11 | "config/routes/annotations.yaml" 12 | ] 13 | }, 14 | "doctrine/cache": { 15 | "version": "1.10.2" 16 | }, 17 | "doctrine/collections": { 18 | "version": "1.6.7" 19 | }, 20 | "doctrine/common": { 21 | "version": "3.1.0" 22 | }, 23 | "doctrine/data-fixtures": { 24 | "version": "1.4.4" 25 | }, 26 | "doctrine/dbal": { 27 | "version": "2.12.1" 28 | }, 29 | "doctrine/doctrine-bundle": { 30 | "version": "2.0", 31 | "recipe": { 32 | "repo": "github.com/symfony/recipes", 33 | "branch": "master", 34 | "version": "2.0", 35 | "ref": "368794356c1fb634e58b38ad2addb36933f2e73e" 36 | }, 37 | "files": [ 38 | "config/packages/doctrine.yaml", 39 | "config/packages/prod/doctrine.yaml", 40 | "src/Entity/.gitignore", 41 | "src/Repository/.gitignore" 42 | ] 43 | }, 44 | "doctrine/doctrine-fixtures-bundle": { 45 | "version": "3.0", 46 | "recipe": { 47 | "repo": "github.com/symfony/recipes", 48 | "branch": "master", 49 | "version": "3.0", 50 | "ref": "e5b542d4ef47d8a003c91beb35650c76907f7e53" 51 | }, 52 | "files": [ 53 | "src/DataFixtures/AppFixtures.php" 54 | ] 55 | }, 56 | "doctrine/doctrine-migrations-bundle": { 57 | "version": "2.2", 58 | "recipe": { 59 | "repo": "github.com/symfony/recipes", 60 | "branch": "master", 61 | "version": "2.2", 62 | "ref": "baaa439e3e3179e69e3da84b671f0a3e4a2f56ad" 63 | }, 64 | "files": [ 65 | "config/packages/doctrine_migrations.yaml", 66 | "migrations/.gitignore" 67 | ] 68 | }, 69 | "doctrine/event-manager": { 70 | "version": "1.1.1" 71 | }, 72 | "doctrine/inflector": { 73 | "version": "2.0.3" 74 | }, 75 | "doctrine/instantiator": { 76 | "version": "1.4.0" 77 | }, 78 | "doctrine/lexer": { 79 | "version": "1.2.1" 80 | }, 81 | "doctrine/migrations": { 82 | "version": "2.3.1" 83 | }, 84 | "doctrine/orm": { 85 | "version": "2.8.1" 86 | }, 87 | "doctrine/persistence": { 88 | "version": "2.1.0" 89 | }, 90 | "doctrine/sql-formatter": { 91 | "version": "1.1.1" 92 | }, 93 | "friendsofsymfony/rest-bundle": { 94 | "version": "2.2", 95 | "recipe": { 96 | "repo": "github.com/symfony/recipes-contrib", 97 | "branch": "master", 98 | "version": "2.2", 99 | "ref": "cad41ef93d6150067ae2bb3c7fd729492dff6f0a" 100 | }, 101 | "files": [ 102 | "config/packages/fos_rest.yaml" 103 | ] 104 | }, 105 | "gesdinet/jwt-refresh-token-bundle": { 106 | "version": "v0.9.1" 107 | }, 108 | "laminas/laminas-code": { 109 | "version": "3.5.1" 110 | }, 111 | "laminas/laminas-eventmanager": { 112 | "version": "3.3.0" 113 | }, 114 | "laminas/laminas-zendframework-bridge": { 115 | "version": "1.1.1" 116 | }, 117 | "lcobucci/clock": { 118 | "version": "2.0.0" 119 | }, 120 | "lcobucci/jwt": { 121 | "version": "4.0.0" 122 | }, 123 | "lexik/jwt-authentication-bundle": { 124 | "version": "2.5", 125 | "recipe": { 126 | "repo": "github.com/symfony/recipes", 127 | "branch": "master", 128 | "version": "2.5", 129 | "ref": "5b2157bcd5778166a5696e42f552ad36529a07a6" 130 | }, 131 | "files": [ 132 | "config/packages/lexik_jwt_authentication.yaml" 133 | ] 134 | }, 135 | "namshi/jose": { 136 | "version": "7.2.3" 137 | }, 138 | "nelmio/api-doc-bundle": { 139 | "version": "3.0", 140 | "recipe": { 141 | "repo": "github.com/symfony/recipes-contrib", 142 | "branch": "master", 143 | "version": "3.0", 144 | "ref": "c8e0c38e1a280ab9e37587a8fa32b251d5bc1c94" 145 | }, 146 | "files": [ 147 | "config/packages/nelmio_api_doc.yaml", 148 | "config/routes/nelmio_api_doc.yaml" 149 | ] 150 | }, 151 | "nikic/php-parser": { 152 | "version": "v4.10.4" 153 | }, 154 | "ocramius/proxy-manager": { 155 | "version": "2.10.0" 156 | }, 157 | "phpdocumentor/reflection-common": { 158 | "version": "2.2.0" 159 | }, 160 | "phpdocumentor/reflection-docblock": { 161 | "version": "5.2.2" 162 | }, 163 | "phpdocumentor/type-resolver": { 164 | "version": "1.4.0" 165 | }, 166 | "predis/predis": { 167 | "version": "v1.1.6" 168 | }, 169 | "psr/cache": { 170 | "version": "1.0.1" 171 | }, 172 | "psr/container": { 173 | "version": "1.0.0" 174 | }, 175 | "psr/event-dispatcher": { 176 | "version": "1.0.0" 177 | }, 178 | "psr/log": { 179 | "version": "1.1.3" 180 | }, 181 | "symfony/asset": { 182 | "version": "v5.2.1" 183 | }, 184 | "symfony/cache": { 185 | "version": "v5.0.11" 186 | }, 187 | "symfony/cache-contracts": { 188 | "version": "v2.2.0" 189 | }, 190 | "symfony/config": { 191 | "version": "v5.0.11" 192 | }, 193 | "symfony/console": { 194 | "version": "4.4", 195 | "recipe": { 196 | "repo": "github.com/symfony/recipes", 197 | "branch": "master", 198 | "version": "4.4", 199 | "ref": "ea8c0eda34fda57e7d5cd8cbd889e2a387e3472c" 200 | }, 201 | "files": [ 202 | "bin/console", 203 | "config/bootstrap.php" 204 | ] 205 | }, 206 | "symfony/dependency-injection": { 207 | "version": "v5.0.11" 208 | }, 209 | "symfony/deprecation-contracts": { 210 | "version": "v2.2.0" 211 | }, 212 | "symfony/doctrine-bridge": { 213 | "version": "v5.0.11" 214 | }, 215 | "symfony/dotenv": { 216 | "version": "v5.0.11" 217 | }, 218 | "symfony/error-handler": { 219 | "version": "v5.0.11" 220 | }, 221 | "symfony/event-dispatcher": { 222 | "version": "v5.0.11" 223 | }, 224 | "symfony/event-dispatcher-contracts": { 225 | "version": "v2.2.0" 226 | }, 227 | "symfony/filesystem": { 228 | "version": "v5.0.11" 229 | }, 230 | "symfony/finder": { 231 | "version": "v5.0.11" 232 | }, 233 | "symfony/flex": { 234 | "version": "1.0", 235 | "recipe": { 236 | "repo": "github.com/symfony/recipes", 237 | "branch": "master", 238 | "version": "1.0", 239 | "ref": "c0eeb50665f0f77226616b6038a9b06c03752d8e" 240 | }, 241 | "files": [ 242 | ".env" 243 | ] 244 | }, 245 | "symfony/framework-bundle": { 246 | "version": "4.4", 247 | "recipe": { 248 | "repo": "github.com/symfony/recipes", 249 | "branch": "master", 250 | "version": "4.4", 251 | "ref": "df1f2fe60b8fbb5cf7e26a7af19445c128a13b90" 252 | }, 253 | "files": [ 254 | "config/bootstrap.php", 255 | "config/packages/cache.yaml", 256 | "config/packages/framework.yaml", 257 | "config/packages/test/framework.yaml", 258 | "config/preload.php", 259 | "config/routes/dev/framework.yaml", 260 | "config/services.yaml", 261 | "public/index.php", 262 | "src/Controller/.gitignore", 263 | "src/Kernel.php" 264 | ] 265 | }, 266 | "symfony/http-client-contracts": { 267 | "version": "v2.3.1" 268 | }, 269 | "symfony/http-foundation": { 270 | "version": "v5.0.11" 271 | }, 272 | "symfony/http-kernel": { 273 | "version": "v5.0.11" 274 | }, 275 | "symfony/maker-bundle": { 276 | "version": "1.0", 277 | "recipe": { 278 | "repo": "github.com/symfony/recipes", 279 | "branch": "master", 280 | "version": "1.0", 281 | "ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f" 282 | } 283 | }, 284 | "symfony/options-resolver": { 285 | "version": "v5.2.1" 286 | }, 287 | "symfony/polyfill-intl-grapheme": { 288 | "version": "v1.20.0" 289 | }, 290 | "symfony/polyfill-intl-normalizer": { 291 | "version": "v1.20.0" 292 | }, 293 | "symfony/polyfill-mbstring": { 294 | "version": "v1.20.0" 295 | }, 296 | "symfony/polyfill-php73": { 297 | "version": "v1.20.0" 298 | }, 299 | "symfony/polyfill-php80": { 300 | "version": "v1.20.0" 301 | }, 302 | "symfony/profiler-pack": { 303 | "version": "v1.0.5" 304 | }, 305 | "symfony/property-access": { 306 | "version": "v5.0.11" 307 | }, 308 | "symfony/property-info": { 309 | "version": "v5.0.11" 310 | }, 311 | "symfony/routing": { 312 | "version": "4.2", 313 | "recipe": { 314 | "repo": "github.com/symfony/recipes", 315 | "branch": "master", 316 | "version": "4.2", 317 | "ref": "683dcb08707ba8d41b7e34adb0344bfd68d248a7" 318 | }, 319 | "files": [ 320 | "config/packages/prod/routing.yaml", 321 | "config/packages/routing.yaml", 322 | "config/routes.yaml" 323 | ] 324 | }, 325 | "symfony/security-bundle": { 326 | "version": "4.4", 327 | "recipe": { 328 | "repo": "github.com/symfony/recipes", 329 | "branch": "master", 330 | "version": "4.4", 331 | "ref": "7b4408dc203049666fe23fabed23cbadc6d8440f" 332 | }, 333 | "files": [ 334 | "config/packages/security.yaml" 335 | ] 336 | }, 337 | "symfony/security-core": { 338 | "version": "v5.0.11" 339 | }, 340 | "symfony/security-csrf": { 341 | "version": "v5.0.11" 342 | }, 343 | "symfony/security-guard": { 344 | "version": "v5.0.11" 345 | }, 346 | "symfony/security-http": { 347 | "version": "v5.0.11" 348 | }, 349 | "symfony/serializer": { 350 | "version": "v5.0.11" 351 | }, 352 | "symfony/serializer-pack": { 353 | "version": "v1.0.4" 354 | }, 355 | "symfony/service-contracts": { 356 | "version": "v2.2.0" 357 | }, 358 | "symfony/stopwatch": { 359 | "version": "v5.0.11" 360 | }, 361 | "symfony/string": { 362 | "version": "v5.2.1" 363 | }, 364 | "symfony/translation-contracts": { 365 | "version": "v2.3.0" 366 | }, 367 | "symfony/twig-bridge": { 368 | "version": "v5.0.11" 369 | }, 370 | "symfony/twig-bundle": { 371 | "version": "5.0", 372 | "recipe": { 373 | "repo": "github.com/symfony/recipes", 374 | "branch": "master", 375 | "version": "5.0", 376 | "ref": "fab9149bbaa4d5eca054ed93f9e1b66cc500895d" 377 | }, 378 | "files": [ 379 | "config/packages/test/twig.yaml", 380 | "config/packages/twig.yaml", 381 | "templates/base.html.twig" 382 | ] 383 | }, 384 | "symfony/validator": { 385 | "version": "4.3", 386 | "recipe": { 387 | "repo": "github.com/symfony/recipes", 388 | "branch": "master", 389 | "version": "4.3", 390 | "ref": "d902da3e4952f18d3bf05aab29512eb61cabd869" 391 | }, 392 | "files": [ 393 | "config/packages/test/validator.yaml", 394 | "config/packages/validator.yaml" 395 | ] 396 | }, 397 | "symfony/var-dumper": { 398 | "version": "v5.0.11" 399 | }, 400 | "symfony/var-exporter": { 401 | "version": "v5.0.11" 402 | }, 403 | "symfony/web-profiler-bundle": { 404 | "version": "3.3", 405 | "recipe": { 406 | "repo": "github.com/symfony/recipes", 407 | "branch": "master", 408 | "version": "3.3", 409 | "ref": "6bdfa1a95f6b2e677ab985cd1af2eae35d62e0f6" 410 | }, 411 | "files": [ 412 | "config/packages/dev/web_profiler.yaml", 413 | "config/packages/test/web_profiler.yaml", 414 | "config/routes/dev/web_profiler.yaml" 415 | ] 416 | }, 417 | "symfony/yaml": { 418 | "version": "v5.0.11" 419 | }, 420 | "twig/twig": { 421 | "version": "v3.1.1" 422 | }, 423 | "webimpress/safe-writer": { 424 | "version": "2.1.0" 425 | }, 426 | "webmozart/assert": { 427 | "version": "1.9.1" 428 | }, 429 | "willdurand/jsonp-callback-validator": { 430 | "version": "v1.1.0" 431 | }, 432 | "willdurand/negotiation": { 433 | "version": "3.0.0" 434 | }, 435 | "zircote/swagger-php": { 436 | "version": "2.1.0" 437 | } 438 | } 439 | -------------------------------------------------------------------------------- /templates/base.html.twig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {% block title %}Welcome!{% endblock %} 6 | {% block stylesheets %}{% endblock %} 7 | 8 | 9 | {% block body %}{% endblock %} 10 | {% block javascripts %}{% endblock %} 11 | 12 | 13 | -------------------------------------------------------------------------------- /templates/default/index.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'base.html.twig' %} 2 | 3 | {% block title %} Meeting api For App Development {% endblock %} 4 | 5 | {% block body %} 6 | 10 |
11 |

Free Meeting RestAPI for Mobile app developement

12 |
13 |

Api features

14 | 19 | See Meetings 20 |
21 |
22 | 23 |
24 | Download postman file 25 |
26 |
27 |

Source code explore

28 |
29 | 30 |
31 | Need any help: Email me 32 |
33 | {% endblock %} 34 | 35 | -------------------------------------------------------------------------------- /templates/emails/registration.html.twig: -------------------------------------------------------------------------------- 1 | {# templates/emails/registration.html.twig #} 2 |

You did it! You registered!

3 | 4 | Hi {{ name }}! You're successfully registered. 5 | 6 | {# example, assuming you have a route named "login" #} 7 | To login, go to: .... 8 | 9 | Thanks! 10 | 11 | {# Makes an absolute URL to the /images/logo.png file #} 12 | 13 | -------------------------------------------------------------------------------- /templates/meeting_registration/index.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'base.html.twig' %} 2 | 3 | {% block title %}Hello {{ controller_name }}!{% endblock %} 4 | 5 | {% block body %} 6 | 10 | 11 |
12 |

Hello {{ controller_name }}! ✅

13 | 14 | This friendly message is coming from: 15 | 19 |
20 | {% endblock %} 21 | -------------------------------------------------------------------------------- /templates/user/index.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'base.html.twig' %} 2 | 3 | {% block title %}Hello {{ controller_name }}!{% endblock %} 4 | 5 | {% block body %} 6 | 10 | 11 |
12 |

Hello {{ controller_name }}! ✅

13 | 14 | This friendly message is coming from: 15 | 19 |
20 | {% endblock %} 21 | -------------------------------------------------------------------------------- /tests/Util/CalculatorTest.php: -------------------------------------------------------------------------------- 1 | add(30, 12); 13 | 14 | // assert that your calculator added the numbers correctly! 15 | $this->assertEquals(42, $result); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ts/index.php: -------------------------------------------------------------------------------- 1 |