Skip to content

Commit 3c2351d

Browse files
committed
Add webapp packages
1 parent 7306618 commit 3c2351d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+9181
-912
lines changed

.env

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,24 @@
1818
APP_ENV=dev
1919
APP_SECRET=
2020
###< symfony/framework-bundle ###
21+
22+
###> doctrine/doctrine-bundle ###
23+
# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
24+
# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
25+
#
26+
# DATABASE_URL="sqlite:///%kernel.project_dir%/var/data_%kernel.environment%.db"
27+
# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8.0.32&charset=utf8mb4"
28+
# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=10.11.2-MariaDB&charset=utf8mb4"
29+
DATABASE_URL="postgresql://app:!ChangeMe!@127.0.0.1:5432/app?serverVersion=16&charset=utf8"
30+
###< doctrine/doctrine-bundle ###
31+
32+
###> symfony/messenger ###
33+
# Choose one of the transports below
34+
# MESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/messages
35+
# MESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages
36+
MESSENGER_TRANSPORT_DSN=doctrine://default?auto_setup=0
37+
###< symfony/messenger ###
38+
39+
###> symfony/mailer ###
40+
MAILER_DSN=null://null
41+
###< symfony/mailer ###

.env.test

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# define your env variables for the test env here
2+
KERNEL_CLASS='App\Kernel'
3+
APP_SECRET='$ecretf0rt3st'

.gitignore

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,13 @@
88
/var/
99
/vendor/
1010
###< symfony/framework-bundle ###
11+
12+
###> phpunit/phpunit ###
13+
/phpunit.xml
14+
/.phpunit.cache/
15+
###< phpunit/phpunit ###
16+
17+
###> symfony/asset-mapper ###
18+
/public/assets/
19+
/assets/vendor/
20+
###< symfony/asset-mapper ###

assets/app.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import './bootstrap.js';
2+
/*
3+
* Welcome to your app's main JavaScript file!
4+
*
5+
* This file will be included onto the page via the importmap() Twig function,
6+
* which should already be in your base.html.twig.
7+
*/
8+
import './styles/app.css';
9+
10+
console.log('This log comes from assets/app.js - welcome to AssetMapper! 🎉');

assets/bootstrap.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { startStimulusApp } from '@symfony/stimulus-bundle';
2+
3+
const app = startStimulusApp();
4+
// register any custom, 3rd party controllers here
5+
// app.register('some_controller_name', SomeImportedController);

