| @@ -0,0 +1,48 @@ | |||||
| <!DOCTYPE html> | |||||
| <html lang="en"> | |||||
| <head> | |||||
| <meta charset="UTF-8"> | |||||
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |||||
| <title>Login Form</title> | |||||
| </head> | |||||
| <body> | |||||
| <h1>Login</h1> | |||||
| <form id="loginForm"> | |||||
| <label for="email">Username (Email):</label> | |||||
| <input type="text" id="email" name="email" required> | |||||
| <br> | |||||
| <label for="password">Password:</label> | |||||
| <input type="password" id="password" name="password" required> | |||||
| <br> | |||||
| <button type="button" id="loginButton">Login</button> | |||||
| </form> | |||||
| <script> | |||||
| document.getElementById('loginButton').addEventListener('click', function() { | |||||
| const email = document.getElementById('email').value; | |||||
| const password = document.getElementById('password').value; | |||||
| const data = { | |||||
| email: email, | |||||
| password: password | |||||
| }; | |||||
| fetch('https://spt-moduled-symfony.ddev.site:8443/spt-core/api/login', { | |||||
| method: 'POST', | |||||
| headers: { | |||||
| 'Content-Type': 'application/json' | |||||
| }, | |||||
| body: JSON.stringify(data) | |||||
| }) | |||||
| .then(response => response.json()) | |||||
| .then(data => { | |||||
| console.log(data); | |||||
| // Handle the response data as needed | |||||
| }) | |||||
| .catch(error => { | |||||
| console.error(error); | |||||
| // Handle errors | |||||
| }); | |||||
| }); | |||||
| </script> | |||||
| </body> | |||||
| </html> | |||||
| @@ -1,2 +1,31 @@ | |||||
| # spt-moduled-smfony | # spt-moduled-smfony | ||||
| Installation: | |||||
| gehe ins root Verzeichnis des Projekts und für aus: ddev config | |||||
| gehe den Installationsprozess durch | |||||
| starte danach ddev mit: ddev start | |||||
| Troubleshooting: | |||||
| Unable to listen on required ports, port 443 is already in use | |||||
| -> setze andere Ports in .ddev/config.yaml z.B. | |||||
| router_http_port: 8080 | |||||
| router_https_port: 8443 | |||||
| PHPMyAdmin installieren: | |||||
| ddev get ddev/ddev-phpmyadmin' | |||||
| ddev restart | |||||
| Symfony Konsolenbefehle mit Ddev ausführen, z.B.: | |||||
| ddev exec php bin/console make:migration | |||||
| Ddev Commands: | |||||
| ddev describe - zeigt Urls und installierte Komponenten | |||||
| @@ -0,0 +1,10 @@ | |||||
| ###> symfony/framework-bundle ### | |||||
| /.env.local | |||||
| /.env.local.php | |||||
| /.env.*.local | |||||
| /config/secrets/prod/prod.decrypt.private.php | |||||
| /public/bundles/ | |||||
| /var/ | |||||
| /vendor/ | |||||
| ###< symfony/framework-bundle ### | |||||
| @@ -0,0 +1,42 @@ | |||||
| { | |||||
| "name": "spt/spt-core-bundle", | |||||
| "version": "1.0.0", | |||||
| "type": "symfony-bundle", | |||||
| "description": "Core bundle for basic functionality", | |||||
| "require": { | |||||
| "php": ">=8.1", | |||||
| "symfony/security-bundle": "^6.3", | |||||
| "nelmio/cors-bundle": "^2.3" | |||||
| }, | |||||
| "autoload": { | |||||
| "psr-4": { | |||||
| "Spt\\SptCoreBundle\\": "src/" | |||||
| } | |||||
| }, | |||||
| "autoload-dev": { | |||||
| "psr-4": { | |||||
| "Spt\\SptCoreBundle\\Tests\\": "tests/" | |||||
| } | |||||
| }, | |||||
| "authors": [ | |||||
| { | |||||
| "name": "Daniel Knudsen", | |||||
| "email": "d.knudsen@spawntree.de" | |||||
| }, | |||||
| { | |||||
| "name": "Florian Eisenmenger", | |||||
| "email": "f.eisenmenger@spawntree.de" | |||||
| } | |||||
| ], | |||||
| "config": { | |||||
| }, | |||||
| "require-dev": { | |||||
| "symfony/maker-bundle": "^1.51" | |||||
| }, | |||||
| "scripts": { | |||||
| "auto-scripts": { | |||||
| "cache:clear": "symfony-cmd", | |||||
| "assets:install %PUBLIC_DIR%": "symfony-cmd" | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,5 @@ | |||||
| <?php | |||||
| return [ | |||||
| Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], | |||||
| ]; | |||||
| @@ -0,0 +1,19 @@ | |||||
| framework: | |||||
| cache: | |||||
| # Unique name of your app: used to compute stable namespaces for cache keys. | |||||
| #prefix_seed: your_vendor_name/app_name | |||||
| # The "app" cache stores to the filesystem by default. | |||||
| # The data in this cache should persist between deploys. | |||||
| # Other options include: | |||||
| # Redis | |||||
| #app: cache.adapter.redis | |||||
| #default_redis_provider: redis://localhost | |||||
| # APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues) | |||||
| #app: cache.adapter.apcu | |||||
| # Namespaced pools use the above "app" backend by default | |||||
| #pools: | |||||
| #my.dedicated.cache: null | |||||
| @@ -0,0 +1,25 @@ | |||||
| # see https://symfony.com/doc/current/reference/configuration/framework.html | |||||
| framework: | |||||
| secret: '%env(APP_SECRET)%' | |||||
| #csrf_protection: true | |||||
| http_method_override: false | |||||
| handle_all_throwables: true | |||||
| # Enables session support. Note that the session will ONLY be started if you read or write from it. | |||||
| # Remove or comment this section to explicitly disable session support. | |||||
| session: | |||||
| handler_id: null | |||||
| cookie_secure: auto | |||||
| cookie_samesite: lax | |||||
| storage_factory_id: session.storage.factory.native | |||||
| #esi: true | |||||
| #fragments: true | |||||
| php_errors: | |||||
| log: true | |||||
| when@test: | |||||
| framework: | |||||
| test: true | |||||
| session: | |||||
| storage_factory_id: session.storage.factory.mock_file | |||||
| @@ -0,0 +1,25 @@ | |||||
| #nelmio_cors: | |||||
| # defaults: | |||||
| # origin_regex: true | |||||
| # allow_origin: ['*'] | |||||
| # allow_methods: ['*'] | |||||
| # allow_headers: ['*'] | |||||
| # expose_headers: ['Link'] | |||||
| # max_age: 3600 | |||||
| # paths: | |||||
| # '^/': null | |||||
| nelmio_cors: | |||||
| defaults: | |||||
| allow_credentials: true | |||||
| allow_origin: [ '*' ] | |||||
| allow_headers: [ '*' ] | |||||
| allow_methods: [ 'POST', 'PUT', 'GET', 'DELETE' ] | |||||
| expose_headers: [ ] | |||||
| max_age: 3600 | |||||
| hosts: [ ] | |||||
| origin_regex: true | |||||
| paths: | |||||
| # Important api settings : | |||||
| # Access-Control-Request-Method | |||||
| '^/': ~ | |||||
| @@ -0,0 +1,12 @@ | |||||
| framework: | |||||
| router: | |||||
| utf8: true | |||||
| # Configure how to generate URLs in non-HTTP contexts, such as CLI commands. | |||||
| # See https://symfony.com/doc/current/routing.html#generating-urls-in-commands | |||||
| #default_uri: http://localhost | |||||
| when@prod: | |||||
| framework: | |||||
| router: | |||||
| strict_requirements: null | |||||
| @@ -4,14 +4,24 @@ security: | |||||
| Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto' | Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto' | ||||
| # https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider | # https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider | ||||
| providers: | providers: | ||||
| users_in_memory: { memory: null } | |||||
| app_user_provider: | |||||
| entity: | |||||
| class: Spt\SptCoreBundle\Entity\User | |||||
| property: email | |||||
| firewalls: | firewalls: | ||||
| dev: | dev: | ||||
| pattern: ^/(_(profiler|wdt)|css|images|js)/ | pattern: ^/(_(profiler|wdt)|css|images|js)/ | ||||
| security: false | security: false | ||||
| main: | main: | ||||
| lazy: true | lazy: true | ||||
| provider: users_in_memory | |||||
| provider: app_user_provider | |||||
| nelmio_cors: ~ | |||||
| json_login: | |||||
| # api_login is a route we will create below | |||||
| check_path: spt_core_api_login | |||||
| username_path: email | |||||
| password_path: password | |||||
| #check_path: spt-core/api/login | |||||
| # activate different ways to authenticate | # activate different ways to authenticate | ||||
| # https://symfony.com/doc/current/security.html#the-firewall | # https://symfony.com/doc/current/security.html#the-firewall | ||||
| @@ -22,6 +32,8 @@ security: | |||||
| # Easy way to control access for large sections of your site | # Easy way to control access for large sections of your site | ||||
| # Note: Only the *first* access control that matches will be used | # Note: Only the *first* access control that matches will be used | ||||
| access_control: | access_control: | ||||
| - { path: ^/spt-core/api/login, roles: IS_AUTHENTICATED_FULLY } | |||||
| # - { path: ^/admin, roles: ROLE_ADMIN } | # - { path: ^/admin, roles: ROLE_ADMIN } | ||||
| # - { path: ^/profile, roles: ROLE_USER } | # - { path: ^/profile, roles: ROLE_USER } | ||||
| @@ -0,0 +1,5 @@ | |||||
| <?php | |||||
| if (file_exists(dirname(__DIR__).'/var/cache/prod/App_KernelProdContainer.preload.php')) { | |||||
| require dirname(__DIR__).'/var/cache/prod/App_KernelProdContainer.preload.php'; | |||||
| } | |||||
| @@ -0,0 +1,4 @@ | |||||
| spt_core_bundle.routes: | |||||
| type: annotation | |||||
| resource: '../src/Controller' | |||||
| prefix: 'spt-core' | |||||
| @@ -0,0 +1,4 @@ | |||||
| when@dev: | |||||
| _errors: | |||||
| resource: '@FrameworkBundle/Resources/config/routing/errors.xml' | |||||
| prefix: /_error | |||||
| @@ -0,0 +1,33 @@ | |||||
| parameters: | |||||
| services: | |||||
| _defaults: | |||||
| autowire: true | |||||
| autoconfigure: true | |||||
| Spt\SptCoreBundle\Controller\SecurityController: ~ | |||||
| # makes classes in src/ available to be used as services | |||||
| # this creates a service per class whose id is the fully-qualified class name | |||||
| Spt\SptCoreBundle\: | |||||
| resource: '../src/' | |||||
| exclude: | |||||
| - '../src/DependencyInjection/' | |||||
| - '../src/Entity/' | |||||
| - '../src/Kernel.php' | |||||
| - '../src/Tests/' | |||||
| # controllers are imported separately to make sure services can be injected | |||||
| # as action arguments even if you don't extend any base controller class | |||||
| Spt\SptCoreBundle\Controller\: | |||||
| resource: '../src/Controller/' | |||||
| tags: ['controller.service_arguments'] | |||||
| Spt\SptCoreBundle\Command\: | |||||
| resource: '../src/Command/' | |||||
| autowire: true | |||||
| autoconfigure: true | |||||
| arguments: [ '@doctrine.orm.entity_manager', '@service_container' ] | |||||
| tags: | |||||
| - { name: 'console.command' } | |||||
| @@ -0,0 +1,9 @@ | |||||
| <?php | |||||
| use App\Kernel; | |||||
| require_once dirname(__DIR__).'/vendor/autoload_runtime.php'; | |||||
| return function (array $context) { | |||||
| return new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']); | |||||
| }; | |||||
| @@ -0,0 +1,37 @@ | |||||
| <?php | |||||
| /** | |||||
| * @author Daniel Knudsen <d.knudsen@spawntree.de> | |||||
| * @date 20.10.23 | |||||
| */ | |||||
| namespace Spt\SptCoreBundle\Controller; | |||||
| use Spt\SptCoreBundle\Entity\User; | |||||
| use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; | |||||
| use Symfony\Bundle\SecurityBundle\Security; | |||||
| use Symfony\Component\HttpFoundation\JsonResponse; | |||||
| use Symfony\Component\HttpFoundation\Request; | |||||
| use Symfony\Component\HttpFoundation\Response; | |||||
| use Symfony\Component\Routing\Annotation\Route; | |||||
| use Symfony\Component\Security\Http\Attribute\CurrentUser; | |||||
| class ApiLoginController extends AbstractController | |||||
| { | |||||
| #[Route('/api/login', name: 'spt_core_api_login', methods: ['POST'])] | |||||
| public function index(Request $request): JsonResponse | |||||
| { | |||||
| $user = $this->getUser(); | |||||
| if (null === $user) { | |||||
| return $this->json([ | |||||
| 'message' => 'missing credentials', | |||||
| ], Response::HTTP_UNAUTHORIZED); | |||||
| } | |||||
| return $this->json([ | |||||
| 'message' => 'Welcome to your new controller!', | |||||
| 'path' => 'src/Controller/ApiLoginController.php', | |||||
| ]); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,37 @@ | |||||
| <?php | |||||
| /** | |||||
| * @author Daniel Knudsen <d.knudsen@spawntree.de> | |||||
| * @date 20.10.23 | |||||
| */ | |||||
| namespace Spt\SptCoreBundle\Controller; | |||||
| use Spt\SptCoreBundle\Entity\User; | |||||
| use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; | |||||
| use Symfony\Component\HttpFoundation\JsonResponse; | |||||
| use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface; | |||||
| class RegistrationController extends AbstractController | |||||
| { | |||||
| public function index(UserPasswordHasherInterface $passwordHasher): JsonResponse | |||||
| { | |||||
| // manually hash pw | |||||
| //php bin/console security:hash-password | |||||
| // ... e.g. get the user data from a registration form | |||||
| // $user = new User(...); | |||||
| // $plaintextPassword = ...; | |||||
| // | |||||
| // // hash the password (based on the security.yaml config for the $user class) | |||||
| // $hashedPassword = $passwordHasher->hashPassword( | |||||
| // $user, | |||||
| // $plaintextPassword | |||||
| // ); | |||||
| // $user->setPassword($hashedPassword); | |||||
| // ... | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,22 @@ | |||||
| <?php | |||||
| namespace Spt\SptCoreBundle\Controller; | |||||
| use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; | |||||
| use Symfony\Component\HttpFoundation\JsonResponse; | |||||
| use Symfony\Component\Routing\Annotation\Route; | |||||
| /** | |||||
| * @author Daniel Knudsen <d.knudsen@spawntree.de> | |||||
| * @date 18.10.23 | |||||
| */ | |||||
| class SecurityController extends AbstractController | |||||
| { | |||||
| #[Route('/test', name: 'spt_core_test')] | |||||
| public function test() | |||||
| { | |||||
| return new JsonResponse('test'); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,32 @@ | |||||
| <?php | |||||
| /** | |||||
| * @author Daniel Knudsen <d.knudsen@spawntree.de> | |||||
| * @date 19.10.23 | |||||
| */ | |||||
| namespace Spt\SptCoreBundle\DependencyInjections; | |||||
| use Exception; | |||||
| use Symfony\Component\Config\FileLocator; | |||||
| use Symfony\Component\DependencyInjection\ContainerBuilder; | |||||
| use Symfony\Component\DependencyInjection\Extension\Extension; | |||||
| use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; | |||||
| class SptCoreExtension extends Extension | |||||
| { | |||||
| /** | |||||
| * @throws Exception | |||||
| */ | |||||
| public function load(array $configs, ContainerBuilder $container): void | |||||
| { | |||||
| $loader = new YamlFileLoader( | |||||
| $container, | |||||
| new FileLocator(__DIR__ . '/../../config') | |||||
| ); | |||||
| $loader->load('services.yaml'); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,99 @@ | |||||
| <?php | |||||
| namespace Spt\SptCoreBundle\Entity; | |||||
| use Doctrine\ORM\Mapping as ORM; | |||||
| use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface; | |||||
| use Symfony\Component\Security\Core\User\UserInterface; | |||||
| #[ORM\Entity] | |||||
| #[ORM\Table(name: "user")] | |||||
| class User implements UserInterface, PasswordAuthenticatedUserInterface | |||||
| { | |||||
| #[ORM\Id] | |||||
| #[ORM\GeneratedValue] | |||||
| #[ORM\Column] | |||||
| private ?int $id = null; | |||||
| #[ORM\Column(length: 180, unique: true)] | |||||
| private ?string $email = null; | |||||
| #[ORM\Column] | |||||
| private array $roles = []; | |||||
| /** | |||||
| * @var string The hashed password | |||||
| */ | |||||
| #[ORM\Column] | |||||
| private ?string $password = null; | |||||
| public function getId(): ?int | |||||
| { | |||||
| return $this->id; | |||||
| } | |||||
| public function getEmail(): ?string | |||||
| { | |||||
| return $this->email; | |||||
| } | |||||
| public function setEmail(string $email): static | |||||
| { | |||||
| $this->email = $email; | |||||
| return $this; | |||||
| } | |||||
| /** | |||||
| * A visual identifier that represents this user. | |||||
| * | |||||
| * @see UserInterface | |||||
| */ | |||||
| public function getUserIdentifier(): string | |||||
| { | |||||
| return (string) $this->email; | |||||
| } | |||||
| /** | |||||
| * @see UserInterface | |||||
| */ | |||||
| public function getRoles(): array | |||||
| { | |||||
| $roles = $this->roles; | |||||
| // guarantee every user at least has ROLE_USER | |||||
| $roles[] = 'ROLE_USER'; | |||||
| return array_unique($roles); | |||||
| } | |||||
| public function setRoles(array $roles): static | |||||
| { | |||||
| $this->roles = $roles; | |||||
| return $this; | |||||
| } | |||||
| /** | |||||
| * @see PasswordAuthenticatedUserInterface | |||||
| */ | |||||
| public function getPassword(): string | |||||
| { | |||||
| return $this->password; | |||||
| } | |||||
| public function setPassword(string $password): static | |||||
| { | |||||
| $this->password = $password; | |||||
| return $this; | |||||
| } | |||||
| /** | |||||
| * @see UserInterface | |||||
| */ | |||||
| public function eraseCredentials(): void | |||||
| { | |||||
| // If you store any temporary, sensitive data on the user, clear it here | |||||
| // $this->plainPassword = null; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,26 @@ | |||||
| <?php | |||||
| /** | |||||
| * @author Daniel Knudsen <d.knudsen@spawntree.de> | |||||
| * @date 18.10.23 | |||||
| */ | |||||
| namespace Spt\SptCoreBundle; | |||||
| use Spt\SptCoreBundle\DependencyInjections\SptCoreExtension; | |||||
| use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; | |||||
| use Symfony\Component\HttpKernel\Bundle\AbstractBundle; | |||||
| use function dirname; | |||||
| class SptCoreBundle extends AbstractBundle | |||||
| { | |||||
| public function getPath(): string | |||||
| { | |||||
| return dirname(__DIR__); | |||||
| } | |||||
| public function getContainerExtension(): ?ExtensionInterface | |||||
| { | |||||
| return new SptCoreExtension(); | |||||
| } | |||||
| } | |||||
| @@ -3,6 +3,12 @@ | |||||
| "license": "proprietary", | "license": "proprietary", | ||||
| "minimum-stability": "stable", | "minimum-stability": "stable", | ||||
| "prefer-stable": true, | "prefer-stable": true, | ||||
| "repositories": [ | |||||
| { | |||||
| "type": "path", | |||||
| "url": "./bundle/Spt/SptCoreBundle" | |||||
| } | |||||
| ], | |||||
| "require": { | "require": { | ||||
| "php": ">=8.1", | "php": ">=8.1", | ||||
| "ext-ctype": "*", | "ext-ctype": "*", | ||||
| @@ -12,6 +18,7 @@ | |||||
| "doctrine/orm": "^2.16", | "doctrine/orm": "^2.16", | ||||
| "phpdocumentor/reflection-docblock": "^5.3", | "phpdocumentor/reflection-docblock": "^5.3", | ||||
| "phpstan/phpdoc-parser": "^1.24", | "phpstan/phpdoc-parser": "^1.24", | ||||
| "spt/spt-core-bundle": "^1.0", | |||||
| "symfony/asset": "6.3.*", | "symfony/asset": "6.3.*", | ||||
| "symfony/console": "6.3.*", | "symfony/console": "6.3.*", | ||||
| "symfony/doctrine-messenger": "6.3.*", | "symfony/doctrine-messenger": "6.3.*", | ||||
| @@ -30,7 +37,7 @@ | |||||
| "symfony/property-access": "6.3.*", | "symfony/property-access": "6.3.*", | ||||
| "symfony/property-info": "6.3.*", | "symfony/property-info": "6.3.*", | ||||
| "symfony/runtime": "6.3.*", | "symfony/runtime": "6.3.*", | ||||
| "symfony/security-bundle": "6.3.*", | |||||
| "symfony/security-bundle": "^6.3", | |||||
| "symfony/serializer": "6.3.*", | "symfony/serializer": "6.3.*", | ||||
| "symfony/string": "6.3.*", | "symfony/string": "6.3.*", | ||||
| "symfony/translation": "6.3.*", | "symfony/translation": "6.3.*", | ||||
| @@ -90,7 +97,9 @@ | |||||
| } | } | ||||
| }, | }, | ||||
| "require-dev": { | "require-dev": { | ||||
| "phpunit/phpunit": "^9.5", | |||||
| "roave/security-advisories": "dev-latest" | |||||
| , | |||||
| "phpunit/phpunit": "^9.5", | |||||
| "symfony/browser-kit": "6.3.*", | "symfony/browser-kit": "6.3.*", | ||||
| "symfony/css-selector": "6.3.*", | "symfony/css-selector": "6.3.*", | ||||
| "symfony/debug-bundle": "6.3.*", | "symfony/debug-bundle": "6.3.*", | ||||
| @@ -11,4 +11,5 @@ return [ | |||||
| Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], | Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], | ||||
| Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true], | Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true], | ||||
| Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true], | Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true], | ||||
| Spt\SptCoreBundle\SptCoreBundle::class => ['all' => true], | |||||
| ]; | ]; | ||||
| @@ -0,0 +1,2 @@ | |||||
| spt_core_bundle.routes: | |||||
| resource: '@SptCoreBundle/config/routes.yaml' | |||||
| @@ -0,0 +1,24 @@ | |||||
| <?php | |||||
| /** | |||||
| * @author Daniel Knudsen <d.knudsen@spawntree.de> | |||||
| * @date 23.10.23 | |||||
| */ | |||||
| namespace App\Controller; | |||||
| use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; | |||||
| use Symfony\Component\HttpFoundation\Request; | |||||
| use Symfony\Component\HttpFoundation\Response; | |||||
| use Symfony\Component\Routing\Annotation\Route; | |||||
| class TestController extends AbstractController | |||||
| { | |||||
| #[Route('/', name: 'test_index')] | |||||
| public function index(Request $request): Response | |||||
| { | |||||
| return $this->render('index.html.twig', []); | |||||
| } | |||||
| } | |||||
| @@ -26,6 +26,18 @@ | |||||
| "migrations/.gitignore" | "migrations/.gitignore" | ||||
| ] | ] | ||||
| }, | }, | ||||
| "nelmio/cors-bundle": { | |||||
| "version": "2.3", | |||||
| "recipe": { | |||||
| "repo": "github.com/symfony/recipes", | |||||
| "branch": "main", | |||||
| "version": "1.5", | |||||
| "ref": "6bea22e6c564fba3a1391615cada1437d0bde39c" | |||||
| }, | |||||
| "files": [ | |||||
| "config/packages/nelmio_cors.yaml" | |||||
| ] | |||||
| }, | |||||
| "phpunit/phpunit": { | "phpunit/phpunit": { | ||||
| "version": "9.6", | "version": "9.6", | ||||
| "recipe": { | "recipe": { | ||||
| @@ -40,6 +52,9 @@ | |||||
| "tests/bootstrap.php" | "tests/bootstrap.php" | ||||
| ] | ] | ||||
| }, | }, | ||||
| "spt/spt-core-bundle": { | |||||
| "version": "1.0.0" | |||||
| }, | |||||
| "symfony/console": { | "symfony/console": { | ||||
| "version": "6.3", | "version": "6.3", | ||||
| "recipe": { | "recipe": { | ||||
| @@ -0,0 +1,48 @@ | |||||
| <!DOCTYPE html> | |||||
| <html lang="en"> | |||||
| <head> | |||||
| <meta charset="UTF-8"> | |||||
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |||||
| <title>Login Form</title> | |||||
| </head> | |||||
| <body> | |||||
| <h1>Login</h1> | |||||
| <form id="loginForm"> | |||||
| <label for="email">Username (Email):</label> | |||||
| <input type="text" id="email" name="email" required> | |||||
| <br> | |||||
| <label for="password">Password:</label> | |||||
| <input type="password" id="password" name="password" required> | |||||
| <br> | |||||
| <button type="button" id="loginButton">Login</button> | |||||
| </form> | |||||
| <script> | |||||
| document.getElementById('loginButton').addEventListener('click', function() { | |||||
| const email = document.getElementById('email').value; | |||||
| const password = document.getElementById('password').value; | |||||
| const data = { | |||||
| email: email, | |||||
| password: password | |||||
| }; | |||||
| fetch('https://spt-moduled-symfony.ddev.site:8443/spt-core/api/login', { | |||||
| method: 'POST', | |||||
| headers: { | |||||
| 'Content-Type': 'application/json' | |||||
| }, | |||||
| body: JSON.stringify(data) | |||||
| }) | |||||
| .then(response => response.json()) | |||||
| .then(data => { | |||||
| console.log(data); | |||||
| // Handle the response data as needed | |||||
| }) | |||||
| .catch(error => { | |||||
| console.error(error); | |||||
| // Handle errors | |||||
| }); | |||||
| }); | |||||
| </script> | |||||
| </body> | |||||
| </html> | |||||