finished user prfile and passwords
This commit is contained in:
		
							
								
								
									
										28
									
								
								.eslintrc
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								.eslintrc
									
									
									
									
									
								
							@@ -2,9 +2,7 @@
 | 
				
			|||||||
	"extends": [
 | 
						"extends": [
 | 
				
			||||||
		// add more generic rulesets here, such as:
 | 
							// add more generic rulesets here, such as:
 | 
				
			||||||
		"eslint:recommended",
 | 
							"eslint:recommended",
 | 
				
			||||||
		"airbnb-base",
 | 
							"airbnb-base"
 | 
				
			||||||
		"plugin:vue/recommended",
 | 
					 | 
				
			||||||
		"plugin:vue/vue3-recommended"
 | 
					 | 
				
			||||||
	],
 | 
						],
 | 
				
			||||||
	"parserOptions": {
 | 
						"parserOptions": {
 | 
				
			||||||
		"parser": "espree",
 | 
							"parser": "espree",
 | 
				
			||||||
@@ -13,35 +11,13 @@
 | 
				
			|||||||
	},
 | 
						},
 | 
				
			||||||
	"env": {
 | 
						"env": {
 | 
				
			||||||
		"es6": true,
 | 
							"es6": true,
 | 
				
			||||||
		"browser": true,
 | 
							"browser": true
 | 
				
			||||||
		"vue/setup-compiler-macros": true
 | 
					 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	"rules": {
 | 
						"rules": {
 | 
				
			||||||
		"semi": [
 | 
							"semi": [
 | 
				
			||||||
			"error",
 | 
								"error",
 | 
				
			||||||
			"never"
 | 
								"never"
 | 
				
			||||||
		],
 | 
							],
 | 
				
			||||||
		"vue/no-v-html": "off",
 | 
					 | 
				
			||||||
		"vue/html-indent": [
 | 
					 | 
				
			||||||
			"error",
 | 
					 | 
				
			||||||
			"tab"
 | 
					 | 
				
			||||||
		],
 | 
					 | 
				
			||||||
		"vue/html-closing-bracket-spacing": [
 | 
					 | 
				
			||||||
			"error",
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				"startTag": "never",
 | 
					 | 
				
			||||||
				"endTag": "never",
 | 
					 | 
				
			||||||
				"selfClosingTag": "never"
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		],
 | 
					 | 
				
			||||||
		"vue/component-api-style": [
 | 
					 | 
				
			||||||
			"error",
 | 
					 | 
				
			||||||
			[
 | 
					 | 
				
			||||||
				"script-setup",
 | 
					 | 
				
			||||||
				"composition"
 | 
					 | 
				
			||||||
			]
 | 
					 | 
				
			||||||
			// "script-setup", "composition", "composition-vue2", or "options"
 | 
					 | 
				
			||||||
		],
 | 
					 | 
				
			||||||
		"indent": [
 | 
							"indent": [
 | 
				
			||||||
			"error",
 | 
								"error",
 | 
				
			||||||
			"tab"
 | 
								"tab"
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -21,3 +21,4 @@ yarn-error.log
 | 
				
			|||||||
/public/media/cache/
 | 
					/public/media/cache/
 | 
				
			||||||
###< liip/imagine-bundle ###
 | 
					###< liip/imagine-bundle ###
 | 
				
			||||||
/tools/php-cs-fixer/vendor/
 | 
					/tools/php-cs-fixer/vendor/
 | 
				
			||||||
 | 
					/public/uploads/
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										4
									
								
								TODO
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								TODO
									
									
									
									
									
								
							@@ -1,7 +1,7 @@
 | 
				
			|||||||
accent color #d43934
 | 
					accent color #d43934
 | 
				
			||||||
 | 
					
 | 
				
			||||||
remove vue
 | 
					merge RequestController/SecurityController
 | 
				
			||||||
use bootsrap
 | 
					don't use html in easyadmin / quotes
 | 
				
			||||||
use turbo
 | 
					use turbo
 | 
				
			||||||
make unit tests
 | 
					make unit tests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,9 +9,9 @@ import 'bootswatch/dist/slate/bootstrap.min.css'
 | 
				
			|||||||
$(document).ready(function () {
 | 
					$(document).ready(function () {
 | 
				
			||||||
    console.log('ready')
 | 
					    console.log('ready')
 | 
				
			||||||
    $('#toggleSidebar').on('click', function () {
 | 
					    $('#toggleSidebar').on('click', function () {
 | 
				
			||||||
        $('#toggleIcon').toggleClass('fa fa-lg fa-fw fa-caret-square-o-left')
 | 
					        let toggleIcon = $('#toggleIcon')
 | 
				
			||||||
        $('#toggleIcon').toggleClass('fa fa-lg fa-fw fa-caret-square-o-right')
 | 
					        toggleIcon.toggleClass('fa fa-lg fa-fw fa-caret-square-o-left')
 | 
				
			||||||
 | 
					        toggleIcon.toggleClass('fa fa-lg fa-fw fa-caret-square-o-right')
 | 
				
			||||||
        $('#sidebar').toggleClass('active')
 | 
					        $('#sidebar').toggleClass('active')
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,7 +15,7 @@
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
html, body{
 | 
					html, body {
 | 
				
			||||||
  margin: 0;
 | 
					  margin: 0;
 | 
				
			||||||
  padding: 0;
 | 
					  padding: 0;
 | 
				
			||||||
  //background: linear-gradient(90deg, rgba(14,14,16,1) 0%, rgba(255,128,64,1) 35%, rgba(14,14,16,1) 100%);
 | 
					  //background: linear-gradient(90deg, rgba(14,14,16,1) 0%, rgba(255,128,64,1) 35%, rgba(14,14,16,1) 100%);
 | 
				
			||||||
@@ -35,6 +35,7 @@ $jet-black: #0e0e10;
 | 
				
			|||||||
#sidebar {
 | 
					#sidebar {
 | 
				
			||||||
  min-width: 180px;
 | 
					  min-width: 180px;
 | 
				
			||||||
  max-width: 180px;
 | 
					  max-width: 180px;
 | 
				
			||||||
 | 
					  height: 100%;
 | 
				
			||||||
  display: inline;
 | 
					  display: inline;
 | 
				
			||||||
  white-space: nowrap;
 | 
					  white-space: nowrap;
 | 
				
			||||||
  overflow: hidden;
 | 
					  overflow: hidden;
 | 
				
			||||||
@@ -54,3 +55,44 @@ $jet-black: #0e0e10;
 | 
				
			|||||||
  display: none;
 | 
					  display: none;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#main_content {
 | 
				
			||||||
 | 
					  overflow-y: auto;
 | 
				
			||||||
 | 
					  height: calc(100vh - 160px)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.form-signin {
 | 
				
			||||||
 | 
					  width: 100%;
 | 
				
			||||||
 | 
					  max-width: 330px;
 | 
				
			||||||
 | 
					  padding: 15px;
 | 
				
			||||||
 | 
					  margin: 50px auto auto;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.form-signin .checkbox {
 | 
				
			||||||
 | 
					  font-weight: 400;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.form-signin .form-control {
 | 
				
			||||||
 | 
					  position: relative;
 | 
				
			||||||
 | 
					  box-sizing: border-box;
 | 
				
			||||||
 | 
					  height: auto;
 | 
				
			||||||
 | 
					  padding: 10px;
 | 
				
			||||||
 | 
					  font-size: 16px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.form-signin .form-control:focus {
 | 
				
			||||||
 | 
					  z-index: 2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.form-signin input {
 | 
				
			||||||
 | 
					  border-radius: 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.form-signin input[id="registration_form_username"] {
 | 
				
			||||||
 | 
					  margin-bottom: -1px;
 | 
				
			||||||
 | 
					  border-radius: 0.375rem 0.375rem 0 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.form-signin input[id="registration_form_password_second"] {
 | 
				
			||||||
 | 
					  margin-bottom: 10px;
 | 
				
			||||||
 | 
					  border-radius: 0 0 0.375rem 0.375rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,6 @@
 | 
				
			|||||||
        "php": ">=8.1.0",
 | 
					        "php": ">=8.1.0",
 | 
				
			||||||
        "ext-ctype": "*",
 | 
					        "ext-ctype": "*",
 | 
				
			||||||
        "ext-iconv": "*",
 | 
					        "ext-iconv": "*",
 | 
				
			||||||
        "api-platform/core": "^2.6",
 | 
					 | 
				
			||||||
        "doctrine/annotations": "^1.0",
 | 
					        "doctrine/annotations": "^1.0",
 | 
				
			||||||
        "doctrine/doctrine-bundle": "^2.7",
 | 
					        "doctrine/doctrine-bundle": "^2.7",
 | 
				
			||||||
        "doctrine/doctrine-migrations-bundle": "^3.2",
 | 
					        "doctrine/doctrine-migrations-bundle": "^3.2",
 | 
				
			||||||
@@ -42,6 +41,7 @@
 | 
				
			|||||||
        "symfony/proxy-manager-bridge": "6.1.*",
 | 
					        "symfony/proxy-manager-bridge": "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/serializer": "6.1.*",
 | 
					        "symfony/serializer": "6.1.*",
 | 
				
			||||||
        "symfony/string": "6.1.*",
 | 
					        "symfony/string": "6.1.*",
 | 
				
			||||||
        "symfony/translation": "6.1.*",
 | 
					        "symfony/translation": "6.1.*",
 | 
				
			||||||
@@ -51,8 +51,11 @@
 | 
				
			|||||||
        "symfony/webapp-meta": "^1.0",
 | 
					        "symfony/webapp-meta": "^1.0",
 | 
				
			||||||
        "symfony/webpack-encore-bundle": "^1.14",
 | 
					        "symfony/webpack-encore-bundle": "^1.14",
 | 
				
			||||||
        "symfony/yaml": "6.1.*",
 | 
					        "symfony/yaml": "6.1.*",
 | 
				
			||||||
 | 
					        "symfonycasts/reset-password-bundle": "^1.16",
 | 
				
			||||||
 | 
					        "symfonycasts/verify-email-bundle": "^1.12",
 | 
				
			||||||
 | 
					        "twig/extra-bundle": "^3.4",
 | 
				
			||||||
        "twig/markdown-extra": "^3.4",
 | 
					        "twig/markdown-extra": "^3.4",
 | 
				
			||||||
        "twig/twig": "3.3.10"
 | 
					        "twig/twig": "3.4.*"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "config": {
 | 
					    "config": {
 | 
				
			||||||
        "allow-plugins": {
 | 
					        "allow-plugins": {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										662
									
								
								composer.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										662
									
								
								composer.lock
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -15,7 +15,7 @@ return [
 | 
				
			|||||||
    Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true],
 | 
					    Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true],
 | 
				
			||||||
    EasyCorp\Bundle\EasyAdminBundle\EasyAdminBundle::class => ['all' => true],
 | 
					    EasyCorp\Bundle\EasyAdminBundle\EasyAdminBundle::class => ['all' => true],
 | 
				
			||||||
    Knp\Bundle\TimeBundle\KnpTimeBundle::class => ['all' => true],
 | 
					    Knp\Bundle\TimeBundle\KnpTimeBundle::class => ['all' => true],
 | 
				
			||||||
    FOS\CKEditorBundle\FOSCKEditorBundle::class => ['all' => true],
 | 
					 | 
				
			||||||
    Nelmio\CorsBundle\NelmioCorsBundle::class => ['all' => true],
 | 
					    Nelmio\CorsBundle\NelmioCorsBundle::class => ['all' => true],
 | 
				
			||||||
    ApiPlatform\Core\Bridge\Symfony\Bundle\ApiPlatformBundle::class => ['all' => true],
 | 
					    SymfonyCasts\Bundle\VerifyEmail\SymfonyCastsVerifyEmailBundle::class => ['all' => true],
 | 
				
			||||||
 | 
					    SymfonyCasts\Bundle\ResetPassword\SymfonyCastsResetPasswordBundle::class => ['all' => true],
 | 
				
			||||||
];
 | 
					];
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +0,0 @@
 | 
				
			|||||||
api_platform:
 | 
					 | 
				
			||||||
    mapping:
 | 
					 | 
				
			||||||
        paths: ['%kernel.project_dir%/src/Entity']
 | 
					 | 
				
			||||||
    patch_formats:
 | 
					 | 
				
			||||||
        json: ['application/merge-patch+json']
 | 
					 | 
				
			||||||
    swagger:
 | 
					 | 
				
			||||||
        versions: [3]
 | 
					 | 
				
			||||||
    show_webby: false
 | 
					 | 
				
			||||||
@@ -1,5 +0,0 @@
 | 
				
			|||||||
# Read the documentation: https://symfony.com/doc/current/bundles/FOSCKEditorBundle/index.html
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
twig:
 | 
					 | 
				
			||||||
    form_themes:
 | 
					 | 
				
			||||||
        - '@FOSCKEditor/Form/ckeditor_widget.html.twig'
 | 
					 | 
				
			||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
# see https://symfony.com/doc/current/reference/configuration/framework.html
 | 
					# see https://symfony.com/doc/current/reference/configuration/framework.html
 | 
				
			||||||
framework:
 | 
					framework:
 | 
				
			||||||
    secret: '%env(APP_SECRET)%'
 | 
					    secret: '%env(APP_SECRET)%'
 | 
				
			||||||
    #csrf_protection: true
 | 
					    csrf_protection: true
 | 
				
			||||||
    http_method_override: false
 | 
					    http_method_override: false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Enables session support. Note that the session will ONLY be started if you read or write from it.
 | 
					    # Enables session support. Note that the session will ONLY be started if you read or write from it.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,7 +16,7 @@ framework:
 | 
				
			|||||||
            # sync: 'sync://'
 | 
					            # sync: 'sync://'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        routing:
 | 
					        routing:
 | 
				
			||||||
            Symfony\Component\Mailer\Messenger\SendEmailMessage: async
 | 
					            #Symfony\Component\Mailer\Messenger\SendEmailMessage: async
 | 
				
			||||||
            Symfony\Component\Notifier\Message\ChatMessage: async
 | 
					            Symfony\Component\Notifier\Message\ChatMessage: async
 | 
				
			||||||
            Symfony\Component\Notifier\Message\SmsMessage: async
 | 
					            Symfony\Component\Notifier\Message\SmsMessage: async
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										4
									
								
								config/packages/reset_password.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								config/packages/reset_password.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					symfonycasts_reset_password:
 | 
				
			||||||
 | 
					    request_password_repository: App\Repository\ResetPasswordRequestRepository
 | 
				
			||||||
 | 
					    lifetime: 3600
 | 
				
			||||||
 | 
					    throttle_limit: 1
 | 
				
			||||||
@@ -22,13 +22,11 @@ security:
 | 
				
			|||||||
        main:
 | 
					        main:
 | 
				
			||||||
            lazy: true
 | 
					            lazy: true
 | 
				
			||||||
            provider: app_user_provider
 | 
					            provider: app_user_provider
 | 
				
			||||||
            # custom_authenticator: App\Security\LoginFormAuthenticator
 | 
					            custom_authenticator: App\Security\LoginFormAuthenticator
 | 
				
			||||||
 | 
					 | 
				
			||||||
            json_login:
 | 
					 | 
				
			||||||
                check_path: app_login
 | 
					 | 
				
			||||||
                username_path: username
 | 
					 | 
				
			||||||
                password_path: password
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ##form_login:
 | 
				
			||||||
 | 
					            #    login_path: app_login
 | 
				
			||||||
 | 
					            #    check_path: app_login
 | 
				
			||||||
            logout:
 | 
					            logout:
 | 
				
			||||||
                path: app_logout
 | 
					                path: app_logout
 | 
				
			||||||
            switch_user: true
 | 
					            switch_user: true
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,10 @@
 | 
				
			|||||||
twig:
 | 
					twig:
 | 
				
			||||||
    default_path: '%kernel.project_dir%/templates'
 | 
					#    default_path: '%kernel.project_dir%/templates'
 | 
				
			||||||
 | 
					    paths:
 | 
				
			||||||
 | 
					        '%kernel.project_dir%/templates/themes/default': default
 | 
				
			||||||
 | 
					        '%kernel.project_dir%/templates/admin': admin
 | 
				
			||||||
    form_themes:
 | 
					    form_themes:
 | 
				
			||||||
        - '@FOSCKEditor/Form/ckeditor_widget.html.twig'
 | 
					        - bootstrap_5_layout.html.twig
 | 
				
			||||||
 | 
					
 | 
				
			||||||
when@test:
 | 
					when@test:
 | 
				
			||||||
    twig:
 | 
					    twig:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +0,0 @@
 | 
				
			|||||||
api_platform:
 | 
					 | 
				
			||||||
    resource: .
 | 
					 | 
				
			||||||
    type: api_platform
 | 
					 | 
				
			||||||
    prefix: /api
 | 
					 | 
				
			||||||
@@ -1,31 +0,0 @@
 | 
				
			|||||||
<?php
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
declare(strict_types=1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace DoctrineMigrations;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use Doctrine\DBAL\Schema\Schema;
 | 
					 | 
				
			||||||
use Doctrine\Migrations\AbstractMigration;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Auto-generated Migration: Please modify to your needs!
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
final class Version20220409135404 extends AbstractMigration
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    public function getDescription(): string
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        return '';
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function up(Schema $schema): void
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // this up() migration is auto-generated, please modify it to your needs
 | 
					 | 
				
			||||||
        $this->addSql('ALTER TABLE user ADD first_name VARCHAR(255) DEFAULT NULL, ADD last_name VARCHAR(255) DEFAULT NULL');
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function down(Schema $schema): void
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // this down() migration is auto-generated, please modify it to your needs
 | 
					 | 
				
			||||||
        $this->addSql('ALTER TABLE `user` DROP first_name, DROP last_name');
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,31 +0,0 @@
 | 
				
			|||||||
<?php
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
declare(strict_types=1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace DoctrineMigrations;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use Doctrine\DBAL\Schema\Schema;
 | 
					 | 
				
			||||||
use Doctrine\Migrations\AbstractMigration;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Auto-generated Migration: Please modify to your needs!
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
final class Version20220409150258 extends AbstractMigration
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    public function getDescription(): string
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        return '';
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function up(Schema $schema): void
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // this up() migration is auto-generated, please modify it to your needs
 | 
					 | 
				
			||||||
        $this->addSql('CREATE TABLE quotes (id INT AUTO_INCREMENT NOT NULL, quote LONGTEXT NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function down(Schema $schema): void
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // this down() migration is auto-generated, please modify it to your needs
 | 
					 | 
				
			||||||
        $this->addSql('DROP TABLE quotes');
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,33 +0,0 @@
 | 
				
			|||||||
<?php
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
declare(strict_types=1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace DoctrineMigrations;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use Doctrine\DBAL\Schema\Schema;
 | 
					 | 
				
			||||||
use Doctrine\Migrations\AbstractMigration;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Auto-generated Migration: Please modify to your needs!
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
final class Version20220410123550 extends AbstractMigration
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    public function getDescription(): string
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        return '';
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function up(Schema $schema): void
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // this up() migration is auto-generated, please modify it to your needs
 | 
					 | 
				
			||||||
        $this->addSql('CREATE TABLE projects (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(255) NOT NULL, description VARCHAR(255) NOT NULL, url VARCHAR(255) NOT NULL, created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
 | 
					 | 
				
			||||||
        $this->addSql('ALTER TABLE user CHANGE first_name first_name VARCHAR(255) DEFAULT NULL');
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function down(Schema $schema): void
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // this down() migration is auto-generated, please modify it to your needs
 | 
					 | 
				
			||||||
        $this->addSql('DROP TABLE projects');
 | 
					 | 
				
			||||||
        $this->addSql('ALTER TABLE `user` CHANGE first_name first_name VARCHAR(255) DEFAULT \'\'');
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,35 +0,0 @@
 | 
				
			|||||||
<?php
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
declare(strict_types=1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace DoctrineMigrations;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use Doctrine\DBAL\Schema\Schema;
 | 
					 | 
				
			||||||
use Doctrine\Migrations\AbstractMigration;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Auto-generated Migration: Please modify to your needs!
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
final class Version20220410131552 extends AbstractMigration
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    public function getDescription(): string
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        return '';
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function up(Schema $schema): void
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // this up() migration is auto-generated, please modify it to your needs
 | 
					 | 
				
			||||||
        $this->addSql('CREATE TABLE projects_user (projects_id INT NOT NULL, user_id INT NOT NULL, INDEX IDX_B38D6A811EDE0F55 (projects_id), INDEX IDX_B38D6A81A76ED395 (user_id), PRIMARY KEY(projects_id, user_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
 | 
					 | 
				
			||||||
        $this->addSql('ALTER TABLE projects_user ADD CONSTRAINT FK_B38D6A811EDE0F55 FOREIGN KEY (projects_id) REFERENCES projects (id) ON DELETE CASCADE');
 | 
					 | 
				
			||||||
        $this->addSql('ALTER TABLE projects_user ADD CONSTRAINT FK_B38D6A81A76ED395 FOREIGN KEY (user_id) REFERENCES `user` (id) ON DELETE CASCADE');
 | 
					 | 
				
			||||||
        $this->addSql('ALTER TABLE projects ADD teaser_image VARCHAR(255) DEFAULT NULL');
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function down(Schema $schema): void
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // this down() migration is auto-generated, please modify it to your needs
 | 
					 | 
				
			||||||
        $this->addSql('DROP TABLE projects_user');
 | 
					 | 
				
			||||||
        $this->addSql('ALTER TABLE projects DROP teaser_image');
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,31 +0,0 @@
 | 
				
			|||||||
<?php
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
declare(strict_types=1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace DoctrineMigrations;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use Doctrine\DBAL\Schema\Schema;
 | 
					 | 
				
			||||||
use Doctrine\Migrations\AbstractMigration;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Auto-generated Migration: Please modify to your needs!
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
final class Version20220412144008 extends AbstractMigration
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    public function getDescription(): string
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        return '';
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function up(Schema $schema): void
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // this up() migration is auto-generated, please modify it to your needs
 | 
					 | 
				
			||||||
        $this->addSql('ALTER TABLE user ADD avatar VARCHAR(255) DEFAULT NULL');
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function down(Schema $schema): void
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // this down() migration is auto-generated, please modify it to your needs
 | 
					 | 
				
			||||||
        $this->addSql('ALTER TABLE `user` DROP avatar');
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,32 +0,0 @@
 | 
				
			|||||||
<?php
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
declare(strict_types=1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace DoctrineMigrations;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use Doctrine\DBAL\Schema\Schema;
 | 
					 | 
				
			||||||
use Doctrine\Migrations\AbstractMigration;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Auto-generated Migration: Please modify to your needs!
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
final class Version20220423085724 extends AbstractMigration
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    public function getDescription(): string
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        return '';
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function up(Schema $schema): void
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // this up() migration is auto-generated, please modify it to your needs
 | 
					 | 
				
			||||||
        $this->addSql('CREATE TABLE pages (id INT AUTO_INCREMENT NOT NULL, owner_id INT NOT NULL, name VARCHAR(255) NOT NULL, content LONGTEXT NOT NULL, created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', modified_at DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\', INDEX IDX_2074E5757E3C61F9 (owner_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
 | 
					 | 
				
			||||||
        $this->addSql('ALTER TABLE pages ADD CONSTRAINT FK_2074E5757E3C61F9 FOREIGN KEY (owner_id) REFERENCES `user` (id)');
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function down(Schema $schema): void
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // this down() migration is auto-generated, please modify it to your needs
 | 
					 | 
				
			||||||
        $this->addSql('DROP TABLE pages');
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,31 +0,0 @@
 | 
				
			|||||||
<?php
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
declare(strict_types=1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace DoctrineMigrations;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use Doctrine\DBAL\Schema\Schema;
 | 
					 | 
				
			||||||
use Doctrine\Migrations\AbstractMigration;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Auto-generated Migration: Please modify to your needs!
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
final class Version20220425082917 extends AbstractMigration
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    public function getDescription(): string
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        return '';
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function up(Schema $schema): void
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // this up() migration is auto-generated, please modify it to your needs
 | 
					 | 
				
			||||||
        $this->addSql('ALTER TABLE user ADD created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', ADD modified_at DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\'');
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function down(Schema $schema): void
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // this down() migration is auto-generated, please modify it to your needs
 | 
					 | 
				
			||||||
        $this->addSql('ALTER TABLE `user` DROP created_at, DROP modified_at');
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										73
									
								
								migrations/Version20221028172857.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								migrations/Version20221028172857.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,73 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					declare(strict_types=1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace DoctrineMigrations;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Doctrine\DBAL\Schema\Schema;
 | 
				
			||||||
 | 
					use Doctrine\Migrations\AbstractMigration;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Auto-generated Migration: Please modify to your needs!
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					final class Version20221028172857 extends AbstractMigration
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public function getDescription(): string
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return '';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function up(Schema $schema): void
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // this up() migration is auto-generated, please modify it to your needs
 | 
				
			||||||
 | 
					        $this->addSql('CREATE TABLE pages (id INT AUTO_INCREMENT NOT NULL, owner_id INT NOT NULL, name VARCHAR(255) NOT NULL, content LONGTEXT NOT NULL, created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', modified_at DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\', slug VARCHAR(255) NOT NULL, INDEX IDX_2074E5757E3C61F9 (owner_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
 | 
				
			||||||
 | 
					        $this->addSql('CREATE TABLE projects (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(255) NOT NULL, description VARCHAR(255) NOT NULL, url VARCHAR(255) NOT NULL, created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', teaser_image VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
 | 
				
			||||||
 | 
					        $this->addSql('CREATE TABLE projects_user (projects_id INT NOT NULL, user_id INT NOT NULL, INDEX IDX_B38D6A811EDE0F55 (projects_id), INDEX IDX_B38D6A81A76ED395 (user_id), PRIMARY KEY(projects_id, user_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
 | 
				
			||||||
 | 
					        $this->addSql('CREATE TABLE quotes (id INT AUTO_INCREMENT NOT NULL, quote LONGTEXT NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
 | 
				
			||||||
 | 
					        $this->addSql('CREATE TABLE messenger_messages (id BIGINT AUTO_INCREMENT NOT NULL, body LONGTEXT NOT NULL, headers LONGTEXT NOT NULL, queue_name VARCHAR(190) NOT NULL, created_at DATETIME NOT NULL, available_at DATETIME NOT NULL, delivered_at DATETIME DEFAULT NULL, INDEX IDX_75EA56E0FB7336F0 (queue_name), INDEX IDX_75EA56E0E3BD61CE (available_at), INDEX IDX_75EA56E016BA31DB (delivered_at), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
 | 
				
			||||||
 | 
					        $this->addSql('ALTER TABLE pages ADD CONSTRAINT FK_2074E5757E3C61F9 FOREIGN KEY (owner_id) REFERENCES user (id)');
 | 
				
			||||||
 | 
					        $this->addSql('ALTER TABLE projects_user ADD CONSTRAINT FK_B38D6A811EDE0F55 FOREIGN KEY (projects_id) REFERENCES projects (id) ON DELETE CASCADE');
 | 
				
			||||||
 | 
					        $this->addSql('ALTER TABLE projects_user ADD CONSTRAINT FK_B38D6A81A76ED395 FOREIGN KEY (user_id) REFERENCES user (id) ON DELETE CASCADE');
 | 
				
			||||||
 | 
					        $this->addSql('ALTER TABLE reset_password_request DROP FOREIGN KEY FK_7CE748AA76ED395');
 | 
				
			||||||
 | 
					        $this->addSql('ALTER TABLE blog DROP FOREIGN KEY FK_C0155143DD7B2EBC');
 | 
				
			||||||
 | 
					        $this->addSql('ALTER TABLE blog DROP FOREIGN KEY FK_C0155143F675F31B');
 | 
				
			||||||
 | 
					        $this->addSql('ALTER TABLE comment DROP FOREIGN KEY FK_9474526CDAE07E97');
 | 
				
			||||||
 | 
					        $this->addSql('ALTER TABLE comment DROP FOREIGN KEY FK_9474526CDD7B2EBC');
 | 
				
			||||||
 | 
					        $this->addSql('ALTER TABLE comment DROP FOREIGN KEY FK_9474526CF675F31B');
 | 
				
			||||||
 | 
					        $this->addSql('ALTER TABLE blog_section DROP FOREIGN KEY FK_C185C76CD823E37A');
 | 
				
			||||||
 | 
					        $this->addSql('ALTER TABLE blog_section DROP FOREIGN KEY FK_C185C76CDAE07E97');
 | 
				
			||||||
 | 
					        $this->addSql('DROP TABLE reset_password_request');
 | 
				
			||||||
 | 
					        $this->addSql('DROP TABLE blog');
 | 
				
			||||||
 | 
					        $this->addSql('DROP TABLE comment');
 | 
				
			||||||
 | 
					        $this->addSql('DROP TABLE blog_section');
 | 
				
			||||||
 | 
					        $this->addSql('DROP TABLE section');
 | 
				
			||||||
 | 
					        $this->addSql('ALTER TABLE user ADD first_name VARCHAR(255) DEFAULT NULL, ADD last_name VARCHAR(255) DEFAULT NULL, ADD modified_at DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\', DROP last_login_at, CHANGE created_at created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\'');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function down(Schema $schema): void
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // this down() migration is auto-generated, please modify it to your needs
 | 
				
			||||||
 | 
					        $this->addSql('CREATE TABLE reset_password_request (id INT AUTO_INCREMENT NOT NULL, user_id INT NOT NULL, selector VARCHAR(20) CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci`, hashed_token VARCHAR(100) CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci`, requested_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', expires_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', INDEX IDX_7CE748AA76ED395 (user_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB COMMENT = \'\' ');
 | 
				
			||||||
 | 
					        $this->addSql('CREATE TABLE blog (id INT AUTO_INCREMENT NOT NULL, author_id INT NOT NULL, edited_by_id INT DEFAULT NULL, title VARCHAR(255) CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci`, teaser LONGTEXT CHARACTER SET utf8mb4 DEFAULT NULL COLLATE `utf8mb4_unicode_ci`, teaser_image VARCHAR(255) CHARACTER SET utf8mb4 DEFAULT NULL COLLATE `utf8mb4_unicode_ci`, content LONGTEXT CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci`, created_at DATETIME NOT NULL, edited_at DATETIME DEFAULT NULL, edit_reason VARCHAR(255) CHARACTER SET utf8mb4 DEFAULT NULL COLLATE `utf8mb4_unicode_ci`, slug VARCHAR(255) CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci`, INDEX IDX_C0155143DD7B2EBC (edited_by_id), UNIQUE INDEX UNIQ_C0155143989D9B62 (slug), INDEX IDX_C0155143F675F31B (author_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB COMMENT = \'\' ');
 | 
				
			||||||
 | 
					        $this->addSql('CREATE TABLE comment (id INT AUTO_INCREMENT NOT NULL, blog_id INT NOT NULL, author_id INT NOT NULL, edited_by_id INT DEFAULT NULL, title VARCHAR(255) CHARACTER SET utf8mb4 DEFAULT NULL COLLATE `utf8mb4_unicode_ci`, content LONGTEXT CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci`, created_at DATETIME NOT NULL, edited_at DATETIME DEFAULT NULL, edit_reason VARCHAR(255) CHARACTER SET utf8mb4 DEFAULT NULL COLLATE `utf8mb4_unicode_ci`, INDEX IDX_9474526CDD7B2EBC (edited_by_id), INDEX IDX_9474526CDAE07E97 (blog_id), INDEX IDX_9474526CF675F31B (author_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB COMMENT = \'\' ');
 | 
				
			||||||
 | 
					        $this->addSql('CREATE TABLE blog_section (blog_id INT NOT NULL, section_id INT NOT NULL, INDEX IDX_C185C76CDAE07E97 (blog_id), INDEX IDX_C185C76CD823E37A (section_id), PRIMARY KEY(blog_id, section_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB COMMENT = \'\' ');
 | 
				
			||||||
 | 
					        $this->addSql('CREATE TABLE section (id INT AUTO_INCREMENT NOT NULL, title VARCHAR(255) CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci`, description VARCHAR(255) CHARACTER SET utf8mb4 DEFAULT NULL COLLATE `utf8mb4_unicode_ci`, teaser_image VARCHAR(255) CHARACTER SET utf8mb4 DEFAULT NULL COLLATE `utf8mb4_unicode_ci`, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB COMMENT = \'\' ');
 | 
				
			||||||
 | 
					        $this->addSql('ALTER TABLE reset_password_request ADD CONSTRAINT FK_7CE748AA76ED395 FOREIGN KEY (user_id) REFERENCES user (id)');
 | 
				
			||||||
 | 
					        $this->addSql('ALTER TABLE blog ADD CONSTRAINT FK_C0155143DD7B2EBC FOREIGN KEY (edited_by_id) REFERENCES user (id)');
 | 
				
			||||||
 | 
					        $this->addSql('ALTER TABLE blog ADD CONSTRAINT FK_C0155143F675F31B FOREIGN KEY (author_id) REFERENCES user (id)');
 | 
				
			||||||
 | 
					        $this->addSql('ALTER TABLE comment ADD CONSTRAINT FK_9474526CDAE07E97 FOREIGN KEY (blog_id) REFERENCES blog (id)');
 | 
				
			||||||
 | 
					        $this->addSql('ALTER TABLE comment ADD CONSTRAINT FK_9474526CDD7B2EBC FOREIGN KEY (edited_by_id) REFERENCES user (id)');
 | 
				
			||||||
 | 
					        $this->addSql('ALTER TABLE comment ADD CONSTRAINT FK_9474526CF675F31B FOREIGN KEY (author_id) REFERENCES user (id)');
 | 
				
			||||||
 | 
					        $this->addSql('ALTER TABLE blog_section ADD CONSTRAINT FK_C185C76CD823E37A FOREIGN KEY (section_id) REFERENCES section (id) ON DELETE CASCADE');
 | 
				
			||||||
 | 
					        $this->addSql('ALTER TABLE blog_section ADD CONSTRAINT FK_C185C76CDAE07E97 FOREIGN KEY (blog_id) REFERENCES blog (id) ON DELETE CASCADE');
 | 
				
			||||||
 | 
					        $this->addSql('ALTER TABLE pages DROP FOREIGN KEY FK_2074E5757E3C61F9');
 | 
				
			||||||
 | 
					        $this->addSql('ALTER TABLE projects_user DROP FOREIGN KEY FK_B38D6A811EDE0F55');
 | 
				
			||||||
 | 
					        $this->addSql('ALTER TABLE projects_user DROP FOREIGN KEY FK_B38D6A81A76ED395');
 | 
				
			||||||
 | 
					        $this->addSql('DROP TABLE pages');
 | 
				
			||||||
 | 
					        $this->addSql('DROP TABLE projects');
 | 
				
			||||||
 | 
					        $this->addSql('DROP TABLE projects_user');
 | 
				
			||||||
 | 
					        $this->addSql('DROP TABLE quotes');
 | 
				
			||||||
 | 
					        $this->addSql('DROP TABLE messenger_messages');
 | 
				
			||||||
 | 
					        $this->addSql('ALTER TABLE user ADD last_login_at DATETIME DEFAULT NULL, DROP first_name, DROP last_name, DROP modified_at, CHANGE created_at created_at DATETIME NOT NULL');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -10,7 +10,7 @@ use Doctrine\Migrations\AbstractMigration;
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * Auto-generated Migration: Please modify to your needs!
 | 
					 * Auto-generated Migration: Please modify to your needs!
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
final class Version20220424100610 extends AbstractMigration
 | 
					final class Version20221030105205 extends AbstractMigration
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    public function getDescription(): string
 | 
					    public function getDescription(): string
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -20,12 +20,12 @@ final class Version20220424100610 extends AbstractMigration
 | 
				
			|||||||
    public function up(Schema $schema): void
 | 
					    public function up(Schema $schema): void
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // this up() migration is auto-generated, please modify it to your needs
 | 
					        // this up() migration is auto-generated, please modify it to your needs
 | 
				
			||||||
        $this->addSql('ALTER TABLE pages ADD slug VARCHAR(255) NOT NULL');
 | 
					        $this->addSql('ALTER TABLE user ADD agreed_terms_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\'');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function down(Schema $schema): void
 | 
					    public function down(Schema $schema): void
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // this down() migration is auto-generated, please modify it to your needs
 | 
					        // this down() migration is auto-generated, please modify it to your needs
 | 
				
			||||||
        $this->addSql('ALTER TABLE pages DROP slug');
 | 
					        $this->addSql('ALTER TABLE user DROP agreed_terms_at');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
							
								
								
									
										33
									
								
								migrations/Version20221030161847.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								migrations/Version20221030161847.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					declare(strict_types=1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace DoctrineMigrations;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Doctrine\DBAL\Schema\Schema;
 | 
				
			||||||
 | 
					use Doctrine\Migrations\AbstractMigration;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Auto-generated Migration: Please modify to your needs!
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					final class Version20221030161847 extends AbstractMigration
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public function getDescription(): string
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return '';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function up(Schema $schema): void
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // this up() migration is auto-generated, please modify it to your needs
 | 
				
			||||||
 | 
					        $this->addSql('CREATE TABLE reset_password_request (id INT AUTO_INCREMENT NOT NULL, user_id INT NOT NULL, selector VARCHAR(20) NOT NULL, hashed_token VARCHAR(100) NOT NULL, requested_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', expires_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', INDEX IDX_7CE748AA76ED395 (user_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
 | 
				
			||||||
 | 
					        $this->addSql('ALTER TABLE reset_password_request ADD CONSTRAINT FK_7CE748AA76ED395 FOREIGN KEY (user_id) REFERENCES user (id)');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function down(Schema $schema): void
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // this down() migration is auto-generated, please modify it to your needs
 | 
				
			||||||
 | 
					        $this->addSql('ALTER TABLE reset_password_request DROP FOREIGN KEY FK_7CE748AA76ED395');
 | 
				
			||||||
 | 
					        $this->addSql('DROP TABLE reset_password_request');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										16
									
								
								src/Controller/BaseController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/Controller/BaseController.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Controller;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
 | 
				
			||||||
 | 
					use App\Entity\User;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					abstract class BaseController extends AbstractController
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    protected function getUser(): User
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return parent::getUser();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -10,27 +10,30 @@ use Exception;
 | 
				
			|||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
 | 
					use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
 | 
				
			||||||
use Symfony\Component\HttpFoundation\Response;
 | 
					use Symfony\Component\HttpFoundation\Response;
 | 
				
			||||||
use Symfony\Component\Routing\Annotation\Route;
 | 
					use Symfony\Component\Routing\Annotation\Route;
 | 
				
			||||||
use Symfony\Component\Serializer\SerializerInterface;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
class FrontendController extends AbstractController
 | 
					class FrontendController extends AbstractController
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const TEMPLATE_DIR = 'themes/default/';
 | 
					    #[Route(path: '/', name: 'app_main')]
 | 
				
			||||||
 | 
					    public function quote(QuotesRepository $quotesRepository): Response
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $user = $this->getUser();
 | 
				
			||||||
 | 
					        $quote = $quotesRepository->findOneRandom();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $this->render(view: '@default/base.html.twig', parameters: [
 | 
				
			||||||
 | 
						        'user' => $user,
 | 
				
			||||||
 | 
						        'quote' => json_encode(value: $quote->getQuote())
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * @throws Exception
 | 
					     * @throws Exception
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    #[Route(path: '/', name: 'app_main')]
 | 
					    #[Route(path: '/logout', name: 'app_logout')]
 | 
				
			||||||
    public function quote(SerializerInterface $serializer, QuotesRepository $quotesRepository): Response
 | 
					    public function logout(): never
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $quote = $quotesRepository->findOneRandom();
 | 
					        throw new Exception(message: 'Logout should never be reached.');
 | 
				
			||||||
 | 
					 | 
				
			||||||
        return $this->render(view: self::TEMPLATE_DIR . 'base.html.twig', parameters: [
 | 
					 | 
				
			||||||
            'template_dir' => self::TEMPLATE_DIR,
 | 
					 | 
				
			||||||
	        'user' => $serializer->serialize(data: $this->getUser(), format: 'jsonld'),
 | 
					 | 
				
			||||||
	        'quote' => json_encode(value: $quote->getQuote())
 | 
					 | 
				
			||||||
        ]);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,8 +10,6 @@ use Symfony\Component\Routing\Annotation\Route;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class PagesController extends AbstractController
 | 
					class PagesController extends AbstractController
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const TEMPLATE_DIR = 'themes/default/';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[Route(path: '/pages/{name}', name: 'pages_display')]
 | 
					    #[Route(path: '/pages/{name}', name: 'pages_display')]
 | 
				
			||||||
    public function display(PagesRepository $pagesRepository, string $name): Response
 | 
					    public function display(PagesRepository $pagesRepository, string $name): Response
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -25,7 +23,7 @@ class PagesController extends AbstractController
 | 
				
			|||||||
            $page->setContent(content: 'The requested page was not found.');
 | 
					            $page->setContent(content: 'The requested page was not found.');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $this->render(view: 'pages/display.html.twig', parameters: [
 | 
					        return $this->render(view: '@default/pages/display.html.twig', parameters: [
 | 
				
			||||||
            'page' => $page,
 | 
					            'page' => $page,
 | 
				
			||||||
        ]);
 | 
					        ]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -33,18 +31,12 @@ class PagesController extends AbstractController
 | 
				
			|||||||
    #[Route(path: '/imprint', name: 'app_imprint')]
 | 
					    #[Route(path: '/imprint', name: 'app_imprint')]
 | 
				
			||||||
    public function imprint(): Response
 | 
					    public function imprint(): Response
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return $this->render(view: self::TEMPLATE_DIR . 'pages/imprint.html.twig', parameters: [
 | 
					        return $this->render(view: '@default/pages/imprint.html.twig');
 | 
				
			||||||
            'template_dir' => self::TEMPLATE_DIR,
 | 
					 | 
				
			||||||
            'controller_name' => 'PagesController',
 | 
					 | 
				
			||||||
        ]);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[Route(path: '/privacy', name: 'app_privacy')]
 | 
					    #[Route(path: '/privacy', name: 'app_privacy')]
 | 
				
			||||||
    public function privacy(): Response
 | 
					    public function privacy(): Response
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return $this->render(view: self::TEMPLATE_DIR . 'pages/privacy.html.twig', parameters: [
 | 
					        return $this->render(view: '@default/pages/privacy.html.twig');
 | 
				
			||||||
            'template_dir' => self::TEMPLATE_DIR,
 | 
					 | 
				
			||||||
            'controller_name' => 'PagesController',
 | 
					 | 
				
			||||||
        ]);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,7 +13,7 @@ class ProjectsController extends AbstractController
 | 
				
			|||||||
    public function index(ProjectsRepository $projectsRepository, string $name = ''): Response
 | 
					    public function index(ProjectsRepository $projectsRepository, string $name = ''): Response
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if ($name == '') {
 | 
					        if ($name == '') {
 | 
				
			||||||
            return $this->render(view: 'projects/index.html.twig', parameters: [
 | 
					            return $this->render(view: '@default/projects/index.html.twig', parameters: [
 | 
				
			||||||
                'projects' => $projectsRepository->findAll(),
 | 
					                'projects' => $projectsRepository->findAll(),
 | 
				
			||||||
            ]);
 | 
					            ]);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
@@ -22,7 +22,7 @@ class ProjectsController extends AbstractController
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                // $parsedReadMe = $markdownParser->transformMarkdown(text: $readMe);
 | 
					                // $parsedReadMe = $markdownParser->transformMarkdown(text: $readMe);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                return $this->render(view: 'projects/show.html.twig', parameters: [
 | 
					                return $this->render(view: '@default/projects/show.html.twig', parameters: [
 | 
				
			||||||
                    'project' => $project,
 | 
					                    'project' => $project,
 | 
				
			||||||
                    'readme' => $readMe,
 | 
					                    'readme' => $readMe,
 | 
				
			||||||
                ]);
 | 
					                ]);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										179
									
								
								src/Controller/ResetPasswordController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										179
									
								
								src/Controller/ResetPasswordController.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,179 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Controller;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Entity\User;
 | 
				
			||||||
 | 
					use App\Form\ChangePasswordFormType;
 | 
				
			||||||
 | 
					use App\Form\ResetPasswordRequestFormType;
 | 
				
			||||||
 | 
					use Doctrine\ORM\EntityManagerInterface;
 | 
				
			||||||
 | 
					use Symfony\Bridge\Twig\Mime\TemplatedEmail;
 | 
				
			||||||
 | 
					use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
 | 
				
			||||||
 | 
					use Symfony\Component\HttpFoundation\RedirectResponse;
 | 
				
			||||||
 | 
					use Symfony\Component\HttpFoundation\Request;
 | 
				
			||||||
 | 
					use Symfony\Component\HttpFoundation\Response;
 | 
				
			||||||
 | 
					use Symfony\Component\Mailer\MailerInterface;
 | 
				
			||||||
 | 
					use Symfony\Component\Mime\Address;
 | 
				
			||||||
 | 
					use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
 | 
				
			||||||
 | 
					use Symfony\Component\Routing\Annotation\Route;
 | 
				
			||||||
 | 
					use Symfony\Contracts\Translation\TranslatorInterface;
 | 
				
			||||||
 | 
					use SymfonyCasts\Bundle\ResetPassword\Controller\ResetPasswordControllerTrait;
 | 
				
			||||||
 | 
					use SymfonyCasts\Bundle\ResetPassword\Exception\ResetPasswordExceptionInterface;
 | 
				
			||||||
 | 
					use SymfonyCasts\Bundle\ResetPassword\ResetPasswordHelperInterface;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ResetPasswordController extends AbstractController
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    use ResetPasswordControllerTrait;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function __construct(
 | 
				
			||||||
 | 
					        private readonly ResetPasswordHelperInterface $resetPasswordHelper,
 | 
				
			||||||
 | 
					        private readonly EntityManagerInterface       $entityManager
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // empty body
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Display & process form to request a password reset.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    #[Route(path: '/security/forgot/password', name: 'security_forgot_password')]
 | 
				
			||||||
 | 
					    public function request(Request $request, MailerInterface $mailer): Response
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $form = $this->createForm(type: ResetPasswordRequestFormType::class);
 | 
				
			||||||
 | 
					        $form->handleRequest(request: $request);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($form->isSubmitted() && $form->isValid()) {
 | 
				
			||||||
 | 
					            return $this->processSendingPasswordResetEmail(
 | 
				
			||||||
 | 
					                formData: $form->get(name: 'account')->getData(),
 | 
				
			||||||
 | 
					                mailer: $mailer
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $this->render(view: '@default/security/forgot_password.html.twig', parameters: [
 | 
				
			||||||
 | 
					            'requestForm' => $form->createView(),
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Confirmation page after a user has requested a password reset.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    #[Route(path: '/security/recovery/mail/sent', name: 'security_recovery_mail_sent')]
 | 
				
			||||||
 | 
					    public function checkEmail(): Response
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // Generate a fake token if the user does not exist or someone hit this page directly.
 | 
				
			||||||
 | 
					        // This prevents exposing whether a user was found with the given email address or username or not
 | 
				
			||||||
 | 
					        if (null === ($resetToken = $this->getTokenObjectFromSession())) {
 | 
				
			||||||
 | 
					            $resetToken = $this->resetPasswordHelper->generateFakeResetToken();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $this->render(view: '@default/security/recovery_mail_sent.html.twig', parameters: [
 | 
				
			||||||
 | 
					            'resetToken' => $resetToken,
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Validates and process the reset URL that the user clicked in their email.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    #[Route(path: '/security/recovery/reset/{token}', name: 'security_recovery_reset')]
 | 
				
			||||||
 | 
					    public function reset(Request $request, UserPasswordHasherInterface $passwordHasher, TranslatorInterface $translator, string $token = null): Response
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if ($token) {
 | 
				
			||||||
 | 
					            // We store the token in session and remove it from the URL, to avoid the URL being
 | 
				
			||||||
 | 
					            // loaded in a browser and potentially leaking the token to 3rd party JavaScript.
 | 
				
			||||||
 | 
					            $this->storeTokenInSession(token: $token);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return $this->redirectToRoute(route: 'security_recovery_reset');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $token = $this->getTokenFromSession();
 | 
				
			||||||
 | 
					        if (null === $token) {
 | 
				
			||||||
 | 
					            throw $this->createNotFoundException(message: 'No reset password token found in the URL or in the session.');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            $user = $this->resetPasswordHelper->validateTokenAndFetchUser(fullToken: $token);
 | 
				
			||||||
 | 
					        } catch (ResetPasswordExceptionInterface $e) {
 | 
				
			||||||
 | 
					            $this->addFlash(type: 'reset_password_error', message: sprintf(
 | 
				
			||||||
 | 
					                '%s - %s',
 | 
				
			||||||
 | 
					                $translator->trans(id: ResetPasswordExceptionInterface::MESSAGE_PROBLEM_VALIDATE, parameters: [], domain: 'ResetPasswordBundle'),
 | 
				
			||||||
 | 
					                $translator->trans(id: $e->getReason(), parameters: [], domain: 'ResetPasswordBundle')
 | 
				
			||||||
 | 
					            ));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return $this->redirectToRoute(route: 'app_forgot_password_request');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // The token is valid; allow the user to change their password.
 | 
				
			||||||
 | 
					        $form = $this->createForm(type: ChangePasswordFormType::class);
 | 
				
			||||||
 | 
					        $form->handleRequest(request: $request);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($form->isSubmitted() && $form->isValid()) {
 | 
				
			||||||
 | 
					            // A password reset token should be used only once, remove it.
 | 
				
			||||||
 | 
					            $this->resetPasswordHelper->removeResetRequest(fullToken: $token);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Encode(hash) the plain password, and set it.
 | 
				
			||||||
 | 
					            $encodedPassword = $passwordHasher->hashPassword(
 | 
				
			||||||
 | 
					                user: $user,
 | 
				
			||||||
 | 
					                plainPassword: $form->get(name: 'plainPassword')->getData()
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $user->setPassword($encodedPassword);
 | 
				
			||||||
 | 
					            $this->entityManager->flush();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // The session is cleaned up after the password has been changed.
 | 
				
			||||||
 | 
					            $this->cleanSessionAfterReset();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $this->addFlash(type: 'success', message: 'Your password has been changed.');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return $this->redirectToRoute(route: 'app_main');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $this->render(view: '@default/security/reset_password.html.twig', parameters: [
 | 
				
			||||||
 | 
					            'resetForm' => $form->createView(),
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private function processSendingPasswordResetEmail(string $formData, MailerInterface $mailer): RedirectResponse
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $user = $this->entityManager->getRepository(entityName: User::class)->findOneBy(criteria: [
 | 
				
			||||||
 | 
					            'email' => $formData,
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!$user) {
 | 
				
			||||||
 | 
					            $user = $this->entityManager->getRepository(entityName: User::class)->findOneBy(criteria: [
 | 
				
			||||||
 | 
					                'username' => $formData,
 | 
				
			||||||
 | 
					            ]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Do not reveal whether a user account was found or not.
 | 
				
			||||||
 | 
					//        if (!$user) {
 | 
				
			||||||
 | 
					//            return $this->redirectToRoute(route: 'app_check_email');
 | 
				
			||||||
 | 
					//        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            $resetToken = $this->resetPasswordHelper->generateResetToken(user: $user);
 | 
				
			||||||
 | 
					        } catch (ResetPasswordExceptionInterface $e) {
 | 
				
			||||||
 | 
					            $this->addFlash(type: 'reset_password_error', message: sprintf(
 | 
				
			||||||
 | 
					                '%s - %s',
 | 
				
			||||||
 | 
					                ResetPasswordExceptionInterface::MESSAGE_PROBLEM_HANDLE,
 | 
				
			||||||
 | 
					                $e->getReason()
 | 
				
			||||||
 | 
					            ));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return $this->redirectToRoute(route: 'security_forgot_password');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $email = (new TemplatedEmail())
 | 
				
			||||||
 | 
					            ->from(new Address(address: 'tracer@24unix.net', name: '24unix.net'))
 | 
				
			||||||
 | 
					            ->to($user->getEmail())
 | 
				
			||||||
 | 
					            ->subject(subject: 'Your password reset request')
 | 
				
			||||||
 | 
					            ->htmlTemplate(template: '@default/security/mail/recovery.html.twig')
 | 
				
			||||||
 | 
					            ->context(context: [
 | 
				
			||||||
 | 
					                'resetToken' => $resetToken,
 | 
				
			||||||
 | 
					            ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $mailer->send(message: $email);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Store the token object in session for retrieval in check-email route.
 | 
				
			||||||
 | 
					        $this->setTokenObjectInSession(token: $resetToken);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $this->redirectToRoute(route: 'security_recovery_mail_sent');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -2,46 +2,117 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace App\Controller;
 | 
					namespace App\Controller;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use ApiPlatform\Core\Api\IriConverterInterface;
 | 
					use App\Form\LoginFormType;
 | 
				
			||||||
use App\Entity\User;
 | 
					use App\Form\RegistrationFormType;
 | 
				
			||||||
 | 
					use App\Repository\UserRepository;
 | 
				
			||||||
 | 
					use App\Security\EmailVerifier;
 | 
				
			||||||
 | 
					use Doctrine\ORM\EntityManagerInterface;
 | 
				
			||||||
 | 
					use Symfony\Bridge\Twig\Mime\TemplatedEmail;
 | 
				
			||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
 | 
					use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
 | 
				
			||||||
use Symfony\Component\Config\Definition\Exception\Exception;
 | 
					use Symfony\Component\HttpFoundation\Request;
 | 
				
			||||||
use Symfony\Component\HttpFoundation\Response;
 | 
					use Symfony\Component\HttpFoundation\Response;
 | 
				
			||||||
 | 
					use Symfony\Component\Mime\Address;
 | 
				
			||||||
 | 
					use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
 | 
				
			||||||
use Symfony\Component\Routing\Annotation\Route;
 | 
					use Symfony\Component\Routing\Annotation\Route;
 | 
				
			||||||
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
 | 
					use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
 | 
				
			||||||
 | 
					use Symfony\Contracts\Translation\TranslatorInterface;
 | 
				
			||||||
 | 
					use SymfonyCasts\Bundle\VerifyEmail\Exception\VerifyEmailExceptionInterface;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
class SecurityController extends AbstractController
 | 
					class SecurityController extends AbstractController
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    #[Route(path: '/login', name: 'app_login')] // *** method post
 | 
					
 | 
				
			||||||
    public function login(AuthenticationUtils $authenticationUtils, IriConverterInterface $iriConverter): Response
 | 
					    public function __construct(private readonly EmailVerifier $emailVerifier)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        // empty body
 | 
				
			||||||
	    /** @var User $user */
 | 
					 | 
				
			||||||
	    $user = $this->getUser() ?? null;
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		return new Response(content: null, status: 204, headers: [
 | 
					 | 
				
			||||||
			'Location' => $iriConverter->getIriFromItem(item: $user)
 | 
					 | 
				
			||||||
		]);
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    	/*
 | 
					    #[Route(path: '/login', name: 'app_login')]
 | 
				
			||||||
        return $this->render(view: 'security/login.html.twig', parameters: [
 | 
					    public function index(AuthenticationUtils $authenticationUtils): Response
 | 
				
			||||||
            'error' => $authenticationUtils->getLastAuthenticationError(),
 | 
					 | 
				
			||||||
            'last_username' => $authenticationUtils->getLastUsername(),
 | 
					 | 
				
			||||||
        ]);
 | 
					 | 
				
			||||||
		*
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * @return mixed
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    #[Route(path: '/logout', name: 'app_logout')]
 | 
					 | 
				
			||||||
    public function logout(): never
 | 
					 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        throw new Exception(message: 'Logout should never be reached.');
 | 
					        // get the login error if there is one
 | 
				
			||||||
 | 
					        if ($error = $authenticationUtils->getLastAuthenticationError()) {
 | 
				
			||||||
 | 
					            $this->addFlash(type: 'error', message: $error->getMessageKey());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // last username entered by the user
 | 
				
			||||||
 | 
					        $lastUsername = $authenticationUtils->getLastUsername();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $this->render(view: '@default/security/login.html.twig', parameters: [
 | 
				
			||||||
 | 
					            'last_username' => $lastUsername,
 | 
				
			||||||
 | 
					            'error' => '',
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[Route(path: '/register', name: 'app_register')]
 | 
				
			||||||
 | 
					    public function register(Request $request, UserPasswordHasherInterface $userPasswordHasher, EntityManagerInterface $entityManager): Response
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $form = $this->createForm(type: RegistrationFormType::class);
 | 
				
			||||||
 | 
					        $form->handleRequest(request: $request);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($form->isSubmitted() && $form->isValid()) {
 | 
				
			||||||
 | 
					            $user = $form->getData();
 | 
				
			||||||
 | 
					            // hash the plain password
 | 
				
			||||||
 | 
					            $user->setPassword(
 | 
				
			||||||
 | 
					                password: $userPasswordHasher->hashPassword(
 | 
				
			||||||
 | 
					                    user: $user,
 | 
				
			||||||
 | 
					                    plainPassword: $form->get(name: 'password')->getData()
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if ($form->get(name: 'agreeTerms')->getData()) {
 | 
				
			||||||
 | 
					                $user->agreeTerms();
 | 
				
			||||||
 | 
					            } // no else, we already confirmed in the form itself
 | 
				
			||||||
 | 
					            $entityManager->persist(entity: $user);
 | 
				
			||||||
 | 
					            $entityManager->flush();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // generate a signed url and email it to the user
 | 
				
			||||||
 | 
					            $this->emailVerifier->sendEmailConfirmation(verifyEmailRouteName: 'app_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/register.html.twig', parameters: [
 | 
				
			||||||
 | 
					            'registrationForm' => $form->createView(),
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[Route(path: '/verify/email', name: 'app_verify_email')]
 | 
				
			||||||
 | 
					    public function verifyUserEmail(Request $request, TranslatorInterface $translator, UserRepository $userRepository): Response
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $id = $request->get(key: 'id');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($id === null) {
 | 
				
			||||||
 | 
					            return $this->redirectToRoute(route: 'app_register');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $user = $userRepository->find($id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($user === null) {
 | 
				
			||||||
 | 
					            return $this->redirectToRoute(route: 'app_register');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // validate email confirmation link, sets User::isVerified=true and persists
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            $this->emailVerifier->handleEmailConfirmation(request: $request, user: $user);
 | 
				
			||||||
 | 
					        } catch (VerifyEmailExceptionInterface $exception) {
 | 
				
			||||||
 | 
					            $this->addFlash(type: 'verify_email_error', message: $translator->trans(id: $exception->getReason(), parameters: [], domain: 'VerifyEmailBundle'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return $this->redirectToRoute(route: 'app_main');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->addFlash(type: 'success', message: 'Your email address has been verified.');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $this->redirectToRoute(route: 'app_main');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,9 +3,13 @@
 | 
				
			|||||||
namespace App\Controller;
 | 
					namespace App\Controller;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use App\Entity\User;
 | 
					use App\Entity\User;
 | 
				
			||||||
 | 
					use App\Form\EditProfileFormType;
 | 
				
			||||||
use App\Repository\UserRepository;
 | 
					use App\Repository\UserRepository;
 | 
				
			||||||
 | 
					use Doctrine\ORM\EntityManagerInterface;
 | 
				
			||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
 | 
					use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
 | 
				
			||||||
 | 
					use Symfony\Component\HttpFoundation\Request;
 | 
				
			||||||
use Symfony\Component\HttpFoundation\Response;
 | 
					use Symfony\Component\HttpFoundation\Response;
 | 
				
			||||||
 | 
					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;
 | 
				
			||||||
@@ -13,31 +17,56 @@ use Symfony\Component\Security\Core\Exception\UserNotFoundException;
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * Class UserController.
 | 
					 * Class UserController.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
class UserController extends AbstractController
 | 
					class UserController extends BaseController
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[Route(path: '/profile/edit/{username}', name: 'app_profile_edit')]
 | 
					    #[Route(path: '/profile/edit/{username}', name: 'app_profile_edit')]
 | 
				
			||||||
    public function editProfile(UserRepository $userRepository, string $username = ''): Response
 | 
					    public function editProfile(Request $request, UserRepository $userRepository, UserPasswordHasherInterface $userPasswordHasher, EntityManagerInterface $entityManager,  string $username = ''): Response
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        /* var User $user */
 | 
					        if ($username !== '') {
 | 
				
			||||||
        if ($username === '') {
 | 
					 | 
				
			||||||
            if ($this->isGranted(attribute: 'ROLE_USER')) {
 | 
					 | 
				
			||||||
                $user = $this->getUser();
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                throw new AccessDeniedException(message: 'You need to be logged in.');
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            if ($this->isGranted(attribute: 'ROLE_ADMIN')) {
 | 
					            if ($this->isGranted(attribute: 'ROLE_ADMIN')) {
 | 
				
			||||||
                $user = $userRepository->findOneBy([
 | 
					                $user = $userRepository->findOneBy([
 | 
				
			||||||
                    'username' => $username,
 | 
					                    'username' => $username,
 | 
				
			||||||
                ]);
 | 
					                ]);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                throw new AccessDeniedException(message: 'Only admins are allowed to edit Profiles.');
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            $user = $this->getUser();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (isset($user)) {
 | 
					        $form = $this->createForm(type: EditProfileFormType::class, data: $user);
 | 
				
			||||||
            return $this->render(view: 'user/edit_profile.html.twig', parameters: [
 | 
					        $form->handleRequest(request: $request);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($form->isSubmitted() && $form->isValid()) {
 | 
				
			||||||
 | 
					            $user = $form->getData();
 | 
				
			||||||
 | 
					            // if there's a new password, use it
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if ($form->get(name: 'newPassword')->getData())
 | 
				
			||||||
 | 
					            $user->setPassword(
 | 
				
			||||||
 | 
					                password: $userPasswordHasher->hashPassword(
 | 
				
			||||||
 | 
					                    user: $user,
 | 
				
			||||||
 | 
					                    plainPassword: $form->get(name: 'newPassword')->getData()
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $entityManager->persist(entity: $user);
 | 
				
			||||||
 | 
					            $entityManager->flush();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return $this->redirectToRoute(route: 'app_main');
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $user = $form->getData();
 | 
				
			||||||
 | 
					        // hash the plain password
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $this->renderForm(view: '@default/user/edit_profile.html.twig', parameters: [
 | 
				
			||||||
            'user' => $user,
 | 
					            'user' => $user,
 | 
				
			||||||
 | 
					            'userForm' => $form
 | 
				
			||||||
        ]);
 | 
					        ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (isset($user)) {
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            throw new UserNotFoundException();
 | 
					            throw new UserNotFoundException();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										39
									
								
								src/Entity/ResetPasswordRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/Entity/ResetPasswordRequest.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Entity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Repository\ResetPasswordRequestRepository;
 | 
				
			||||||
 | 
					use Doctrine\ORM\Mapping as ORM;
 | 
				
			||||||
 | 
					use SymfonyCasts\Bundle\ResetPassword\Model\ResetPasswordRequestInterface;
 | 
				
			||||||
 | 
					use SymfonyCasts\Bundle\ResetPassword\Model\ResetPasswordRequestTrait;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[ORM\Entity(repositoryClass: ResetPasswordRequestRepository::class)]
 | 
				
			||||||
 | 
					class ResetPasswordRequest implements ResetPasswordRequestInterface
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    use ResetPasswordRequestTrait;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[ORM\Id]
 | 
				
			||||||
 | 
					    #[ORM\GeneratedValue]
 | 
				
			||||||
 | 
					    #[ORM\Column]
 | 
				
			||||||
 | 
					    private ?int $id = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[ORM\ManyToOne]
 | 
				
			||||||
 | 
					    #[ORM\JoinColumn(nullable: false)]
 | 
				
			||||||
 | 
					    private ?User $user = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function __construct(User $user, \DateTimeInterface $expiresAt, string $selector, string $hashedToken)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->user = $user;
 | 
				
			||||||
 | 
					        $this->initialize(expiresAt: $expiresAt, selector: $selector, hashedToken: $hashedToken);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function getId(): ?int
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->id;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function getUser(): object
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->user;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -2,48 +2,40 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace App\Entity;
 | 
					namespace App\Entity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use ApiPlatform\Core\Annotation\ApiFilter;
 | 
					 | 
				
			||||||
use ApiPlatform\Core\Annotation\ApiResource;
 | 
					 | 
				
			||||||
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter;
 | 
					 | 
				
			||||||
use App\Repository\UserRepository;
 | 
					use App\Repository\UserRepository;
 | 
				
			||||||
use DateTimeImmutable;
 | 
					use DateTimeImmutable;
 | 
				
			||||||
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;
 | 
				
			||||||
 | 
					use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
 | 
				
			||||||
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
 | 
					use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
 | 
				
			||||||
use Symfony\Component\Security\Core\User\UserInterface;
 | 
					use Symfony\Component\Security\Core\User\UserInterface;
 | 
				
			||||||
 | 
					use Symfony\Component\Validator\Constraints as Assert;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * => ["security" => "is_granted('ROLE_ADMIN') or object.owner == user"]
 | 
					 | 
				
			||||||
attributes          : ['security' => 'is_granted("ROLE_USER")']
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#[ORM\Entity(repositoryClass: UserRepository::class), ORM\HasLifecycleCallbacks]
 | 
					#[ORM\Entity(repositoryClass: UserRepository::class), ORM\HasLifecycleCallbacks]
 | 
				
			||||||
#[ApiResource(
 | 
					#[UniqueEntity(fields: ['username', 'email'], message: 'There is already an account with this username or email.')]
 | 
				
			||||||
	collectionOperations: ['get', 'post'],
 | 
					 | 
				
			||||||
	itemOperations      : ['get'],
 | 
					 | 
				
			||||||
)]
 | 
					 | 
				
			||||||
#[ApiFilter(filterClass: SearchFilter::class, properties: ['username' => 'exact'])]
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class User implements UserInterface, PasswordAuthenticatedUserInterface, \Stringable
 | 
					class User implements UserInterface, PasswordAuthenticatedUserInterface
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    #[ORM\Id]
 | 
					    #[ORM\Id]
 | 
				
			||||||
    #[ORM\GeneratedValue]
 | 
					    #[ORM\GeneratedValue]
 | 
				
			||||||
    #[ORM\Column(type: 'integer')]
 | 
					    #[ORM\Column(type: 'integer')]
 | 
				
			||||||
    private int $id;
 | 
					    private int $id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[ORM\Column(type: 'string', length: 180, unique: true)]
 | 
					    #[ORM\Column(type: 'string', length: 180, unique: true, nullable: false)]
 | 
				
			||||||
    private string $username;
 | 
					    private string $username;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[ORM\Column(type: 'json')]
 | 
					    #[ORM\Column(type: 'json')]
 | 
				
			||||||
    private array $roles = [];
 | 
					    private array $roles = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[ORM\Column(type: 'string')]
 | 
					    #[ORM\Column(type: 'string', nullable: false)]
 | 
				
			||||||
    private string $password;
 | 
					    private string $password;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private string $plainPassword;
 | 
					    #[ORM\Column(type: 'string', length: 255, nullable: false)]
 | 
				
			||||||
 | 
					    #[Assert\Email(
 | 
				
			||||||
    #[ORM\Column(type: 'string', length: 255)]
 | 
					        message: 'The eMail {{ value }} is not a valid eMail.'
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
    private string $email;
 | 
					    private string $email;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[ORM\Column(type: 'string', length: 255, nullable: true)]
 | 
					    #[ORM\Column(type: 'string', length: 255, nullable: true)]
 | 
				
			||||||
@@ -67,15 +59,18 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface, \String
 | 
				
			|||||||
    #[ORM\Column(type: 'datetime_immutable', nullable: true)]
 | 
					    #[ORM\Column(type: 'datetime_immutable', nullable: true)]
 | 
				
			||||||
    private $modifiedAt;
 | 
					    private $modifiedAt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[ORM\Column(type: 'boolean')]
 | 
				
			||||||
 | 
					    private $isVerified = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[ORM\Column]
 | 
				
			||||||
 | 
					    private ?DateTimeImmutable $agreedTermsAt = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function __construct()
 | 
					    public function __construct()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $this->projects = new ArrayCollection();
 | 
					        $this->projects = new ArrayCollection();
 | 
				
			||||||
        $this->pages = new ArrayCollection();
 | 
					        $this->pages = new ArrayCollection();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * @return string|null
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public function __toString(): string
 | 
					    public function __toString(): string
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return $this->username;
 | 
					        return $this->username;
 | 
				
			||||||
@@ -86,11 +81,6 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface, \String
 | 
				
			|||||||
        return $this->id;
 | 
					        return $this->id;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function getPlainPassword(): string
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        return $this->plainPassword;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function getUsername(): ?string
 | 
					    public function getUsername(): ?string
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return $this->username;
 | 
					        return $this->username;
 | 
				
			||||||
@@ -308,4 +298,28 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface, \String
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        $this->modifiedAt = new DateTimeImmutable(datetime: 'now');
 | 
					        $this->modifiedAt = new DateTimeImmutable(datetime: 'now');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function isVerified(): bool
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->isVerified;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function setIsVerified(bool $isVerified): self
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->isVerified = $isVerified;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function getAgreedTermsAt(): ?DateTimeImmutable
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->agreedTermsAt;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function agreeTerms(): self
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->agreedTermsAt = new DateTimeImmutable();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										54
									
								
								src/Form/ChangePasswordFormType.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/Form/ChangePasswordFormType.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Form;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Symfony\Component\Form\AbstractType;
 | 
				
			||||||
 | 
					use Symfony\Component\Form\Extension\Core\Type\PasswordType;
 | 
				
			||||||
 | 
					use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
 | 
				
			||||||
 | 
					use Symfony\Component\Form\FormBuilderInterface;
 | 
				
			||||||
 | 
					use Symfony\Component\OptionsResolver\OptionsResolver;
 | 
				
			||||||
 | 
					use Symfony\Component\Validator\Constraints\Length;
 | 
				
			||||||
 | 
					use Symfony\Component\Validator\Constraints\NotBlank;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ChangePasswordFormType extends AbstractType
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public function buildForm(FormBuilderInterface $builder, array $options): void
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $builder
 | 
				
			||||||
 | 
					            ->add(child: 'plainPassword', type: RepeatedType::class, options: [
 | 
				
			||||||
 | 
					                'type' => PasswordType::class,
 | 
				
			||||||
 | 
					                'options' => [
 | 
				
			||||||
 | 
					                    'attr' => [
 | 
				
			||||||
 | 
					                        'autocomplete' => 'new-password',
 | 
				
			||||||
 | 
					                    ],
 | 
				
			||||||
 | 
					                ],
 | 
				
			||||||
 | 
					                'first_options' => [
 | 
				
			||||||
 | 
					                    'constraints' => [
 | 
				
			||||||
 | 
					                        new NotBlank(options: [
 | 
				
			||||||
 | 
					                            'message' => 'Please enter a password',
 | 
				
			||||||
 | 
					                        ]),
 | 
				
			||||||
 | 
					                        new Length(exactly: [
 | 
				
			||||||
 | 
					                            'min' => 6,
 | 
				
			||||||
 | 
					                            'minMessage' => 'Your password should be at least {{ limit }} characters',
 | 
				
			||||||
 | 
					                            // max length allowed by Symfony for security reasons
 | 
				
			||||||
 | 
					                            'max' => 4096,
 | 
				
			||||||
 | 
					                        ]),
 | 
				
			||||||
 | 
					                    ],
 | 
				
			||||||
 | 
					                    'label' => 'New password',
 | 
				
			||||||
 | 
					                ],
 | 
				
			||||||
 | 
					                'second_options' => [
 | 
				
			||||||
 | 
					                    'label' => 'Repeat Password',
 | 
				
			||||||
 | 
					                ],
 | 
				
			||||||
 | 
					                'invalid_message' => 'The password fields must match.',
 | 
				
			||||||
 | 
					                // Instead of being set onto the object directly,
 | 
				
			||||||
 | 
					                // this is read and encoded in the controller
 | 
				
			||||||
 | 
					                'mapped' => false,
 | 
				
			||||||
 | 
					            ])
 | 
				
			||||||
 | 
					        ;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function configureOptions(OptionsResolver $resolver): void
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $resolver->setDefaults(defaults: []);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										45
									
								
								src/Form/EditProfileFormType.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/Form/EditProfileFormType.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Form;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Entity\User;
 | 
				
			||||||
 | 
					use Symfony\Component\Form\AbstractType;
 | 
				
			||||||
 | 
					use Symfony\Component\Form\Extension\Core\Type\EmailType;
 | 
				
			||||||
 | 
					use Symfony\Component\Form\Extension\Core\Type\PasswordType;
 | 
				
			||||||
 | 
					use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
 | 
				
			||||||
 | 
					use Symfony\Component\Form\FormBuilderInterface;
 | 
				
			||||||
 | 
					use Symfony\Component\OptionsResolver\OptionsResolver;
 | 
				
			||||||
 | 
					use Symfony\Component\Validator\Constraints\Length;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class EditProfileFormType extends AbstractType
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public function buildForm(FormBuilderInterface $builder, array $options): void
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $builder
 | 
				
			||||||
 | 
					            ->add(child: 'username')
 | 
				
			||||||
 | 
					            ->add(child: 'firstName')
 | 
				
			||||||
 | 
					            ->add(child: 'lastName')
 | 
				
			||||||
 | 
					            ->add(child: 'email', type: EmailType::class)
 | 
				
			||||||
 | 
					            ->add(child: 'newPassword', type: RepeatedType::class, options: [
 | 
				
			||||||
 | 
					                'type' => PasswordType::class,
 | 
				
			||||||
 | 
					                'mapped' => false,
 | 
				
			||||||
 | 
					                'invalid_message' => 'The password fields must match.',
 | 
				
			||||||
 | 
					                'options' => ['attr' => ['class' => 'password-field', 'autocomplete' => 'off']],
 | 
				
			||||||
 | 
					                'required' => false,
 | 
				
			||||||
 | 
					                'first_options' => ['label' => 'Password'],
 | 
				
			||||||
 | 
					                'second_options' => ['label' => 'Repeat Password (only needed if you want to update the password'],
 | 
				
			||||||
 | 
					                'constraints' => [new Length(exactly: ['min' => 6])]
 | 
				
			||||||
 | 
					            ])
 | 
				
			||||||
 | 
					        ;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function configureOptions(OptionsResolver $resolver): void
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $resolver->setDefaults(defaults: [
 | 
				
			||||||
 | 
					            'data_class' => User::class,
 | 
				
			||||||
 | 
					            'csrf_protection' => true,
 | 
				
			||||||
 | 
					            'csrf_field_name' => '_csrf_token',
 | 
				
			||||||
 | 
					            'csrf_token_id' => 'authenticate'
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										49
									
								
								src/Form/RegistrationFormType.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/Form/RegistrationFormType.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Form;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Entity\User;
 | 
				
			||||||
 | 
					use Symfony\Component\Form\AbstractType;
 | 
				
			||||||
 | 
					use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
 | 
				
			||||||
 | 
					use Symfony\Component\Form\Extension\Core\Type\EmailType;
 | 
				
			||||||
 | 
					use Symfony\Component\Form\Extension\Core\Type\PasswordType;
 | 
				
			||||||
 | 
					use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
 | 
				
			||||||
 | 
					use Symfony\Component\Form\FormBuilderInterface;
 | 
				
			||||||
 | 
					use Symfony\Component\OptionsResolver\OptionsResolver;
 | 
				
			||||||
 | 
					use Symfony\Component\Validator\Constraints\IsTrue;
 | 
				
			||||||
 | 
					use Symfony\Component\Validator\Constraints\Length;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class RegistrationFormType extends AbstractType
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public function buildForm(FormBuilderInterface $builder, array $options): void
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $builder
 | 
				
			||||||
 | 
					            ->add(child: 'username')
 | 
				
			||||||
 | 
					            ->add(child: 'email', type: EmailType::class)
 | 
				
			||||||
 | 
					            ->add(child: 'password', type: RepeatedType::class, options: [
 | 
				
			||||||
 | 
					                'type' => PasswordType::class,
 | 
				
			||||||
 | 
					                'invalid_message' => 'The password fields must match.',
 | 
				
			||||||
 | 
					                'options' => ['attr' => ['class' => 'password-field']],
 | 
				
			||||||
 | 
					                'required' => true,
 | 
				
			||||||
 | 
					                'first_options' => ['label' => 'Password'],
 | 
				
			||||||
 | 
					                'second_options' => ['label' => 'Repeat Password'],
 | 
				
			||||||
 | 
					                'constraints' => [new Length(exactly: ['min' => 6])]
 | 
				
			||||||
 | 
					            ])
 | 
				
			||||||
 | 
					            ->add(child: 'agreeTerms', type: CheckboxType::class, options: [
 | 
				
			||||||
 | 
					                'mapped' => false,
 | 
				
			||||||
 | 
					                'constraints' => [
 | 
				
			||||||
 | 
					                    new IsTrue(options: [
 | 
				
			||||||
 | 
					                        'message' => 'You should agree to our terms.',
 | 
				
			||||||
 | 
					                    ]),
 | 
				
			||||||
 | 
					                ],
 | 
				
			||||||
 | 
					            ])
 | 
				
			||||||
 | 
					        ;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function configureOptions(OptionsResolver $resolver): void
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $resolver->setDefaults(defaults: [
 | 
				
			||||||
 | 
					            'data_class' => User::class,
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										31
									
								
								src/Form/ResetPasswordRequestFormType.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/Form/ResetPasswordRequestFormType.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Form;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Symfony\Component\Form\AbstractType;
 | 
				
			||||||
 | 
					use Symfony\Component\Form\Extension\Core\Type\EmailType;
 | 
				
			||||||
 | 
					use Symfony\Component\Form\FormBuilderInterface;
 | 
				
			||||||
 | 
					use Symfony\Component\OptionsResolver\OptionsResolver;
 | 
				
			||||||
 | 
					use Symfony\Component\Validator\Constraints\NotBlank;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ResetPasswordRequestFormType extends AbstractType
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public function buildForm(FormBuilderInterface $builder, array $options): void
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $builder
 | 
				
			||||||
 | 
					            ->add(child: 'account', type: null, options: [
 | 
				
			||||||
 | 
					                'mapped' => false,
 | 
				
			||||||
 | 
					                'constraints' => [
 | 
				
			||||||
 | 
					                    new NotBlank(options: [
 | 
				
			||||||
 | 
					                        'message' => 'Please enter your email or username',
 | 
				
			||||||
 | 
					                    ]),
 | 
				
			||||||
 | 
					                ],
 | 
				
			||||||
 | 
					            ])
 | 
				
			||||||
 | 
					        ;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function configureOptions(OptionsResolver $resolver): void
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $resolver->setDefaults(defaults: []);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										51
									
								
								src/Repository/ResetPasswordRequestRepository.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/Repository/ResetPasswordRequestRepository.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Repository;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Entity\ResetPasswordRequest;
 | 
				
			||||||
 | 
					use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
 | 
				
			||||||
 | 
					use Doctrine\Persistence\ManagerRegistry;
 | 
				
			||||||
 | 
					use SymfonyCasts\Bundle\ResetPassword\Model\ResetPasswordRequestInterface;
 | 
				
			||||||
 | 
					use SymfonyCasts\Bundle\ResetPassword\Persistence\Repository\ResetPasswordRequestRepositoryTrait;
 | 
				
			||||||
 | 
					use SymfonyCasts\Bundle\ResetPassword\Persistence\ResetPasswordRequestRepositoryInterface;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @extends ServiceEntityRepository<ResetPasswordRequest>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @method ResetPasswordRequest|null find($id, $lockMode = null, $lockVersion = null)
 | 
				
			||||||
 | 
					 * @method ResetPasswordRequest|null findOneBy(array $criteria, array $orderBy = null)
 | 
				
			||||||
 | 
					 * @method ResetPasswordRequest[]    findAll()
 | 
				
			||||||
 | 
					 * @method ResetPasswordRequest[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class ResetPasswordRequestRepository extends ServiceEntityRepository implements ResetPasswordRequestRepositoryInterface
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    use ResetPasswordRequestRepositoryTrait;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function __construct(ManagerRegistry $registry)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        parent::__construct($registry, ResetPasswordRequest::class);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function save(ResetPasswordRequest $entity, bool $flush = false): void
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->getEntityManager()->persist($entity);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($flush) {
 | 
				
			||||||
 | 
					            $this->getEntityManager()->flush();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function remove(ResetPasswordRequest $entity, bool $flush = false): void
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->getEntityManager()->remove($entity);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($flush) {
 | 
				
			||||||
 | 
					            $this->getEntityManager()->flush();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function createResetPasswordRequest(object $user, \DateTimeInterface $expiresAt, string $selector, string $hashedToken): ResetPasswordRequestInterface
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return new ResetPasswordRequest($user, $expiresAt, $selector, $hashedToken);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										54
									
								
								src/Security/EmailVerifier.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/Security/EmailVerifier.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Security;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Entity\User;
 | 
				
			||||||
 | 
					use Doctrine\ORM\EntityManagerInterface;
 | 
				
			||||||
 | 
					use Symfony\Bridge\Twig\Mime\TemplatedEmail;
 | 
				
			||||||
 | 
					use Symfony\Component\HttpFoundation\Request;
 | 
				
			||||||
 | 
					use Symfony\Component\Mailer\MailerInterface;
 | 
				
			||||||
 | 
					use Symfony\Component\Security\Core\User\UserInterface;
 | 
				
			||||||
 | 
					use SymfonyCasts\Bundle\VerifyEmail\Exception\VerifyEmailExceptionInterface;
 | 
				
			||||||
 | 
					use SymfonyCasts\Bundle\VerifyEmail\VerifyEmailHelperInterface;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class EmailVerifier
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public function __construct(
 | 
				
			||||||
 | 
					        private readonly VerifyEmailHelperInterface $verifyEmailHelper,
 | 
				
			||||||
 | 
					        private readonly MailerInterface            $mailer,
 | 
				
			||||||
 | 
					        private readonly EntityManagerInterface $entityManager
 | 
				
			||||||
 | 
					    ) {
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function sendEmailConfirmation(string $verifyEmailRouteName, User /* UserInterface */ $user, TemplatedEmail $email): void
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $signatureComponents = $this->verifyEmailHelper->generateSignature(
 | 
				
			||||||
 | 
					            routeName: $verifyEmailRouteName,
 | 
				
			||||||
 | 
					            userId: $user->getId(),
 | 
				
			||||||
 | 
					            userEmail: $user->getEmail(),
 | 
				
			||||||
 | 
					            extraParams: ['id' => $user->getId()]
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $context = $email->getContext();
 | 
				
			||||||
 | 
					        $context['signedUrl'] = $signatureComponents->getSignedUrl();
 | 
				
			||||||
 | 
					        $context['expiresAtMessageKey'] = $signatureComponents->getExpirationMessageKey();
 | 
				
			||||||
 | 
					        $context['expiresAtMessageData'] = $signatureComponents->getExpirationMessageData();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $email->context(context: $context);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->mailer->send(message: $email);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @throws VerifyEmailExceptionInterface
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function handleEmailConfirmation(Request $request, User /*UserInterface*/ $user): void
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->verifyEmailHelper->validateEmailConfirmation(signedUrl: $request->getUri(), userId: $user->getId(), userEmail: $user->getEmail());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $user->setIsVerified(isVerified: true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->entityManager->persist(entity: $user);
 | 
				
			||||||
 | 
					        $this->entityManager->flush();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -3,12 +3,17 @@
 | 
				
			|||||||
namespace App\Security;
 | 
					namespace App\Security;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use App\Entity\User;
 | 
					use App\Entity\User;
 | 
				
			||||||
 | 
					use App\Form\LoginFormType;
 | 
				
			||||||
use App\Repository\UserRepository;
 | 
					use App\Repository\UserRepository;
 | 
				
			||||||
 | 
					use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
 | 
				
			||||||
 | 
					use Symfony\Component\Form\FormBuilder;
 | 
				
			||||||
 | 
					use Symfony\Component\Form\FormBuilderInterface;
 | 
				
			||||||
use Symfony\Component\HttpFoundation\RedirectResponse;
 | 
					use Symfony\Component\HttpFoundation\RedirectResponse;
 | 
				
			||||||
use Symfony\Component\HttpFoundation\Request;
 | 
					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\AuthenticationException;
 | 
				
			||||||
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;
 | 
				
			||||||
@@ -16,7 +21,9 @@ use Symfony\Component\Security\Http\Authenticator\Passport\Badge\CsrfTokenBadge;
 | 
				
			|||||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\RememberMeBadge;
 | 
					use Symfony\Component\Security\Http\Authenticator\Passport\Badge\RememberMeBadge;
 | 
				
			||||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
 | 
					use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
 | 
				
			||||||
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\CustomCredentials;
 | 
					use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\CustomCredentials;
 | 
				
			||||||
 | 
					use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
 | 
				
			||||||
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
 | 
					use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
 | 
				
			||||||
 | 
					use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
 | 
				
			||||||
use Symfony\Component\Security\Http\Util\TargetPathTrait;
 | 
					use Symfony\Component\Security\Http\Util\TargetPathTrait;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@@ -39,14 +46,12 @@ class LoginFormAuthenticator extends AbstractLoginFormAuthenticator
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $request->getSession()->set(name: Security::LAST_USERNAME, value: $username);
 | 
					        $request->getSession()->set(name: Security::LAST_USERNAME, value: $username);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		dd("here");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return new Passport(
 | 
					        return new Passport(
 | 
				
			||||||
            userBadge: new UserBadge(userIdentifier: $username, userLoader: function ($userIdentifier) {
 | 
					            userBadge: new UserBadge(userIdentifier: $username, userLoader: function ($username) {
 | 
				
			||||||
                $user = $this->userRepository->findOneBy(['username' => $userIdentifier]);
 | 
					                $user = $this->userRepository->findOneBy(['username' => $username]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (!$user) {
 | 
					                if (!$user) {
 | 
				
			||||||
                    $user = $this->userRepository->findOneBy(['email' => $userIdentifier]);
 | 
					                    $user = $this->userRepository->findOneBy(['email' => $username]);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (!$user) {
 | 
					                if (!$user) {
 | 
				
			||||||
@@ -56,10 +61,7 @@ class LoginFormAuthenticator extends AbstractLoginFormAuthenticator
 | 
				
			|||||||
                return $user;
 | 
					                return $user;
 | 
				
			||||||
            }),
 | 
					            }),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // remove me later for PasswordCredentials()
 | 
					            credentials: new PasswordCredentials(password: $password),
 | 
				
			||||||
            credentials: new CustomCredentials(customCredentialsChecker: fn($credentials, User $user) => $credentials === 'test', credentials             : $password),
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // new PasswordCredentials($password),
 | 
					 | 
				
			||||||
            badges: [
 | 
					            badges: [
 | 
				
			||||||
                new CsrfTokenBadge(csrfTokenId: 'authenticate', csrfToken: $csrfToken),
 | 
					                new CsrfTokenBadge(csrfTokenId: 'authenticate', csrfToken: $csrfToken),
 | 
				
			||||||
                new RememberMeBadge(),
 | 
					                new RememberMeBadge(),
 | 
				
			||||||
@@ -82,4 +84,5 @@ class LoginFormAuthenticator extends AbstractLoginFormAuthenticator
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        return $this->router->generate(name: 'app_login');
 | 
					        return $this->router->generate(name: 'app_login');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										32
									
								
								symfony.lock
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								symfony.lock
									
									
									
									
									
								
							@@ -1,18 +1,4 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    "api-platform/core": {
 | 
					 | 
				
			||||||
        "version": "2.7",
 | 
					 | 
				
			||||||
        "recipe": {
 | 
					 | 
				
			||||||
            "repo": "github.com/symfony/recipes",
 | 
					 | 
				
			||||||
            "branch": "main",
 | 
					 | 
				
			||||||
            "version": "2.5",
 | 
					 | 
				
			||||||
            "ref": "05b57782a78c21a664a42055dc11cf1954ca36bb"
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "files": [
 | 
					 | 
				
			||||||
            "config/packages/api_platform.yaml",
 | 
					 | 
				
			||||||
            "config/routes/api_platform.yaml",
 | 
					 | 
				
			||||||
            "src/Entity/.gitignore"
 | 
					 | 
				
			||||||
        ]
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "doctrine/annotations": {
 | 
					    "doctrine/annotations": {
 | 
				
			||||||
        "version": "1.13",
 | 
					        "version": "1.13",
 | 
				
			||||||
        "recipe": {
 | 
					        "recipe": {
 | 
				
			||||||
@@ -303,5 +289,23 @@
 | 
				
			|||||||
            "package.json",
 | 
					            "package.json",
 | 
				
			||||||
            "webpack.config.js"
 | 
					            "webpack.config.js"
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "symfonycasts/reset-password-bundle": {
 | 
				
			||||||
 | 
					        "version": "1.16",
 | 
				
			||||||
 | 
					        "recipe": {
 | 
				
			||||||
 | 
					            "repo": "github.com/symfony/recipes",
 | 
				
			||||||
 | 
					            "branch": "main",
 | 
				
			||||||
 | 
					            "version": "1.0",
 | 
				
			||||||
 | 
					            "ref": "97c1627c0384534997ae1047b93be517ca16de43"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "files": [
 | 
				
			||||||
 | 
					            "config/packages/reset_password.yaml"
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "symfonycasts/verify-email-bundle": {
 | 
				
			||||||
 | 
					        "version": "v1.12.0"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "twig/extra-bundle": {
 | 
				
			||||||
 | 
					        "version": "v3.4.0"
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,19 +0,0 @@
 | 
				
			|||||||
<!DOCTYPE html>
 | 
					 | 
				
			||||||
<html>
 | 
					 | 
				
			||||||
    <head>
 | 
					 | 
				
			||||||
        <meta charset="UTF-8">
 | 
					 | 
				
			||||||
        <title>{% block title %}Welcome!{% endblock %}</title>
 | 
					 | 
				
			||||||
        <link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 128 128%22><text y=%221.2em%22 font-size=%2296%22>⚫️</text></svg>">
 | 
					 | 
				
			||||||
        {# Run `composer require symfony/webpack-encore-bundle` to start using Symfony UX #}
 | 
					 | 
				
			||||||
        {% block stylesheets %}
 | 
					 | 
				
			||||||
            {{ encore_entry_link_tags('app') }}
 | 
					 | 
				
			||||||
        {% endblock %}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        {% block javascripts %}
 | 
					 | 
				
			||||||
            {{ encore_entry_script_tags('app') }}
 | 
					 | 
				
			||||||
        {% endblock %}
 | 
					 | 
				
			||||||
    </head>
 | 
					 | 
				
			||||||
    <body>
 | 
					 | 
				
			||||||
        {% block body %}{% endblock %}
 | 
					 | 
				
			||||||
    </body>
 | 
					 | 
				
			||||||
</html>
 | 
					 | 
				
			||||||
@@ -21,7 +21,7 @@
 | 
				
			|||||||
            {% 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 ml-auto mb-2 button-login">
 | 
					                            class="btn btn-primary dropdown-toggle button-login">
 | 
				
			||||||
                        {{ app.user.username }}
 | 
					                        {{ app.user.username }}
 | 
				
			||||||
                    </button>
 | 
					                    </button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -38,7 +38,7 @@
 | 
				
			|||||||
{% include '@default/_header.html.twig' %}
 | 
					{% include '@default/_header.html.twig' %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<!-- sidebar -->
 | 
					<!-- sidebar -->
 | 
				
			||||||
    <nav id="sidebar" class="m-3">
 | 
					<nav id="sidebar" class="m-3">
 | 
				
			||||||
    <ul class="list-group ml1" id="main-menu">
 | 
					    <ul class="list-group ml1" id="main-menu">
 | 
				
			||||||
        <li class="list-group-item list-group-item-action">
 | 
					        <li class="list-group-item list-group-item-action">
 | 
				
			||||||
            <a href="{{ path('app_projects') }}" class="text-decoration-none">
 | 
					            <a href="{{ path('app_projects') }}" class="text-decoration-none">
 | 
				
			||||||
@@ -67,7 +67,7 @@
 | 
				
			|||||||
        </li>
 | 
					        </li>
 | 
				
			||||||
        <!--                <a href="//pastebin.24unix.net">pastebin.24unix.net</a>-->
 | 
					        <!--                <a href="//pastebin.24unix.net">pastebin.24unix.net</a>-->
 | 
				
			||||||
    </ul>
 | 
					    </ul>
 | 
				
			||||||
    </nav>
 | 
					</nav>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div class="container-fluid" id="content">
 | 
					<div class="container-fluid" id="content">
 | 
				
			||||||
    {% for message in app.flashes('success') %}
 | 
					    {% for message in app.flashes('success') %}
 | 
				
			||||||
@@ -82,7 +82,7 @@
 | 
				
			|||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
    {% endfor %}
 | 
					    {% endfor %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <div class="col">
 | 
					    <div class="col m-3" id="main_content">
 | 
				
			||||||
        {% block body %}
 | 
					        {% block body %}
 | 
				
			||||||
            <h1 class="q-title-show">Quote of the Moment</h1>
 | 
					            <h1 class="q-title-show">Quote of the Moment</h1>
 | 
				
			||||||
            <div class="q-display p-3">
 | 
					            <div class="q-display p-3">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,13 +1,16 @@
 | 
				
			|||||||
{% extends template_dir ~ 'base.html.twig' %}
 | 
					{% extends '@default/base.html.twig' %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% block title %}Imprint{% endblock %}
 | 
					{% block title %}Imprint{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% block body %}
 | 
					{% block body %}
 | 
				
			||||||
    <div class="imprint-wrapper">
 | 
					    <div class="imprint-wrapper">
 | 
				
			||||||
        <p>This page is only available in German, as the server is located in Germany.</p>
 | 
					        <h2>This page is only available in German, as the server is located in Germany.</h2>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <p>Inhaltlich Verantwortlicher gemäß § 55 Abs. 2RStV: Michael Espey, Große Kirchreihe 27, 25377 Kollmar</p>
 | 
					        <p>Inhaltlich Verantwortlicher gemäß § 55 Abs. 2RStV:<br><br>
 | 
				
			||||||
 | 
					            Michael Espey<br>
 | 
				
			||||||
 | 
					            Große Kirchreihe 27<br>
 | 
				
			||||||
 | 
					            25377 Kollmar</p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <p>eMail: webmaster (AT) 24unix.net</p>
 | 
					        <p>eMail: webmaster (AT) 24unix.net</p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
{% extends template_dir ~'base.html.twig' %}
 | 
					{% extends '@default/base.html.twig' %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% block title %}Privacy{% endblock %}
 | 
					{% block title %}Privacy{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										70
									
								
								templates/themes/default/projects/index.html.twig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								templates/themes/default/projects/index.html.twig
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,70 @@
 | 
				
			|||||||
 | 
					{# templates/projects/index.html.twig #}
 | 
				
			||||||
 | 
					{% extends '@default/base.html.twig' %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block title %} Projects {% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block body %}
 | 
				
			||||||
 | 
					    <div class="container-fluid box">
 | 
				
			||||||
 | 
					        <div class="row">
 | 
				
			||||||
 | 
					            <h2>This is an overview of my current public (and open source) projects.</h2>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <!-- projects List -->
 | 
				
			||||||
 | 
					            <div class="col-sm-12">
 | 
				
			||||||
 | 
					                {% for project in projects %}
 | 
				
			||||||
 | 
					                    <div class="project-container bg-dark my-4">
 | 
				
			||||||
 | 
					                        <div class="row">
 | 
				
			||||||
 | 
					                            <div class="col-sm-3">
 | 
				
			||||||
 | 
					                                <a href="{{ path('app_projects', { name: project.name }) }}">
 | 
				
			||||||
 | 
					                                    {% if project.teaserImage %}
 | 
				
			||||||
 | 
					                                        <img
 | 
				
			||||||
 | 
					                                                class="blog-img"
 | 
				
			||||||
 | 
					                                                src="/uploads/projects/{{  project.teaserImage  }}"
 | 
				
			||||||
 | 
					                                                alt="Teaser">
 | 
				
			||||||
 | 
					                                    {% else %}
 | 
				
			||||||
 | 
					                                        <img
 | 
				
			||||||
 | 
					                                                class="blog-img"
 | 
				
			||||||
 | 
					                                                src="{{ asset('build/images/24unix/24_logo_bg_96x96.png') }}"
 | 
				
			||||||
 | 
					                                                alt="Teaser">
 | 
				
			||||||
 | 
					                                    {% endif %}
 | 
				
			||||||
 | 
					                                </a>
 | 
				
			||||||
 | 
					                                <br>
 | 
				
			||||||
 | 
					                                <div>
 | 
				
			||||||
 | 
					                                    {% for developer in project.developer %}
 | 
				
			||||||
 | 
					                                        <a class="align-left blog-details"
 | 
				
			||||||
 | 
					                                           href="{{ path('app_profile', { 'username':developer.username }) }}">
 | 
				
			||||||
 | 
					                                            <img class="article-author-img rounded-circle"
 | 
				
			||||||
 | 
					                                                 src="{{ asset('build/images/tracer_schmolle.png') }}"
 | 
				
			||||||
 | 
					                                                 alt="profile"></a>
 | 
				
			||||||
 | 
					                                        <a href="{{ path('app_profile', { 'username':developer.username }) }}">{{ developer.username }}</a>
 | 
				
			||||||
 | 
					                                    {% endfor %}
 | 
				
			||||||
 | 
					                                </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            </div>
 | 
				
			||||||
 | 
					                            <div class="col-sm-8 mt-2">
 | 
				
			||||||
 | 
					                                <a href="{{ path('app_projects', { name: project.name }) }}">
 | 
				
			||||||
 | 
					                                    <div class="article-title d-inline-block pl-3 align-middle">
 | 
				
			||||||
 | 
					                                        <h2>{{ project.name }}</h2>
 | 
				
			||||||
 | 
					                                    </div>
 | 
				
			||||||
 | 
					                                </a>
 | 
				
			||||||
 | 
					                                <br>
 | 
				
			||||||
 | 
					                                <div class="blog-teaser mb-2 pb-2 text-xl-start">
 | 
				
			||||||
 | 
					                                    {{ project.description }}
 | 
				
			||||||
 | 
					                                    <br>
 | 
				
			||||||
 | 
					                                    <br>
 | 
				
			||||||
 | 
					                                    started: {{ project.createdAt | ago }}
 | 
				
			||||||
 | 
					                                </div>
 | 
				
			||||||
 | 
					                            </div>
 | 
				
			||||||
 | 
					                        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                {% endfor %}
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            {% if is_granted('ROLE_ADMIN') %}
 | 
				
			||||||
 | 
					                <div class="text-xl-start">
 | 
				
			||||||
 | 
					                    <a href="{{ path('app_main') }}"><i class="fa fa-plus-circle"></i></a>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            {%  endif %}
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
							
								
								
									
										35
									
								
								templates/themes/default/projects/show.html.twig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								templates/themes/default/projects/show.html.twig
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					{# templates/blog/blog_show.html.twig #}
 | 
				
			||||||
 | 
					{% extends '@default/base.html.twig' %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block title %}Projects{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block body %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <div class="row">
 | 
				
			||||||
 | 
					        <div class="col-sm-12">
 | 
				
			||||||
 | 
					            {% if is_granted('ROLE_ADMIN') %}
 | 
				
			||||||
 | 
					                <div class="d-flex justify-content-end">
 | 
				
			||||||
 | 
					                    <a href="{{ path('app_main', { id : project.id }) }}"><i class="fa fa-3x fa-fw fa-edit"></i></a>
 | 
				
			||||||
 | 
					                    <a href="{{ path('app_main', { id : project.id }) }}"><i class="fa fa-3x fa-fw fa-trash"></i></a>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            {% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <div class="show-article-container p-3 mt-4">
 | 
				
			||||||
 | 
					                <div class="show-article-title-container d-inline-block pl-3 align-middle">
 | 
				
			||||||
 | 
					                    <h2>{{ project.name }}</h2>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					                <div>
 | 
				
			||||||
 | 
					                    Source: <a href="{{ project.url }}" target="_blank">{{ project.url }}</a> <i
 | 
				
			||||||
 | 
					                            class="fa fa-external-link" aria-hidden="true"></i>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					                <div class="row">
 | 
				
			||||||
 | 
					                    <div class="col-sm-12">
 | 
				
			||||||
 | 
					                        <div class="article-text">
 | 
				
			||||||
 | 
					                            {{ readme | markdown_to_html }}
 | 
				
			||||||
 | 
					                        </div>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					{%  endblock %}
 | 
				
			||||||
							
								
								
									
										22
									
								
								templates/themes/default/security/forgot_password.html.twig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								templates/themes/default/security/forgot_password.html.twig
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					{% extends '@default/base.html.twig' %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block title %}Reset your password{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block body %}
 | 
				
			||||||
 | 
					    {% for flash_error in app.flashes('reset_password_error') %}
 | 
				
			||||||
 | 
					        <div class="alert alert-danger" role="alert">{{ flash_error }}</div>
 | 
				
			||||||
 | 
					    {% endfor %}
 | 
				
			||||||
 | 
					    <h1>Reset your password</h1>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {{ form_start(requestForm) }}
 | 
				
			||||||
 | 
					        {{ form_row(requestForm.account) }}
 | 
				
			||||||
 | 
					        <div>
 | 
				
			||||||
 | 
					            <small>
 | 
				
			||||||
 | 
					                Enter your email address or your username and we will send you a
 | 
				
			||||||
 | 
					                link to reset your password.
 | 
				
			||||||
 | 
					            </small>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <button class="btn btn-primary float-end">Send password reset email</button>
 | 
				
			||||||
 | 
					    {{ form_end(requestForm) }}
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
@@ -1,9 +1,9 @@
 | 
				
			|||||||
{% extends '../themes/default/base.html.twig' %}
 | 
					{% extends '@default/base.html.twig' %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% block title %}Log In!{% endblock %}
 | 
					{% block title %}Log In!{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% block body %}
 | 
					{% block body %}
 | 
				
			||||||
    <div class="container box">
 | 
					    <div class="container rounded">
 | 
				
			||||||
        <div class="row">
 | 
					        <div class="row">
 | 
				
			||||||
            <div class="login-form bg-dark mt-4 p-4">
 | 
					            <div class="login-form bg-dark mt-4 p-4">
 | 
				
			||||||
                <form method="post" class="row g-3">
 | 
					                <form method="post" class="row g-3">
 | 
				
			||||||
@@ -15,9 +15,13 @@
 | 
				
			|||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
                    {% endif %}
 | 
					                    {% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    <input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    <div class="col-12">
 | 
					                    <div class="col-12">
 | 
				
			||||||
                        <label for="inputEmail">Username or eMail</label>
 | 
					                        <label for="inputUsername">Username or eMail</label>
 | 
				
			||||||
                        <input type="text" name="username" id="inputUsername" class="form-control" value="{{ last_username }}" required autofocus>
 | 
					                        <input type="text" name="username" id="inputUsername"
 | 
				
			||||||
 | 
					                               class="form-control" {#  value="{{ last_username }}" #} required autofocus>
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                    <div class="col-12">
 | 
					                    <div class="col-12">
 | 
				
			||||||
                        <label for="inputPassword">Password</label>
 | 
					                        <label for="inputPassword">Password</label>
 | 
				
			||||||
@@ -28,13 +32,9 @@
 | 
				
			|||||||
                            <input type="checkbox" name="_remember_me" class="form-check-input">Remember me
 | 
					                            <input type="checkbox" name="_remember_me" class="form-check-input">Remember me
 | 
				
			||||||
                        </label>
 | 
					                        </label>
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                    <input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}">
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    <div class="col-12">
 | 
					 | 
				
			||||||
                    <button class="btn btn-lg btn-primary float-end" type="submit">
 | 
					                    <button class="btn btn-lg btn-primary float-end" type="submit">
 | 
				
			||||||
                        Sign in
 | 
					                        Sign in
 | 
				
			||||||
                    </button>
 | 
					                    </button>
 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                </form>
 | 
					                </form>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					<h1>Hi!</h1>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<p>To reset your password, please visit the following link</p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<a href="{{ url('security_recovery_reset', {token: resetToken.token}) }}">Reset password</a>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<p>This link will expire in {{ resetToken.expirationMessageKey|trans(resetToken.expirationMessageData, 'ResetPasswordBundle') }}.</p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<p>Cheers!</p>
 | 
				
			||||||
@@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 | 
				
			||||||
 | 
					<html lang="en" style="margin:0;padding:0;">
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
					    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
 | 
				
			||||||
 | 
					    <meta name="viewport" content="width=device-width, initial-scale=1"/>
 | 
				
			||||||
 | 
					    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
 | 
				
			||||||
 | 
					    <meta name="format-detection" content="telephone=no"/>
 | 
				
			||||||
 | 
					    <title></title>
 | 
				
			||||||
 | 
					    <style type="text/css">
 | 
				
			||||||
 | 
					        @media screen and (max-width: 599px) {
 | 
				
			||||||
 | 
					            div {
 | 
				
			||||||
 | 
					                max-width: 100% !important;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        body {
 | 
				
			||||||
 | 
					            background-color: #1e1f1e;
 | 
				
			||||||
 | 
					            margin:25px;
 | 
				
			||||||
 | 
					            padding:0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    </style>
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
					<div style="border-collapse:collapse;border-spacing:0;">
 | 
				
			||||||
 | 
					    <h1>Hi {{ username }}, please confirm your email!</h1>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <p>
 | 
				
			||||||
 | 
					        Please confirm your email address by clicking the following link: <br><br>
 | 
				
			||||||
 | 
					        <a href="{{ signedUrl|raw }}">Confirm my Email</a>.
 | 
				
			||||||
 | 
					        <br>
 | 
				
			||||||
 | 
					        This link will expire in {{ expiresAtMessageKey|trans(expiresAtMessageData, 'VerifyEmailBundle') }}.
 | 
				
			||||||
 | 
					    </p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <p>
 | 
				
			||||||
 | 
					        Kind regards,
 | 
				
			||||||
 | 
					        24unix.net
 | 
				
			||||||
 | 
					    </p>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					{% extends '@default/base.html.twig' %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block title %}Password Reset Email Sent{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block body %}
 | 
				
			||||||
 | 
					    <p>
 | 
				
			||||||
 | 
					        If an account matching your email exists, then an email was just sent that contains a link that you can use to reset your password.
 | 
				
			||||||
 | 
					        This link will expire in {{ resetToken.expirationMessageKey|trans(resetToken.expirationMessageData, 'ResetPasswordBundle') }}.
 | 
				
			||||||
 | 
					    </p>
 | 
				
			||||||
 | 
					    <p>If you don't receive an email please check your spam folder or <a href="{{ path('security_forgot_password') }}">try again</a>.</p>
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
							
								
								
									
										60
									
								
								templates/themes/default/security/register.html.twig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								templates/themes/default/security/register.html.twig
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,60 @@
 | 
				
			|||||||
 | 
					{% extends '@default/base.html.twig' %}
 | 
				
			||||||
 | 
					{% form_theme registrationForm _self %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block title %}Register{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block form_row %}
 | 
				
			||||||
 | 
					    {%- set widget_attr = {} -%}
 | 
				
			||||||
 | 
					    {%- if help is not empty -%}
 | 
				
			||||||
 | 
					        {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%}
 | 
				
			||||||
 | 
					    {%- endif -%}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {{- form_label(form, null, {
 | 
				
			||||||
 | 
					        label_attr: { class: 'sr-only' }
 | 
				
			||||||
 | 
					    }) -}}
 | 
				
			||||||
 | 
					    {{- form_errors(form) -}}
 | 
				
			||||||
 | 
					    {{- form_widget(form, widget_attr) -}}
 | 
				
			||||||
 | 
					    {{- form_help(form) -}}
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block body %}
 | 
				
			||||||
 | 
					    {% for flash_error in app.flashes('verify_email_error') %}
 | 
				
			||||||
 | 
					        <div class="alert alert-danger" role="alert">{{ flash_error }}</div>
 | 
				
			||||||
 | 
					    {% endfor %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <div class="container rounded">
 | 
				
			||||||
 | 
					        <div class="row">
 | 
				
			||||||
 | 
					            <div class="login-form bg-dark mt-4 p-4">
 | 
				
			||||||
 | 
					                <h1 class="h3 mb-3 font-weight-normal">Register</h1>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                {{ form_start(registrationForm, {
 | 
				
			||||||
 | 
					                    attr: { class: 'form-signin' }
 | 
				
			||||||
 | 
					                }) }}
 | 
				
			||||||
 | 
					                <input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}">
 | 
				
			||||||
 | 
					                {{ form_row(registrationForm.username, {
 | 
				
			||||||
 | 
					                    attr: { placeholder: 'User name' }
 | 
				
			||||||
 | 
					                }) }}
 | 
				
			||||||
 | 
					                {{ form_row(registrationForm.email, {
 | 
				
			||||||
 | 
					                    attr: { placeholder: 'eMail' }
 | 
				
			||||||
 | 
					                }) }}
 | 
				
			||||||
 | 
					                {{ form_row(registrationForm.password.first, {
 | 
				
			||||||
 | 
					                    attr: { placeholder: 'Password'}
 | 
				
			||||||
 | 
					                }) }}
 | 
				
			||||||
 | 
					                {{ form_row(registrationForm.password.second, {
 | 
				
			||||||
 | 
					                    attr: { placeholder: 'Confirm password'}
 | 
				
			||||||
 | 
					                }) }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                {{ form_row(registrationForm.agreeTerms) }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                <button type="submit" class="btn btn-primary float-end">Register</button>
 | 
				
			||||||
 | 
					                {{ form_end(registrationForm) }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					{% extends '@default/base.html.twig' %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block title %}Registration finished{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block body %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <div class="container rounded">
 | 
				
			||||||
 | 
					        <div class="row">
 | 
				
			||||||
 | 
					            <div class="login-form bg-dark mt-4 p-4">
 | 
				
			||||||
 | 
					                <h1 class="h3 mb-3 font-weight-normal">Registration finished</h1>
 | 
				
			||||||
 | 
					                <p>You'll receive an email soon to confirm your identity.</p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										12
									
								
								templates/themes/default/security/reset_password.html.twig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								templates/themes/default/security/reset_password.html.twig
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					{% extends '@default/base.html.twig' %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block title %}Reset your password{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block body %}
 | 
				
			||||||
 | 
					    <h1>Reset your password</h1>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {{ form_start(resetForm) }}
 | 
				
			||||||
 | 
					        {{ form_row(resetForm.plainPassword) }}
 | 
				
			||||||
 | 
					        <button class="btn btn-primary">Reset password</button>
 | 
				
			||||||
 | 
					    {{ form_end(resetForm) }}
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
{% extends '../themes/default/base.html.twig' %}
 | 
					{% extends '@default/base.html.twig' %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% block title %}
 | 
					{% block title %}
 | 
				
			||||||
    Profile of {{ user.username }}
 | 
					    Profile of {{ user.username }}
 | 
				
			||||||
@@ -13,38 +13,30 @@
 | 
				
			|||||||
                    <img class="rounded-circle mt-5"
 | 
					                    <img class="rounded-circle mt-5"
 | 
				
			||||||
                         width="150px"
 | 
					                         width="150px"
 | 
				
			||||||
                         src=" {{ asset('build/images/tracer_schmolle150x150.png') }}" alt="profile image">
 | 
					                         src=" {{ asset('build/images/tracer_schmolle150x150.png') }}" alt="profile image">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    <span class="font-weight-bold">{{ user.username }}</span>
 | 
					                    <span class="font-weight-bold">{{ user.username }}</span>
 | 
				
			||||||
                    <span class="text-white-50"><i class="fa fa-lg fa-envelope me-1"></i>{{ user.email }}</span>
 | 
					                    <span class="text-white-50"><i class="fa fa-lg fa-envelope me-1"></i>{{ user.email }}</span>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
            <div class="col-md-5 border-right">
 | 
					            <div class="col-md-5 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">
 | 
				
			||||||
                        <div class="col-md-6">
 | 
					                        {{ form_row(userForm.username) }}
 | 
				
			||||||
                            <label class="labels" for="first-name">First Name</label>
 | 
					                        {{ form_row(userForm.firstName) }}
 | 
				
			||||||
                            <input type="text" id="first-name" class="form-control" placeholder="First Name" value="{{ user.firstName }}">
 | 
					                        {{ form_row(userForm.lastName) }}
 | 
				
			||||||
 | 
					                        {{ form_row(userForm.email) }}
 | 
				
			||||||
 | 
					                        {{ form_row(userForm.newPassword.first) }}
 | 
				
			||||||
 | 
					                        {{ form_row(userForm.newPassword.second) }}
 | 
				
			||||||
 | 
					                        {{  form_rest(userForm) }}
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
 | 
					                    <div class="mb-5 text-center float-end">
 | 
				
			||||||
                        <div class="col-md-6">
 | 
					                        <button class="btn btn-primary profile-button" type="submit">Save Profile</button>
 | 
				
			||||||
                            <label class="labels" for="last-name">Last Name</label>
 | 
					 | 
				
			||||||
                            <input type="text" id="last-name" class="form-control" value="{{ user.lastName }}" placeholder="Last Name">
 | 
					 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
 | 
					 | 
				
			||||||
                    <div class="col-md-6">
 | 
					 | 
				
			||||||
                        <label class="labels" for="username">Username</label>
 | 
					 | 
				
			||||||
                        <input type="text" class="form-control" id="username" placeholder="eMail address" value="{{ user.email }}">
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    <!--
 | 
					 | 
				
			||||||
                    <div class="mt-5 text-center">
 | 
					 | 
				
			||||||
                        <button class="btn btn-primary profile-button" type="button">Save Profile</button>
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                    -->
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
{% extends '../themes/default/base.html.twig' %}
 | 
					{% extends '@default/base.html.twig' %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% block title %}
 | 
					{% block title %}
 | 
				
			||||||
    Profile of {{ user.username }}
 | 
					    Profile of {{ user.username }}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user