before switch to turbo
This commit is contained in:
parent
219f4097ff
commit
23139a5835
6
.env
6
.env
@ -42,3 +42,9 @@ CORS_ALLOW_ORIGIN='^https?://(localhost|127\.0\.0\.1)(:[0-9]+)?$'
|
|||||||
# MESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/messages
|
# MESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/messages
|
||||||
# MESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages
|
# MESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages
|
||||||
###< symfony/messenger ###
|
###< symfony/messenger ###
|
||||||
|
|
||||||
|
###> symfony/lock ###
|
||||||
|
# Choose one of the stores below
|
||||||
|
# postgresql+advisory://db_user:db_password@localhost/db_name
|
||||||
|
LOCK_DSN=flock
|
||||||
|
###< symfony/lock ###
|
||||||
|
1
TODO
1
TODO
@ -2,6 +2,7 @@ accent color #d43934
|
|||||||
|
|
||||||
add dates and author to pages
|
add dates and author to pages
|
||||||
|
|
||||||
|
blog
|
||||||
use turbo
|
use turbo
|
||||||
make unit tests
|
make unit tests
|
||||||
|
|
||||||
|
@ -10,6 +10,41 @@ import 'fork-awesome/scss/fork-awesome.scss'
|
|||||||
import './styles/app.scss'
|
import './styles/app.scss'
|
||||||
import $ from 'jquery'
|
import $ from 'jquery'
|
||||||
import 'bootstrap'
|
import 'bootstrap'
|
||||||
|
|
||||||
|
// Dropzone stuff move to component
|
||||||
|
import {Dropzone} from 'dropzone'
|
||||||
|
|
||||||
|
// TODO handle error (Chapter 26)
|
||||||
|
const formElement = $('#dropzoneForm')
|
||||||
|
if (formElement) {
|
||||||
|
const previewContent = $('#preview-content').html()
|
||||||
|
console.log(previewContent)
|
||||||
|
const dropzone = new Dropzone('#dropzoneForm', {
|
||||||
|
acceptedFiles: '.jpg, .jpeg, .png',
|
||||||
|
maxFiles: 1,
|
||||||
|
init: function () {
|
||||||
|
this.hiddenFileInput.removeAttribute('multiple')
|
||||||
|
this.on('maxfilesexceeded', (file) => {
|
||||||
|
this.removeAllFiles()
|
||||||
|
this.addFile(file)
|
||||||
|
})
|
||||||
|
this.on('error', (file, data) => {
|
||||||
|
console.log('error');
|
||||||
|
if (data.detail) {
|
||||||
|
this.emit('error', file, data.detail)
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
console.log('filename', previewContent)
|
||||||
|
const mockFile = { name: previewContent }
|
||||||
|
console.log('file', mockFile)
|
||||||
|
dropzone.displayExistingFile(mockFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
// End Dropzone stuff move to component
|
||||||
|
|
||||||
//import './js/index'
|
//import './js/index'
|
||||||
// needed for legacy code
|
// needed for legacy code
|
||||||
//global.$ = $
|
//global.$ = $
|
||||||
@ -27,5 +62,6 @@ $(document).ready(() => {
|
|||||||
$('#sidebar').toggleClass('active')
|
$('#sidebar').toggleClass('active')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// start the Stimulus application
|
// start the Stimulus application
|
||||||
//import './bootstrap'
|
//import './bootstrap'
|
||||||
|
1
assets/js/components/_avatarDropzone.js
Normal file
1
assets/js/components/_avatarDropzone.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
i
|
@ -1,3 +0,0 @@
|
|||||||
body {
|
|
||||||
background-color: lightgray;
|
|
||||||
}
|
|
@ -18,13 +18,17 @@
|
|||||||
$primary: #FF8040;
|
$primary: #FF8040;
|
||||||
$jet-black: #0e0e10;
|
$jet-black: #0e0e10;
|
||||||
|
|
||||||
$body-color: #3f3f3f;
|
|
||||||
$list-group-bg: $body-color;
|
|
||||||
$list-group-hover-bg: #232323;
|
|
||||||
$list-group-active-bg: #232323;
|
|
||||||
$list-group-action-active-bg: #232323;
|
|
||||||
|
|
||||||
@import '~bootstrap';
|
|
||||||
|
$body-color: #9f9f9f;
|
||||||
|
$list-group: #232323;
|
||||||
|
$list-group-bg: $list-group;
|
||||||
|
$list-group-hover-bg: darken($list-group, 10%);
|
||||||
|
$list-group-active-bg: $list-group;
|
||||||
|
$list-group-action-active-bg: $list-group;
|
||||||
|
|
||||||
|
@import 'bootstrap/scss/bootstrap';
|
||||||
|
@import 'dropzone/dist/dropzone';
|
||||||
|
|
||||||
@import './components/sidebar';
|
@import './components/sidebar';
|
||||||
|
|
||||||
@ -36,7 +40,16 @@ html, body {
|
|||||||
background: #0e0e10;
|
background: #0e0e10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dropzone
|
||||||
|
|
||||||
|
.dropzone .dz-preview.dz-image-preview {
|
||||||
|
background: transparent !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.article-author-img {
|
||||||
|
width: 80px;
|
||||||
|
margin: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
"easycorp/easyadmin-bundle": "^4.0",
|
"easycorp/easyadmin-bundle": "^4.0",
|
||||||
"knplabs/knp-time-bundle": "^1.18",
|
"knplabs/knp-time-bundle": "^1.18",
|
||||||
"league/commonmark": "^2.3",
|
"league/commonmark": "^2.3",
|
||||||
|
"liip/imagine-bundle": "^2.9",
|
||||||
"nelmio/cors-bundle": "^2.2",
|
"nelmio/cors-bundle": "^2.2",
|
||||||
"phpdocumentor/reflection-docblock": "^5.3",
|
"phpdocumentor/reflection-docblock": "^5.3",
|
||||||
"phpstan/phpdoc-parser": "^1.4",
|
"phpstan/phpdoc-parser": "^1.4",
|
||||||
@ -39,6 +40,7 @@
|
|||||||
"symfony/property-access": "6.1.*",
|
"symfony/property-access": "6.1.*",
|
||||||
"symfony/property-info": "6.1.*",
|
"symfony/property-info": "6.1.*",
|
||||||
"symfony/proxy-manager-bridge": "6.1.*",
|
"symfony/proxy-manager-bridge": "6.1.*",
|
||||||
|
"symfony/rate-limiter": "6.1.*",
|
||||||
"symfony/runtime": "6.1.*",
|
"symfony/runtime": "6.1.*",
|
||||||
"symfony/security-bundle": "6.1.*",
|
"symfony/security-bundle": "6.1.*",
|
||||||
"symfony/security-csrf": "6.1.*",
|
"symfony/security-csrf": "6.1.*",
|
||||||
|
313
composer.lock
generated
313
composer.lock
generated
@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "a389aa46db42a7da38ebb6610fb97a52",
|
"content-hash": "1c940d128112ec366d0f81bc6eccee45",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "dflydev/dot-access-data",
|
"name": "dflydev/dot-access-data",
|
||||||
@ -1689,6 +1689,68 @@
|
|||||||
],
|
],
|
||||||
"time": "2022-10-17T19:48:16+00:00"
|
"time": "2022-10-17T19:48:16+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "imagine/imagine",
|
||||||
|
"version": "1.3.2",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/php-imagine/Imagine.git",
|
||||||
|
"reference": "ae864f26afbf8859ebd2e2b9df92d77ee175dc13"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/php-imagine/Imagine/zipball/ae864f26afbf8859ebd2e2b9df92d77ee175dc13",
|
||||||
|
"reference": "ae864f26afbf8859ebd2e2b9df92d77ee175dc13",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.5"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^4.8 || ^5.7 || ^6.5 || ^7.5 || ^8.4 || ^9.3"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-exif": "to read EXIF metadata",
|
||||||
|
"ext-gd": "to use the GD implementation",
|
||||||
|
"ext-gmagick": "to use the Gmagick implementation",
|
||||||
|
"ext-imagick": "to use the Imagick implementation"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-develop": "1.x-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Imagine\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Bulat Shakirzyanov",
|
||||||
|
"email": "mallluhuct@gmail.com",
|
||||||
|
"homepage": "http://avalanche123.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Image processing for PHP 5.3",
|
||||||
|
"homepage": "http://imagine.readthedocs.org/",
|
||||||
|
"keywords": [
|
||||||
|
"drawing",
|
||||||
|
"graphics",
|
||||||
|
"image manipulation",
|
||||||
|
"image processing"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/php-imagine/Imagine/issues",
|
||||||
|
"source": "https://github.com/php-imagine/Imagine/tree/1.3.2"
|
||||||
|
},
|
||||||
|
"time": "2022-04-01T11:58:30+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "knplabs/knp-time-bundle",
|
"name": "knplabs/knp-time-bundle",
|
||||||
"version": "v1.20.0",
|
"version": "v1.20.0",
|
||||||
@ -2016,6 +2078,108 @@
|
|||||||
],
|
],
|
||||||
"time": "2021-08-14T12:15:32+00:00"
|
"time": "2021-08-14T12:15:32+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "liip/imagine-bundle",
|
||||||
|
"version": "2.9.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/liip/LiipImagineBundle.git",
|
||||||
|
"reference": "ba164fef7be638f28d298f9c89b5a8364c3e0a4d"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/liip/LiipImagineBundle/zipball/ba164fef7be638f28d298f9c89b5a8364c3e0a4d",
|
||||||
|
"reference": "ba164fef7be638f28d298f9c89b5a8364c3e0a4d",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-mbstring": "*",
|
||||||
|
"imagine/imagine": "^1.2.4",
|
||||||
|
"php": "^7.1|^8.0",
|
||||||
|
"symfony/filesystem": "^3.4|^4.4|^5.3|^6.0",
|
||||||
|
"symfony/finder": "^3.4|^4.4|^5.3|^6.0",
|
||||||
|
"symfony/framework-bundle": "^3.4.23|^4.4|^5.3|^6.0",
|
||||||
|
"symfony/mime": "^4.4|^5.3|^6.0",
|
||||||
|
"symfony/options-resolver": "^3.4|^4.4|^5.3|^6.0",
|
||||||
|
"symfony/process": "^3.4|^4.4|^5.3|^6.0",
|
||||||
|
"twig/twig": "^1.44|^2.9|^3.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"amazonwebservices/aws-sdk-for-php": "^1.0",
|
||||||
|
"aws/aws-sdk-php": "^2.4",
|
||||||
|
"doctrine/cache": "^1.11|^2.0",
|
||||||
|
"doctrine/persistence": "^1.3|^2.0",
|
||||||
|
"enqueue/enqueue-bundle": "^0.9|^0.10",
|
||||||
|
"ext-gd": "*",
|
||||||
|
"league/flysystem": "^1.0|^2.0|^3.0",
|
||||||
|
"phpstan/phpstan": "^0.12.64",
|
||||||
|
"psr/cache": "^1.0|^2.0|^3.0",
|
||||||
|
"psr/log": "^1.0",
|
||||||
|
"symfony/browser-kit": "^3.4|^4.4|^5.3|^6.0",
|
||||||
|
"symfony/cache": "^3.4|^4.4|^5.3|^6.0",
|
||||||
|
"symfony/console": "^3.4|^4.4|^5.3|^6.0",
|
||||||
|
"symfony/dependency-injection": "^3.4|^4.4|^5.3|^6.0",
|
||||||
|
"symfony/form": "^3.4|^4.4|^5.3|^6.0",
|
||||||
|
"symfony/messenger": "^4.4|^5.3|^6.0",
|
||||||
|
"symfony/phpunit-bridge": "^5.3",
|
||||||
|
"symfony/templating": "^3.4|^4.4|^5.3|^6.0",
|
||||||
|
"symfony/validator": "^3.4|^4.4|^5.3|^6.0",
|
||||||
|
"symfony/yaml": "^3.4|^4.4|^5.3|^6.0"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"alcaeus/mongo-php-adapter": "required for mongodb components",
|
||||||
|
"amazonwebservices/aws-sdk-for-php": "required to use AWS version 1 cache resolver",
|
||||||
|
"aws/aws-sdk-php": "required to use AWS version 2/3 cache resolver",
|
||||||
|
"doctrine/mongodb-odm": "required to use mongodb-backed doctrine components",
|
||||||
|
"enqueue/enqueue-bundle": "^0.9 add if you like to process images in background",
|
||||||
|
"ext-exif": "required to read EXIF metadata from images",
|
||||||
|
"ext-gd": "required to use gd driver",
|
||||||
|
"ext-gmagick": "required to use gmagick driver",
|
||||||
|
"ext-imagick": "required to use imagick driver",
|
||||||
|
"ext-mongodb": "required for mongodb components",
|
||||||
|
"league/flysystem": "required to use FlySystem data loader or cache resolver",
|
||||||
|
"monolog/monolog": "A psr/log compatible logger is required to enable logging",
|
||||||
|
"symfony/messenger": "If you like to process images in background",
|
||||||
|
"symfony/templating": "required to use deprecated Templating component instead of Twig"
|
||||||
|
},
|
||||||
|
"type": "symfony-bundle",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Liip\\ImagineBundle\\": ""
|
||||||
|
},
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/Tests/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Liip and other contributors",
|
||||||
|
"homepage": "https://github.com/liip/LiipImagineBundle/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "This bundle provides an image manipulation abstraction toolkit for Symfony-based projects.",
|
||||||
|
"homepage": "http://liip.ch",
|
||||||
|
"keywords": [
|
||||||
|
"bundle",
|
||||||
|
"image",
|
||||||
|
"imagine",
|
||||||
|
"liip",
|
||||||
|
"manipulation",
|
||||||
|
"photos",
|
||||||
|
"pictures",
|
||||||
|
"symfony",
|
||||||
|
"transformation"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/liip/LiipImagineBundle/issues",
|
||||||
|
"source": "https://github.com/liip/LiipImagineBundle/tree/2.9.0"
|
||||||
|
},
|
||||||
|
"time": "2022-10-06T06:33:35+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "monolog/monolog",
|
"name": "monolog/monolog",
|
||||||
"version": "3.2.0",
|
"version": "3.2.0",
|
||||||
@ -5076,6 +5240,83 @@
|
|||||||
],
|
],
|
||||||
"time": "2022-10-23T10:33:34+00:00"
|
"time": "2022-10-23T10:33:34+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/lock",
|
||||||
|
"version": "v6.1.7",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/lock.git",
|
||||||
|
"reference": "98d6c4b6608d15e403a228c15afb4f3e71b22a57"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/lock/zipball/98d6c4b6608d15e403a228c15afb4f3e71b22a57",
|
||||||
|
"reference": "98d6c4b6608d15e403a228c15afb4f3e71b22a57",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=8.1",
|
||||||
|
"psr/log": "^1|^2|^3"
|
||||||
|
},
|
||||||
|
"conflict": {
|
||||||
|
"doctrine/dbal": "<2.13"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"doctrine/dbal": "^2.13|^3.0",
|
||||||
|
"predis/predis": "~1.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Component\\Lock\\": ""
|
||||||
|
},
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/Tests/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Jérémy Derussé",
|
||||||
|
"email": "jeremy@derusse.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Creates and manages locks, a mechanism to provide exclusive access to a shared resource",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"keywords": [
|
||||||
|
"cas",
|
||||||
|
"flock",
|
||||||
|
"locking",
|
||||||
|
"mutex",
|
||||||
|
"redlock",
|
||||||
|
"semaphore"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/lock/tree/v6.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": "2022-10-28T16:23:08+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/mailer",
|
"name": "symfony/mailer",
|
||||||
"version": "v6.1.7",
|
"version": "v6.1.7",
|
||||||
@ -6495,6 +6736,76 @@
|
|||||||
],
|
],
|
||||||
"time": "2022-03-02T13:21:45+00:00"
|
"time": "2022-03-02T13:21:45+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/rate-limiter",
|
||||||
|
"version": "v6.1.3",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/rate-limiter.git",
|
||||||
|
"reference": "9e75706446f7c3686773c408f422ffb5ec4ba32b"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/rate-limiter/zipball/9e75706446f7c3686773c408f422ffb5ec4ba32b",
|
||||||
|
"reference": "9e75706446f7c3686773c408f422ffb5ec4ba32b",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=8.1",
|
||||||
|
"symfony/lock": "^5.4|^6.0",
|
||||||
|
"symfony/options-resolver": "^5.4|^6.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"psr/cache": "^1.0|^2.0|^3.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Component\\RateLimiter\\": ""
|
||||||
|
},
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/Tests/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Wouter de Jong",
|
||||||
|
"email": "wouter@wouterj.nl"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Provides a Token Bucket implementation to rate limit input and output in your application",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"keywords": [
|
||||||
|
"limiter",
|
||||||
|
"rate-limiter"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/rate-limiter/tree/v6.1.3"
|
||||||
|
},
|
||||||
|
"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": "2022-07-20T13:46:29+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/routing",
|
"name": "symfony/routing",
|
||||||
"version": "v6.1.7",
|
"version": "v6.1.7",
|
||||||
|
@ -18,4 +18,5 @@ return [
|
|||||||
Nelmio\CorsBundle\NelmioCorsBundle::class => ['all' => true],
|
Nelmio\CorsBundle\NelmioCorsBundle::class => ['all' => true],
|
||||||
SymfonyCasts\Bundle\VerifyEmail\SymfonyCastsVerifyEmailBundle::class => ['all' => true],
|
SymfonyCasts\Bundle\VerifyEmail\SymfonyCastsVerifyEmailBundle::class => ['all' => true],
|
||||||
SymfonyCasts\Bundle\ResetPassword\SymfonyCastsResetPasswordBundle::class => ['all' => true],
|
SymfonyCasts\Bundle\ResetPassword\SymfonyCastsResetPasswordBundle::class => ['all' => true],
|
||||||
|
Liip\ImagineBundle\LiipImagineBundle::class => ['all' => true],
|
||||||
];
|
];
|
||||||
|
24
config/packages/liip_imagine.yaml
Normal file
24
config/packages/liip_imagine.yaml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Documentation on how to configure the bundle can be found at: https://symfony.com/doc/current/bundles/LiipImagineBundle/basic-usage.html
|
||||||
|
liip_imagine:
|
||||||
|
# valid drivers options include "gd" or "gmagick" or "imagick"
|
||||||
|
driver: "gd"
|
||||||
|
|
||||||
|
filter_sets:
|
||||||
|
squared_thumbnail_small:
|
||||||
|
filters:
|
||||||
|
thumbnail:
|
||||||
|
size: [100, 100]
|
||||||
|
mode: outbound
|
||||||
|
allow_upscale: true
|
||||||
|
squared_thumbnail_medium:
|
||||||
|
filters:
|
||||||
|
thumbnail:
|
||||||
|
size: [200, 200]
|
||||||
|
mode: outbound
|
||||||
|
allow_upscale: true
|
||||||
|
squared_thumbnail_large:
|
||||||
|
filters:
|
||||||
|
thumbnail:
|
||||||
|
size: [400, 400]
|
||||||
|
mode: outbound
|
||||||
|
allow_upscale: true
|
2
config/packages/lock.yaml
Normal file
2
config/packages/lock.yaml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
framework:
|
||||||
|
lock: '%env(LOCK_DSN)%'
|
@ -28,6 +28,8 @@ security:
|
|||||||
path: security_logout
|
path: security_logout
|
||||||
switch_user: true
|
switch_user: true
|
||||||
|
|
||||||
|
login_throttling: true
|
||||||
|
|
||||||
remember_me:
|
remember_me:
|
||||||
secret: '%kernel.secret%'
|
secret: '%kernel.secret%'
|
||||||
signature_properties: [password]
|
signature_properties: [password]
|
||||||
|
2
config/routes/liip_imagine.yaml
Normal file
2
config/routes/liip_imagine.yaml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
_liip_imagine:
|
||||||
|
resource: "@LiipImagineBundle/Resources/config/routing.yaml"
|
@ -11,6 +11,9 @@ services:
|
|||||||
autowire: true # Automatically injects dependencies in your services.
|
autowire: true # Automatically injects dependencies in your services.
|
||||||
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
|
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
|
||||||
|
|
||||||
|
# bind
|
||||||
|
# $var: 'content'
|
||||||
|
|
||||||
# makes classes in src/ available to be used as services
|
# makes classes in src/ available to be used as services
|
||||||
# this creates a service per class whose id is the fully-qualified class name
|
# this creates a service per class whose id is the fully-qualified class name
|
||||||
App\:
|
App\:
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
"@typescript-eslint/eslint-plugin-tslint": "^5.26.0",
|
"@typescript-eslint/eslint-plugin-tslint": "^5.26.0",
|
||||||
"axios": "^0.27.1",
|
"axios": "^0.27.1",
|
||||||
"bootstrap": "^5.2.2",
|
"bootstrap": "^5.2.2",
|
||||||
"bootswatch": "^5.2.2",
|
"dropzone": "^6.0.0-beta.2",
|
||||||
"eslint": "^8.15.0",
|
"eslint": "^8.15.0",
|
||||||
"eslint-config-airbnb-base": "^15.0.0",
|
"eslint-config-airbnb-base": "^15.0.0",
|
||||||
"eslint-plugin-import": "^2.26.0",
|
"eslint-plugin-import": "^2.26.0",
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 4.7 KiB |
Binary file not shown.
Before Width: | Height: | Size: 416 KiB |
@ -4,6 +4,8 @@ namespace App\Controller\Admin;
|
|||||||
|
|
||||||
use App\Entity\Projects;
|
use App\Entity\Projects;
|
||||||
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
|
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
|
||||||
|
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
|
||||||
|
use EasyCorp\Bundle\EasyAdminBundle\Field\Field;
|
||||||
use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
|
use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
|
||||||
use EasyCorp\Bundle\EasyAdminBundle\Field\ImageField;
|
use EasyCorp\Bundle\EasyAdminBundle\Field\ImageField;
|
||||||
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
|
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
|
||||||
@ -20,11 +22,13 @@ class ProjectsCrudController extends AbstractCrudController
|
|||||||
yield IdField::new(propertyName: 'id')
|
yield IdField::new(propertyName: 'id')
|
||||||
->onlyOnIndex();
|
->onlyOnIndex();
|
||||||
yield TextField::new(propertyName: 'name');
|
yield TextField::new(propertyName: 'name');
|
||||||
yield TextField::new(propertyName: 'description');
|
yield AssociationField::new('developer');
|
||||||
yield TextField::new(propertyName: 'description');
|
yield TextField::new(propertyName: 'description');
|
||||||
yield ImageField::new(propertyName: 'teaserImage')
|
yield ImageField::new(propertyName: 'teaserImage')
|
||||||
->setBasePath(path: 'uploads/projects')
|
->setBasePath(path: 'uploads/projects')
|
||||||
->setUploadDir(uploadDirPath: 'public/uploads/projects')
|
->setUploadDir(uploadDirPath: 'public/uploads/projects')
|
||||||
->setUploadedFileNamePattern(patternOrCallable: '[timestamp]-[slug].[extension]');
|
->setUploadedFileNamePattern(patternOrCallable: '[timestamp]-[slug].[extension]');
|
||||||
|
yield Field::new('createdAt')
|
||||||
|
->hideOnForm();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,18 +87,7 @@ class SecurityController extends AbstractController
|
|||||||
} // no else, we already confirmed in the form itself
|
} // no else, we already confirmed in the form itself
|
||||||
$entityManager->persist(entity: $user);
|
$entityManager->persist(entity: $user);
|
||||||
$entityManager->flush();
|
$entityManager->flush();
|
||||||
|
$this->generateSignedUrlAndEmailToTheUser($user);
|
||||||
// generate a signed url and email it to the user
|
|
||||||
$this->sendEmailConfirmation(verifyEmailRouteName: 'security_verify_email', user: $user,
|
|
||||||
email: (new TemplatedEmail())
|
|
||||||
->from(new Address(address: 'info@24unix.net', name: '24unix.net'))
|
|
||||||
->to($user->getEmail())
|
|
||||||
->subject(subject: 'Please Confirm your Email')
|
|
||||||
->htmlTemplate(template: '@default/security/mail/registration.html.twig')
|
|
||||||
->context(context: [
|
|
||||||
'username' => $user->getUsername()
|
|
||||||
])
|
|
||||||
);
|
|
||||||
|
|
||||||
return $this->render(view: '@default/security/registration_finished.html.twig');
|
return $this->render(view: '@default/security/registration_finished.html.twig');
|
||||||
}
|
}
|
||||||
@ -127,7 +116,7 @@ class SecurityController extends AbstractController
|
|||||||
try {
|
try {
|
||||||
$this->handleEmailConfirmation(request: $request, user: $user);
|
$this->handleEmailConfirmation(request: $request, user: $user);
|
||||||
} catch (VerifyEmailExceptionInterface $exception) {
|
} catch (VerifyEmailExceptionInterface $exception) {
|
||||||
$this->addFlash(type: 'verify_email_error', message: $translator->trans(id: $exception->getReason(), parameters: [], domain: 'VerifyEmailBundle'));
|
$this->addFlash(type: 'error', message: $translator->trans(id: $exception->getReason(), parameters: [], domain: 'VerifyEmailBundle'));
|
||||||
|
|
||||||
return $this->redirectToRoute(route: 'app_main');
|
return $this->redirectToRoute(route: 'app_main');
|
||||||
}
|
}
|
||||||
@ -316,10 +305,47 @@ class SecurityController extends AbstractController
|
|||||||
public function handleEmailConfirmation(Request $request, User /*UserInterface*/ $user): void
|
public function handleEmailConfirmation(Request $request, User /*UserInterface*/ $user): void
|
||||||
{
|
{
|
||||||
$this->verifyEmailHelper->validateEmailConfirmation(signedUrl: $request->getUri(), userId: $user->getId(), userEmail: $user->getEmail());
|
$this->verifyEmailHelper->validateEmailConfirmation(signedUrl: $request->getUri(), userId: $user->getId(), userEmail: $user->getEmail());
|
||||||
|
|
||||||
$user->setIsVerified(isVerified: true);
|
$user->setIsVerified(isVerified: true);
|
||||||
|
|
||||||
$this->entityManager->persist(entity: $user);
|
$this->entityManager->persist(entity: $user);
|
||||||
$this->entityManager->flush();
|
$this->entityManager->flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mixed $user
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function generateSignedUrlAndEmailToTheUser(mixed $user): void
|
||||||
|
{
|
||||||
|
$this->sendEmailConfirmation(verifyEmailRouteName: 'security_verify_email', user: $user,
|
||||||
|
email: (new TemplatedEmail())
|
||||||
|
->from(new Address(address: 'info@24unix.net', name: '24unix.net'))
|
||||||
|
->to($user->getEmail())
|
||||||
|
->subject(subject: 'Please Confirm your Email')
|
||||||
|
->htmlTemplate(template: '@default/security/mail/registration.html.twig')
|
||||||
|
->context(context: [
|
||||||
|
'username' => $user->getUsername()
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[Route('/security/resend/verify_email', name: 'security_resend_verify_email')]
|
||||||
|
public function resendVerifyEmail(Request $request, UserRepository $userRepository)
|
||||||
|
{
|
||||||
|
|
||||||
|
if ($request->isMethod('POST')) {
|
||||||
|
|
||||||
|
$email = $request->getSession()->get('non_verified_email');
|
||||||
|
$user = $userRepository->findOneBy(['email' => $email]);
|
||||||
|
if (!$user) {
|
||||||
|
throw $this->createNotFoundException('user not found for email');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->generateSignedUrlAndEmailToTheUser(user: $user);
|
||||||
|
$this->addFlash('success', 'eMail has been sent.');
|
||||||
|
|
||||||
|
return $this->redirectToRoute('app_main');
|
||||||
|
}
|
||||||
|
return $this->render('@default/security/resend_activation.html.twig');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,13 +6,18 @@ use App\Entity\User;
|
|||||||
use App\Form\EditProfileFormType;
|
use App\Form\EditProfileFormType;
|
||||||
use App\Repository\UserRepository;
|
use App\Repository\UserRepository;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Sunrise\Slugger\Slugger;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
|
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
|
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
|
||||||
use Symfony\Component\Routing\Annotation\Route;
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
|
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
|
||||||
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
|
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
|
||||||
|
use Symfony\Component\Validator\Constraints\File;
|
||||||
|
use Symfony\Component\Validator\Constraints\NotBlank;
|
||||||
|
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class UserController.
|
* Class UserController.
|
||||||
@ -56,10 +61,6 @@ class UserController extends BaseController
|
|||||||
return $this->redirectToRoute(route: 'app_main');
|
return $this->redirectToRoute(route: 'app_main');
|
||||||
};
|
};
|
||||||
|
|
||||||
$user = $form->getData();
|
|
||||||
// hash the plain password
|
|
||||||
|
|
||||||
|
|
||||||
return $this->renderForm(view: '@default/user/edit_profile.html.twig', parameters: [
|
return $this->renderForm(view: '@default/user/edit_profile.html.twig', parameters: [
|
||||||
'user' => $user,
|
'user' => $user,
|
||||||
'userForm' => $form
|
'userForm' => $form
|
||||||
@ -93,4 +94,48 @@ class UserController extends BaseController
|
|||||||
'users' => $users,
|
'users' => $users,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO move to a helper class
|
||||||
|
function humanFilesize($bytes, $decimals = 2)
|
||||||
|
{
|
||||||
|
$sz = 'BKMGTP';
|
||||||
|
$factor = floor((strlen($bytes) - 1) / 3);
|
||||||
|
return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . @$sz[$factor];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[Route(path: '/user/upload/avatar/{id}', name: 'user_upload_avatar')]
|
||||||
|
public function uploadAvatar(
|
||||||
|
Request $request,
|
||||||
|
UserRepository $userRepository,
|
||||||
|
EntityManagerInterface $entityManager,
|
||||||
|
ValidatorInterface $validator,
|
||||||
|
int $id)
|
||||||
|
{
|
||||||
|
$user = $userRepository->find($id);
|
||||||
|
|
||||||
|
if (!$user) {
|
||||||
|
return $this->json('User not found.', 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
$postMaxSize = UploadedFile::getMaxFilesize();
|
||||||
|
$contentLength = $request->headers->get('Content-length');
|
||||||
|
|
||||||
|
if ($contentLength > $postMaxSize) {
|
||||||
|
return $this->json('File is bigger than the allowed ' . $this->humanFilesize($postMaxSize) . ' Bytes.', 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
$uploadedAvatar = $request->files->get('file');
|
||||||
|
$destination = $this->getParameter(name: 'kernel.project_dir') . '/public/uploads/avatars';
|
||||||
|
$originalFilename = pathinfo($uploadedAvatar->getClientOriginalName(), PATHINFO_FILENAME);
|
||||||
|
$slugger = new Slugger();
|
||||||
|
$cleanFilename = $slugger->slugify($originalFilename);
|
||||||
|
$newFilename = $cleanFilename . '-' . uniqid() . '.' . $uploadedAvatar->guessExtension();
|
||||||
|
$uploadedAvatar->move($destination, $newFilename);
|
||||||
|
$user->setAvatar($newFilename);
|
||||||
|
$entityManager->persist(entity: $user);
|
||||||
|
$entityManager->flush();
|
||||||
|
|
||||||
|
return $this->json(data: 'OK', status: 201);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,15 +2,14 @@
|
|||||||
|
|
||||||
namespace App\Entity;
|
namespace App\Entity;
|
||||||
|
|
||||||
use ApiPlatform\Core\Annotation\ApiResource;
|
|
||||||
use App\Repository\ProjectsRepository;
|
use App\Repository\ProjectsRepository;
|
||||||
use Doctrine\Common\Collections\ArrayCollection;
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
use Doctrine\Common\Collections\Collection;
|
use Doctrine\Common\Collections\Collection;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
use Stringable;
|
||||||
|
|
||||||
#[ORM\Entity(repositoryClass: ProjectsRepository::class)]
|
#[ORM\Entity(repositoryClass: ProjectsRepository::class)]
|
||||||
#[ApiResource]
|
class Projects implements Stringable
|
||||||
class Projects implements \Stringable
|
|
||||||
{
|
{
|
||||||
#[ORM\Id]
|
#[ORM\Id]
|
||||||
#[ORM\GeneratedValue]
|
#[ORM\GeneratedValue]
|
||||||
@ -33,7 +32,7 @@ class Projects implements \Stringable
|
|||||||
private ?string $teaserImage = null;
|
private ?string $teaserImage = null;
|
||||||
|
|
||||||
#[ORM\ManyToMany(targetEntity: User::class, inversedBy: 'projects')]
|
#[ORM\ManyToMany(targetEntity: User::class, inversedBy: 'projects')]
|
||||||
private $developer;
|
private Collection $developer;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
|
61
src/EventSubscriber/CheckVerifiedUserSubscriber.php
Normal file
61
src/EventSubscriber/CheckVerifiedUserSubscriber.php
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\EventSubscriber;
|
||||||
|
|
||||||
|
use App\Exception\UserNotVerifiedException;
|
||||||
|
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||||
|
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||||
|
use Symfony\Component\HttpFoundation\RequestStack;
|
||||||
|
use Symfony\Component\Routing\RouterInterface;
|
||||||
|
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
|
||||||
|
use Symfony\Component\Security\Http\Event\CheckPassportEvent;
|
||||||
|
use Symfony\Component\Security\Http\Event\LoginFailureEvent;
|
||||||
|
|
||||||
|
class CheckVerifiedUserSubscriber implements EventSubscriberInterface
|
||||||
|
{
|
||||||
|
|
||||||
|
public function __construct(private readonly RouterInterface $router)
|
||||||
|
{
|
||||||
|
// empty body
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function onCheckPassport(CheckPassportEvent $event)
|
||||||
|
{
|
||||||
|
$passport = $event->getPassport();
|
||||||
|
/*
|
||||||
|
* var User $user
|
||||||
|
*/
|
||||||
|
$user = $passport->getUser();
|
||||||
|
|
||||||
|
if (!$user->isVerified()) {
|
||||||
|
throw new UserNotVerifiedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function onValidationFailure(LoginFailureEvent $failureEvent)
|
||||||
|
{
|
||||||
|
if (!$failureEvent->getException() instanceof UserNotVerifiedException) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$request = $failureEvent->getRequest();
|
||||||
|
$email = $failureEvent->getPassport()->getUser()->getEmail();
|
||||||
|
$request->getSession()->set('non_verified_email', $email);
|
||||||
|
|
||||||
|
$response = new RedirectResponse(
|
||||||
|
$this->router->generate('security_resend_verify_email')
|
||||||
|
);
|
||||||
|
$failureEvent->setResponse($response);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static function getSubscribedEvents(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
CheckPassportEvent::class => ['onCheckPassport', -10],
|
||||||
|
LoginFailureEvent::class => 'onValidationFailure'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -2,62 +2,10 @@
|
|||||||
|
|
||||||
namespace App\Exception;
|
namespace App\Exception;
|
||||||
|
|
||||||
use JetBrains\PhpStorm\ArrayShape;
|
|
||||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||||
use function is_array;
|
|
||||||
|
|
||||||
class UserNotVerifiedException extends AuthenticationException
|
class UserNotVerifiedException extends AuthenticationException
|
||||||
{
|
{
|
||||||
private ?string $identifier = null;
|
// empty body
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function getMessageKey(): string
|
|
||||||
{
|
|
||||||
return 'User is not verified.';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the user identifier (e.g. username or email address).
|
|
||||||
*/
|
|
||||||
public function getUserIdentifier(): ?string
|
|
||||||
{
|
|
||||||
return $this->identifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the user identifier (e.g. username or email address).
|
|
||||||
*/
|
|
||||||
public function setUserIdentifier(string $identifier): void
|
|
||||||
{
|
|
||||||
$this->identifier = $identifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
#[ArrayShape(shape: ['{{ username }}' => "null|string", '{{ user_identifier }}' => "null|string"])]
|
|
||||||
public function getMessageData(): array
|
|
||||||
{
|
|
||||||
return ['{{ username }}' => $this->identifier, '{{ user_identifier }}' => $this->identifier];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function __serialize(): array
|
|
||||||
{
|
|
||||||
return [$this->identifier, parent::__serialize()];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function __unserialize(array $data): void
|
|
||||||
{
|
|
||||||
[$this->identifier, $parentData] = $data;
|
|
||||||
$parentData = is_array(value: $parentData) ? $parentData : unserialize(data: $parentData);
|
|
||||||
parent::__unserialize(data: $parentData);
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -5,10 +5,12 @@ namespace App\Form;
|
|||||||
use App\Entity\User;
|
use App\Entity\User;
|
||||||
use Symfony\Component\Form\AbstractType;
|
use Symfony\Component\Form\AbstractType;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\EmailType;
|
use Symfony\Component\Form\Extension\Core\Type\EmailType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\FileType;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
|
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
|
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
use Symfony\Component\Validator\Constraints\Image;
|
||||||
use Symfony\Component\Validator\Constraints\Length;
|
use Symfony\Component\Validator\Constraints\Length;
|
||||||
|
|
||||||
class EditProfileFormType extends AbstractType
|
class EditProfileFormType extends AbstractType
|
||||||
@ -27,7 +29,7 @@ class EditProfileFormType extends AbstractType
|
|||||||
'options' => ['attr' => ['class' => 'password-field', 'autocomplete' => 'off']],
|
'options' => ['attr' => ['class' => 'password-field', 'autocomplete' => 'off']],
|
||||||
'required' => false,
|
'required' => false,
|
||||||
'first_options' => ['label' => 'Password'],
|
'first_options' => ['label' => 'Password'],
|
||||||
'second_options' => ['label' => 'Repeat Password (only needed if you want to update the password'],
|
'second_options' => ['label' => 'Repeat Password (only needed if you want to update the password)'],
|
||||||
'constraints' => [new Length(exactly: ['min' => 6])]
|
'constraints' => [new Length(exactly: ['min' => 6])]
|
||||||
])
|
])
|
||||||
;
|
;
|
||||||
|
@ -9,6 +9,7 @@ use Symfony\Component\HttpFoundation\Request;
|
|||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\Routing\RouterInterface;
|
use Symfony\Component\Routing\RouterInterface;
|
||||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||||
|
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
|
||||||
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
|
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
|
||||||
use Symfony\Component\Security\Core\Security;
|
use Symfony\Component\Security\Core\Security;
|
||||||
use Symfony\Component\Security\Http\Authenticator\AbstractLoginFormAuthenticator;
|
use Symfony\Component\Security\Http\Authenticator\AbstractLoginFormAuthenticator;
|
||||||
@ -51,10 +52,6 @@ class LoginFormAuthenticator extends AbstractLoginFormAuthenticator
|
|||||||
throw new UserNotFoundException();
|
throw new UserNotFoundException();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$user->isVerified()) {
|
|
||||||
throw new UserNotVerifiedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $user;
|
return $user;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
27
src/Twig/AppExtension.php
Normal file
27
src/Twig/AppExtension.php
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Twig;
|
||||||
|
|
||||||
|
use Psr\Container\ContainerInterface;
|
||||||
|
use Twig\Extension\AbstractExtension;
|
||||||
|
use Twig\TwigFunction;
|
||||||
|
|
||||||
|
class AppExtension extends AbstractExtension
|
||||||
|
{
|
||||||
|
// public function __construct(private ContainerInterface $container)
|
||||||
|
// {
|
||||||
|
// }
|
||||||
|
|
||||||
|
public function getFunctions(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
new TwigFunction('avatar_asset', [$this, 'getAvatarPath'])
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAvatarPath(string $path): string
|
||||||
|
{
|
||||||
|
return '/uploads/avatars/' . $path;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
25
symfony.lock
25
symfony.lock
@ -47,6 +47,19 @@
|
|||||||
"knplabs/knp-time-bundle": {
|
"knplabs/knp-time-bundle": {
|
||||||
"version": "v1.20.0"
|
"version": "v1.20.0"
|
||||||
},
|
},
|
||||||
|
"liip/imagine-bundle": {
|
||||||
|
"version": "2.9",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes-contrib",
|
||||||
|
"branch": "main",
|
||||||
|
"version": "1.8",
|
||||||
|
"ref": "d1227d002b70d1a1f941d91845fcd7ac7fbfc929"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"config/packages/liip_imagine.yaml",
|
||||||
|
"config/routes/liip_imagine.yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
"nelmio/cors-bundle": {
|
"nelmio/cors-bundle": {
|
||||||
"version": "2.2",
|
"version": "2.2",
|
||||||
"recipe": {
|
"recipe": {
|
||||||
@ -138,6 +151,18 @@
|
|||||||
"src/Kernel.php"
|
"src/Kernel.php"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"symfony/lock": {
|
||||||
|
"version": "6.1",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "main",
|
||||||
|
"version": "5.2",
|
||||||
|
"ref": "8e937ff2b4735d110af1770f242c1107fdab4c8e"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"config/packages/lock.yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
"symfony/mailer": {
|
"symfony/mailer": {
|
||||||
"version": "6.1",
|
"version": "6.1",
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
@ -21,8 +21,15 @@
|
|||||||
{% if is_granted('ROLE_USER') %}
|
{% if is_granted('ROLE_USER') %}
|
||||||
<li class="nav-item dropdown me-auto">
|
<li class="nav-item dropdown me-auto">
|
||||||
<button type="button" id="navbar-dropdown" data-bs-target="#dropdown-menu" data-bs-toggle="dropdown"
|
<button type="button" id="navbar-dropdown" data-bs-target="#dropdown-menu" data-bs-toggle="dropdown"
|
||||||
class="btn btn-primary dropdown-toggle button-login">
|
class="btn btn-outline-dark dropdown-toggle button-login">
|
||||||
|
{% if app.user.avatar %}
|
||||||
|
<img class="rounded-circle"
|
||||||
|
width="50px"
|
||||||
|
src="{{ avatar_asset(app.user.avatar)|imagine_filter('squared_thumbnail_small') }}"
|
||||||
|
alt="profile image"/>
|
||||||
|
{% else %}
|
||||||
{{ app.user.username }}
|
{{ app.user.username }}
|
||||||
|
{% endif %}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div class="dropdown-menu dropdown-menu-dark dropdown-menu-end" id="dropdown-menu"
|
<div class="dropdown-menu dropdown-menu-dark dropdown-menu-end" id="dropdown-menu"
|
||||||
|
@ -70,6 +70,10 @@
|
|||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div class="container-fluid" id="content">
|
<div class="container-fluid" id="content">
|
||||||
|
|
||||||
|
|
||||||
|
<div class="col m-3" id="main_content">
|
||||||
|
|
||||||
{% for message in app.flashes('success') %}
|
{% for message in app.flashes('success') %}
|
||||||
<div class="alert alert-success">
|
<div class="alert alert-success">
|
||||||
{{ message }}
|
{{ message }}
|
||||||
@ -82,8 +86,6 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
<div class="col m-3" id="main_content">
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<div class="m-5">
|
<div class="m-5">
|
||||||
<h1 class="title-show">Quote of the Moment</h1>
|
<h1 class="title-show">Quote of the Moment</h1>
|
||||||
|
@ -32,10 +32,14 @@
|
|||||||
{% for developer in project.developer %}
|
{% for developer in project.developer %}
|
||||||
<a class="align-left blog-details"
|
<a class="align-left blog-details"
|
||||||
href="{{ path('app_profile', { 'username':developer.username }) }}">
|
href="{{ path('app_profile', { 'username':developer.username }) }}">
|
||||||
<img class="article-author-img rounded-circle"
|
{% if developer.avatar is not null %}
|
||||||
src="{{ asset('build/images/tracer_schmolle.png') }}"
|
<img class="rounded-circle mt-5 mb-4 ms-5"
|
||||||
alt="profile"></a>
|
src="{{ avatar_asset(developer.avatar)|imagine_filter('squared_thumbnail_small') }}" alt="profile image"/>
|
||||||
|
<br>
|
||||||
|
{% endif %}
|
||||||
|
<div class="ms-5 mb-4">
|
||||||
<a href="{{ path('app_profile', { 'username':developer.username }) }}">{{ developer.username }}</a>
|
<a href="{{ path('app_profile', { 'username':developer.username }) }}">{{ developer.username }}</a>
|
||||||
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
{% extends '@default/base.html.twig' %}
|
||||||
|
|
||||||
|
{% block title %}Verify eMail{% endblock %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="login-form bg-dark mt-4 p-4">
|
||||||
|
<h1 class="h3 mb-3 font-weight-normal">Verify your Email</h1>
|
||||||
|
<p>
|
||||||
|
A verification email was sent - please check it to enable your
|
||||||
|
account before logging in.
|
||||||
|
</p>
|
||||||
|
<form method="POST">
|
||||||
|
<button type="submit" class="btn btn-primary">Re-send Email</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
@ -7,24 +7,34 @@
|
|||||||
{% block body %}
|
{% block body %}
|
||||||
|
|
||||||
<div class="container box rounded bg-dark mt-5 mb-5">
|
<div class="container box rounded bg-dark mt-5 mb-5">
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-3 border-right">
|
<div class="col-md-3 border-right">
|
||||||
<div class="d-flex flex-column align-items-center text-center p-3 py-5">
|
<div class="d-flex flex-column align-items-center text-center p-3 py-5">
|
||||||
<img class="rounded-circle mt-5"
|
{% if user.avatar is not null %}
|
||||||
width="150px"
|
<img class="rounded-circle mt-5 mb-4"
|
||||||
src=" {{ asset('build/images/tracer_schmolle150x150.png') }}" alt="profile image">
|
src="{{ avatar_asset(user.avatar)|imagine_filter('squared_thumbnail_small') }}"
|
||||||
|
alt="profile image"/>
|
||||||
|
{% endif %}
|
||||||
|
{# {{ form_row(userForm.avatarName, { 'label': false }) }} #}
|
||||||
|
<form
|
||||||
|
action="{{ path('user_upload_avatar', { id: user.id}) }}"
|
||||||
|
method="POST"
|
||||||
|
enctype="multipart/form-data"
|
||||||
|
class="dropzone" id="dropzoneForm">
|
||||||
|
</form>
|
||||||
|
<div id="preview-content">{{ avatar_asset(user.avatar)|imagine_filter('squared_thumbnail_small') }}</div>
|
||||||
<span class="font-weight-bold">{{ user.username }}</span>
|
<span class="font-weight-bold">{{ user.username }}</span>
|
||||||
<span class="text-white-50"><span class="fa fa-lg fa-envelope me-1"></span>{{ user.email }}</span>
|
<span class="text-white-50"><span class="fa fa-lg fa-envelope me-1"></span>{{ user.email }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-5 border-right">
|
<div class="col-md-8 border-right">
|
||||||
{{ form_start(userForm) }}
|
|
||||||
<div class="p-3 py-5">
|
<div class="p-3 py-5">
|
||||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||||
<h4 class="text-right">User Profile</h4>
|
<h4 class="text-right">User Profile</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mt-2">
|
<div class="row mt-2">
|
||||||
|
{{ form_start(userForm) }}
|
||||||
{{ form_row(userForm.username) }}
|
{{ form_row(userForm.username) }}
|
||||||
{{ form_row(userForm.firstName) }}
|
{{ form_row(userForm.firstName) }}
|
||||||
{{ form_row(userForm.lastName) }}
|
{{ form_row(userForm.lastName) }}
|
||||||
@ -32,6 +42,7 @@
|
|||||||
{{ form_row(userForm.newPassword.first) }}
|
{{ form_row(userForm.newPassword.first) }}
|
||||||
{{ form_row(userForm.newPassword.second) }}
|
{{ form_row(userForm.newPassword.second) }}
|
||||||
{{ form_rest(userForm) }}
|
{{ form_rest(userForm) }}
|
||||||
|
{{ form_end(userForm) }}
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-5 text-center float-end">
|
<div class="mb-5 text-center float-end">
|
||||||
<button class="btn btn-primary profile-button" type="submit">Save Profile</button>
|
<button class="btn btn-primary profile-button" type="submit">Save Profile</button>
|
||||||
@ -41,5 +52,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -10,9 +10,10 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-3 border-right">
|
<div class="col-md-3 border-right">
|
||||||
<div class="d-flex flex-column align-items-center text-center p-3 py-5">
|
<div class="d-flex flex-column align-items-center text-center p-3 py-5">
|
||||||
<img class="rounded-circle mt-5"
|
{% if user.avatar is not null %}
|
||||||
width="150px"
|
<img class="rounded-circle mt-5 mb-4"
|
||||||
src=" {{ asset('/uploads/avatars/' ~ user.avatar) }}" alt="profile image">
|
src="{{ avatar_asset(user.avatar)|imagine_filter('squared_thumbnail_small') }}" alt="profile image"/>
|
||||||
|
{% endif %}
|
||||||
<span class="font-weight-bold">{{ user.username }}</span>
|
<span class="font-weight-bold">{{ user.username }}</span>
|
||||||
{% if is_granted('ROLE_ADMIN') %}
|
{% if is_granted('ROLE_ADMIN') %}
|
||||||
<span class="font-weight-bold">
|
<span class="font-weight-bold">
|
||||||
|
@ -17,7 +17,7 @@ Encore
|
|||||||
.splitEntryChunks()
|
.splitEntryChunks()
|
||||||
// will require an extra script tag for runtime.js
|
// will require an extra script tag for runtime.js
|
||||||
// but, you probably want this, unless you're building a single-page app
|
// but, you probably want this, unless you're building a single-page app
|
||||||
.enableSingleRuntimeChunk()
|
.disableSingleRuntimeChunk()
|
||||||
.cleanupOutputBeforeBuild()
|
.cleanupOutputBeforeBuild()
|
||||||
.enableBuildNotifications()
|
.enableBuildNotifications()
|
||||||
.enableSourceMaps(!Encore.isProduction())
|
.enableSourceMaps(!Encore.isProduction())
|
||||||
|
23
yarn.lock
23
yarn.lock
@ -1043,6 +1043,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.6.tgz#cee20bd55e68a1720bdab363ecf0c821ded4cd45"
|
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.6.tgz#cee20bd55e68a1720bdab363ecf0c821ded4cd45"
|
||||||
integrity sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==
|
integrity sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==
|
||||||
|
|
||||||
|
"@swc/helpers@^0.2.13":
|
||||||
|
version "0.2.14"
|
||||||
|
resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.2.14.tgz#20288c3627442339dd3d743c944f7043ee3590f0"
|
||||||
|
integrity sha512-wpCQMhf5p5GhNg2MmGKXzUNwxe7zRiCsmqYsamez2beP7mKPCSiu+BjZcdN95yYSzO857kr0VfQewmGpS77nqA==
|
||||||
|
|
||||||
"@symfony/stimulus-bridge@^3.0.0":
|
"@symfony/stimulus-bridge@^3.0.0":
|
||||||
version "3.2.1"
|
version "3.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/@symfony/stimulus-bridge/-/stimulus-bridge-3.2.1.tgz#b9c261ad72830fd17898cf27c97862d1cc15b46a"
|
resolved "https://registry.yarnpkg.com/@symfony/stimulus-bridge/-/stimulus-bridge-3.2.1.tgz#b9c261ad72830fd17898cf27c97862d1cc15b46a"
|
||||||
@ -1748,11 +1753,6 @@ bootstrap@^5.2.2:
|
|||||||
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.2.2.tgz#834e053eed584a65e244d8aa112a6959f56e27a0"
|
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.2.2.tgz#834e053eed584a65e244d8aa112a6959f56e27a0"
|
||||||
integrity sha512-dEtzMTV71n6Fhmbg4fYJzQsw1N29hJKO1js5ackCgIpDcGid2ETMGC6zwSYw09v05Y+oRdQ9loC54zB1La3hHQ==
|
integrity sha512-dEtzMTV71n6Fhmbg4fYJzQsw1N29hJKO1js5ackCgIpDcGid2ETMGC6zwSYw09v05Y+oRdQ9loC54zB1La3hHQ==
|
||||||
|
|
||||||
bootswatch@^5.2.2:
|
|
||||||
version "5.2.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/bootswatch/-/bootswatch-5.2.2.tgz#4d3d15dffd8de16112b64fa37c1164cca1543110"
|
|
||||||
integrity sha512-ByybawTUbMzzsdIb+5lYjme088UBYtNBhJCBt4W77PKG57fzjd2Y11rdGDgHgFGXVTMD2Oaci3/qJon4L0ceTQ==
|
|
||||||
|
|
||||||
brace-expansion@^1.1.7:
|
brace-expansion@^1.1.7:
|
||||||
version "1.1.11"
|
version "1.1.11"
|
||||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
|
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
|
||||||
@ -2333,6 +2333,14 @@ domutils@^2.5.2, domutils@^2.8.0:
|
|||||||
domelementtype "^2.2.0"
|
domelementtype "^2.2.0"
|
||||||
domhandler "^4.2.0"
|
domhandler "^4.2.0"
|
||||||
|
|
||||||
|
dropzone@^6.0.0-beta.2:
|
||||||
|
version "6.0.0-beta.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/dropzone/-/dropzone-6.0.0-beta.2.tgz#098be8fa84bdc08674cf0b74f4c889e2679083d6"
|
||||||
|
integrity sha512-k44yLuFFhRk53M8zP71FaaNzJYIzr99SKmpbO/oZKNslDjNXQsBTdfLs+iONd0U0L94zzlFzRnFdqbLcs7h9fQ==
|
||||||
|
dependencies:
|
||||||
|
"@swc/helpers" "^0.2.13"
|
||||||
|
just-extend "^5.0.0"
|
||||||
|
|
||||||
ee-first@1.1.1:
|
ee-first@1.1.1:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
|
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
|
||||||
@ -3528,6 +3536,11 @@ json5@^2.1.2, json5@^2.2.1:
|
|||||||
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c"
|
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c"
|
||||||
integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==
|
integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==
|
||||||
|
|
||||||
|
just-extend@^5.0.0:
|
||||||
|
version "5.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-5.1.1.tgz#4f33b1fc719964f816df55acc905776694b713ab"
|
||||||
|
integrity sha512-b+z6yF1d4EOyDgylzQo5IminlUmzSeqR1hs/bzjBNjuGras4FXq/6TrzjxfN0j+TmI0ltJzTNlqXUMCniciwKQ==
|
||||||
|
|
||||||
kind-of@^6.0.2:
|
kind-of@^6.0.2:
|
||||||
version "6.0.3"
|
version "6.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
|
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
|
||||||
|
Loading…
Reference in New Issue
Block a user