First commit

master
mirakinparis 3 years ago
parent 204fa572e6
commit 56812804bd
  1. 72
      .gitignore
  2. 1
      README.md
  3. 15
      assets/app.js
  4. 11
      assets/bootstrap.js
  5. 4
      assets/controllers.json
  6. 16
      assets/controllers/hello_controller.js
  7. 125
      assets/styles/_variables.scss
  8. 66
      assets/styles/app.scss
  9. 86
      composer.json
  10. 7263
      composer.lock
  11. 23
      config/bootstrap.php
  12. 17
      config/bundles.php
  13. 3
      config/packages/assets.yaml
  14. 19
      config/packages/cache.yaml
  15. 4
      config/packages/dev/debug.yaml
  16. 19
      config/packages/dev/monolog.yaml
  17. 6
      config/packages/dev/web_profiler.yaml
  18. 18
      config/packages/doctrine.yaml
  19. 6
      config/packages/doctrine_migrations.yaml
  20. 29
      config/packages/easy_admin.yaml
  21. 17
      config/packages/framework.yaml
  22. 3
      config/packages/mailer.yaml
  23. 8
      config/packages/prod/deprecations.yaml
  24. 20
      config/packages/prod/doctrine.yaml
  25. 17
      config/packages/prod/monolog.yaml
  26. 3
      config/packages/prod/routing.yaml
  27. 4
      config/packages/prod/webpack_encore.yaml
  28. 5
      config/packages/reset_password.yaml
  29. 3
      config/packages/routing.yaml
  30. 38
      config/packages/security.yaml
  31. 3
      config/packages/sensio_framework_extra.yaml
  32. 4
      config/packages/test/doctrine.yaml
  33. 4
      config/packages/test/framework.yaml
  34. 12
      config/packages/test/monolog.yaml
  35. 2
      config/packages/test/twig.yaml
  36. 3
      config/packages/test/validator.yaml
  37. 6
      config/packages/test/web_profiler.yaml
  38. 2
      config/packages/test/webpack_encore.yaml
  39. 6
      config/packages/translation.yaml
  40. 4
      config/packages/twig.yaml
  41. 8
      config/packages/validator.yaml
  42. 30
      config/packages/webpack_encore.yaml
  43. 9
      config/preload.php
  44. 3
      config/routes.yaml
  45. 7
      config/routes/annotations.yaml
  46. 3
      config/routes/dev/framework.yaml
  47. 7
      config/routes/dev/web_profiler.yaml
  48. 5
      config/routes/easy_admin.yaml
  49. 31
      config/services.yaml
  50. 25
      docker-compose.yml
  51. 0
      migrations/.gitignore
  52. 35
      migrations/Version20210731104520.php
  53. 14608
      package-lock.json
  54. 27
      package.json
  55. 27
      public/index.php
  56. 68
      public/sandbox.php
  57. 0
      src/Controller/.gitignore
  58. 177
      src/Controller/ResetPasswordController.php
  59. 38
      src/Controller/SecurityController.php
  60. 71
      src/Controller/SfyCASAdminController.php
  61. 98
      src/Controller/SfyCASLoginController.php
  62. 36
      src/Controller/SfyCASServiceValidator.php
  63. 0
      src/Entity/.gitignore
  64. 45
      src/Entity/ResetPasswordRequest.php
  65. 72
      src/Entity/SfyCASSession.php
  66. 155
      src/Entity/User.php
  67. 51
      src/Form/ChangePasswordFormType.php
  68. 127
      src/Form/DataTransformer/SfyCASRoleTransformer.php
  69. 31
      src/Form/ResetPasswordRequestFormType.php
  70. 34
      src/Form/Type/SfyCASRoleType.php
  71. 54
      src/Kernel.php
  72. 0
      src/Repository/.gitignore
  73. 31
      src/Repository/ResetPasswordRequestRepository.php
  74. 50
      src/Repository/SfyCASSessionRepository.php
  75. 67
      src/Repository/UserRepository.php
  76. 125
      src/Security/AppAuthenticator.php
  77. 12
      src/Service/SfyCASTicketGenerator.php
  78. 498
      symfony.lock
  79. 19
      templates/base.html.twig
  80. 11
      templates/reset_password/check_email.html.twig
  81. 9
      templates/reset_password/email.html.twig
  82. 22
      templates/reset_password/request.html.twig
  83. 12
      templates/reset_password/reset.html.twig
  84. 42
      templates/security/login.html.twig
  85. 5
      templates/sfy_cas_login/cas_validate.html.twig
  86. 42
      templates/sfy_cas_login/caslogin.html.twig
  87. 20
      templates/sfy_cas_login/index.html.twig
  88. 0
      translations/.gitignore
  89. 75
      webpack.config.js
  90. 5754
      yarn.lock

72
.gitignore vendored

@ -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 ###

@ -1,2 +1 @@
# sfycas

@ -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"
}
}

7263
composer.lock generated

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');
}
}

14608
package-lock.json generated

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();

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save