diff --git a/.ddev/config.yaml b/.ddev/config.yaml index 49b0d62..80f6a29 100644 --- a/.ddev/config.yaml +++ b/.ddev/config.yaml @@ -7,12 +7,13 @@ xdebug_enabled: false additional_hostnames: [] additional_fqdns: [] database: - type: mariadb - version: "10.11" + type: postgres + version: "17" use_dns_when_possible: true composer_version: "2" web_environment: [] corepack_enable: false +host_db_port: "5432" # Key features of DDEV's config.yaml: diff --git a/.env b/.env index 6273996..20bbac1 100644 --- a/.env +++ b/.env @@ -26,5 +26,5 @@ APP_SECRET=bfc9c288ee3dcce80dec8622c2870f27 # DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db" # DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8.0.32&charset=utf8mb4" # DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=10.11.2-MariaDB&charset=utf8mb4" -DATABASE_URL="postgresql://app:!ChangeMe!@127.0.0.1:5432/app?serverVersion=16&charset=utf8" +DATABASE_URL="postgresql://db:db@db:5432/db?serverVersion=16&charset=utf8" ###< doctrine/doctrine-bundle ### diff --git a/composer.json b/composer.json index a364e85..bb2291e 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,10 @@ "symfony/framework-bundle": "7.1.*", "symfony/runtime": "7.1.*", "symfony/security-bundle": "7.1.*", - "symfony/yaml": "7.1.*" + "symfony/twig-bundle": "7.1.*", + "symfony/yaml": "7.1.*", + "twig/extra-bundle": "^2.12|^3.0", + "twig/twig": "^2.12|^3.0" }, "config": { "allow-plugins": { @@ -69,6 +72,8 @@ } }, "require-dev": { - "symfony/maker-bundle": "^1.61" + "symfony/maker-bundle": "^1.61", + "symfony/stopwatch": "7.1.*", + "symfony/web-profiler-bundle": "7.1.*" } } diff --git a/composer.lock b/composer.lock index 7731e52..9936360 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "edf4e74c57879cd142446d6bfdd2e566", + "content-hash": "008ffb3050a2c2d2d0d72443a467a1db", "packages": [ { "name": "doctrine/cache", @@ -4281,6 +4281,277 @@ ], "time": "2024-11-13T13:31:21+00:00" }, + { + "name": "symfony/translation-contracts", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation-contracts.git", + "reference": "b9d2189887bb6b2e0367a9fc7136c5239ab9b05a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/b9d2189887bb6b2e0367a9fc7136c5239ab9b05a", + "reference": "b9d2189887bb6b2e0367a9fc7136c5239ab9b05a", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to translation", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/translation-contracts/tree/v3.5.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:32:20+00:00" + }, + { + "name": "symfony/twig-bridge", + "version": "v7.1.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/twig-bridge.git", + "reference": "535ab0be4fc563b2bc5fc0cc9e388626d226c63f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/535ab0be4fc563b2bc5fc0cc9e388626d226c63f", + "reference": "535ab0be4fc563b2bc5fc0cc9e388626d226c63f", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/translation-contracts": "^2.5|^3", + "twig/twig": "^3.9" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<1.4.0", + "symfony/console": "<6.4", + "symfony/form": "<6.4", + "symfony/http-foundation": "<6.4", + "symfony/http-kernel": "<6.4", + "symfony/mime": "<6.4", + "symfony/serializer": "<6.4", + "symfony/translation": "<6.4", + "symfony/workflow": "<6.4" + }, + "require-dev": { + "egulias/email-validator": "^2.1.10|^3|^4", + "league/html-to-markdown": "^5.0", + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "symfony/asset": "^6.4|^7.0", + "symfony/asset-mapper": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/emoji": "^7.1", + "symfony/expression-language": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", + "symfony/form": "^6.4|^7.0", + "symfony/html-sanitizer": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", + "symfony/mime": "^6.4|^7.0", + "symfony/polyfill-intl-icu": "~1.0", + "symfony/property-info": "^6.4|^7.0", + "symfony/routing": "^6.4|^7.0", + "symfony/security-acl": "^2.8|^3.0", + "symfony/security-core": "^6.4|^7.0", + "symfony/security-csrf": "^6.4|^7.0", + "symfony/security-http": "^6.4|^7.0", + "symfony/serializer": "^6.4.3|^7.0.3", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/translation": "^6.4|^7.0", + "symfony/web-link": "^6.4|^7.0", + "symfony/workflow": "^6.4|^7.0", + "symfony/yaml": "^6.4|^7.0", + "twig/cssinliner-extra": "^2.12|^3", + "twig/inky-extra": "^2.12|^3", + "twig/markdown-extra": "^2.12|^3" + }, + "type": "symfony-bridge", + "autoload": { + "psr-4": { + "Symfony\\Bridge\\Twig\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides integration for Twig with various Symfony components", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/twig-bridge/tree/v7.1.8" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-11-10T02:47:09+00:00" + }, + { + "name": "symfony/twig-bundle", + "version": "v7.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/twig-bundle.git", + "reference": "af902314a71fb412ae412094f7e1d7e49594507b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/af902314a71fb412ae412094f7e1d7e49594507b", + "reference": "af902314a71fb412ae412094f7e1d7e49594507b", + "shasum": "" + }, + "require": { + "composer-runtime-api": ">=2.1", + "php": ">=8.2", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/twig-bridge": "^6.4|^7.0", + "twig/twig": "^3.0.4" + }, + "conflict": { + "symfony/framework-bundle": "<6.4", + "symfony/translation": "<6.4" + }, + "require-dev": { + "symfony/asset": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", + "symfony/form": "^6.4|^7.0", + "symfony/framework-bundle": "^6.4|^7.0", + "symfony/routing": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/translation": "^6.4|^7.0", + "symfony/web-link": "^6.4|^7.0", + "symfony/yaml": "^6.4|^7.0" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "Symfony\\Bundle\\TwigBundle\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a tight integration of Twig into the Symfony full-stack framework", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/twig-bundle/tree/v7.1.6" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:20:29+00:00" + }, { "name": "symfony/type-info", "version": "v7.1.8", @@ -4592,6 +4863,159 @@ } ], "time": "2024-09-25T14:20:29+00:00" + }, + { + "name": "twig/extra-bundle", + "version": "v3.13.0", + "source": { + "type": "git", + "url": "https://github.com/twigphp/twig-extra-bundle.git", + "reference": "21a9a7aa9f79d4493bb6fed4eb2794339f9551f5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twigphp/twig-extra-bundle/zipball/21a9a7aa9f79d4493bb6fed4eb2794339f9551f5", + "reference": "21a9a7aa9f79d4493bb6fed4eb2794339f9551f5", + "shasum": "" + }, + "require": { + "php": ">=8.0.2", + "symfony/framework-bundle": "^5.4|^6.4|^7.0", + "symfony/twig-bundle": "^5.4|^6.4|^7.0", + "twig/twig": "^3.0|^4.0" + }, + "require-dev": { + "league/commonmark": "^1.0|^2.0", + "symfony/phpunit-bridge": "^6.4|^7.0", + "twig/cache-extra": "^3.0", + "twig/cssinliner-extra": "^3.0", + "twig/html-extra": "^3.0", + "twig/inky-extra": "^3.0", + "twig/intl-extra": "^3.0", + "twig/markdown-extra": "^3.0", + "twig/string-extra": "^3.0" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "Twig\\Extra\\TwigExtraBundle\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + } + ], + "description": "A Symfony bundle for extra Twig extensions", + "homepage": "https://twig.symfony.com", + "keywords": [ + "bundle", + "extra", + "twig" + ], + "support": { + "source": "https://github.com/twigphp/twig-extra-bundle/tree/v3.13.0" + }, + "funding": [ + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/twig/twig", + "type": "tidelift" + } + ], + "time": "2024-09-01T20:39:12+00:00" + }, + { + "name": "twig/twig", + "version": "v3.14.2", + "source": { + "type": "git", + "url": "https://github.com/twigphp/Twig.git", + "reference": "0b6f9d8370bb3b7f1ce5313ed8feb0fafd6e399a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/0b6f9d8370bb3b7f1ce5313ed8feb0fafd6e399a", + "reference": "0b6f9d8370bb3b7f1ce5313ed8feb0fafd6e399a", + "shasum": "" + }, + "require": { + "php": ">=8.0.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-mbstring": "^1.3", + "symfony/polyfill-php81": "^1.29" + }, + "require-dev": { + "psr/container": "^1.0|^2.0", + "symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0" + }, + "type": "library", + "autoload": { + "files": [ + "src/Resources/core.php", + "src/Resources/debug.php", + "src/Resources/escaper.php", + "src/Resources/string_loader.php" + ], + "psr-4": { + "Twig\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + }, + { + "name": "Twig Team", + "role": "Contributors" + }, + { + "name": "Armin Ronacher", + "email": "armin.ronacher@active-4.com", + "role": "Project Founder" + } + ], + "description": "Twig, the flexible, fast, and secure template language for PHP", + "homepage": "https://twig.symfony.com", + "keywords": [ + "templating" + ], + "support": { + "issues": "https://github.com/twigphp/Twig/issues", + "source": "https://github.com/twigphp/Twig/tree/v3.14.2" + }, + "funding": [ + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/twig/twig", + "type": "tidelift" + } + ], + "time": "2024-11-07T12:36:22+00:00" } ], "packages-dev": [ @@ -4805,6 +5229,87 @@ } ], "time": "2024-11-06T14:23:19+00:00" + }, + { + "name": "symfony/web-profiler-bundle", + "version": "v7.1.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/web-profiler-bundle.git", + "reference": "13d97a9acb23663550495fa2480e8cc95033ad61" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/13d97a9acb23663550495fa2480e8cc95033ad61", + "reference": "13d97a9acb23663550495fa2480e8cc95033ad61", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/config": "^6.4|^7.0", + "symfony/framework-bundle": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/routing": "^6.4|^7.0", + "symfony/twig-bundle": "^6.4|^7.0", + "twig/twig": "^3.10" + }, + "conflict": { + "symfony/form": "<6.4", + "symfony/mailer": "<6.4", + "symfony/messenger": "<6.4" + }, + "require-dev": { + "symfony/browser-kit": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/css-selector": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "Symfony\\Bundle\\WebProfilerBundle\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a development tool that gives detailed information about the execution of any request", + "homepage": "https://symfony.com", + "keywords": [ + "dev" + ], + "support": { + "source": "https://github.com/symfony/web-profiler-bundle/tree/v7.1.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-11-05T07:52:02+00:00" } ], "aliases": [], diff --git a/config/bundles.php b/config/bundles.php index 952dff2..82c2ebe 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -6,4 +6,7 @@ return [ Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true], Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true], + Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], + Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true], + Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true], ]; diff --git a/config/packages/security.yaml b/config/packages/security.yaml index 359194a..1cb4a6e 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -28,6 +28,7 @@ security: # Easy way to control access for large sections of your site # Note: Only the *first* access control that matches will be used access_control: + - { path: /, roles: ROLE_USER} # - { path: ^/admin, roles: ROLE_ADMIN } # - { path: ^/profile, roles: ROLE_USER } diff --git a/config/packages/twig.yaml b/config/packages/twig.yaml new file mode 100644 index 0000000..3f795d9 --- /dev/null +++ b/config/packages/twig.yaml @@ -0,0 +1,6 @@ +twig: + file_name_pattern: '*.twig' + +when@test: + twig: + strict_variables: true diff --git a/config/packages/web_profiler.yaml b/config/packages/web_profiler.yaml new file mode 100644 index 0000000..b946111 --- /dev/null +++ b/config/packages/web_profiler.yaml @@ -0,0 +1,17 @@ +when@dev: + web_profiler: + toolbar: true + intercept_redirects: false + + framework: + profiler: + only_exceptions: false + collect_serializer_data: true + +when@test: + web_profiler: + toolbar: false + intercept_redirects: false + + framework: + profiler: { collect: false } diff --git a/config/routes/web_profiler.yaml b/config/routes/web_profiler.yaml new file mode 100644 index 0000000..8d85319 --- /dev/null +++ b/config/routes/web_profiler.yaml @@ -0,0 +1,8 @@ +when@dev: + web_profiler_wdt: + resource: '@WebProfilerBundle/Resources/config/routing/wdt.xml' + prefix: /_wdt + + web_profiler_profiler: + resource: '@WebProfilerBundle/Resources/config/routing/profiler.xml' + prefix: /_profiler diff --git a/public/icon.png b/public/icon.png new file mode 100644 index 0000000..f26a0a8 Binary files /dev/null and b/public/icon.png differ diff --git a/src/Controller/HomeController.php b/src/Controller/HomeController.php new file mode 100644 index 0000000..e62441b --- /dev/null +++ b/src/Controller/HomeController.php @@ -0,0 +1,17 @@ +render('index.html.twig'); + } +} \ No newline at end of file diff --git a/src/Entity/User.php b/src/Entity/User.php index 752945b..2c77648 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -18,23 +18,20 @@ class User implements UserInterface private ?int $id = null; #[ORM\Column(length: 180)] - private ?string $email = null; + private string $email = ''; #[ORM\Column(length: 255)] - private ?string $firstname = null; + private string $name = ''; #[ORM\Column(length: 255)] - private ?string $lastname = null; - - #[ORM\Column(length: 255)] - private ?string $username = null; + private string $username = ''; public function getId(): ?int { return $this->id; } - public function getEmail(): ?string + public function getEmail(): string { return $this->email; } @@ -48,7 +45,7 @@ class User implements UserInterface public function getUserIdentifier(): string { - return (string)$this->email; + return $this->email; } public function getRoles(): array @@ -60,31 +57,19 @@ class User implements UserInterface { } - public function getFirstname(): ?string + public function getName(): string { - return $this->firstname; + return $this->name; } - public function setFirstname(string $firstname): static + public function setName(?string $name): static { - $this->firstname = $firstname; + $this->name = $name; return $this; } - public function getLastname(): ?string - { - return $this->lastname; - } - - public function setLastname(string $lastname): static - { - $this->lastname = $lastname; - - return $this; - } - - public function getUsername(): ?string + public function getUsername(): string { return $this->username; } @@ -100,8 +85,7 @@ class User implements UserInterface { return (new self()) ->setEmail($request->headers->get('x-authentik-email')) - ->setFirstname($request->headers->get('x-authentik-firstname')) - ->setLastname($request->headers->get('x-authentik-lastname')) + ->setName($request->headers->get('x-authentik-name')) ->setUsername($request->headers->get('x-authentik-username')); } } diff --git a/src/Security/Authenticator.php b/src/Security/Authenticator.php index f4dbeb7..b9eafa8 100644 --- a/src/Security/Authenticator.php +++ b/src/Security/Authenticator.php @@ -25,14 +25,14 @@ class Authenticator extends AbstractAuthenticator { return $request->headers->has('x-authentik-username') && $request->headers->has('x-authentik-email') - && $request->headers->has('x-authentik-firstname') - && $request->headers->has('x-authentik-lastname'); + && $request->headers->has('x-authentik-name'); } public function authenticate(Request $request): Passport { $email = $request->headers->get('x-authentik-email'); + $this->checkGroup($request); $this->createUserIfNotExists($email, $request); return new SelfValidatingPassport(new UserBadge($email), [new RememberMeBadge()]); @@ -45,7 +45,8 @@ class Authenticator extends AbstractAuthenticator public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response { - return new JsonResponse([], Response::HTTP_UNAUTHORIZED); + dd($exception); + return new JsonResponse([$exception], Response::HTTP_UNAUTHORIZED); } private function createUserIfNotExists(string $email, Request $request): void @@ -55,4 +56,13 @@ class Authenticator extends AbstractAuthenticator $this->userRepository->save($user); } } + + private function checkGroup(Request $request): void + { + $groups = explode('|', $request->headers->get('x-authentik-groups')); + + if (!in_array('file-explorer user', $groups)) { + throw new \LogicException('You are not allowed to access this resource'); + } + } } diff --git a/symfony.lock b/symfony.lock index 9ce8fc4..7f4768a 100644 --- a/symfony.lock +++ b/symfony.lock @@ -103,5 +103,34 @@ "config/packages/security.yaml", "config/routes/security.yaml" ] + }, + "symfony/twig-bundle": { + "version": "7.1", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "6.4", + "ref": "cab5fd2a13a45c266d45a7d9337e28dee6272877" + }, + "files": [ + "config/packages/twig.yaml", + "templates/base.html.twig" + ] + }, + "symfony/web-profiler-bundle": { + "version": "7.1", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "6.1", + "ref": "e42b3f0177df239add25373083a564e5ead4e13a" + }, + "files": [ + "config/packages/web_profiler.yaml", + "config/routes/web_profiler.yaml" + ] + }, + "twig/extra-bundle": { + "version": "v3.13.0" } } diff --git a/templates/base.html.twig b/templates/base.html.twig new file mode 100644 index 0000000..7e9bc52 --- /dev/null +++ b/templates/base.html.twig @@ -0,0 +1,16 @@ + + +
+ +