parent
204fa572e6
commit
56812804bd
@ -1,54 +1,20 @@ |
|||||||
# ---> Symfony |
*.sql |
||||||
# Cache and logs (Symfony2) |
*.back |
||||||
/app/cache/* |
*.tar.gz |
||||||
/app/logs/* |
###> symfony/framework-bundle ### |
||||||
!app/cache/.gitkeep |
/.env.local |
||||||
!app/logs/.gitkeep |
/.env.local.php |
||||||
|
/.env.*.local |
||||||
# Email spool folder |
/config/secrets/prod/prod.decrypt.private.php |
||||||
/app/spool/* |
/public/bundles/ |
||||||
|
/var/ |
||||||
# Cache, session files and logs (Symfony3) |
|
||||||
/var/cache/* |
|
||||||
/var/logs/* |
|
||||||
/var/sessions/* |
|
||||||
!var/cache/.gitkeep |
|
||||||
!var/logs/.gitkeep |
|
||||||
!var/sessions/.gitkeep |
|
||||||
|
|
||||||
# Logs (Symfony4) |
|
||||||
/var/log/* |
|
||||||
!var/log/.gitkeep |
|
||||||
|
|
||||||
# Parameters |
|
||||||
/app/config/parameters.yml |
|
||||||
/app/config/parameters.ini |
|
||||||
|
|
||||||
# Managed by Composer |
|
||||||
/app/bootstrap.php.cache |
|
||||||
/var/bootstrap.php.cache |
|
||||||
/bin/* |
|
||||||
!bin/console |
|
||||||
!bin/symfony_requirements |
|
||||||
/vendor/ |
/vendor/ |
||||||
|
###< symfony/framework-bundle ### |
||||||
# Assets and user uploads |
.idea |
||||||
/web/bundles/ |
|
||||||
/web/uploads/ |
###> symfony/webpack-encore-bundle ### |
||||||
|
/node_modules/ |
||||||
# PHPUnit |
/public/build/ |
||||||
/app/phpunit.xml |
npm-debug.log |
||||||
/phpunit.xml |
yarn-error.log |
||||||
|
###< symfony/webpack-encore-bundle ### |
||||||
# Build data |
|
||||||
/build/ |
|
||||||
|
|
||||||
# Composer PHAR |
|
||||||
/composer.phar |
|
||||||
|
|
||||||
# Backup entities generated with doctrine:generate:entities command |
|
||||||
**/Entity/*~ |
|
||||||
|
|
||||||
# Embedded web-server pid file |
|
||||||
/.web-server-pid |
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,15 @@ |
|||||||
|
/* |
||||||
|
* Welcome to your app's main JavaScript file! |
||||||
|
* |
||||||
|
* We recommend including the built version of this JavaScript file |
||||||
|
* (and its CSS file) in your base layout (base.html.twig). |
||||||
|
*/ |
||||||
|
|
||||||
|
// any CSS you import will output into a single css file (app.css in this case)
|
||||||
|
import './styles/app.scss'; |
||||||
|
|
||||||
|
// start the Stimulus application
|
||||||
|
import './bootstrap'; |
||||||
|
import bsCustomFileInput from "bs-custom-file-input"; |
||||||
|
|
||||||
|
bsCustomFileInput.init(); |
||||||
@ -0,0 +1,11 @@ |
|||||||
|
import { startStimulusApp } from '@symfony/stimulus-bridge'; |
||||||
|
|
||||||
|
// Registers Stimulus controllers from controllers.json and in the controllers/ directory
|
||||||
|
export const app = startStimulusApp(require.context( |
||||||
|
'@symfony/stimulus-bridge/lazy-controller-loader!./controllers', |
||||||
|
true, |
||||||
|
/\.(j|t)sx?$/ |
||||||
|
)); |
||||||
|
|
||||||
|
// register any custom, 3rd party controllers here
|
||||||
|
// app.register('some_controller_name', SomeImportedController);
|
||||||
@ -0,0 +1,4 @@ |
|||||||
|
{ |
||||||
|
"controllers": [], |
||||||
|
"entrypoints": [] |
||||||
|
} |
||||||
@ -0,0 +1,16 @@ |
|||||||
|
import { Controller } from 'stimulus'; |
||||||
|
|
||||||
|
/* |
||||||
|
* This is an example Stimulus controller! |
||||||
|
* |
||||||
|
* Any element with a data-controller="hello" attribute will cause |
||||||
|
* this controller to be executed. The name "hello" comes from the filename: |
||||||
|
* hello_controller.js -> "hello" |
||||||
|
* |
||||||
|
* Delete this file or adapt it for your use! |
||||||
|
*/ |
||||||
|
export default class extends Controller { |
||||||
|
connect() { |
||||||
|
this.element.textContent = 'Hello Stimulus! Edit me in assets/controllers/hello_controller.js'; |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,125 @@ |
|||||||
|
// Colors |
||||||
|
|
||||||
|
$white: #fff; |
||||||
|
$gray-100: #f5f5f5; |
||||||
|
$gray-200: #e9ecef; |
||||||
|
$gray-300: #ddd; |
||||||
|
$gray-400: #ced4da; |
||||||
|
$gray-500: #adb5bd; |
||||||
|
$gray-600: #868e96; |
||||||
|
$gray-700: #495057; |
||||||
|
$gray-800: #343a40; |
||||||
|
$gray-900: #212529; |
||||||
|
$black: #000; |
||||||
|
|
||||||
|
$blue: #175fc9; |
||||||
|
$pink: #ff737c; |
||||||
|
$red: #d9534f; |
||||||
|
$yellow: #fcee60; |
||||||
|
$orange: #ffae73; |
||||||
|
$green: #02B875; |
||||||
|
$teal: #55e7cc; |
||||||
|
$cyan: #8ce6ff; |
||||||
|
|
||||||
|
$primary: $blue; |
||||||
|
$secondary: #666; |
||||||
|
$success: $green; |
||||||
|
$info: $cyan; |
||||||
|
$warning: $yellow; |
||||||
|
$danger: $red; |
||||||
|
$light: $gray-100; |
||||||
|
$dark: $gray-800; |
||||||
|
|
||||||
|
$theme-colors: ( |
||||||
|
"blue": $blue, |
||||||
|
"soft-blue": rgba(23, 95, 201, 0.15), |
||||||
|
"pink": $pink, |
||||||
|
"yellow": $yellow, |
||||||
|
"orange": $orange, |
||||||
|
"soft-orange": rgba(255, 174, 115, 0.15), |
||||||
|
"teal": $teal, |
||||||
|
"cyan": $cyan, |
||||||
|
); |
||||||
|
|
||||||
|
$yiq-contrasted-threshold: 190; |
||||||
|
|
||||||
|
$text-muted: #999; |
||||||
|
|
||||||
|
// Shadow |
||||||
|
|
||||||
|
$box-shadow: 0 15px 30px 0 rgba(0, 0, 0, 0.1); |
||||||
|
|
||||||
|
// Grid |
||||||
|
|
||||||
|
$spacer: 1rem; |
||||||
|
$spacers: ( |
||||||
|
0: 0, |
||||||
|
1: ($spacer * .25), |
||||||
|
2: ($spacer * .5), |
||||||
|
3: $spacer, |
||||||
|
4: ($spacer * 1.5), |
||||||
|
5: ($spacer * 3), |
||||||
|
6: ($spacer * 4.5), |
||||||
|
7: ($spacer * 6) |
||||||
|
); |
||||||
|
|
||||||
|
// Body |
||||||
|
|
||||||
|
$body-bg: $white; |
||||||
|
$body-color: $black; |
||||||
|
|
||||||
|
// Fonts |
||||||
|
|
||||||
|
$font-family-base: 'Open Sans', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; |
||||||
|
$font-family-title: Georgia, Times, 'New Roman', serif; |
||||||
|
|
||||||
|
$font-size-base: 1rem; |
||||||
|
|
||||||
|
$font-weight-normal: 400; |
||||||
|
$font-weight-medium: 500; |
||||||
|
$font-weight-bold: 600; |
||||||
|
|
||||||
|
// Headings |
||||||
|
|
||||||
|
$headings-font-family: $font-family-title; |
||||||
|
$headings-font-weight: $font-weight-normal; |
||||||
|
$headings-color: $gray-900; |
||||||
|
|
||||||
|
// Navbar |
||||||
|
|
||||||
|
$navbar-light-brand-color: $black; |
||||||
|
$navbar-light-brand-hover-color: $primary; |
||||||
|
$navbar-light-hover-color: $primary; |
||||||
|
|
||||||
|
// Dropdown |
||||||
|
|
||||||
|
$dropdown-link-hover-bg: $gray-200; |
||||||
|
|
||||||
|
// Tables |
||||||
|
|
||||||
|
$table-border-color: rgba(0, 0, 0, 0.1); |
||||||
|
|
||||||
|
// Forms and buttons |
||||||
|
|
||||||
|
$input-border-color: rgba(0, 0, 0, .1); |
||||||
|
$input-group-addon-bg: $gray-200; |
||||||
|
$btn-font-weight: $font-weight-bold; |
||||||
|
$custom-control-indicator-size: 1.3rem; |
||||||
|
|
||||||
|
// Tooltips |
||||||
|
|
||||||
|
$tooltip-font-size: 11px; |
||||||
|
|
||||||
|
// Badges |
||||||
|
|
||||||
|
$badge-font-weight: normal; |
||||||
|
$badge-padding-y: 0.6em; |
||||||
|
$badge-padding-x: 1.2em; |
||||||
|
|
||||||
|
// Alerts |
||||||
|
|
||||||
|
$alert-border-width: 0; |
||||||
|
|
||||||
|
// Cards |
||||||
|
|
||||||
|
$card-border-width: 0; |
||||||
@ -0,0 +1,66 @@ |
|||||||
|
@import './_variables'; |
||||||
|
@import '~bootstrap/scss/bootstrap'; |
||||||
|
|
||||||
|
body { |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
height: 100vh; |
||||||
|
} |
||||||
|
main { |
||||||
|
flex: 1; |
||||||
|
} |
||||||
|
|
||||||
|
// Darken buttons |
||||||
|
@each $color, $value in $theme-colors { |
||||||
|
.btn-#{$color} { |
||||||
|
@include button-variant($value, $value, darken($value, 10%)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.navbar-brand { |
||||||
|
font-family: $font-family-title; |
||||||
|
font-weight: $font-weight-normal; |
||||||
|
font-size: 1.8rem; |
||||||
|
} |
||||||
|
|
||||||
|
.navbar-brand, .nav-link { |
||||||
|
transition: all .15s; |
||||||
|
} |
||||||
|
|
||||||
|
.nav-conference { |
||||||
|
display: inline-block; |
||||||
|
padding: 5px 10px; |
||||||
|
color: #666; |
||||||
|
text-transform: uppercase; |
||||||
|
font-weight: bold; |
||||||
|
font-size: 0.8rem; |
||||||
|
} |
||||||
|
|
||||||
|
.lift { |
||||||
|
transition: box-shadow .25s ease,transform .25s ease; |
||||||
|
|
||||||
|
&:focus, &:hover { |
||||||
|
box-shadow: 0 1rem 2.5rem rgba(22,28,45,.1),0 .5rem 1rem -.75rem rgba(22,28,45,.1)!important; |
||||||
|
transform: translate3d(0, -4px, 0); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.comment-img { |
||||||
|
width: 250px; |
||||||
|
height: 150px; |
||||||
|
|
||||||
|
img { |
||||||
|
max-width: 250px; |
||||||
|
max-height: 150px; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.comment-text { |
||||||
|
font-size: 12px; |
||||||
|
line-height: 15px; |
||||||
|
} |
||||||
|
|
||||||
|
footer { |
||||||
|
background: #18171b; |
||||||
|
} |
||||||
|
|
||||||
@ -0,0 +1,86 @@ |
|||||||
|
{ |
||||||
|
"type": "project", |
||||||
|
"license": "proprietary", |
||||||
|
"require": { |
||||||
|
"php": "^7.4", |
||||||
|
"ext-ctype": "*", |
||||||
|
"ext-iconv": "*", |
||||||
|
"composer/package-versions-deprecated": "1.11.99.1", |
||||||
|
"doctrine/annotations": "^1.13", |
||||||
|
"doctrine/doctrine-bundle": "^2.3", |
||||||
|
"doctrine/doctrine-migrations-bundle": "^3.1", |
||||||
|
"doctrine/orm": "^2.8", |
||||||
|
"easycorp/easyadmin-bundle": "^2.0", |
||||||
|
"sensio/framework-extra-bundle": "^6.1", |
||||||
|
"symfony/console": "5.0.*", |
||||||
|
"symfony/dotenv": "5.0.*", |
||||||
|
"symfony/flex": "^1.3.1", |
||||||
|
"symfony/framework-bundle": "5.0.*", |
||||||
|
"symfony/mailer": "5.0.*", |
||||||
|
"symfony/proxy-manager-bridge": "5.0.*", |
||||||
|
"symfony/security-bundle": "5.0.*", |
||||||
|
"symfony/webpack-encore-bundle": "^1.12", |
||||||
|
"symfony/yaml": "5.0.*", |
||||||
|
"symfonycasts/reset-password-bundle": "^1.9" |
||||||
|
}, |
||||||
|
"config": { |
||||||
|
"preferred-install": { |
||||||
|
"*": "dist" |
||||||
|
}, |
||||||
|
"sort-packages": true, |
||||||
|
"allow-plugins": { |
||||||
|
"composer/package-versions-deprecated": true, |
||||||
|
"symfony/flex": true |
||||||
|
} |
||||||
|
}, |
||||||
|
"autoload": { |
||||||
|
"psr-4": { |
||||||
|
"App\\": "src/" |
||||||
|
} |
||||||
|
}, |
||||||
|
"autoload-dev": { |
||||||
|
"psr-4": { |
||||||
|
"App\\Tests\\": "tests/" |
||||||
|
} |
||||||
|
}, |
||||||
|
"replace": { |
||||||
|
"paragonie/random_compat": "2.*", |
||||||
|
"symfony/polyfill-ctype": "*", |
||||||
|
"symfony/polyfill-iconv": "*", |
||||||
|
"symfony/polyfill-php72": "*", |
||||||
|
"symfony/polyfill-php71": "*", |
||||||
|
"symfony/polyfill-php70": "*", |
||||||
|
"symfony/polyfill-php56": "*" |
||||||
|
}, |
||||||
|
"scripts": { |
||||||
|
"auto-scripts": { |
||||||
|
"cache:clear": "symfony-cmd", |
||||||
|
"assets:install %PUBLIC_DIR%": "symfony-cmd" |
||||||
|
}, |
||||||
|
"post-install-cmd": [ |
||||||
|
"@auto-scripts" |
||||||
|
], |
||||||
|
"post-update-cmd": [ |
||||||
|
"@auto-scripts" |
||||||
|
] |
||||||
|
}, |
||||||
|
"conflict": { |
||||||
|
"symfony/symfony": "*" |
||||||
|
}, |
||||||
|
"extra": { |
||||||
|
"symfony": { |
||||||
|
"allow-contrib": false, |
||||||
|
"require": "5.0.*" |
||||||
|
} |
||||||
|
}, |
||||||
|
"require-dev": { |
||||||
|
"symfony/debug-bundle": "^5.0", |
||||||
|
"symfony/google-mailer": "5.0.*", |
||||||
|
"symfony/maker-bundle": "^1.31", |
||||||
|
"symfony/monolog-bundle": "^3.0", |
||||||
|
"symfony/stopwatch": "^5.0", |
||||||
|
"symfony/twig-bundle": "^5.0", |
||||||
|
"symfony/var-dumper": "^5.0", |
||||||
|
"symfony/web-profiler-bundle": "^5.0" |
||||||
|
} |
||||||
|
} |
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,23 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
use Symfony\Component\Dotenv\Dotenv; |
||||||
|
|
||||||
|
require dirname(__DIR__).'/vendor/autoload.php'; |
||||||
|
|
||||||
|
if (!class_exists(Dotenv::class)) { |
||||||
|
throw new LogicException('Please run "composer require symfony/dotenv" to load the ".env" files configuring the application.'); |
||||||
|
} |
||||||
|
|
||||||
|
// Load cached env vars if the .env.local.php file exists |
||||||
|
// Run "composer dump-env prod" to create it (requires symfony/flex >=1.2) |
||||||
|
if (is_array($env = @include dirname(__DIR__).'/.env.local.php') && (!isset($env['APP_ENV']) || ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? $env['APP_ENV']) === $env['APP_ENV'])) { |
||||||
|
(new Dotenv(false))->populate($env); |
||||||
|
} else { |
||||||
|
// load all the .env files |
||||||
|
(new Dotenv(false))->loadEnv(dirname(__DIR__).'/.env'); |
||||||
|
} |
||||||
|
|
||||||
|
$_SERVER += $_ENV; |
||||||
|
$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? null) ?: 'dev'; |
||||||
|
$_SERVER['APP_DEBUG'] = $_SERVER['APP_DEBUG'] ?? $_ENV['APP_DEBUG'] ?? 'prod' !== $_SERVER['APP_ENV']; |
||||||
|
$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = (int) $_SERVER['APP_DEBUG'] || filter_var($_SERVER['APP_DEBUG'], FILTER_VALIDATE_BOOLEAN) ? '1' : '0'; |
||||||
@ -0,0 +1,17 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
return [ |
||||||
|
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true], |
||||||
|
Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true], |
||||||
|
Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], |
||||||
|
Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true], |
||||||
|
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], |
||||||
|
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true], |
||||||
|
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true], |
||||||
|
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true], |
||||||
|
Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true], |
||||||
|
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], |
||||||
|
EasyCorp\Bundle\EasyAdminBundle\EasyAdminBundle::class => ['all' => true], |
||||||
|
SymfonyCasts\Bundle\ResetPassword\SymfonyCastsResetPasswordBundle::class => ['all' => true], |
||||||
|
Symfony\WebpackEncoreBundle\WebpackEncoreBundle::class => ['all' => true], |
||||||
|
]; |
||||||
@ -0,0 +1,3 @@ |
|||||||
|
framework: |
||||||
|
assets: |
||||||
|
json_manifest_path: '%kernel.project_dir%/public/build/manifest.json' |
||||||
@ -0,0 +1,19 @@ |
|||||||
|
framework: |
||||||
|
cache: |
||||||
|
# Unique name of your app: used to compute stable namespaces for cache keys. |
||||||
|
#prefix_seed: your_vendor_name/app_name |
||||||
|
|
||||||
|
# The "app" cache stores to the filesystem by default. |
||||||
|
# The data in this cache should persist between deploys. |
||||||
|
# Other options include: |
||||||
|
|
||||||
|
# Redis |
||||||
|
#app: cache.adapter.redis |
||||||
|
#default_redis_provider: redis://localhost |
||||||
|
|
||||||
|
# APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues) |
||||||
|
#app: cache.adapter.apcu |
||||||
|
|
||||||
|
# Namespaced pools use the above "app" backend by default |
||||||
|
#pools: |
||||||
|
#my.dedicated.cache: null |
||||||
@ -0,0 +1,4 @@ |
|||||||
|
debug: |
||||||
|
# Forwards VarDumper Data clones to a centralized server allowing to inspect dumps on CLI or in your browser. |
||||||
|
# See the "server:dump" command to start a new server. |
||||||
|
dump_destination: "tcp://%env(VAR_DUMPER_SERVER)%" |
||||||
@ -0,0 +1,19 @@ |
|||||||
|
monolog: |
||||||
|
handlers: |
||||||
|
main: |
||||||
|
type: stream |
||||||
|
path: "%kernel.logs_dir%/%kernel.environment%.log" |
||||||
|
level: debug |
||||||
|
channels: ["!event"] |
||||||
|
# uncomment to get logging in your browser |
||||||
|
# you may have to allow bigger header sizes in your Web server configuration |
||||||
|
#firephp: |
||||||
|
# type: firephp |
||||||
|
# level: info |
||||||
|
#chromephp: |
||||||
|
# type: chromephp |
||||||
|
# level: info |
||||||
|
console: |
||||||
|
type: console |
||||||
|
process_psr_3_messages: false |
||||||
|
channels: ["!event", "!doctrine", "!console"] |
||||||
@ -0,0 +1,6 @@ |
|||||||
|
web_profiler: |
||||||
|
toolbar: true |
||||||
|
intercept_redirects: false |
||||||
|
|
||||||
|
framework: |
||||||
|
profiler: { only_exceptions: false } |
||||||
@ -0,0 +1,18 @@ |
|||||||
|
doctrine: |
||||||
|
dbal: |
||||||
|
url: '%env(resolve:DATABASE_URL)%' |
||||||
|
|
||||||
|
# IMPORTANT: You MUST configure your server version, |
||||||
|
# either here or in the DATABASE_URL env var (see .env file) |
||||||
|
#server_version: '13' |
||||||
|
orm: |
||||||
|
auto_generate_proxy_classes: true |
||||||
|
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware |
||||||
|
auto_mapping: true |
||||||
|
mappings: |
||||||
|
App: |
||||||
|
is_bundle: false |
||||||
|
type: annotation |
||||||
|
dir: '%kernel.project_dir%/src/Entity' |
||||||
|
prefix: 'App\Entity' |
||||||
|
alias: App |
||||||
@ -0,0 +1,6 @@ |
|||||||
|
doctrine_migrations: |
||||||
|
migrations_paths: |
||||||
|
# namespace is arbitrary but should be different from App\Migrations |
||||||
|
# as migrations classes should NOT be autoloaded |
||||||
|
'DoctrineMigrations': '%kernel.project_dir%/migrations' |
||||||
|
enable_profiler: '%kernel.debug%' |
||||||
@ -0,0 +1,29 @@ |
|||||||
|
easy_admin: |
||||||
|
entities: |
||||||
|
User: |
||||||
|
class: App\Entity\User |
||||||
|
label: User |
||||||
|
list: |
||||||
|
fields: |
||||||
|
- {property: 'username'} |
||||||
|
- {property: 'roles', type: 'App\Form\Type\SfyCASRoleType'} |
||||||
|
- {property: 'email', type: 'email'} |
||||||
|
edit: |
||||||
|
fields: |
||||||
|
- {property: 'username'} |
||||||
|
- {property: 'roles', type: 'App\Form\Type\SfyCASRoleType'} |
||||||
|
- {property: 'email', type: 'email'} |
||||||
|
#- {property: 'password', type: 'password', type_options: { required: false }} |
||||||
|
- { property: plainPassword, type: 'password', type_options: { required: false } } |
||||||
|
new: |
||||||
|
fields: |
||||||
|
- {property: 'username'} |
||||||
|
- {property: 'email', type: 'email'} |
||||||
|
- {property: 'password', type: 'password', type_options: { required: false }} |
||||||
|
# plain password |
||||||
|
- { property: plainPassword, type: 'password', type_options: { required: false } } |
||||||
|
# - App\Entity\User |
||||||
|
# # List the entity cla ss name you want to manage |
||||||
|
# - App\Entity\Product |
||||||
|
# - App\Entity\Category |
||||||
|
# - App\Entity\User |
||||||
@ -0,0 +1,17 @@ |
|||||||
|
# see https://symfony.com/doc/current/reference/configuration/framework.html |
||||||
|
framework: |
||||||
|
secret: '%env(APP_SECRET)%' |
||||||
|
#csrf_protection: true |
||||||
|
#http_method_override: true |
||||||
|
|
||||||
|
# Enables session support. Note that the session will ONLY be started if you read or write from it. |
||||||
|
# Remove or comment this section to explicitly disable session support. |
||||||
|
session: |
||||||
|
handler_id: null |
||||||
|
cookie_secure: auto |
||||||
|
cookie_samesite: lax |
||||||
|
|
||||||
|
#esi: true |
||||||
|
#fragments: true |
||||||
|
php_errors: |
||||||
|
log: true |
||||||
@ -0,0 +1,3 @@ |
|||||||
|
framework: |
||||||
|
mailer: |
||||||
|
dsn: '%env(MAILER_DSN)%' |
||||||
@ -0,0 +1,8 @@ |
|||||||
|
# As of Symfony 5.1, deprecations are logged in the dedicated "deprecation" channel when it exists |
||||||
|
#monolog: |
||||||
|
# channels: [deprecation] |
||||||
|
# handlers: |
||||||
|
# deprecation: |
||||||
|
# type: stream |
||||||
|
# channels: [deprecation] |
||||||
|
# path: php://stderr |
||||||
@ -0,0 +1,20 @@ |
|||||||
|
doctrine: |
||||||
|
orm: |
||||||
|
auto_generate_proxy_classes: false |
||||||
|
metadata_cache_driver: |
||||||
|
type: pool |
||||||
|
pool: doctrine.system_cache_pool |
||||||
|
query_cache_driver: |
||||||
|
type: pool |
||||||
|
pool: doctrine.system_cache_pool |
||||||
|
result_cache_driver: |
||||||
|
type: pool |
||||||
|
pool: doctrine.result_cache_pool |
||||||
|
|
||||||
|
framework: |
||||||
|
cache: |
||||||
|
pools: |
||||||
|
doctrine.result_cache_pool: |
||||||
|
adapter: cache.app |
||||||
|
doctrine.system_cache_pool: |
||||||
|
adapter: cache.system |
||||||
@ -0,0 +1,17 @@ |
|||||||
|
monolog: |
||||||
|
handlers: |
||||||
|
main: |
||||||
|
type: fingers_crossed |
||||||
|
action_level: error |
||||||
|
handler: nested |
||||||
|
excluded_http_codes: [404, 405] |
||||||
|
buffer_size: 50 # How many messages should be saved? Prevent memory leaks |
||||||
|
nested: |
||||||
|
type: stream |
||||||
|
path: php://stderr |
||||||
|
level: debug |
||||||
|
formatter: monolog.formatter.json |
||||||
|
console: |
||||||
|
type: console |
||||||
|
process_psr_3_messages: false |
||||||
|
channels: ["!event", "!doctrine"] |
||||||
@ -0,0 +1,3 @@ |
|||||||
|
framework: |
||||||
|
router: |
||||||
|
strict_requirements: null |
||||||
@ -0,0 +1,4 @@ |
|||||||
|
#webpack_encore: |
||||||
|
# Cache the entrypoints.json (rebuild Symfony's cache when entrypoints.json changes) |
||||||
|
# Available in version 1.2 |
||||||
|
#cache: true |
||||||
@ -0,0 +1,5 @@ |
|||||||
|
symfonycasts_reset_password: |
||||||
|
request_password_repository: App\Repository\ResetPasswordRequestRepository |
||||||
|
lifetime: 3600 |
||||||
|
throttle_limit: 5 |
||||||
|
enable_garbage_collection: true |
||||||
@ -0,0 +1,3 @@ |
|||||||
|
framework: |
||||||
|
router: |
||||||
|
utf8: true |
||||||
@ -0,0 +1,38 @@ |
|||||||
|
security: |
||||||
|
encoders: |
||||||
|
App\Entity\User: |
||||||
|
algorithm: auto |
||||||
|
|
||||||
|
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers |
||||||
|
providers: |
||||||
|
# used to reload user from session & other features (e.g. switch_user) |
||||||
|
app_user_provider: |
||||||
|
entity: |
||||||
|
class: App\Entity\User |
||||||
|
property: username |
||||||
|
firewalls: |
||||||
|
dev: |
||||||
|
pattern: ^/(_(profiler|wdt)|css|images|js)/ |
||||||
|
security: false |
||||||
|
main: |
||||||
|
anonymous: lazy |
||||||
|
guard: |
||||||
|
authenticators: |
||||||
|
- App\Security\AppAuthenticator |
||||||
|
logout: |
||||||
|
path: app_logout |
||||||
|
# where to redirect after logout |
||||||
|
# target: app_any_route |
||||||
|
|
||||||
|
# activate different ways to authenticate |
||||||
|
# https://symfony.com/doc/current/security.html#firewalls-authentication |
||||||
|
|
||||||
|
# https://symfony.com/doc/current/security/impersonating_user.html |
||||||
|
# switch_user: true |
||||||
|
|
||||||
|
# Easy way to control access for large sections of your site |
||||||
|
# Note: Only the *first* access control that matches will be used |
||||||
|
access_control: |
||||||
|
- { path: ^/admin, roles: ROLE_ADMIN } |
||||||
|
#- { path: ^/cas/login, roles: ROLE_ADMIN } |
||||||
|
# - { path: ^/profile, roles: ROLE_USER } |
||||||
@ -0,0 +1,3 @@ |
|||||||
|
sensio_framework_extra: |
||||||
|
router: |
||||||
|
annotations: false |
||||||
@ -0,0 +1,4 @@ |
|||||||
|
doctrine: |
||||||
|
dbal: |
||||||
|
# "TEST_TOKEN" is typically set by ParaTest |
||||||
|
dbname: 'main_test%env(default::TEST_TOKEN)%' |
||||||
@ -0,0 +1,4 @@ |
|||||||
|
framework: |
||||||
|
test: true |
||||||
|
session: |
||||||
|
storage_id: session.storage.mock_file |
||||||
@ -0,0 +1,12 @@ |
|||||||
|
monolog: |
||||||
|
handlers: |
||||||
|
main: |
||||||
|
type: fingers_crossed |
||||||
|
action_level: error |
||||||
|
handler: nested |
||||||
|
excluded_http_codes: [404, 405] |
||||||
|
channels: ["!event"] |
||||||
|
nested: |
||||||
|
type: stream |
||||||
|
path: "%kernel.logs_dir%/%kernel.environment%.log" |
||||||
|
level: debug |
||||||
@ -0,0 +1,2 @@ |
|||||||
|
twig: |
||||||
|
strict_variables: true |
||||||
@ -0,0 +1,3 @@ |
|||||||
|
framework: |
||||||
|
validation: |
||||||
|
not_compromised_password: false |
||||||
@ -0,0 +1,6 @@ |
|||||||
|
web_profiler: |
||||||
|
toolbar: false |
||||||
|
intercept_redirects: false |
||||||
|
|
||||||
|
framework: |
||||||
|
profiler: { collect: false } |
||||||
@ -0,0 +1,2 @@ |
|||||||
|
#webpack_encore: |
||||||
|
# strict_mode: false |
||||||
@ -0,0 +1,6 @@ |
|||||||
|
framework: |
||||||
|
default_locale: en |
||||||
|
translator: |
||||||
|
default_path: '%kernel.project_dir%/translations' |
||||||
|
fallbacks: |
||||||
|
- en |
||||||
@ -0,0 +1,4 @@ |
|||||||
|
twig: |
||||||
|
default_path: '%kernel.project_dir%/templates' |
||||||
|
form_themes: ['bootstrap_4_layout.html.twig'] |
||||||
|
|
||||||
@ -0,0 +1,8 @@ |
|||||||
|
framework: |
||||||
|
validation: |
||||||
|
email_validation_mode: html5 |
||||||
|
|
||||||
|
# Enables validator auto-mapping support. |
||||||
|
# For instance, basic validation constraints will be inferred from Doctrine's metadata. |
||||||
|
#auto_mapping: |
||||||
|
# App\Entity\: [] |
||||||
@ -0,0 +1,30 @@ |
|||||||
|
webpack_encore: |
||||||
|
# The path where Encore is building the assets - i.e. Encore.setOutputPath() |
||||||
|
output_path: '%kernel.project_dir%/public/build' |
||||||
|
# If multiple builds are defined (as shown below), you can disable the default build: |
||||||
|
# output_path: false |
||||||
|
|
||||||
|
# Set attributes that will be rendered on all script and link tags |
||||||
|
script_attributes: |
||||||
|
defer: true |
||||||
|
# link_attributes: |
||||||
|
|
||||||
|
# If using Encore.enableIntegrityHashes() and need the crossorigin attribute (default: false, or use 'anonymous' or 'use-credentials') |
||||||
|
# crossorigin: 'anonymous' |
||||||
|
|
||||||
|
# Preload all rendered script and link tags automatically via the HTTP/2 Link header |
||||||
|
# preload: true |
||||||
|
|
||||||
|
# Throw an exception if the entrypoints.json file is missing or an entry is missing from the data |
||||||
|
# strict_mode: false |
||||||
|
|
||||||
|
# If you have multiple builds: |
||||||
|
# builds: |
||||||
|
# pass "frontend" as the 3rg arg to the Twig functions |
||||||
|
# {{ encore_entry_script_tags('entry1', null, 'frontend') }} |
||||||
|
|
||||||
|
# frontend: '%kernel.project_dir%/public/frontend/build' |
||||||
|
|
||||||
|
# Cache the entrypoints.json (rebuild Symfony's cache when entrypoints.json changes) |
||||||
|
# Put in config/packages/prod/webpack_encore.yaml |
||||||
|
# cache: true |
||||||
@ -0,0 +1,9 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
if (file_exists(dirname(__DIR__).'/var/cache/prod/srcApp_KernelProdContainer.preload.php')) { |
||||||
|
require dirname(__DIR__).'/var/cache/prod/srcApp_KernelProdContainer.preload.php'; |
||||||
|
} |
||||||
|
|
||||||
|
if (file_exists(dirname(__DIR__).'/var/cache/prod/App_KernelProdContainer.preload.php')) { |
||||||
|
require dirname(__DIR__).'/var/cache/prod/App_KernelProdContainer.preload.php'; |
||||||
|
} |
||||||
@ -0,0 +1,3 @@ |
|||||||
|
#index: |
||||||
|
# path: / |
||||||
|
# controller: App\Controller\DefaultController::index |
||||||
@ -0,0 +1,7 @@ |
|||||||
|
controllers: |
||||||
|
resource: ../../src/Controller/ |
||||||
|
type: annotation |
||||||
|
|
||||||
|
kernel: |
||||||
|
resource: ../../src/Kernel.php |
||||||
|
type: annotation |
||||||
@ -0,0 +1,3 @@ |
|||||||
|
_errors: |
||||||
|
resource: '@FrameworkBundle/Resources/config/routing/errors.xml' |
||||||
|
prefix: /_error |
||||||
@ -0,0 +1,7 @@ |
|||||||
|
web_profiler_wdt: |
||||||
|
resource: '@WebProfilerBundle/Resources/config/routing/wdt.xml' |
||||||
|
prefix: /_wdt |
||||||
|
|
||||||
|
web_profiler_profiler: |
||||||
|
resource: '@WebProfilerBundle/Resources/config/routing/profiler.xml' |
||||||
|
prefix: /_profiler |
||||||
@ -0,0 +1,5 @@ |
|||||||
|
easy_admin_bundle: |
||||||
|
#resource: '@EasyAdminBundle/Controller/EasyAdminController.php' |
||||||
|
resource: '../../src/Controller/SfyCASAdminController.php' |
||||||
|
prefix: /admin |
||||||
|
type: annotation |
||||||
@ -0,0 +1,31 @@ |
|||||||
|
# This file is the entry point to configure your own services. |
||||||
|
# Files in the packages/ subdirectory configure your dependencies. |
||||||
|
|
||||||
|
# Put parameters here that don't need to change on each machine where the app is deployed |
||||||
|
# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration |
||||||
|
parameters: |
||||||
|
|
||||||
|
services: |
||||||
|
# default configuration for services in *this* file |
||||||
|
_defaults: |
||||||
|
autowire: true # Automatically injects dependencies in your services. |
||||||
|
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc. |
||||||
|
|
||||||
|
# makes classes in src/ available to be used as services |
||||||
|
# this creates a service per class whose id is the fully-qualified class name |
||||||
|
App\: |
||||||
|
resource: '../src/' |
||||||
|
exclude: |
||||||
|
- '../src/DependencyInjection/' |
||||||
|
- '../src/Entity/' |
||||||
|
- '../src/Kernel.php' |
||||||
|
- '../src/Tests/' |
||||||
|
|
||||||
|
# controllers are imported separately to make sure services can be injected |
||||||
|
# as action arguments even if you don't extend any base controller class |
||||||
|
App\Controller\: |
||||||
|
resource: '../src/Controller/' |
||||||
|
tags: ['controller.service_arguments'] |
||||||
|
|
||||||
|
# add more service definitions when explicit configuration is needed |
||||||
|
# please note that last definitions always *replace* previous ones |
||||||
@ -0,0 +1,25 @@ |
|||||||
|
version: '2' |
||||||
|
services: |
||||||
|
httpd: |
||||||
|
build: |
||||||
|
context: . |
||||||
|
dockerfile: ./docker/httpd |
||||||
|
ports: |
||||||
|
- 8008:80 |
||||||
|
volumes: |
||||||
|
- ./data:/var/www/html |
||||||
|
networks: |
||||||
|
- sfycas |
||||||
|
|
||||||
|
phpfpm: |
||||||
|
image: "php:7.4-fpm-buster" |
||||||
|
expose: |
||||||
|
- 9174 |
||||||
|
volumes: |
||||||
|
- ./data:/var/www/html |
||||||
|
networks: |
||||||
|
- sfycas |
||||||
|
|
||||||
|
networks: |
||||||
|
sfycas: |
||||||
|
driver: bridge |
||||||
@ -0,0 +1,35 @@ |
|||||||
|
<?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 Version20210731104520 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 cas_session ADD user_id INT DEFAULT NULL, DROP user'); |
||||||
|
$this->addSql('ALTER TABLE cas_session ADD CONSTRAINT FK_94943A4BA76ED395 FOREIGN KEY (user_id) REFERENCES `user` (id)'); |
||||||
|
$this->addSql('CREATE UNIQUE INDEX UNIQ_94943A4BA76ED395 ON cas_session (user_id)'); |
||||||
|
} |
||||||
|
|
||||||
|
public function down(Schema $schema): void |
||||||
|
{ |
||||||
|
// this down() migration is auto-generated, please modify it to your needs |
||||||
|
$this->addSql('ALTER TABLE cas_session DROP FOREIGN KEY FK_94943A4BA76ED395'); |
||||||
|
$this->addSql('DROP INDEX UNIQ_94943A4BA76ED395 ON cas_session'); |
||||||
|
$this->addSql('ALTER TABLE cas_session ADD user VARCHAR(255) CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci`, DROP user_id'); |
||||||
|
} |
||||||
|
} |
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,27 @@ |
|||||||
|
{ |
||||||
|
"devDependencies": { |
||||||
|
"@symfony/stimulus-bridge": "^2.0.0", |
||||||
|
"@symfony/webpack-encore": "^1.0.0", |
||||||
|
"bootstrap": "^5.0.2", |
||||||
|
"bs-custom-file-input": "^1.3.4", |
||||||
|
"core-js": "^3.0.0", |
||||||
|
"jquery": "^3.6.0", |
||||||
|
"popper.js": "^1.16.1", |
||||||
|
"regenerator-runtime": "^0.13.2", |
||||||
|
"stimulus": "^2.0.0", |
||||||
|
"webpack-notifier": "^1.6.0" |
||||||
|
}, |
||||||
|
"license": "UNLICENSED", |
||||||
|
"private": true, |
||||||
|
"scripts": { |
||||||
|
"dev-server": "encore dev-server", |
||||||
|
"dev": "encore dev", |
||||||
|
"watch": "encore dev --watch", |
||||||
|
"build": "encore production --progress" |
||||||
|
}, |
||||||
|
"dependencies": { |
||||||
|
"node-sass": "4", |
||||||
|
"sass-loader": "10.0.0", |
||||||
|
"yarn": "^1.22.10" |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,27 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
use App\Kernel; |
||||||
|
use Symfony\Component\ErrorHandler\Debug; |
||||||
|
use Symfony\Component\HttpFoundation\Request; |
||||||
|
|
||||||
|
require dirname(__DIR__).'/config/bootstrap.php'; |
||||||
|
|
||||||
|
if ($_SERVER['APP_DEBUG']) { |
||||||
|
umask(0000); |
||||||
|
|
||||||
|
Debug::enable(); |
||||||
|
} |
||||||
|
|
||||||
|
if ($trustedProxies = $_SERVER['TRUSTED_PROXIES'] ?? false) { |
||||||
|
Request::setTrustedProxies(explode(',', $trustedProxies), Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO); |
||||||
|
} |
||||||
|
|
||||||
|
if ($trustedHosts = $_SERVER['TRUSTED_HOSTS'] ?? false) { |
||||||
|
Request::setTrustedHosts([$trustedHosts]); |
||||||
|
} |
||||||
|
|
||||||
|
$kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']); |
||||||
|
$request = Request::createFromGlobals(); |
||||||
|
$response = $kernel->handle($request); |
||||||
|
$response->send(); |
||||||
|
$kernel->terminate($request, $response); |
||||||
@ -0,0 +1,68 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
$data = [1, 2, 3, 4, 5]; |
||||||
|
|
||||||
|
$values=array_map( |
||||||
|
fn($item) : int => $item**2, |
||||||
|
$data |
||||||
|
); |
||||||
|
|
||||||
|
print_r($values); |
||||||
|
|
||||||
|
$poem = [ |
||||||
|
'the horse and the hound and the horn that belonged to', |
||||||
|
'the farmer sowing his corn that kept', |
||||||
|
'the rooster that crowed in the morn that woke', |
||||||
|
'the priest all shaven and shorn that married', |
||||||
|
'the man all tattered and torn that kissed', |
||||||
|
'the maiden all forlorn that milked', |
||||||
|
'the cow with the crumpled horn that tossed', |
||||||
|
'the dog that worried', |
||||||
|
'the cat that killed', |
||||||
|
'the rat that ate', |
||||||
|
'the malt that lay in', |
||||||
|
'the house that Jack built', |
||||||
|
]; |
||||||
|
|
||||||
|
echo '<br>'; |
||||||
|
$parts=array_slice($poem, -3, 2); |
||||||
|
//print_r(implode("\n ", $parts)); |
||||||
|
|
||||||
|
$reduce=array_reduce( |
||||||
|
$data, |
||||||
|
fn($output, $item) => [...$output, "$item $item"], |
||||||
|
[] |
||||||
|
); |
||||||
|
|
||||||
|
|
||||||
|
$reduce=array_reduce( |
||||||
|
$data, |
||||||
|
function($output, $item) { |
||||||
|
echo $item; |
||||||
|
echo '<pre>'; |
||||||
|
print_r($output); |
||||||
|
echo '</pre>'; |
||||||
|
echo '<br><br>'; |
||||||
|
return [...$output, "$item $item"]; |
||||||
|
}, |
||||||
|
[] |
||||||
|
); |
||||||
|
|
||||||
|
$filter=array_filter( |
||||||
|
$data, |
||||||
|
fn($item) => $item % 2 == 0 |
||||||
|
); |
||||||
|
|
||||||
|
echo '<pre>'; |
||||||
|
print_r([...$data, 6, 7, 8]); |
||||||
|
print_r([$data, 6, 7, 8]); |
||||||
|
echo '</pre>'; |
||||||
|
|
||||||
|
|
||||||
|
echo '<br>'; |
||||||
|
echo '<pre>'; |
||||||
|
print_r($reduce); |
||||||
|
echo '</pre>'; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,177 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace App\Controller; |
||||||
|
|
||||||
|
use App\Entity\User; |
||||||
|
use App\Form\ChangePasswordFormType; |
||||||
|
use App\Form\ResetPasswordRequestFormType; |
||||||
|
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\Routing\Annotation\Route; |
||||||
|
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; |
||||||
|
use SymfonyCasts\Bundle\ResetPassword\Controller\ResetPasswordControllerTrait; |
||||||
|
use SymfonyCasts\Bundle\ResetPassword\Exception\ResetPasswordExceptionInterface; |
||||||
|
use SymfonyCasts\Bundle\ResetPassword\ResetPasswordHelperInterface; |
||||||
|
|
||||||
|
/** |
||||||
|
* @Route("/reset-password") |
||||||
|
*/ |
||||||
|
class ResetPasswordController extends AbstractController |
||||||
|
{ |
||||||
|
use ResetPasswordControllerTrait; |
||||||
|
|
||||||
|
private $resetPasswordHelper; |
||||||
|
|
||||||
|
public function __construct(ResetPasswordHelperInterface $resetPasswordHelper) |
||||||
|
{ |
||||||
|
$this->resetPasswordHelper = $resetPasswordHelper; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Display & process form to request a password reset. |
||||||
|
* |
||||||
|
* @Route("", name="app_forgot_password_request") |
||||||
|
*/ |
||||||
|
public function request(Request $request, MailerInterface $mailer): Response |
||||||
|
{ |
||||||
|
$form = $this->createForm(ResetPasswordRequestFormType::class); |
||||||
|
$form->handleRequest($request); |
||||||
|
|
||||||
|
if ($form->isSubmitted() && $form->isValid()) { |
||||||
|
return $this->processSendingPasswordResetEmail( |
||||||
|
$form->get('email')->getData(), |
||||||
|
$mailer |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
return $this->render('reset_password/request.html.twig', [ |
||||||
|
'requestForm' => $form->createView(), |
||||||
|
]); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Confirmation page after a user has requested a password reset. |
||||||
|
* |
||||||
|
* @Route("/check-email", name="app_check_email") |
||||||
|
*/ |
||||||
|
public function checkEmail(): Response |
||||||
|
{ |
||||||
|
// Generate a fake token if the user does not exist or someone hit this page directly. |
||||||
|
// This prevents exposing whether or not a user was found with the given email address or not |
||||||
|
if (null === ($resetToken = $this->getTokenObjectFromSession())) { |
||||||
|
$resetToken = $this->resetPasswordHelper->generateFakeResetToken(); |
||||||
|
} |
||||||
|
|
||||||
|
return $this->render('reset_password/check_email.html.twig', [ |
||||||
|
'resetToken' => $resetToken, |
||||||
|
]); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Validates and process the reset URL that the user clicked in their email. |
||||||
|
* |
||||||
|
* @Route("/reset/{token}", name="app_reset_password") |
||||||
|
*/ |
||||||
|
public function reset(Request $request, UserPasswordEncoderInterface $passwordEncoder, 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); |
||||||
|
|
||||||
|
return $this->redirectToRoute('app_reset_password'); |
||||||
|
} |
||||||
|
|
||||||
|
$token = $this->getTokenFromSession(); |
||||||
|
if (null === $token) { |
||||||
|
throw $this->createNotFoundException('No reset password token found in the URL or in the session.'); |
||||||
|
} |
||||||
|
|
||||||
|
try { |
||||||
|
$user = $this->resetPasswordHelper->validateTokenAndFetchUser($token); |
||||||
|
} catch (ResetPasswordExceptionInterface $e) { |
||||||
|
$this->addFlash('reset_password_error', sprintf( |
||||||
|
'There was a problem validating your reset request - %s', |
||||||
|
$e->getReason() |
||||||
|
)); |
||||||
|
|
||||||
|
return $this->redirectToRoute('app_forgot_password_request'); |
||||||
|
} |
||||||
|
|
||||||
|
// The token is valid; allow the user to change their password. |
||||||
|
$form = $this->createForm(ChangePasswordFormType::class); |
||||||
|
$form->handleRequest($request); |
||||||
|
|
||||||
|
if ($form->isSubmitted() && $form->isValid()) { |
||||||
|
// A password reset token should be used only once, remove it. |
||||||
|
$this->resetPasswordHelper->removeResetRequest($token); |
||||||
|
|
||||||
|
// Encode the plain password, and set it. |
||||||
|
$encodedPassword = $passwordEncoder->encodePassword( |
||||||
|
$user, |
||||||
|
$form->get('plainPassword')->getData() |
||||||
|
); |
||||||
|
|
||||||
|
$user->setPassword($encodedPassword); |
||||||
|
$this->getDoctrine()->getManager()->flush(); |
||||||
|
|
||||||
|
// The session is cleaned up after the password has been changed. |
||||||
|
$this->cleanSessionAfterReset(); |
||||||
|
|
||||||
|
return $this->redirectToRoute('app_home'); |
||||||
|
} |
||||||
|
|
||||||
|
return $this->render('reset_password/reset.html.twig', [ |
||||||
|
'resetForm' => $form->createView(), |
||||||
|
]); |
||||||
|
} |
||||||
|
|
||||||
|
private function processSendingPasswordResetEmail(string $emailFormData, MailerInterface $mailer): RedirectResponse |
||||||
|
{ |
||||||
|
$user = $this->getDoctrine()->getRepository(User::class)->findOneBy([ |
||||||
|
'email' => $emailFormData, |
||||||
|
]); |
||||||
|
|
||||||
|
// Do not reveal whether a user account was found or not. |
||||||
|
if (!$user) { |
||||||
|
return $this->redirectToRoute('app_check_email'); |
||||||
|
} |
||||||
|
|
||||||
|
try { |
||||||
|
$resetToken = $this->resetPasswordHelper->generateResetToken($user); |
||||||
|
} catch (ResetPasswordExceptionInterface $e) { |
||||||
|
// If you want to tell the user why a reset email was not sent, uncomment |
||||||
|
// the lines below and change the redirect to 'app_forgot_password_request'. |
||||||
|
// Caution: This may reveal if a user is registered or not. |
||||||
|
// |
||||||
|
// $this->addFlash('reset_password_error', sprintf( |
||||||
|
// 'There was a problem handling your password reset request - %s', |
||||||
|
// $e->getReason() |
||||||
|
// )); |
||||||
|
|
||||||
|
return $this->redirectToRoute('app_check_email'); |
||||||
|
} |
||||||
|
|
||||||
|
$email = (new TemplatedEmail()) |
||||||
|
->from(new Address('k.jouini@tyr.local', 'SfyCAS Mail Bot')) |
||||||
|
->to($user->getEmail()) |
||||||
|
->subject('Your password reset request') |
||||||
|
->htmlTemplate('reset_password/email.html.twig') |
||||||
|
->context([ |
||||||
|
'resetToken' => $resetToken, |
||||||
|
]) |
||||||
|
; |
||||||
|
|
||||||
|
$mailer->send($email); |
||||||
|
|
||||||
|
// Store the token object in session for retrieval in check-email route. |
||||||
|
$this->setTokenObjectInSession($resetToken); |
||||||
|
|
||||||
|
return $this->redirectToRoute('app_check_email'); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,38 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace App\Controller; |
||||||
|
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; |
||||||
|
use Symfony\Component\HttpFoundation\Response; |
||||||
|
use Symfony\Component\Routing\Annotation\Route; |
||||||
|
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils; |
||||||
|
|
||||||
|
class SecurityController extends AbstractController |
||||||
|
{ |
||||||
|
/** |
||||||
|
* @Route("/login", name="app_login") |
||||||
|
*/ |
||||||
|
public function login(AuthenticationUtils $authenticationUtils): Response |
||||||
|
{ |
||||||
|
if ($this->getUser()) { |
||||||
|
//return $this->redirectToRoute('target_path'); |
||||||
|
$user=$this->getUser(); |
||||||
|
echo $user->getUsername(); |
||||||
|
} |
||||||
|
|
||||||
|
// get the login error if there is one |
||||||
|
$error = $authenticationUtils->getLastAuthenticationError(); |
||||||
|
// last username entered by the user |
||||||
|
$lastUsername = $authenticationUtils->getLastUsername(); |
||||||
|
|
||||||
|
return $this->render('security/login.html.twig', ['last_username' => $lastUsername, 'error' => $error]); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @Route("/logout", name="app_logout") |
||||||
|
*/ |
||||||
|
public function logout() |
||||||
|
{ |
||||||
|
throw new \LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.'); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,71 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
|
||||||
|
namespace App\Controller; |
||||||
|
|
||||||
|
|
||||||
|
use EasyCorp\Bundle\EasyAdminBundle\Controller\EasyAdminController; |
||||||
|
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; |
||||||
|
use Psr\Log\LoggerInterface; |
||||||
|
|
||||||
|
class SfyCASAdminController extends EasyAdminController |
||||||
|
{ |
||||||
|
|
||||||
|
private UserPasswordEncoderInterface $passwordEncoder; |
||||||
|
private LoggerInterface $logger; |
||||||
|
|
||||||
|
public function __construct (UserPasswordEncoderInterface $passwordEncoder, LoggerInterface $logger) { |
||||||
|
//parent::__construct(); |
||||||
|
$this->passwordEncoder=$passwordEncoder; |
||||||
|
$this->logger=$logger; |
||||||
|
$logger->info('I am in sfycasadmincontroller'); |
||||||
|
} |
||||||
|
|
||||||
|
protected function persistUserEntity($user) |
||||||
|
{ |
||||||
|
$this->logger->info('SFYCAS persisting entity'); |
||||||
|
$this->logger->info('SFYCAS user name ' . $user->getUserName()); |
||||||
|
$this->logger->info('SFYCAS user pass ' . $user->getPassword()); |
||||||
|
$this->logger->info('SFYCAS user plain pass ' . $user->getPlainPassword()); |
||||||
|
|
||||||
|
|
||||||
|
$encodedPassword = $this->encodePassword($user, $user->getPlainPassword()); |
||||||
|
$user->setPassword($encodedPassword); |
||||||
|
|
||||||
|
parent::persistEntity($user); |
||||||
|
} |
||||||
|
|
||||||
|
protected function updateUserEntity($user) |
||||||
|
{ |
||||||
|
$this->logger->info('SFYCAS updating entity'); |
||||||
|
$this->logger->info('SFYCAS user name ' . $user->getUserName()); |
||||||
|
$this->logger->info('SFYCAS user pass ' . $user->getPassword()); |
||||||
|
$this->logger->info('SFYCAS user plain pass ' . $user->getPlainPassword()); |
||||||
|
|
||||||
|
$tmpPass=$user->getPlainPassword(); |
||||||
|
if( $tmpPass === null || trim($tmpPass) === '') { |
||||||
|
$encodedPassword = $user->getPassword(); |
||||||
|
} else { |
||||||
|
$encodedPassword = $this->encodePassword($user, $user->getPlainPassword()); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
$user->setPassword($encodedPassword); |
||||||
|
parent::updateEntity($user); |
||||||
|
} |
||||||
|
|
||||||
|
private function encodePassword($user, $password) |
||||||
|
{ |
||||||
|
/*$passwordEncoderFactory = new EncoderFactory([ |
||||||
|
User::class => new MessageDigestPasswordEncoder('sha512', true, 5000) |
||||||
|
]); |
||||||
|
|
||||||
|
$encoder = $passwordEncoderFactory->getEncoder($user); |
||||||
|
return $encoder->encodePassword($password, $user->getSalt()); |
||||||
|
*/ |
||||||
|
|
||||||
|
return $this->passwordEncoder->encodePassword($user, $password); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,98 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace App\Controller; |
||||||
|
|
||||||
|
use App\Entity\SfyCASSession; |
||||||
|
use App\Repository\SfyCASSessionRepository; |
||||||
|
use App\Service\SfyCASTicketGenerator; |
||||||
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; |
||||||
|
use Symfony\Component\HttpFoundation\RedirectResponse; |
||||||
|
use Symfony\Component\HttpFoundation\Response; |
||||||
|
use Symfony\Component\HttpFoundation\Request; |
||||||
|
use Symfony\Component\Routing\Annotation\Route; |
||||||
|
use Symfony\Component\HttpFoundation\Cookie; |
||||||
|
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils; |
||||||
|
use Psr\Log\LoggerInterface; |
||||||
|
|
||||||
|
class SfyCASLoginController extends AbstractController |
||||||
|
{ |
||||||
|
/** |
||||||
|
* @Route("/", name="app_home") |
||||||
|
*/ |
||||||
|
public function index(AuthenticationUtils $authenticationUtils, LoggerInterface $logger): Response |
||||||
|
{ |
||||||
|
if(! $this->getUser() ) { |
||||||
|
$logger->debug('SFYCAS: redirecting'); |
||||||
|
return $this->redirectToRoute('app_cas_login'); |
||||||
|
} else { |
||||||
|
$logger->debug('SFYCAS: user already authenticated'); |
||||||
|
return $this->render('sfy_cas_login/index.html.twig', [ |
||||||
|
'controller_name' => 'SfyCASLoginController', |
||||||
|
]); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* @Route("/cas/login", name="app_cas_login") |
||||||
|
*/ |
||||||
|
public function login(AuthenticationUtils $authenticationUtils, |
||||||
|
Request $request, |
||||||
|
LoggerInterface $logger, |
||||||
|
SfyCASSessionRepository $sfyCASSessionRepository, |
||||||
|
SfyCASTicketGenerator $ticketGenerator): Response |
||||||
|
{ |
||||||
|
if ($this->getUser()) { |
||||||
|
//return $this->redirectToRoute('target_path'); |
||||||
|
/*echo '<pre>'; |
||||||
|
print_r($request->query->get('service')); |
||||||
|
echo '<br>'; |
||||||
|
*/ |
||||||
|
|
||||||
|
$_casSession=$sfyCASSessionRepository->findBy(['user' => $this->getUser()]); |
||||||
|
if(is_array($_casSession) && count($_casSession) > 0) { |
||||||
|
$casSession=$_casSession[0]; |
||||||
|
$logger->info('SFYCAS Session : ' . $casSession->getTicket()); |
||||||
|
} else { |
||||||
|
$casSession=new SfyCASSession(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
$service=$request->query->get('service'); |
||||||
|
$user=$this->getUser(); |
||||||
|
//echo $user->getUsername(); |
||||||
|
$ticket=$ticketGenerator->getTicket(); |
||||||
|
|
||||||
|
$casSession->setLogin($user->getUsername()); |
||||||
|
$casSession->setUser($user); |
||||||
|
$casSession->setTicket('ST-' . $ticket); |
||||||
|
$entityManager = $this->getDoctrine()->getManager(); |
||||||
|
$entityManager->persist($casSession); |
||||||
|
$entityManager->flush(); |
||||||
|
|
||||||
|
//$response = new RedirectResponse($service. '?ticket=ST-ABFDABFE'); |
||||||
|
$response = new RedirectResponse($service. '&ticket=ST-' . $ticket); |
||||||
|
$response->headers->setCookie(Cookie::create('CASTGC', 'ST-' . $ticket)); |
||||||
|
$logger->info('SFYCAS login user : ' . $user . ' service : ' . $service); |
||||||
|
|
||||||
|
return $response; |
||||||
|
//return $this->redirect($service. '?ticket=ST-ABFDABFE'); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
// get the login error if there is one |
||||||
|
$error = $authenticationUtils->getLastAuthenticationError(); |
||||||
|
// last username entered by the user |
||||||
|
$lastUsername = $authenticationUtils->getLastUsername(); |
||||||
|
|
||||||
|
return $this->render('sfy_cas_login/caslogin.html.twig', ['last_username' => $lastUsername, 'error' => $error]); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @Route("/cas/logout", name="app_cas_logout") |
||||||
|
*/ |
||||||
|
public function logout() |
||||||
|
{ |
||||||
|
throw new \LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.'); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,36 @@ |
|||||||
|
<?php |
||||||
|
namespace App\Controller; |
||||||
|
|
||||||
|
use App\Entity\SfyCASSession; |
||||||
|
use App\Form\DataTransformer\SfyCASRoleTransformer; |
||||||
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; |
||||||
|
use Symfony\Component\HttpFoundation\Response; |
||||||
|
use Symfony\Component\HttpFoundation\Request; |
||||||
|
use Symfony\Component\Routing\Annotation\Route; |
||||||
|
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils; |
||||||
|
use Psr\Log\LoggerInterface; |
||||||
|
|
||||||
|
|
||||||
|
class SfyCASServiceValidator extends AbstractController { |
||||||
|
|
||||||
|
/** |
||||||
|
* @Route("/cas/serviceValidate", defaults={"_format"="xml"}, name="app_cas_validate") |
||||||
|
*/ |
||||||
|
public function validate(Request $request, LoggerInterface $logger): Response |
||||||
|
{ |
||||||
|
$logger->warning('SFYCAS validate ' . $request->query->get('ticket')); |
||||||
|
$ticket=$request->query->get('ticket'); |
||||||
|
|
||||||
|
$casSession = $this->getDoctrine()->getRepository(SfyCASSession::class) |
||||||
|
->findOneBy(['ticket' => $ticket]); |
||||||
|
|
||||||
|
$logger->info('SFYCAS validate found session ' . $casSession->getLogin()); |
||||||
|
|
||||||
|
return $this->render('sfy_cas_login/cas_validate.html.twig', [ |
||||||
|
'controller_name' => 'SfyCASServiceValidator', |
||||||
|
'login' => $casSession->getLogin(), |
||||||
|
'ticket' => $casSession->getTicket(), |
||||||
|
]); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,45 @@ |
|||||||
|
<?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(type="integer") |
||||||
|
*/ |
||||||
|
private $id; |
||||||
|
|
||||||
|
/** |
||||||
|
* @ORM\ManyToOne(targetEntity=User::class) |
||||||
|
* @ORM\JoinColumn(nullable=false) |
||||||
|
*/ |
||||||
|
private $user; |
||||||
|
|
||||||
|
public function __construct(object $user, \DateTimeInterface $expiresAt, string $selector, string $hashedToken) |
||||||
|
{ |
||||||
|
$this->user = $user; |
||||||
|
$this->initialize($expiresAt, $selector, $hashedToken); |
||||||
|
} |
||||||
|
|
||||||
|
public function getId(): ?int |
||||||
|
{ |
||||||
|
return $this->id; |
||||||
|
} |
||||||
|
|
||||||
|
public function getUser(): object |
||||||
|
{ |
||||||
|
return $this->user; |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,72 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace App\Entity; |
||||||
|
|
||||||
|
use App\Repository\SfyCASSessionRepository; |
||||||
|
use Doctrine\ORM\Mapping as ORM; |
||||||
|
|
||||||
|
/** |
||||||
|
* @ORM\Entity(repositoryClass=SfyCASSessionRepository::class) |
||||||
|
* @ORM\Table(name="cas_session") |
||||||
|
*/ |
||||||
|
class SfyCASSession |
||||||
|
{ |
||||||
|
/** |
||||||
|
* @ORM\Id |
||||||
|
* @ORM\GeneratedValue |
||||||
|
* @ORM\Column(type="integer") |
||||||
|
*/ |
||||||
|
private $id; |
||||||
|
|
||||||
|
/** |
||||||
|
* @ORM\OneToOne(targetEntity=User::class) |
||||||
|
*/ |
||||||
|
private $user; |
||||||
|
|
||||||
|
/** |
||||||
|
* @ORM\Column(type="string", length=255) |
||||||
|
*/ |
||||||
|
private $login; |
||||||
|
|
||||||
|
/** |
||||||
|
* @ORM\Column(type="string", length=255) |
||||||
|
*/ |
||||||
|
private $ticket; |
||||||
|
|
||||||
|
public function getId(): ?int |
||||||
|
{ |
||||||
|
return $this->id; |
||||||
|
} |
||||||
|
|
||||||
|
public function getUser() |
||||||
|
{ |
||||||
|
return $this->user; |
||||||
|
} |
||||||
|
|
||||||
|
public function setUser($user) |
||||||
|
{ |
||||||
|
$this->user = $user; |
||||||
|
} |
||||||
|
|
||||||
|
public function getLogin(): ?string |
||||||
|
{ |
||||||
|
return $this->login; |
||||||
|
} |
||||||
|
|
||||||
|
public function setLogin(string $login) |
||||||
|
{ |
||||||
|
$this->login = $login; |
||||||
|
} |
||||||
|
|
||||||
|
public function getTicket(): ?string |
||||||
|
{ |
||||||
|
return $this->ticket; |
||||||
|
} |
||||||
|
|
||||||
|
public function setTicket(string $ticket): self |
||||||
|
{ |
||||||
|
$this->ticket = $ticket; |
||||||
|
|
||||||
|
return $this; |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,155 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace App\Entity; |
||||||
|
|
||||||
|
use App\Repository\UserRepository; |
||||||
|
use Doctrine\ORM\Mapping as ORM; |
||||||
|
use Symfony\Component\Security\Core\User\UserInterface; |
||||||
|
|
||||||
|
/** |
||||||
|
* @ORM\Entity(repositoryClass=UserRepository::class) |
||||||
|
* @ORM\Table(name="`user`") |
||||||
|
*/ |
||||||
|
class User implements UserInterface |
||||||
|
{ |
||||||
|
/** |
||||||
|
* @ORM\Id |
||||||
|
* @ORM\GeneratedValue |
||||||
|
* @ORM\Column(type="integer") |
||||||
|
*/ |
||||||
|
private $id; |
||||||
|
|
||||||
|
/** |
||||||
|
* @ORM\Column(type="string", length=180, unique=true) |
||||||
|
*/ |
||||||
|
private $email; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* @ORM\Column(type="string", length=180, unique=true) |
||||||
|
*/ |
||||||
|
private $username; |
||||||
|
|
||||||
|
/** |
||||||
|
* @ORM\Column(type="json") |
||||||
|
*/ |
||||||
|
private $roles = []; |
||||||
|
|
||||||
|
/** |
||||||
|
* @var string The hashed password |
||||||
|
* @ORM\Column(type="string") |
||||||
|
*/ |
||||||
|
private $password; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private ?string $plainPassword = null; |
||||||
|
|
||||||
|
|
||||||
|
public function getId(): ?int |
||||||
|
{ |
||||||
|
return $this->id; |
||||||
|
} |
||||||
|
|
||||||
|
public function getEmail(): ?string |
||||||
|
{ |
||||||
|
return $this->email; |
||||||
|
} |
||||||
|
|
||||||
|
public function setEmail(string $email): self |
||||||
|
{ |
||||||
|
$this->email = $email; |
||||||
|
|
||||||
|
return $this; |
||||||
|
} |
||||||
|
|
||||||
|
public function setUsername(string $username): self |
||||||
|
{ |
||||||
|
$this->username = $username; |
||||||
|
|
||||||
|
return $this; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* A visual identifier that represents this user. |
||||||
|
* |
||||||
|
* @see UserInterface |
||||||
|
*/ |
||||||
|
public function getUsername(): string |
||||||
|
{ |
||||||
|
return (string) $this->username; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @see UserInterface |
||||||
|
*/ |
||||||
|
public function getRoles(): array |
||||||
|
{ |
||||||
|
$roles = $this->roles; |
||||||
|
// guarantee every user at least has ROLE_USER |
||||||
|
if(empty($roles)) { |
||||||
|
$roles[] = 'ROLE_USER'; |
||||||
|
} |
||||||
|
return array_unique($roles); |
||||||
|
} |
||||||
|
|
||||||
|
public function setRoles(array $roles): self |
||||||
|
{ |
||||||
|
$this->roles = $roles; |
||||||
|
|
||||||
|
return $this; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @see UserInterface |
||||||
|
*/ |
||||||
|
public function getPassword(): ?string |
||||||
|
{ |
||||||
|
return $this->password; |
||||||
|
} |
||||||
|
|
||||||
|
public function setPassword(?string $password): self |
||||||
|
{ |
||||||
|
$this->password = $password; |
||||||
|
|
||||||
|
return $this; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public function getPlainPassword(): ?string |
||||||
|
{ |
||||||
|
return $this->plainPassword; |
||||||
|
} |
||||||
|
|
||||||
|
public function setPlainPassword(string $password): void |
||||||
|
{ |
||||||
|
$this->plainPassword = $password; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Returning a salt is only needed, if you are not using a modern |
||||||
|
* hashing algorithm (e.g. bcrypt or sodium) in your security.yaml. |
||||||
|
* |
||||||
|
* @see UserInterface |
||||||
|
*/ |
||||||
|
public function getSalt(): ?string |
||||||
|
{ |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @see UserInterface |
||||||
|
*/ |
||||||
|
public function eraseCredentials() |
||||||
|
{ |
||||||
|
// If you store any temporary, sensitive data on the user, clear it here |
||||||
|
// $this->plainPassword = null; |
||||||
|
} |
||||||
|
|
||||||
|
public function __toString(): string |
||||||
|
{ |
||||||
|
return (string) $this->getEmail(); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,51 @@ |
|||||||
|
<?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('plainPassword', RepeatedType::class, [ |
||||||
|
'type' => PasswordType::class, |
||||||
|
'first_options' => [ |
||||||
|
'attr' => ['autocomplete' => 'new-password'], |
||||||
|
'constraints' => [ |
||||||
|
new NotBlank([ |
||||||
|
'message' => 'Please enter a password', |
||||||
|
]), |
||||||
|
new Length([ |
||||||
|
'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' => [ |
||||||
|
'attr' => ['autocomplete' => 'new-password'], |
||||||
|
'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([]); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,127 @@ |
|||||||
|
<?php |
||||||
|
namespace App\Form\DataTransformer; |
||||||
|
|
||||||
|
|
||||||
|
use Symfony\Component\Form\DataTransformerInterface; |
||||||
|
use Symfony\Component\Form\Exception\TransformationFailedException; |
||||||
|
|
||||||
|
class SfyCASRoleTransformer implements DataTransformerInterface |
||||||
|
{ |
||||||
|
/** |
||||||
|
* Transforms a value from the original representation to a transformed representation. |
||||||
|
* |
||||||
|
* This method is called when the form field is initialized with its default data, on |
||||||
|
* two occasions for two types of transformers: |
||||||
|
* |
||||||
|
* 1. Model transformers which normalize the model data. |
||||||
|
* This is mainly useful when the same form type (the same configuration) |
||||||
|
* has to handle different kind of underlying data, e.g The DateType can |
||||||
|
* deal with strings or \DateTime objects as input. |
||||||
|
* |
||||||
|
* 2. View transformers which adapt the normalized data to the view format. |
||||||
|
* a/ When the form is simple, the value returned by convention is used |
||||||
|
* directly in the view and thus can only be a string or an array. In |
||||||
|
* this case the data class should be null. |
||||||
|
* |
||||||
|
* b/ When the form is compound the returned value should be an array or |
||||||
|
* an object to be mapped to the children. Each property of the compound |
||||||
|
* data will be used as model data by each child and will be transformed |
||||||
|
* too. In this case data class should be the class of the object, or null |
||||||
|
* when it is an array. |
||||||
|
* |
||||||
|
* All transformers are called in a configured order from model data to view value. |
||||||
|
* At the end of this chain the view data will be validated against the data class |
||||||
|
* setting. |
||||||
|
* |
||||||
|
* This method must be able to deal with empty values. Usually this will |
||||||
|
* be NULL, but depending on your implementation other empty values are |
||||||
|
* possible as well (such as empty strings). The reasoning behind this is |
||||||
|
* that data transformers must be chainable. If the transform() method |
||||||
|
* of the first data transformer outputs NULL, the second must be able to |
||||||
|
* process that value. |
||||||
|
* |
||||||
|
* @param mixed $value The value in the original representation |
||||||
|
* |
||||||
|
* @return mixed The value in the transformed representation |
||||||
|
* |
||||||
|
* @throws TransformationFailedException when the transformation fails |
||||||
|
*/ |
||||||
|
public function transform($value) |
||||||
|
{ |
||||||
|
$retval=''; |
||||||
|
print_r("transform"); |
||||||
|
print_r($value); |
||||||
|
print_r(gettype($value)); |
||||||
|
if(is_array($value)) { |
||||||
|
foreach($value as $val) { |
||||||
|
$retval .= $val; |
||||||
|
$retval .= ','; |
||||||
|
} |
||||||
|
return $retval; |
||||||
|
//return json_encode($value); |
||||||
|
|
||||||
|
} else if(is_string($value)) { |
||||||
|
$retval=[]; |
||||||
|
//print_r($value); |
||||||
|
$roles=explode(",", $value); |
||||||
|
//print_r($roles); |
||||||
|
|
||||||
|
foreach($roles as $role) { |
||||||
|
array_push($retval, $role); |
||||||
|
} |
||||||
|
//return json_encode($retval); |
||||||
|
return $retval; |
||||||
|
//return "toin tsoin"; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
//return json_encode(json_decode($value), JSON_PRETTY_PRINT); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Transforms a value from the transformed representation to its original |
||||||
|
* representation. |
||||||
|
* |
||||||
|
* This method is called when {@link Form::submit()} is called to transform the requests tainted data |
||||||
|
* into an acceptable format. |
||||||
|
* |
||||||
|
* The same transformers are called in the reverse order so the responsibility is to |
||||||
|
* return one of the types that would be expected as input of transform(). |
||||||
|
* |
||||||
|
* This method must be able to deal with empty values. Usually this will |
||||||
|
* be an empty string, but depending on your implementation other empty |
||||||
|
* values are possible as well (such as NULL). The reasoning behind |
||||||
|
* this is that value transformers must be chainable. If the |
||||||
|
* reverseTransform() method of the first value transformer outputs an |
||||||
|
* empty string, the second value transformer must be able to process that |
||||||
|
* value. |
||||||
|
* |
||||||
|
* By convention, reverseTransform() should return NULL if an empty string |
||||||
|
* is passed. |
||||||
|
* |
||||||
|
* @param mixed $value The value in the transformed representation |
||||||
|
* |
||||||
|
* @return mixed The value in the original representation |
||||||
|
* |
||||||
|
* @throws TransformationFailedException when the transformation fails |
||||||
|
*/ |
||||||
|
public function reverseTransform($value) |
||||||
|
{ |
||||||
|
$retval=[]; |
||||||
|
//print_r($value); |
||||||
|
print_r("reverse"); |
||||||
|
$roles=explode(",", $value); |
||||||
|
//print_r($roles); |
||||||
|
|
||||||
|
foreach($roles as $role) { |
||||||
|
array_push($retval, $role); |
||||||
|
} |
||||||
|
|
||||||
|
return $retval; |
||||||
|
//return 'tsoin tsoin'; |
||||||
|
//return json_encode($retval); |
||||||
|
//return json_encode(json_decode($value)); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
@ -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('email', EmailType::class, [ |
||||||
|
'attr' => ['autocomplete' => 'email'], |
||||||
|
'constraints' => [ |
||||||
|
new NotBlank([ |
||||||
|
'message' => 'Please enter your email', |
||||||
|
]), |
||||||
|
], |
||||||
|
]) |
||||||
|
; |
||||||
|
} |
||||||
|
|
||||||
|
public function configureOptions(OptionsResolver $resolver): void |
||||||
|
{ |
||||||
|
$resolver->setDefaults([]); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,34 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace App\Form\Type; |
||||||
|
|
||||||
|
use App\Form\DataTransformer\SfyCASRoleTransformer; |
||||||
|
use Symfony\Component\Form\AbstractType; |
||||||
|
use Symfony\Component\Form\Extension\Core\Type\ChoiceType; |
||||||
|
use Symfony\Component\Form\Extension\Core\Type\TextType; |
||||||
|
use Symfony\Component\Form\FormBuilderInterface; |
||||||
|
use Symfony\Component\OptionsResolver\OptionsResolver; |
||||||
|
|
||||||
|
class SfyCASRoleType extends AbstractType |
||||||
|
{ |
||||||
|
/*public function configureOptions(OptionsResolver $resolver): void |
||||||
|
{ |
||||||
|
$resolver->setDefaults([ |
||||||
|
'choices' => [ |
||||||
|
'Admin role' => 'ROLE_ADMIN', |
||||||
|
'CAS user role' => 'ROLE_CAS_USER', |
||||||
|
], |
||||||
|
]); |
||||||
|
}*/ |
||||||
|
|
||||||
|
public function buildForm(FormBuilderInterface $builder, array $options) |
||||||
|
{ |
||||||
|
parent::buildForm($builder, $options); |
||||||
|
$builder->addViewTransformer(new SfyCASRoleTransformer()); |
||||||
|
} |
||||||
|
|
||||||
|
public function getParent() |
||||||
|
{ |
||||||
|
return TextType::class; |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,54 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace App; |
||||||
|
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; |
||||||
|
use Symfony\Component\Config\Loader\LoaderInterface; |
||||||
|
use Symfony\Component\Config\Resource\FileResource; |
||||||
|
use Symfony\Component\DependencyInjection\ContainerBuilder; |
||||||
|
use Symfony\Component\HttpKernel\Kernel as BaseKernel; |
||||||
|
use Symfony\Component\Routing\RouteCollectionBuilder; |
||||||
|
|
||||||
|
class Kernel extends BaseKernel |
||||||
|
{ |
||||||
|
use MicroKernelTrait; |
||||||
|
|
||||||
|
private const CONFIG_EXTS = '.{php,xml,yaml,yml}'; |
||||||
|
|
||||||
|
public function registerBundles(): iterable |
||||||
|
{ |
||||||
|
$contents = require $this->getProjectDir().'/config/bundles.php'; |
||||||
|
foreach ($contents as $class => $envs) { |
||||||
|
if ($envs[$this->environment] ?? $envs['all'] ?? false) { |
||||||
|
yield new $class(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public function getProjectDir(): string |
||||||
|
{ |
||||||
|
return \dirname(__DIR__); |
||||||
|
} |
||||||
|
|
||||||
|
protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader): void |
||||||
|
{ |
||||||
|
$container->addResource(new FileResource($this->getProjectDir().'/config/bundles.php')); |
||||||
|
$container->setParameter('container.dumper.inline_class_loader', \PHP_VERSION_ID < 70400 || $this->debug); |
||||||
|
$container->setParameter('container.dumper.inline_factories', true); |
||||||
|
$confDir = $this->getProjectDir().'/config'; |
||||||
|
|
||||||
|
$loader->load($confDir.'/{packages}/*'.self::CONFIG_EXTS, 'glob'); |
||||||
|
$loader->load($confDir.'/{packages}/'.$this->environment.'/*'.self::CONFIG_EXTS, 'glob'); |
||||||
|
$loader->load($confDir.'/{services}'.self::CONFIG_EXTS, 'glob'); |
||||||
|
$loader->load($confDir.'/{services}_'.$this->environment.self::CONFIG_EXTS, 'glob'); |
||||||
|
} |
||||||
|
|
||||||
|
protected function configureRoutes(RouteCollectionBuilder $routes): void |
||||||
|
{ |
||||||
|
$confDir = $this->getProjectDir().'/config'; |
||||||
|
|
||||||
|
$routes->import($confDir.'/{routes}/'.$this->environment.'/*'.self::CONFIG_EXTS, '/', 'glob'); |
||||||
|
$routes->import($confDir.'/{routes}/*'.self::CONFIG_EXTS, '/', 'glob'); |
||||||
|
$routes->import($confDir.'/{routes}'.self::CONFIG_EXTS, '/', 'glob'); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,31 @@ |
|||||||
|
<?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; |
||||||
|
|
||||||
|
/** |
||||||
|
* @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 createResetPasswordRequest(object $user, \DateTimeInterface $expiresAt, string $selector, string $hashedToken): ResetPasswordRequestInterface |
||||||
|
{ |
||||||
|
return new ResetPasswordRequest($user, $expiresAt, $selector, $hashedToken); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,50 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace App\Repository; |
||||||
|
|
||||||
|
use App\Entity\SfyCASSession; |
||||||
|
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; |
||||||
|
use Doctrine\Persistence\ManagerRegistry; |
||||||
|
|
||||||
|
/** |
||||||
|
* @method SfyCASSession|null find($id, $lockMode = null, $lockVersion = null) |
||||||
|
* @method SfyCASSession|null findOneBy(array $criteria, array $orderBy = null) |
||||||
|
* @method SfyCASSession[] findAll() |
||||||
|
* @method SfyCASSession[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) |
||||||
|
*/ |
||||||
|
class SfyCASSessionRepository extends ServiceEntityRepository |
||||||
|
{ |
||||||
|
public function __construct(ManagerRegistry $registry) |
||||||
|
{ |
||||||
|
parent::__construct($registry, SfyCASSession::class); |
||||||
|
} |
||||||
|
|
||||||
|
// /** |
||||||
|
// * @return SfyCASSession[] Returns an array of SfyCASSession objects |
||||||
|
// */ |
||||||
|
/* |
||||||
|
public function findByExampleField($value) |
||||||
|
{ |
||||||
|
return $this->createQueryBuilder('s') |
||||||
|
->andWhere('s.exampleField = :val') |
||||||
|
->setParameter('val', $value) |
||||||
|
->orderBy('s.id', 'ASC') |
||||||
|
->setMaxResults(10) |
||||||
|
->getQuery() |
||||||
|
->getResult() |
||||||
|
; |
||||||
|
} |
||||||
|
*/ |
||||||
|
|
||||||
|
/* |
||||||
|
public function findOneBySomeField($value): ?SfyCASSession |
||||||
|
{ |
||||||
|
return $this->createQueryBuilder('s') |
||||||
|
->andWhere('s.exampleField = :val') |
||||||
|
->setParameter('val', $value) |
||||||
|
->getQuery() |
||||||
|
->getOneOrNullResult() |
||||||
|
; |
||||||
|
} |
||||||
|
*/ |
||||||
|
} |
||||||
@ -0,0 +1,67 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace App\Repository; |
||||||
|
|
||||||
|
use App\Entity\User; |
||||||
|
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; |
||||||
|
use Doctrine\Persistence\ManagerRegistry; |
||||||
|
use Symfony\Component\Security\Core\Exception\UnsupportedUserException; |
||||||
|
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface; |
||||||
|
use Symfony\Component\Security\Core\User\UserInterface; |
||||||
|
|
||||||
|
/** |
||||||
|
* @method User|null find($id, $lockMode = null, $lockVersion = null) |
||||||
|
* @method User|null findOneBy(array $criteria, array $orderBy = null) |
||||||
|
* @method User[] findAll() |
||||||
|
* @method User[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) |
||||||
|
*/ |
||||||
|
class UserRepository extends ServiceEntityRepository implements PasswordUpgraderInterface |
||||||
|
{ |
||||||
|
public function __construct(ManagerRegistry $registry) |
||||||
|
{ |
||||||
|
parent::__construct($registry, User::class); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Used to upgrade (rehash) the user's password automatically over time. |
||||||
|
*/ |
||||||
|
public function upgradePassword(UserInterface $user, string $newEncodedPassword): void |
||||||
|
{ |
||||||
|
if (!$user instanceof User) { |
||||||
|
throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', \get_class($user))); |
||||||
|
} |
||||||
|
|
||||||
|
$user->setPassword($newEncodedPassword); |
||||||
|
$this->_em->persist($user); |
||||||
|
$this->_em->flush(); |
||||||
|
} |
||||||
|
|
||||||
|
// /** |
||||||
|
// * @return User[] Returns an array of User objects |
||||||
|
// */ |
||||||
|
/* |
||||||
|
public function findByExampleField($value) |
||||||
|
{ |
||||||
|
return $this->createQueryBuilder('u') |
||||||
|
->andWhere('u.exampleField = :val') |
||||||
|
->setParameter('val', $value) |
||||||
|
->orderBy('u.id', 'ASC') |
||||||
|
->setMaxResults(10) |
||||||
|
->getQuery() |
||||||
|
->getResult() |
||||||
|
; |
||||||
|
} |
||||||
|
*/ |
||||||
|
|
||||||
|
/* |
||||||
|
public function findOneBySomeField($value): ?User |
||||||
|
{ |
||||||
|
return $this->createQueryBuilder('u') |
||||||
|
->andWhere('u.exampleField = :val') |
||||||
|
->setParameter('val', $value) |
||||||
|
->getQuery() |
||||||
|
->getOneOrNullResult() |
||||||
|
; |
||||||
|
} |
||||||
|
*/ |
||||||
|
} |
||||||
@ -0,0 +1,125 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace App\Security; |
||||||
|
|
||||||
|
use App\Entity\User; |
||||||
|
use Doctrine\ORM\EntityManagerInterface; |
||||||
|
use Symfony\Component\HttpFoundation\RedirectResponse; |
||||||
|
use Symfony\Component\HttpFoundation\Request; |
||||||
|
use Symfony\Component\Routing\Generator\UrlGeneratorInterface; |
||||||
|
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; |
||||||
|
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; |
||||||
|
use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException; |
||||||
|
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; |
||||||
|
use Symfony\Component\Security\Core\Security; |
||||||
|
use Symfony\Component\Security\Core\User\UserInterface; |
||||||
|
use Symfony\Component\Security\Core\User\UserProviderInterface; |
||||||
|
use Symfony\Component\Security\Csrf\CsrfToken; |
||||||
|
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; |
||||||
|
use Symfony\Component\Security\Guard\Authenticator\AbstractFormLoginAuthenticator; |
||||||
|
use Symfony\Component\Security\Guard\PasswordAuthenticatedInterface; |
||||||
|
use Symfony\Component\Security\Http\Util\TargetPathTrait; |
||||||
|
|
||||||
|
class AppAuthenticator extends AbstractFormLoginAuthenticator implements PasswordAuthenticatedInterface |
||||||
|
{ |
||||||
|
use TargetPathTrait; |
||||||
|
|
||||||
|
public const LOGIN_ROUTE = 'app_login'; |
||||||
|
public const CAS_LOGIN_ROUTE ='app_cas_login'; |
||||||
|
|
||||||
|
private $entityManager; |
||||||
|
private $urlGenerator; |
||||||
|
private $csrfTokenManager; |
||||||
|
private $passwordEncoder; |
||||||
|
|
||||||
|
public function __construct(EntityManagerInterface $entityManager, UrlGeneratorInterface $urlGenerator, CsrfTokenManagerInterface $csrfTokenManager, UserPasswordEncoderInterface $passwordEncoder) |
||||||
|
{ |
||||||
|
$this->entityManager = $entityManager; |
||||||
|
$this->urlGenerator = $urlGenerator; |
||||||
|
$this->csrfTokenManager = $csrfTokenManager; |
||||||
|
$this->passwordEncoder = $passwordEncoder; |
||||||
|
} |
||||||
|
|
||||||
|
public function supports(Request $request) |
||||||
|
{ |
||||||
|
return (self::LOGIN_ROUTE === $request->attributes->get('_route') || |
||||||
|
self::CAS_LOGIN_ROUTE === $request->attributes->get('_route')) |
||||||
|
&& $request->isMethod('POST'); |
||||||
|
} |
||||||
|
|
||||||
|
public function getCredentials(Request $request) |
||||||
|
{ |
||||||
|
$credentials = [ |
||||||
|
'username' => $request->request->get('username'), |
||||||
|
'password' => $request->request->get('password'), |
||||||
|
'csrf_token' => $request->request->get('_csrf_token'), |
||||||
|
]; |
||||||
|
$request->getSession()->set( |
||||||
|
Security::LAST_USERNAME, |
||||||
|
$credentials['username'] |
||||||
|
); |
||||||
|
|
||||||
|
return $credentials; |
||||||
|
} |
||||||
|
|
||||||
|
public function getUser($credentials, UserProviderInterface $userProvider) |
||||||
|
{ |
||||||
|
$token = new CsrfToken('authenticate', $credentials['csrf_token']); |
||||||
|
if (!$this->csrfTokenManager->isTokenValid($token)) { |
||||||
|
throw new InvalidCsrfTokenException(); |
||||||
|
} |
||||||
|
|
||||||
|
$user = $this->entityManager->getRepository(User::class)->findOneBy(['username' => $credentials['username']]); |
||||||
|
|
||||||
|
if (!$user) { |
||||||
|
throw new UsernameNotFoundException('Username could not be found.'); |
||||||
|
} |
||||||
|
|
||||||
|
return $user; |
||||||
|
} |
||||||
|
|
||||||
|
public function checkCredentials($credentials, UserInterface $user) |
||||||
|
{ |
||||||
|
return $this->passwordEncoder->isPasswordValid($user, $credentials['password']); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Used to upgrade (rehash) the user's password automatically over time. |
||||||
|
*/ |
||||||
|
public function getPassword($credentials): ?string |
||||||
|
{ |
||||||
|
return $credentials['password']; |
||||||
|
} |
||||||
|
|
||||||
|
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $providerKey) |
||||||
|
{ |
||||||
|
/*echo '<pre>'; |
||||||
|
|
||||||
|
print_r($request->query->get('service')); |
||||||
|
echo '<br>'; |
||||||
|
print_r($this->getTargetPath($request->getSession(), $providerKey)); |
||||||
|
echo '<br>'; |
||||||
|
print_r($request); |
||||||
|
|
||||||
|
echo '</pre>'; |
||||||
|
*/ |
||||||
|
$service=$request->query->get('service'); |
||||||
|
if(isset($service)) { |
||||||
|
return new RedirectResponse($request->query->get('service')); |
||||||
|
} else { |
||||||
|
return new RedirectResponse('/admin'); |
||||||
|
} |
||||||
|
|
||||||
|
/*if ($targetPath = $this->getTargetPath($request->getSession(), $providerKey)) { |
||||||
|
//return new RedirectResponse($targetPath); |
||||||
|
}*/ |
||||||
|
|
||||||
|
// For example : return new RedirectResponse($this->urlGenerator->generate('some_route')); |
||||||
|
throw new \Exception('TODO: provide a valid redirect inside '.__FILE__); |
||||||
|
} |
||||||
|
|
||||||
|
protected function getLoginUrl() |
||||||
|
{ |
||||||
|
return $this->urlGenerator->generate(self::LOGIN_ROUTE); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,12 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace App\Service; |
||||||
|
|
||||||
|
class SfyCASTicketGenerator |
||||||
|
{ |
||||||
|
public function getTicket(): string |
||||||
|
{ |
||||||
|
$bytes = random_bytes(16); |
||||||
|
return bin2hex($bytes); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,498 @@ |
|||||||
|
{ |
||||||
|
"composer/package-versions-deprecated": { |
||||||
|
"version": "1.11.99.1" |
||||||
|
}, |
||||||
|
"doctrine/annotations": { |
||||||
|
"version": "1.0", |
||||||
|
"recipe": { |
||||||
|
"repo": "github.com/symfony/recipes", |
||||||
|
"branch": "master", |
||||||
|
"version": "1.0", |
||||||
|
"ref": "a2759dd6123694c8d901d0ec80006e044c2e6457" |
||||||
|
}, |
||||||
|
"files": [ |
||||||
|
"config/routes/annotations.yaml" |
||||||
|
] |
||||||
|
}, |
||||||
|
"doctrine/cache": { |
||||||
|
"version": "1.11.2" |
||||||
|
}, |
||||||
|
"doctrine/collections": { |
||||||
|
"version": "1.6.7" |
||||||
|
}, |
||||||
|
"doctrine/common": { |
||||||
|
"version": "3.1.2" |
||||||
|
}, |
||||||
|
"doctrine/dbal": { |
||||||
|
"version": "2.13.1" |
||||||
|
}, |
||||||
|
"doctrine/deprecations": { |
||||||
|
"version": "v0.5.3" |
||||||
|
}, |
||||||
|
"doctrine/doctrine-bundle": { |
||||||
|
"version": "2.3", |
||||||
|
"recipe": { |
||||||
|
"repo": "github.com/symfony/recipes", |
||||||
|
"branch": "master", |
||||||
|
"version": "2.3", |
||||||
|
"ref": "c9e656a395646ea4fad2bd3e2b3816028baf9026" |
||||||
|
}, |
||||||
|
"files": [ |
||||||
|
"config/packages/doctrine.yaml", |
||||||
|
"config/packages/prod/doctrine.yaml", |
||||||
|
"config/packages/test/doctrine.yaml", |
||||||
|
"src/Entity/.gitignore", |
||||||
|
"src/Repository/.gitignore" |
||||||
|
] |
||||||
|
}, |
||||||
|
"doctrine/doctrine-migrations-bundle": { |
||||||
|
"version": "3.1", |
||||||
|
"recipe": { |
||||||
|
"repo": "github.com/symfony/recipes", |
||||||
|
"branch": "master", |
||||||
|
"version": "3.1", |
||||||
|
"ref": "ee609429c9ee23e22d6fa5728211768f51ed2818" |
||||||
|
}, |
||||||
|
"files": [ |
||||||
|
"config/packages/doctrine_migrations.yaml", |
||||||
|
"migrations/.gitignore" |
||||||
|
] |
||||||
|
}, |
||||||
|
"doctrine/event-manager": { |
||||||
|
"version": "1.1.1" |
||||||
|
}, |
||||||
|
"doctrine/inflector": { |
||||||
|
"version": "2.0.3" |
||||||
|
}, |
||||||
|
"doctrine/instantiator": { |
||||||
|
"version": "1.4.0" |
||||||
|
}, |
||||||
|
"doctrine/lexer": { |
||||||
|
"version": "1.2.1" |
||||||
|
}, |
||||||
|
"doctrine/migrations": { |
||||||
|
"version": "3.1.2" |
||||||
|
}, |
||||||
|
"doctrine/orm": { |
||||||
|
"version": "2.8.4" |
||||||
|
}, |
||||||
|
"doctrine/persistence": { |
||||||
|
"version": "2.2.1" |
||||||
|
}, |
||||||
|
"doctrine/sql-formatter": { |
||||||
|
"version": "1.1.1" |
||||||
|
}, |
||||||
|
"easycorp/easyadmin-bundle": { |
||||||
|
"version": "2.0", |
||||||
|
"recipe": { |
||||||
|
"repo": "github.com/symfony/recipes", |
||||||
|
"branch": "master", |
||||||
|
"version": "2.0", |
||||||
|
"ref": "0a51040a43c6f2172a3a0135cd15daf2043905d7" |
||||||
|
}, |
||||||
|
"files": [ |
||||||
|
"config/packages/easy_admin.yaml", |
||||||
|
"config/routes/easy_admin.yaml" |
||||||
|
] |
||||||
|
}, |
||||||
|
"egulias/email-validator": { |
||||||
|
"version": "2.1.25" |
||||||
|
}, |
||||||
|
"friendsofphp/proxy-manager-lts": { |
||||||
|
"version": "v1.0.4" |
||||||
|
}, |
||||||
|
"laminas/laminas-code": { |
||||||
|
"version": "4.3.0" |
||||||
|
}, |
||||||
|
"laminas/laminas-eventmanager": { |
||||||
|
"version": "3.3.1" |
||||||
|
}, |
||||||
|
"laminas/laminas-zendframework-bridge": { |
||||||
|
"version": "1.2.0" |
||||||
|
}, |
||||||
|
"monolog/monolog": { |
||||||
|
"version": "2.2.0" |
||||||
|
}, |
||||||
|
"nikic/php-parser": { |
||||||
|
"version": "v4.10.5" |
||||||
|
}, |
||||||
|
"pagerfanta/pagerfanta": { |
||||||
|
"version": "v2.7.1" |
||||||
|
}, |
||||||
|
"psr/cache": { |
||||||
|
"version": "1.0.1" |
||||||
|
}, |
||||||
|
"psr/container": { |
||||||
|
"version": "1.1.1" |
||||||
|
}, |
||||||
|
"psr/event-dispatcher": { |
||||||
|
"version": "1.0.0" |
||||||
|
}, |
||||||
|
"psr/log": { |
||||||
|
"version": "1.1.4" |
||||||
|
}, |
||||||
|
"sensio/framework-extra-bundle": { |
||||||
|
"version": "5.2", |
||||||
|
"recipe": { |
||||||
|
"repo": "github.com/symfony/recipes", |
||||||
|
"branch": "master", |
||||||
|
"version": "5.2", |
||||||
|
"ref": "fb7e19da7f013d0d422fa9bce16f5c510e27609b" |
||||||
|
}, |
||||||
|
"files": [ |
||||||
|
"config/packages/sensio_framework_extra.yaml" |
||||||
|
] |
||||||
|
}, |
||||||
|
"symfony/asset": { |
||||||
|
"version": "v5.0.11" |
||||||
|
}, |
||||||
|
"symfony/cache": { |
||||||
|
"version": "v5.0.11" |
||||||
|
}, |
||||||
|
"symfony/cache-contracts": { |
||||||
|
"version": "v2.4.0" |
||||||
|
}, |
||||||
|
"symfony/config": { |
||||||
|
"version": "v5.0.11" |
||||||
|
}, |
||||||
|
"symfony/console": { |
||||||
|
"version": "4.4", |
||||||
|
"recipe": { |
||||||
|
"repo": "github.com/symfony/recipes", |
||||||
|
"branch": "master", |
||||||
|
"version": "4.4", |
||||||
|
"ref": "ea8c0eda34fda57e7d5cd8cbd889e2a387e3472c" |
||||||
|
}, |
||||||
|
"files": [ |
||||||
|
"bin/console", |
||||||
|
"config/bootstrap.php" |
||||||
|
] |
||||||
|
}, |
||||||
|
"symfony/debug-bundle": { |
||||||
|
"version": "4.1", |
||||||
|
"recipe": { |
||||||
|
"repo": "github.com/symfony/recipes", |
||||||
|
"branch": "master", |
||||||
|
"version": "4.1", |
||||||
|
"ref": "0ce7a032d344fb7b661cd25d31914cd703ad445b" |
||||||
|
}, |
||||||
|
"files": [ |
||||||
|
"config/packages/dev/debug.yaml" |
||||||
|
] |
||||||
|
}, |
||||||
|
"symfony/debug-pack": { |
||||||
|
"version": "v1.0.9" |
||||||
|
}, |
||||||
|
"symfony/dependency-injection": { |
||||||
|
"version": "v5.0.11" |
||||||
|
}, |
||||||
|
"symfony/deprecation-contracts": { |
||||||
|
"version": "v2.4.0" |
||||||
|
}, |
||||||
|
"symfony/doctrine-bridge": { |
||||||
|
"version": "v5.0.11" |
||||||
|
}, |
||||||
|
"symfony/dotenv": { |
||||||
|
"version": "v5.0.11" |
||||||
|
}, |
||||||
|
"symfony/error-handler": { |
||||||
|
"version": "v5.0.11" |
||||||
|
}, |
||||||
|
"symfony/event-dispatcher": { |
||||||
|
"version": "v5.0.11" |
||||||
|
}, |
||||||
|
"symfony/event-dispatcher-contracts": { |
||||||
|
"version": "v2.4.0" |
||||||
|
}, |
||||||
|
"symfony/expression-language": { |
||||||
|
"version": "v5.0.11" |
||||||
|
}, |
||||||
|
"symfony/filesystem": { |
||||||
|
"version": "v5.0.11" |
||||||
|
}, |
||||||
|
"symfony/finder": { |
||||||
|
"version": "v5.0.11" |
||||||
|
}, |
||||||
|
"symfony/flex": { |
||||||
|
"version": "1.0", |
||||||
|
"recipe": { |
||||||
|
"repo": "github.com/symfony/recipes", |
||||||
|
"branch": "master", |
||||||
|
"version": "1.0", |
||||||
|
"ref": "c0eeb50665f0f77226616b6038a9b06c03752d8e" |
||||||
|
}, |
||||||
|
"files": [ |
||||||
|
".env" |
||||||
|
] |
||||||
|
}, |
||||||
|
"symfony/form": { |
||||||
|
"version": "v5.0.11" |
||||||
|
}, |
||||||
|
"symfony/framework-bundle": { |
||||||
|
"version": "4.4", |
||||||
|
"recipe": { |
||||||
|
"repo": "github.com/symfony/recipes", |
||||||
|
"branch": "master", |
||||||
|
"version": "4.4", |
||||||
|
"ref": "df1f2fe60b8fbb5cf7e26a7af19445c128a13b90" |
||||||
|
}, |
||||||
|
"files": [ |
||||||
|
"config/bootstrap.php", |
||||||
|
"config/packages/cache.yaml", |
||||||
|
"config/packages/framework.yaml", |
||||||
|
"config/packages/test/framework.yaml", |
||||||
|
"config/preload.php", |
||||||
|
"config/routes/dev/framework.yaml", |
||||||
|
"config/services.yaml", |
||||||
|
"public/index.php", |
||||||
|
"src/Controller/.gitignore", |
||||||
|
"src/Kernel.php" |
||||||
|
] |
||||||
|
}, |
||||||
|
"symfony/google-mailer": { |
||||||
|
"version": "4.4", |
||||||
|
"recipe": { |
||||||
|
"repo": "github.com/symfony/recipes", |
||||||
|
"branch": "master", |
||||||
|
"version": "4.4", |
||||||
|
"ref": "f8fd4ddb9b477510f8f4bce2b9c054ab428c0120" |
||||||
|
} |
||||||
|
}, |
||||||
|
"symfony/http-foundation": { |
||||||
|
"version": "v5.0.11" |
||||||
|
}, |
||||||
|
"symfony/http-kernel": { |
||||||
|
"version": "v5.0.11" |
||||||
|
}, |
||||||
|
"symfony/inflector": { |
||||||
|
"version": "v5.0.11" |
||||||
|
}, |
||||||
|
"symfony/intl": { |
||||||
|
"version": "v5.0.11" |
||||||
|
}, |
||||||
|
"symfony/mailer": { |
||||||
|
"version": "4.3", |
||||||
|
"recipe": { |
||||||
|
"repo": "github.com/symfony/recipes", |
||||||
|
"branch": "master", |
||||||
|
"version": "4.3", |
||||||
|
"ref": "15658c2a0176cda2e7dba66276a2030b52bd81b2" |
||||||
|
}, |
||||||
|
"files": [ |
||||||
|
"config/packages/mailer.yaml" |
||||||
|
] |
||||||
|
}, |
||||||
|
"symfony/maker-bundle": { |
||||||
|
"version": "1.0", |
||||||
|
"recipe": { |
||||||
|
"repo": "github.com/symfony/recipes", |
||||||
|
"branch": "master", |
||||||
|
"version": "1.0", |
||||||
|
"ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f" |
||||||
|
} |
||||||
|
}, |
||||||
|
"symfony/mime": { |
||||||
|
"version": "v5.0.11" |
||||||
|
}, |
||||||
|
"symfony/monolog-bridge": { |
||||||
|
"version": "v5.0.11" |
||||||
|
}, |
||||||
|
"symfony/monolog-bundle": { |
||||||
|
"version": "3.7", |
||||||
|
"recipe": { |
||||||
|
"repo": "github.com/symfony/recipes", |
||||||
|
"branch": "master", |
||||||
|
"version": "3.7", |
||||||
|
"ref": "329f6a5ef2e7aa033f802be833ef8d1268dd0848" |
||||||
|
}, |
||||||
|
"files": [ |
||||||
|
"config/packages/dev/monolog.yaml", |
||||||
|
"config/packages/prod/deprecations.yaml", |
||||||
|
"config/packages/prod/monolog.yaml", |
||||||
|
"config/packages/test/monolog.yaml" |
||||||
|
] |
||||||
|
}, |
||||||
|
"symfony/options-resolver": { |
||||||
|
"version": "v5.0.11" |
||||||
|
}, |
||||||
|
"symfony/orm-pack": { |
||||||
|
"version": "v2.1.0" |
||||||
|
}, |
||||||
|
"symfony/polyfill-intl-icu": { |
||||||
|
"version": "v1.22.1" |
||||||
|
}, |
||||||
|
"symfony/polyfill-intl-idn": { |
||||||
|
"version": "v1.22.1" |
||||||
|
}, |
||||||
|
"symfony/polyfill-intl-normalizer": { |
||||||
|
"version": "v1.22.1" |
||||||
|
}, |
||||||
|
"symfony/polyfill-mbstring": { |
||||||
|
"version": "v1.22.1" |
||||||
|
}, |
||||||
|
"symfony/polyfill-php73": { |
||||||
|
"version": "v1.22.1" |
||||||
|
}, |
||||||
|
"symfony/polyfill-php80": { |
||||||
|
"version": "v1.22.1" |
||||||
|
}, |
||||||
|
"symfony/profiler-pack": { |
||||||
|
"version": "v1.0.5" |
||||||
|
}, |
||||||
|
"symfony/property-access": { |
||||||
|
"version": "v5.0.11" |
||||||
|
}, |
||||||
|
"symfony/proxy-manager-bridge": { |
||||||
|
"version": "v5.0.11" |
||||||
|
}, |
||||||
|
"symfony/routing": { |
||||||
|
"version": "4.2", |
||||||
|
"recipe": { |
||||||
|
"repo": "github.com/symfony/recipes", |
||||||
|
"branch": "master", |
||||||
|
"version": "4.2", |
||||||
|
"ref": "683dcb08707ba8d41b7e34adb0344bfd68d248a7" |
||||||
|
}, |
||||||
|
"files": [ |
||||||
|
"config/packages/prod/routing.yaml", |
||||||
|
"config/packages/routing.yaml", |
||||||
|
"config/routes.yaml" |
||||||
|
] |
||||||
|
}, |
||||||
|
"symfony/security-bundle": { |
||||||
|
"version": "4.4", |
||||||
|
"recipe": { |
||||||
|
"repo": "github.com/symfony/recipes", |
||||||
|
"branch": "master", |
||||||
|
"version": "4.4", |
||||||
|
"ref": "7b4408dc203049666fe23fabed23cbadc6d8440f" |
||||||
|
}, |
||||||
|
"files": [ |
||||||
|
"config/packages/security.yaml" |
||||||
|
] |
||||||
|
}, |
||||||
|
"symfony/security-core": { |
||||||
|
"version": "v5.0.11" |
||||||
|
}, |
||||||
|
"symfony/security-csrf": { |
||||||
|
"version": "v5.0.11" |
||||||
|
}, |
||||||
|
"symfony/security-guard": { |
||||||
|
"version": "v5.0.11" |
||||||
|
}, |
||||||
|
"symfony/security-http": { |
||||||
|
"version": "v5.0.11" |
||||||
|
}, |
||||||
|
"symfony/service-contracts": { |
||||||
|
"version": "v2.4.0" |
||||||
|
}, |
||||||
|
"symfony/stopwatch": { |
||||||
|
"version": "v5.0.11" |
||||||
|
}, |
||||||
|
"symfony/translation": { |
||||||
|
"version": "3.3", |
||||||
|
"recipe": { |
||||||
|
"repo": "github.com/symfony/recipes", |
||||||
|
"branch": "master", |
||||||
|
"version": "3.3", |
||||||
|
"ref": "2ad9d2545bce8ca1a863e50e92141f0b9d87ffcd" |
||||||
|
}, |
||||||
|
"files": [ |
||||||
|
"config/packages/translation.yaml", |
||||||
|
"translations/.gitignore" |
||||||
|
] |
||||||
|
}, |
||||||
|
"symfony/translation-contracts": { |
||||||
|
"version": "v2.4.0" |
||||||
|
}, |
||||||
|
"symfony/twig-bridge": { |
||||||
|
"version": "v5.0.11" |
||||||
|
}, |
||||||
|
"symfony/twig-bundle": { |
||||||
|
"version": "5.0", |
||||||
|
"recipe": { |
||||||
|
"repo": "github.com/symfony/recipes", |
||||||
|
"branch": "master", |
||||||
|
"version": "5.0", |
||||||
|
"ref": "fab9149bbaa4d5eca054ed93f9e1b66cc500895d" |
||||||
|
}, |
||||||
|
"files": [ |
||||||
|
"config/packages/test/twig.yaml", |
||||||
|
"config/packages/twig.yaml", |
||||||
|
"templates/base.html.twig" |
||||||
|
] |
||||||
|
}, |
||||||
|
"symfony/validator": { |
||||||
|
"version": "4.3", |
||||||
|
"recipe": { |
||||||
|
"repo": "github.com/symfony/recipes", |
||||||
|
"branch": "master", |
||||||
|
"version": "4.3", |
||||||
|
"ref": "d902da3e4952f18d3bf05aab29512eb61cabd869" |
||||||
|
}, |
||||||
|
"files": [ |
||||||
|
"config/packages/test/validator.yaml", |
||||||
|
"config/packages/validator.yaml" |
||||||
|
] |
||||||
|
}, |
||||||
|
"symfony/var-dumper": { |
||||||
|
"version": "v5.0.11" |
||||||
|
}, |
||||||
|
"symfony/var-exporter": { |
||||||
|
"version": "v5.0.11" |
||||||
|
}, |
||||||
|
"symfony/web-profiler-bundle": { |
||||||
|
"version": "3.3", |
||||||
|
"recipe": { |
||||||
|
"repo": "github.com/symfony/recipes", |
||||||
|
"branch": "master", |
||||||
|
"version": "3.3", |
||||||
|
"ref": "6bdfa1a95f6b2e677ab985cd1af2eae35d62e0f6" |
||||||
|
}, |
||||||
|
"files": [ |
||||||
|
"config/packages/dev/web_profiler.yaml", |
||||||
|
"config/packages/test/web_profiler.yaml", |
||||||
|
"config/routes/dev/web_profiler.yaml" |
||||||
|
] |
||||||
|
}, |
||||||
|
"symfony/webpack-encore-bundle": { |
||||||
|
"version": "1.9", |
||||||
|
"recipe": { |
||||||
|
"repo": "github.com/symfony/recipes", |
||||||
|
"branch": "master", |
||||||
|
"version": "1.9", |
||||||
|
"ref": "12e0ad8155c23b9f9290e8c49215d4ec921cdf71" |
||||||
|
}, |
||||||
|
"files": [ |
||||||
|
"assets/app.js", |
||||||
|
"assets/bootstrap.js", |
||||||
|
"assets/controllers.json", |
||||||
|
"assets/controllers/hello_controller.js", |
||||||
|
"assets/styles/app.css", |
||||||
|
"config/packages/assets.yaml", |
||||||
|
"config/packages/prod/webpack_encore.yaml", |
||||||
|
"config/packages/test/webpack_encore.yaml", |
||||||
|
"config/packages/webpack_encore.yaml", |
||||||
|
"package.json", |
||||||
|
"webpack.config.js" |
||||||
|
] |
||||||
|
}, |
||||||
|
"symfony/yaml": { |
||||||
|
"version": "v5.0.11" |
||||||
|
}, |
||||||
|
"symfonycasts/reset-password-bundle": { |
||||||
|
"version": "1.0", |
||||||
|
"recipe": { |
||||||
|
"repo": "github.com/symfony/recipes", |
||||||
|
"branch": "master", |
||||||
|
"version": "1.0", |
||||||
|
"ref": "97c1627c0384534997ae1047b93be517ca16de43" |
||||||
|
}, |
||||||
|
"files": [ |
||||||
|
"config/packages/reset_password.yaml" |
||||||
|
] |
||||||
|
}, |
||||||
|
"twig/twig": { |
||||||
|
"version": "v3.3.2" |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,19 @@ |
|||||||
|
<!DOCTYPE html> |
||||||
|
<html> |
||||||
|
<head> |
||||||
|
<meta charset="UTF-8"> |
||||||
|
<title>{% block title %}Welcome!{% endblock %}</title> |
||||||
|
{# Run `composer require symfony/webpack-encore-bundle` |
||||||
|
and uncomment the following Encore helpers 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> |
||||||
@ -0,0 +1,11 @@ |
|||||||
|
{% extends '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('app_forgot_password_request') }}">try again</a>.</p> |
||||||
|
{% endblock %} |
||||||
@ -0,0 +1,9 @@ |
|||||||
|
<h1>Hi!</h1> |
||||||
|
|
||||||
|
<p>To reset your password, please visit the following link</p> |
||||||
|
|
||||||
|
<a href="{{ url('app_reset_password', {token: resetToken.token}) }}">{{ url('app_reset_password', {token: resetToken.token}) }}</a> |
||||||
|
|
||||||
|
<p>This link will expire in {{ resetToken.expirationMessageKey|trans(resetToken.expirationMessageData, 'ResetPasswordBundle') }}.</p> |
||||||
|
|
||||||
|
<p>Cheers!</p> |
||||||
@ -0,0 +1,22 @@ |
|||||||
|
{% extends 'base.html.twig' %} |
||||||
|
|
||||||
|
{% block title %}Reset your password{% endblock %} |
||||||
|
|
||||||
|
{% block body %} |
||||||
|
{% for flashError in app.flashes('reset_password_error') %} |
||||||
|
<div class="alert alert-danger" role="alert">{{ flashError }}</div> |
||||||
|
{% endfor %} |
||||||
|
<h1>Reset your password</h1> |
||||||
|
|
||||||
|
{{ form_start(requestForm) }} |
||||||
|
{{ form_row(requestForm.email) }} |
||||||
|
<div> |
||||||
|
<small> |
||||||
|
Enter your email address and we we will send you a |
||||||
|
link to reset your password. |
||||||
|
</small> |
||||||
|
</div> |
||||||
|
|
||||||
|
<button class="btn btn-primary">Send password reset email</button> |
||||||
|
{{ form_end(requestForm) }} |
||||||
|
{% endblock %} |
||||||
@ -0,0 +1,12 @@ |
|||||||
|
{% extends '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 %} |
||||||
@ -0,0 +1,42 @@ |
|||||||
|
{% extends 'base.html.twig' %} |
||||||
|
|
||||||
|
{% block title %}Log in!{% endblock %} |
||||||
|
|
||||||
|
{% block body %} |
||||||
|
<form method="post"> |
||||||
|
{% if error %} |
||||||
|
<div class="alert alert-danger">{{ error.messageKey|trans(error.messageData, 'security') }}</div> |
||||||
|
{% endif %} |
||||||
|
|
||||||
|
{% if app.user %} |
||||||
|
<div class="mb-3"> |
||||||
|
You are logged in as {{ app.user.username }}, <a href="{{ path('app_logout') }}">Logout</a> |
||||||
|
</div> |
||||||
|
{% endif %} |
||||||
|
|
||||||
|
<h1 class="h3 mb-3 font-weight-normal">Please sign in</h1> |
||||||
|
<label for="inputUsername">Username</label> |
||||||
|
<input type="text" value="{{ last_username }}" name="username" id="inputUsername" class="form-control" autocomplete="username" required autofocus> |
||||||
|
<label for="inputPassword">Password</label> |
||||||
|
<input type="password" name="password" id="inputPassword" class="form-control" autocomplete="current-password" required> |
||||||
|
|
||||||
|
<input type="hidden" name="_csrf_token" |
||||||
|
value="{{ csrf_token('authenticate') }}" |
||||||
|
> |
||||||
|
|
||||||
|
{# |
||||||
|
Uncomment this section and add a remember_me option below your firewall to activate remember me functionality. |
||||||
|
See https://symfony.com/doc/current/security/remember_me.html |
||||||
|
|
||||||
|
<div class="checkbox mb-3"> |
||||||
|
<label> |
||||||
|
<input type="checkbox" name="_remember_me"> Remember me |
||||||
|
</label> |
||||||
|
</div> |
||||||
|
#} |
||||||
|
|
||||||
|
<button class="btn btn-lg btn-primary" type="submit"> |
||||||
|
Sign in |
||||||
|
</button> |
||||||
|
</form> |
||||||
|
{% endblock %} |
||||||
@ -0,0 +1,5 @@ |
|||||||
|
<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'> |
||||||
|
<cas:authenticationSuccess> |
||||||
|
<cas:user>{{ login }}</cas:user> |
||||||
|
</cas:authenticationSuccess> |
||||||
|
</cas:serviceResponse> |
||||||
@ -0,0 +1,42 @@ |
|||||||
|
{% extends 'base.html.twig' %} |
||||||
|
|
||||||
|
{% block title %}CAS Log in!{% endblock %} |
||||||
|
|
||||||
|
{% block body %} |
||||||
|
<form method="post"> |
||||||
|
{% if error %} |
||||||
|
<div class="alert alert-danger">{{ error.messageKey|trans(error.messageData, 'security') }}</div> |
||||||
|
{% endif %} |
||||||
|
|
||||||
|
{% if app.user %} |
||||||
|
<div class="mb-3"> |
||||||
|
You are logged in as {{ app.user.username }}, <a href="{{ path('app_logout') }}">Logout</a> |
||||||
|
</div> |
||||||
|
{% endif %} |
||||||
|
|
||||||
|
<h1 class="h3 mb-3 font-weight-normal">CAS Authentication : Please sign in</h1> |
||||||
|
<label for="inputUsername">Username</label> |
||||||
|
<input type="text" value="{{ last_username }}" name="username" id="inputUsername" class="form-control" autocomplete="username" required autofocus> |
||||||
|
<label for="inputPassword">Password</label> |
||||||
|
<input type="password" name="password" id="inputPassword" class="form-control" autocomplete="current-password" required> |
||||||
|
|
||||||
|
<input type="hidden" name="_csrf_token" |
||||||
|
value="{{ csrf_token('authenticate') }}" |
||||||
|
> |
||||||
|
|
||||||
|
{# |
||||||
|
Uncomment this section and add a remember_me option below your firewall to activate remember me functionality. |
||||||
|
See https://symfony.com/doc/current/security/remember_me.html |
||||||
|
|
||||||
|
<div class="checkbox mb-3"> |
||||||
|
<label> |
||||||
|
<input type="checkbox" name="_remember_me"> Remember me |
||||||
|
</label> |
||||||
|
</div> |
||||||
|
#} |
||||||
|
|
||||||
|
<button class="btn btn-lg btn-primary" type="submit"> |
||||||
|
Sign in |
||||||
|
</button> |
||||||
|
</form> |
||||||
|
{% endblock %} |
||||||
@ -0,0 +1,20 @@ |
|||||||
|
{% extends 'base.html.twig' %} |
||||||
|
|
||||||
|
{% block title %}Hello SfyCASLoginController!{% endblock %} |
||||||
|
|
||||||
|
{% block body %} |
||||||
|
<style> |
||||||
|
.example-wrapper { margin: 1em auto; max-width: 800px; width: 95%; font: 18px/1.5 sans-serif; } |
||||||
|
.example-wrapper code { background: #F5F5F5; padding: 2px 6px; } |
||||||
|
</style> |
||||||
|
|
||||||
|
<div class="example-wrapper"> |
||||||
|
<h1>Hello {{ controller_name }}! ✅</h1> |
||||||
|
|
||||||
|
This friendly message is coming from: |
||||||
|
<ul> |
||||||
|
<li>Your controller at <code><a href="{{ '/home/karim/Web/sfycas/src/Controller/SfyCASLoginController.php'|file_link(0) }}">src/Controller/SfyCASLoginController.php</a></code></li> |
||||||
|
<li>Your template at <code><a href="{{ '/home/karim/Web/sfycas/templates/sfy_cas_login/index.html.twig'|file_link(0) }}">templates/sfy_cas_login/index.html.twig</a></code></li> |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
{% endblock %} |
||||||
@ -0,0 +1,75 @@ |
|||||||
|
const Encore = require('@symfony/webpack-encore'); |
||||||
|
|
||||||
|
// Manually configure the runtime environment if not already configured yet by the "encore" command.
|
||||||
|
// It's useful when you use tools that rely on webpack.config.js file.
|
||||||
|
if (!Encore.isRuntimeEnvironmentConfigured()) { |
||||||
|
Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev'); |
||||||
|
} |
||||||
|
|
||||||
|
Encore |
||||||
|
// directory where compiled assets will be stored
|
||||||
|
.setOutputPath('public/build/') |
||||||
|
// public path used by the web server to access the output path
|
||||||
|
.setPublicPath('/build') |
||||||
|
// only needed for CDN's or sub-directory deploy
|
||||||
|
//.setManifestKeyPrefix('build/')
|
||||||
|
|
||||||
|
/* |
||||||
|
* ENTRY CONFIG |
||||||
|
* |
||||||
|
* Each entry will result in one JavaScript file (e.g. app.js) |
||||||
|
* and one CSS file (e.g. app.css) if your JavaScript imports CSS. |
||||||
|
*/ |
||||||
|
.addEntry('app', './assets/app.js') |
||||||
|
|
||||||
|
// enables the Symfony UX Stimulus bridge (used in assets/bootstrap.js)
|
||||||
|
.enableStimulusBridge('./assets/controllers.json') |
||||||
|
|
||||||
|
// When enabled, Webpack "splits" your files into smaller pieces for greater optimization.
|
||||||
|
.splitEntryChunks() |
||||||
|
|
||||||
|
// will require an extra script tag for runtime.js
|
||||||
|
// but, you probably want this, unless you're building a single-page app
|
||||||
|
.enableSingleRuntimeChunk() |
||||||
|
|
||||||
|
/* |
||||||
|
* FEATURE CONFIG |
||||||
|
* |
||||||
|
* Enable & configure other features below. For a full |
||||||
|
* list of features, see: |
||||||
|
* https://symfony.com/doc/current/frontend.html#adding-more-features
|
||||||
|
*/ |
||||||
|
.cleanupOutputBeforeBuild() |
||||||
|
.enableBuildNotifications() |
||||||
|
.enableSourceMaps(!Encore.isProduction()) |
||||||
|
// enables hashed filenames (e.g. app.abc123.css)
|
||||||
|
.enableVersioning(Encore.isProduction()) |
||||||
|
|
||||||
|
.configureBabel((config) => { |
||||||
|
config.plugins.push('@babel/plugin-proposal-class-properties'); |
||||||
|
}) |
||||||
|
|
||||||
|
// enables @babel/preset-env polyfills
|
||||||
|
.configureBabelPresetEnv((config) => { |
||||||
|
config.useBuiltIns = 'usage'; |
||||||
|
config.corejs = 3; |
||||||
|
}) |
||||||
|
|
||||||
|
// enables Sass/SCSS support
|
||||||
|
.enableSassLoader() |
||||||
|
|
||||||
|
// uncomment if you use TypeScript
|
||||||
|
//.enableTypeScriptLoader()
|
||||||
|
|
||||||
|
// uncomment if you use React
|
||||||
|
//.enableReactPreset()
|
||||||
|
|
||||||
|
// uncomment to get integrity="..." attributes on your script & link tags
|
||||||
|
// requires WebpackEncoreBundle 1.4 or higher
|
||||||
|
//.enableIntegrityHashes(Encore.isProduction())
|
||||||
|
|
||||||
|
// uncomment if you're having problems with a jQuery plugin
|
||||||
|
//.autoProvidejQuery()
|
||||||
|
; |
||||||
|
|
||||||
|
module.exports = Encore.getWebpackConfig(); |
||||||
Loading…
Reference in new issue