assets/controllers.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"controllers": {
3+
"@symfony/ux-turbo": {
4+
"turbo-core": {
5+
"enabled": true,
6+
"fetch": "eager"
7+
},
8+
"mercure-turbo-stream": {
9+
"enabled": false,
10+
"fetch": "eager"
11+
}
12+
}
13+
},
14+
"entrypoints": []
15+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
const nameCheck = /^[-_a-zA-Z0-9]{4,22}$/;
2+
const tokenCheck = /^[-_\/+a-zA-Z0-9]{24,}$/;
3+
4+
// Generate and double-submit a CSRF token in a form field and a cookie, as defined by Symfony's SameOriginCsrfTokenManager
5+
document.addEventListener('submit', function (event) {
6+
generateCsrfToken(event.target);
7+
}, true);
8+
9+
// When @hotwired/turbo handles form submissions, send the CSRF token in a header in addition to a cookie
10+
// The `framework.csrf_protection.check_header` config option needs to be enabled for the header to be checked
11+
document.addEventListener('turbo:submit-start', function (event) {
12+
const h = generateCsrfHeaders(event.detail.formSubmission.formElement);
13+
Object.keys(h).map(function (k) {
14+
event.detail.formSubmission.fetchRequest.headers[k] = h[k];
15+
});
16+
});
17+
18+
// When @hotwired/turbo handles form submissions, remove the CSRF cookie once a form has been submitted
19+
document.addEventListener('turbo:submit-end', function (event) {
20+
removeCsrfToken(event.detail.formSubmission.formElement);
21+
});
22+
23+
export function generateCsrfToken (formElement) {
24+
const csrfField = formElement.querySelector('input[data-controller="csrf-protection"], input[name="_csrf_token"]');
25+
26+
if (!csrfField) {
27+
return;
28+
}
29+
30+
let csrfCookie = csrfField.getAttribute('data-csrf-protection-cookie-value');
31+
let csrfToken = csrfField.value;
32+
33+
if (!csrfCookie && nameCheck.test(csrfToken)) {
34+
csrfField.setAttribute('data-csrf-protection-cookie-value', csrfCookie = csrfToken);
35+
csrfField.defaultValue = csrfToken = btoa(String.fromCharCode.apply(null, (window.crypto || window.msCrypto).getRandomValues(new Uint8Array(18))));
36+
csrfField.dispatchEvent(new Event('change', { bubbles: true }));
37+
}
38+
39+
if (csrfCookie && tokenCheck.test(csrfToken)) {
40+
const cookie = csrfCookie + '_' + csrfToken + '=' + csrfCookie + '; path=/; samesite=strict';
41+
document.cookie = window.location.protocol === 'https:' ? '__Host-' + cookie + '; secure' : cookie;
42+
}
43+
}
44+
45+
export function generateCsrfHeaders (formElement) {
46+
const headers = {};
47+
const csrfField = formElement.querySelector('input[data-controller="csrf-protection"], input[name="_csrf_token"]');
48+
49+
if (!csrfField) {
50+
return headers;
51+
}
52+
53+
const csrfCookie = csrfField.getAttribute('data-csrf-protection-cookie-value');
54+
55+
if (tokenCheck.test(csrfField.value) && nameCheck.test(csrfCookie)) {
56+
headers[csrfCookie] = csrfField.value;
57+
}
58+
59+
return headers;
60+
}
61+
62+
export function removeCsrfToken (formElement) {
63+
const csrfField = formElement.querySelector('input[data-controller="csrf-protection"], input[name="_csrf_token"]');
64+
65+
if (!csrfField) {
66+
return;
67+
}
68+
69+
const csrfCookie = csrfField.getAttribute('data-csrf-protection-cookie-value');
70+
71+
if (tokenCheck.test(csrfField.value) && nameCheck.test(csrfCookie)) {
72+
const cookie = csrfCookie + '_' + csrfField.value + '=0; path=/; samesite=strict; max-age=0';
73+
74+
document.cookie = window.location.protocol === 'https:' ? '__Host-' + cookie + '; secure' : cookie;
75+
}
76+
}
77+
78+
/* stimulusFetch: 'lazy' */
79+
export default 'csrf-protection-controller';
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { Controller } from '@hotwired/stimulus';
2+
3+
/*
4+
* This is an example Stimulus controller!
5+
*
6+
* Any element with a data-controller="hello" attribute will cause
7+
* this controller to be executed. The name "hello" comes from the filename:
8+
* hello_controller.js -> "hello"
9+
*
10+
* Delete this file or adapt it for your use!
11+
*/
12+
export default class extends Controller {
13+
connect() {
14+
this.element.textContent = 'Hello Stimulus! Edit me in assets/controllers/hello_controller.js';
15+
}
16+
}

assets/styles/app.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
body {
2+
background-color: skyblue;
3+
}

bin/phpunit

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/usr/bin/env php
2+
<?php
3+
4+
if (!ini_get('date.timezone')) {
5+
ini_set('date.timezone', 'UTC');
6+
}
7+
8+
if (is_file(dirname(__DIR__).'/vendor/phpunit/phpunit/phpunit')) {
9+
if (PHP_VERSION_ID >= 80000) {
10+
require dirname(__DIR__).'/vendor/phpunit/phpunit/phpunit';
11+
} else {
12+
define('PHPUNIT_COMPOSER_INSTALL', dirname(__DIR__).'/vendor/autoload.php');
13+
require PHPUNIT_COMPOSER_INSTALL;
14+
PHPUnit\TextUI\Command::main();
15+
}
16+
} else {
17+
if (!is_file(dirname(__DIR__).'/vendor/symfony/phpunit-bridge/bin/simple-phpunit.php')) {
18+
echo "Unable to find the `simple-phpunit.php` script in `vendor/symfony/phpunit-bridge/bin/`.\n";
19+
exit(1);
20+
}
21+
22+
require dirname(__DIR__).'/vendor/symfony/phpunit-bridge/bin/simple-phpunit.php';
23+
}

0 commit comments

Comments
 (0)