parent
204fa572e6
commit
56812804bd
@ -1,54 +1,20 @@ |
||||
# ---> Symfony |
||||
# Cache and logs (Symfony2) |
||||
/app/cache/* |
||||
/app/logs/* |
||||
!app/cache/.gitkeep |
||||
!app/logs/.gitkeep |
||||
|
||||
# Email spool folder |
||||
/app/spool/* |
||||
|
||||
# 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 |
||||
*.sql |
||||
*.back |
||||
*.tar.gz |
||||
###> symfony/framework-bundle ### |
||||
/.env.local |
||||
/.env.local.php |
||||
/.env.*.local |
||||
/config/secrets/prod/prod.decrypt.private.php |
||||
/public/bundles/ |
||||
/var/ |
||||
/vendor/ |
||||
|
||||
# Assets and user uploads |
||||
/web/bundles/ |
||||
/web/uploads/ |
||||
|
||||
# PHPUnit |
||||
/app/phpunit.xml |
||||
/phpunit.xml |
||||
|
||||
# Build data |
||||
/build/ |
||||
|
||||
# Composer PHAR |
||||
/composer.phar |
||||
|
||||
# Backup entities generated with doctrine:generate:entities command |
||||
**/Entity/*~ |
||||
|
||||
# Embedded web-server pid file |
||||
/.web-server-pid |
||||
|
||||
###< symfony/framework-bundle ### |
||||
.idea |
||||
|
||||
###> symfony/webpack-encore-bundle ### |
||||
/node_modules/ |
||||
/public/build/ |
||||
npm-debug.log |
||||
yarn-error.log |
||||
###< symfony/webpack-encore-bundle ### |
||||
|
||||
@ -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