mirror of
https://github.com/symfony/demo.git
synced 2026-03-24 00:02:32 +01:00
chore: sync recipes
(cherry picked from commit 5cf07ff96971540d282cb8bb8fc91c4691709edf)
This commit is contained in:
7
.env
7
.env
@@ -23,11 +23,12 @@ APP_SECRET=
|
||||
# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
|
||||
# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
|
||||
#
|
||||
DATABASE_URL=sqlite:///%kernel.project_dir%/data/database.sqlite
|
||||
# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8&charset=utf8mb4"
|
||||
DATABASE_URL="sqlite:///%kernel.project_dir%/data/database.sqlite"
|
||||
# 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"
|
||||
###< doctrine/doctrine-bundle ###
|
||||
|
||||
###> symfony/mailer ###
|
||||
# MAILER_DSN=null://null
|
||||
MAILER_DSN=null://null
|
||||
###< symfony/mailer ###
|
||||
|
||||
1
assets/bootstrap.js
vendored
1
assets/bootstrap.js
vendored
@@ -1,6 +1,5 @@
|
||||
import { startStimulusApp } from '@symfony/stimulus-bundle';
|
||||
|
||||
const app = startStimulusApp();
|
||||
|
||||
// register any custom, 3rd party controllers here
|
||||
// app.register('some_controller_name', SomeImportedController);
|
||||
|
||||
79
assets/controllers/csrf_protection_controller.js
Normal file
79
assets/controllers/csrf_protection_controller.js
Normal file
@@ -0,0 +1,79 @@
|
||||
const nameCheck = /^[-_a-zA-Z0-9]{4,22}$/;
|
||||
const tokenCheck = /^[-_\/+a-zA-Z0-9]{24,}$/;
|
||||
|
||||
// Generate and double-submit a CSRF token in a form field and a cookie, as defined by Symfony's SameOriginCsrfTokenManager
|
||||
document.addEventListener('submit', function (event) {
|
||||
generateCsrfToken(event.target);
|
||||
}, true);
|
||||
|
||||
// When @hotwired/turbo handles form submissions, send the CSRF token in a header in addition to a cookie
|
||||
// The `framework.csrf_protection.check_header` config option needs to be enabled for the header to be checked
|
||||
document.addEventListener('turbo:submit-start', function (event) {
|
||||
const h = generateCsrfHeaders(event.detail.formSubmission.formElement);
|
||||
Object.keys(h).map(function (k) {
|
||||
event.detail.formSubmission.fetchRequest.headers[k] = h[k];
|
||||
});
|
||||
});
|
||||
|
||||
// When @hotwired/turbo handles form submissions, remove the CSRF cookie once a form has been submitted
|
||||
document.addEventListener('turbo:submit-end', function (event) {
|
||||
removeCsrfToken(event.detail.formSubmission.formElement);
|
||||
});
|
||||
|
||||
export function generateCsrfToken (formElement) {
|
||||
const csrfField = formElement.querySelector('input[data-controller="csrf-protection"], input[name="_csrf_token"]');
|
||||
|
||||
if (!csrfField) {
|
||||
return;
|
||||
}
|
||||
|
||||
let csrfCookie = csrfField.getAttribute('data-csrf-protection-cookie-value');
|
||||
let csrfToken = csrfField.value;
|
||||
|
||||
if (!csrfCookie && nameCheck.test(csrfToken)) {
|
||||
csrfField.setAttribute('data-csrf-protection-cookie-value', csrfCookie = csrfToken);
|
||||
csrfField.defaultValue = csrfToken = btoa(String.fromCharCode.apply(null, (window.crypto || window.msCrypto).getRandomValues(new Uint8Array(18))));
|
||||
csrfField.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
}
|
||||
|
||||
if (csrfCookie && tokenCheck.test(csrfToken)) {
|
||||
const cookie = csrfCookie + '_' + csrfToken + '=' + csrfCookie + '; path=/; samesite=strict';
|
||||
document.cookie = window.location.protocol === 'https:' ? '__Host-' + cookie + '; secure' : cookie;
|
||||
}
|
||||
}
|
||||
|
||||
export function generateCsrfHeaders (formElement) {
|
||||
const headers = {};
|
||||
const csrfField = formElement.querySelector('input[data-controller="csrf-protection"], input[name="_csrf_token"]');
|
||||
|
||||
if (!csrfField) {
|
||||
return headers;
|
||||
}
|
||||
|
||||
const csrfCookie = csrfField.getAttribute('data-csrf-protection-cookie-value');
|
||||
|
||||
if (tokenCheck.test(csrfField.value) && nameCheck.test(csrfCookie)) {
|
||||
headers[csrfCookie] = csrfField.value;
|
||||
}
|
||||
|
||||
return headers;
|
||||
}
|
||||
|
||||
export function removeCsrfToken (formElement) {
|
||||
const csrfField = formElement.querySelector('input[data-controller="csrf-protection"], input[name="_csrf_token"]');
|
||||
|
||||
if (!csrfField) {
|
||||
return;
|
||||
}
|
||||
|
||||
const csrfCookie = csrfField.getAttribute('data-csrf-protection-cookie-value');
|
||||
|
||||
if (tokenCheck.test(csrfField.value) && nameCheck.test(csrfCookie)) {
|
||||
const cookie = csrfCookie + '_' + csrfField.value + '=0; path=/; samesite=strict; max-age=0';
|
||||
|
||||
document.cookie = window.location.protocol === 'https:' ? '__Host-' + cookie + '; secure' : cookie;
|
||||
}
|
||||
}
|
||||
|
||||
/* stimulusFetch: 'lazy' */
|
||||
export default 'csrf-protection-controller';
|
||||
9270
composer.lock
generated
Normal file
9270
composer.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -3,3 +3,9 @@ framework:
|
||||
# The paths to make available to the asset mapper.
|
||||
paths:
|
||||
- assets/
|
||||
missing_import_mode: strict
|
||||
|
||||
when@prod:
|
||||
framework:
|
||||
asset_mapper:
|
||||
missing_import_mode: warn
|
||||
|
||||
11
config/packages/csrf.yaml
Normal file
11
config/packages/csrf.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
# Enable stateless CSRF protection for forms and logins/logouts
|
||||
framework:
|
||||
form:
|
||||
csrf_protection:
|
||||
token_id: submit
|
||||
|
||||
csrf_protection:
|
||||
stateless_token_ids:
|
||||
- submit
|
||||
- authenticate
|
||||
- logout
|
||||
@@ -11,10 +11,12 @@ doctrine:
|
||||
orm:
|
||||
auto_generate_proxy_classes: true
|
||||
enable_lazy_ghost_objects: true
|
||||
report_fields_where_declared: true
|
||||
validate_xml_mapping: true
|
||||
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
|
||||
identity_generation_preferences:
|
||||
Doctrine\DBAL\Platforms\PostgreSQLPlatform: identity
|
||||
auto_mapping: true
|
||||
report_fields_where_declared: true
|
||||
mappings:
|
||||
App:
|
||||
type: attribute
|
||||
|
||||
@@ -50,7 +50,7 @@ DirectoryIndex index.php
|
||||
# - use Apache >= 2.3.9 and replace all L flags by END flags and remove the
|
||||
# following RewriteCond (best solution)
|
||||
RewriteCond %{ENV:REDIRECT_STATUS} =""
|
||||
RewriteRule ^index\.php(?:/(.*)|$) %{ENV:BASE}/$1 [R=301,L]
|
||||
RewriteRule ^index\.php(?:/(.*)|$) %{ENV:BASE}/$1 [R=308,L]
|
||||
|
||||
# If the requested filename exists, simply serve it.
|
||||
# We only want to let Apache serve files and not directories.
|
||||
|
||||
0
src/Entity/.gitignore
vendored
Normal file
0
src/Entity/.gitignore
vendored
Normal file
0
src/Repository/.gitignore
vendored
Normal file
0
src/Repository/.gitignore
vendored
Normal file
95
symfony.lock
95
symfony.lock
@@ -16,13 +16,13 @@
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "2.12",
|
||||
"ref": "7266981c201efbbe02ae53c87f8bb378e3f825ae"
|
||||
"version": "2.13",
|
||||
"ref": "8d96c0b51591ffc26794d865ba3ee7d193438a83"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/doctrine.yaml",
|
||||
"src/Entity/.gitignore",
|
||||
"src/Repository/.gitignore"
|
||||
"./config/packages/doctrine.yaml",
|
||||
"./src/Entity/.gitignore",
|
||||
"./src/Repository/.gitignore"
|
||||
]
|
||||
},
|
||||
"doctrine/doctrine-fixtures-bundle": {
|
||||
@@ -68,10 +68,10 @@
|
||||
"repo": "github.com/symfony/recipes-contrib",
|
||||
"branch": "main",
|
||||
"version": "1.0",
|
||||
"ref": "0f18b4decdf5695d692c1d0dfd65516a07a6adf1"
|
||||
"ref": "5d454ec6cc4c700ed3d963f3803e1d427d9669fb"
|
||||
},
|
||||
"files": [
|
||||
"public/.htaccess"
|
||||
"./public/.htaccess"
|
||||
]
|
||||
},
|
||||
"symfony/asset-mapper": {
|
||||
@@ -80,13 +80,13 @@
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "6.4",
|
||||
"ref": "6c28c471640cc2c6e60812ebcb961c526ef8997f"
|
||||
"ref": "5ad1308aa756d58f999ffbe1540d1189f5d7d14a"
|
||||
},
|
||||
"files": [
|
||||
"assets/app.js",
|
||||
"assets/styles/app.css",
|
||||
"config/packages/asset_mapper.yaml",
|
||||
"importmap.php"
|
||||
"./assets/app.js",
|
||||
"./assets/styles/app.css",
|
||||
"./config/packages/asset_mapper.yaml",
|
||||
"./importmap.php"
|
||||
]
|
||||
},
|
||||
"symfony/console": {
|
||||
@@ -118,11 +118,43 @@
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "1.0",
|
||||
"ref": "146251ae39e06a95be0fe3d13c807bcf3938b172"
|
||||
"version": "2.4",
|
||||
"ref": "52e9754527a15e2b79d9a610f98185a1fe46622a"
|
||||
},
|
||||
"files": [
|
||||
".env"
|
||||
"./.env",
|
||||
"./.env.dev"
|
||||
]
|
||||
},
|
||||
"symfony/form": {
|
||||
"version": "7.2",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "7.2",
|
||||
"ref": "7d86a6723f4a623f59e2bf966b6aad2fc461d36b"
|
||||
},
|
||||
"files": [
|
||||
"./config/packages/csrf.yaml"
|
||||
]
|
||||
},
|
||||
"symfony/framework-bundle": {
|
||||
"version": "7.2",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "7.2",
|
||||
"ref": "87bcf6f7c55201f345d8895deda46d2adbdbaa89"
|
||||
},
|
||||
"files": [
|
||||
"./config/packages/cache.yaml",
|
||||
"./config/packages/framework.yaml",
|
||||
"./config/preload.php",
|
||||
"./config/routes/framework.yaml",
|
||||
"./config/services.yaml",
|
||||
"./public/index.php",
|
||||
"./src/Controller/.gitignore",
|
||||
"./src/Kernel.php"
|
||||
]
|
||||
},
|
||||
"symfony/mailer": {
|
||||
@@ -131,10 +163,10 @@
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "4.3",
|
||||
"ref": "df66ee1f226c46f01e85c29c2f7acce0596ba35a"
|
||||
"ref": "09051cfde49476e3c12cd3a0e44289ace1c75a4f"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/mailer.yaml"
|
||||
"./config/packages/mailer.yaml"
|
||||
]
|
||||
},
|
||||
"symfony/maker-bundle": {
|
||||
@@ -200,17 +232,18 @@
|
||||
]
|
||||
},
|
||||
"symfony/stimulus-bundle": {
|
||||
"version": "2.20",
|
||||
"version": "2.23",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "2.13",
|
||||
"ref": "6acd9ff4f7fd5626d2962109bd4ebab351d43c43"
|
||||
"version": "2.20",
|
||||
"ref": "3acc494b566816514a6873a89023a35440b6386d"
|
||||
},
|
||||
"files": [
|
||||
"assets/bootstrap.js",
|
||||
"assets/controllers.json",
|
||||
"assets/controllers/hello_controller.js"
|
||||
"./assets/bootstrap.js",
|
||||
"./assets/controllers.json",
|
||||
"./assets/controllers/csrf_protection_controller.js",
|
||||
"./assets/controllers/hello_controller.js"
|
||||
]
|
||||
},
|
||||
"symfony/translation": {
|
||||
@@ -239,6 +272,18 @@
|
||||
"templates/base.html.twig"
|
||||
]
|
||||
},
|
||||
"symfony/ux-icons": {
|
||||
"version": "2.23",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "2.17",
|
||||
"ref": "803a3bbd5893f9584969ab8670290cdfb6a0a5b5"
|
||||
},
|
||||
"files": [
|
||||
"./assets/icons/symfony.svg"
|
||||
]
|
||||
},
|
||||
"symfony/ux-live-component": {
|
||||
"version": "2.20",
|
||||
"recipe": {
|
||||
@@ -289,9 +334,9 @@
|
||||
]
|
||||
},
|
||||
"symfonycasts/sass-bundle": {
|
||||
"version": "v0.3.0"
|
||||
"version": "v0.7.0"
|
||||
},
|
||||
"twig/extra-bundle": {
|
||||
"version": "v3.13.0"
|
||||
"version": "v3.20.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<input type="hidden" name="_target_path" value="{{ app.request.get('redirect_to') }}"/>
|
||||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}"/>
|
||||
<input type="hidden" name="_csrf_token" data-controller="csrf-protection" value="{{ csrf_token('authenticate') }}"/>
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<twig:ux:icon name="tabler:login"/> {{ 'action.sign_in'|trans }}
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user