From 10bf90bd931c5c234fb23cfdded0c0aba885f330 Mon Sep 17 00:00:00 2001 From: "R. Eric Wheeler" Date: Sat, 22 Apr 2017 12:43:30 -0700 Subject: [PATCH] OAuth integration --- Gruntfile.js | 11 +- app/AppCache.php | 18 + app/AppKernel.php | 21 +- .../views/Profile/edit.html.twig | 6 +- .../views/Profile/edit_content.html.twig | 29 +- .../views/Profile/show.html.twig | 6 +- .../views/Profile/show_content.html.twig | 35 +- .../views/Registration/confirmed.html.twig | 11 +- .../Registration/register_content.html.twig | 36 +- .../views/Resetting/request.html.twig | 6 +- .../views/Security/login.html.twig | 6 +- .../views/Security/login_content.html.twig | 33 +- .../views/Connect/connect_confirm.html.twig | 25 +- .../views/Connect/registration.html.twig | 28 +- .../SikofittDoughnutweddingBundle.en.yml | 9 + app/Resources/translations/default.en.yml | 1 + app/Resources/translations/messages.en.yml | 1 + app/Resources/views/base.html.twig | 10 + app/Resources/views/default/index.html.twig | 18 +- app/Resources/views/social_login.html.twig | 8 +- app/autoload.php | 20 +- app/config/config.yml | 26 +- app/config/config_dev.yml | 5 +- app/config/google-storage-key.json | 12 + app/config/routing.yml | 6 +- app/config/security.yml | 12 +- app/config/services.yml | 14 +- build/images/logo.png | Bin 0 -> 82555 bytes build/js/doughnut.js | 3 +- build/less/doughnut.less | 13 +- composer.json | 4 +- docker/php/Dockerfile | 4 +- .../Controller/DefaultController.php | 42 +- .../Controller/ImageController.php | 40 +- .../Controller/RsvpController.php | 2 +- .../Controller/UserController.php | 215 ------ .../DependencyInjection/Configuration.php | 23 +- .../SikofittDoughnutWeddingExtension.php | 24 +- .../DoughnutWeddingBundle/Entity/User.php | 627 +++++++----------- .../RedirectOnUserRegisterListener.php | 31 + .../UserRedirectOnLoggedInListener.php | 113 ++++ .../Form/ProfileEditType.php | 84 +++ .../Form/RegistrationType.php | 107 +-- .../DoughnutWeddingBundle/Form/RsvpType.php | 4 +- .../SikofittDoughnutweddingBundle.en.yml | 1 + .../SikofittDoughnutWeddingBundle.php | 18 + .../Controller/DefaultControllerTest.php | 19 +- .../Tests/Controller/ImageControllerTest.php | 19 +- var/SymfonyRequirements.php | 0 web/app_dev.php | 4 +- web/config.php | 14 +- 51 files changed, 1017 insertions(+), 807 deletions(-) create mode 100644 app/Resources/translations/SikofittDoughnutweddingBundle.en.yml create mode 100644 app/Resources/translations/default.en.yml create mode 100644 app/Resources/translations/messages.en.yml create mode 100644 app/config/google-storage-key.json create mode 100644 build/images/logo.png delete mode 100644 src/Sikofitt/DoughnutWeddingBundle/Controller/UserController.php create mode 100644 src/Sikofitt/DoughnutWeddingBundle/EventListener/RedirectOnUserRegisterListener.php create mode 100644 src/Sikofitt/DoughnutWeddingBundle/EventListener/UserRedirectOnLoggedInListener.php create mode 100644 src/Sikofitt/DoughnutWeddingBundle/Form/ProfileEditType.php create mode 100644 src/Sikofitt/DoughnutWeddingBundle/Resources/translations/SikofittDoughnutweddingBundle.en.yml mode change 100644 => 100755 var/SymfonyRequirements.php diff --git a/Gruntfile.js b/Gruntfile.js index 757cab6..3950e24 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -52,7 +52,14 @@ module.exports = function (grunt) { src: ['*.css', '!*.min.css'], dest: 'build/dist/css', ext: '.min.css' - }] + }, + { + expand: true, + cwd: 'build/css', + src: ['*.css', '!*.min.css'], + dest: 'build/dist/css', + ext: '.min.css' + }] } }, jshint: { @@ -134,7 +141,7 @@ module.exports = function (grunt) { 'build/dist', 'web/js/*.js', 'web/css/*.css', - 'web/images/*.svg' + 'web/images/*' ] }); diff --git a/app/AppCache.php b/app/AppCache.php index 639ec2c..dd10cc5 100644 --- a/app/AppCache.php +++ b/app/AppCache.php @@ -1,5 +1,23 @@ . + */ + use Symfony\Bundle\FrameworkBundle\HttpCache\HttpCache; class AppCache extends HttpCache diff --git a/app/AppKernel.php b/app/AppKernel.php index 8b07f3e..b6eb9b6 100644 --- a/app/AppKernel.php +++ b/app/AppKernel.php @@ -1,13 +1,30 @@ . + */ + use Symfony\Component\Config\Loader\LoaderInterface; +use Symfony\Component\HttpKernel\Kernel; class AppKernel extends Kernel { public function registerBundles() { - $bundles = [ new Symfony\Bundle\FrameworkBundle\FrameworkBundle(), new Symfony\Bundle\SecurityBundle\SecurityBundle(), diff --git a/app/Resources/FOSUserBundle/views/Profile/edit.html.twig b/app/Resources/FOSUserBundle/views/Profile/edit.html.twig index bd7fbdc..5aa007b 100644 --- a/app/Resources/FOSUserBundle/views/Profile/edit.html.twig +++ b/app/Resources/FOSUserBundle/views/Profile/edit.html.twig @@ -1,5 +1,5 @@ -{% extends "@FOSUser/layout.html.twig" %} +{% extends "base.html.twig" %} -{% block fos_user_content %} +{% block body %} {% include "@FOSUser/Profile/edit_content.html.twig" %} -{% endblock fos_user_content %} +{% endblock body %} diff --git a/app/Resources/FOSUserBundle/views/Profile/edit_content.html.twig b/app/Resources/FOSUserBundle/views/Profile/edit_content.html.twig index c827436..106a91b 100644 --- a/app/Resources/FOSUserBundle/views/Profile/edit_content.html.twig +++ b/app/Resources/FOSUserBundle/views/Profile/edit_content.html.twig @@ -1,8 +1,29 @@ {% trans_default_domain 'FOSUserBundle' %} +{% if form.vars.errors is not empty %} +
+ {{ form_errors(form) }} -{{ form_start(form, { 'action': path('fos_user_profile_edit'), 'attr': { 'class': 'fos_user_profile_edit' } }) }} - {{ form_widget(form) }} -
-
+{% endif %} +{{ form_start(form, { 'action': path('fos_user_profile_edit'), 'attr': { 'class': 'uk-form-horizontal fos_user_profile_edit' } }) }} + {{ form_label(form.email) }} +
+ {{ form_widget(form.email) }} +
+ {{ form_label(form.name) }} +
+ {{ form_widget(form.name) }} +
+{{ form_label(form.rsvp) }} +
+ {{ form_widget(form.rsvp) }} +
+ +
+ +
+
+ Cancel +
+{{ form_rest(form) }} {{ form_end(form) }} diff --git a/app/Resources/FOSUserBundle/views/Profile/show.html.twig b/app/Resources/FOSUserBundle/views/Profile/show.html.twig index 1e4a259..3e1f355 100644 --- a/app/Resources/FOSUserBundle/views/Profile/show.html.twig +++ b/app/Resources/FOSUserBundle/views/Profile/show.html.twig @@ -1,5 +1,5 @@ -{% extends "@FOSUser/layout.html.twig" %} +{% extends "base.html.twig" %} -{% block fos_user_content %} +{% block body %} {% include "@FOSUser/Profile/show_content.html.twig" %} -{% endblock fos_user_content %} +{% endblock body %} diff --git a/app/Resources/FOSUserBundle/views/Profile/show_content.html.twig b/app/Resources/FOSUserBundle/views/Profile/show_content.html.twig index 3c819d2..6648fe1 100644 --- a/app/Resources/FOSUserBundle/views/Profile/show_content.html.twig +++ b/app/Resources/FOSUserBundle/views/Profile/show_content.html.twig @@ -1,6 +1,31 @@ -{% trans_default_domain 'FOSUserBundle' %} +{% trans_default_domain 'SikofittDoughnutweddingBundle' %} +

User Information

-
-

{{ 'profile.show.username'|trans }}: {{ user.username }}

-

{{ 'profile.show.email'|trans }}: {{ user.email }}

-
+
+ +

{{ 'profile.name'|trans }}

+

{{ user.name }}

+ +

{{ 'profile.email'|trans }}

+

{{ user.email }}

+ +

{{ 'profile.rsvp'|trans }}

+

{% if user.rsvp is not null %}{{ user.rsvp.guests }}{% else %}0{% endif %}

+ +
+
+ +
    +
  • + +
  • +
  • +
  • +
  • +
  • + +
  • +
+
+
{{ 'profile.member_since'|trans({'%date%':user.created|date('l F jS, Y (h:i a)')}) }}
diff --git a/app/Resources/FOSUserBundle/views/Registration/confirmed.html.twig b/app/Resources/FOSUserBundle/views/Registration/confirmed.html.twig index 4402b4f..73e9c3e 100644 --- a/app/Resources/FOSUserBundle/views/Registration/confirmed.html.twig +++ b/app/Resources/FOSUserBundle/views/Registration/confirmed.html.twig @@ -1,10 +1,11 @@ -{% extends "@FOSUser/layout.html.twig" %} +{% extends "base.html.twig" %} {% trans_default_domain 'FOSUserBundle' %} -{% block fos_user_content %} -

{{ 'registration.confirmed'|trans({'%username%': user.username}) }}

+{% block body %} +

{{ 'registration.confirmed'|trans({'%username%': user.firstname }) }}

+

Continue to the home page.

{% if targetUrl %} -

{{ 'registration.back'|trans }}

+

{{ 'registration.back'|trans }}

{% endif %} -{% endblock fos_user_content %} +{% endblock body %} diff --git a/app/Resources/FOSUserBundle/views/Registration/register_content.html.twig b/app/Resources/FOSUserBundle/views/Registration/register_content.html.twig index c28cb96..c92b982 100644 --- a/app/Resources/FOSUserBundle/views/Registration/register_content.html.twig +++ b/app/Resources/FOSUserBundle/views/Registration/register_content.html.twig @@ -2,6 +2,7 @@
{{ form_errors(form) }}
+{{ dump(app.session) }} {{ form_start(form, {'method': 'post', 'action': path('fos_user_registration_register'), 'attr': {'class': 'fos_user_registration_register uk-form'}}) }}
@@ -14,43 +15,12 @@
- +
- {{ form_widget(form.username, { 'attr': {'placeholder':'Username', 'class':'uk-input uk-form-large uk-padding-small'} }) }} + {{ form_widget(form.name, { 'attr': {'placeholder':'Name', 'class':'uk-input uk-form-large uk-padding-small'} }) }}
-
- -
- {{ form_widget(form.first_name, { 'attr': {'placeholder':'First name', 'class':'uk-input uk-form-large uk-padding-small'} }) }} -
-
-
- -
- {{ form_widget(form.last_name, { 'attr': {'placeholder':'Last name', 'class':'uk-input uk-input uk-form-large uk-padding-small'} }) }} -
-
-
-
- {{ form_label(form.familyside) }} -
-
-
- {{ form_widget(form.familyside) }} -
-
-
-
-
- {{ form_label(form.family) }} -
-
- {{ form_widget(form.family, { 'attr': {'class':'uk-checkbox'} }) }} - -
-
diff --git a/app/Resources/FOSUserBundle/views/Resetting/request.html.twig b/app/Resources/FOSUserBundle/views/Resetting/request.html.twig index 87e7b41..2da4765 100644 --- a/app/Resources/FOSUserBundle/views/Resetting/request.html.twig +++ b/app/Resources/FOSUserBundle/views/Resetting/request.html.twig @@ -1,5 +1,5 @@ -{% extends "@FOSUser/layout.html.twig" %} +{% extends "base.html.twig" %} -{% block fos_user_content %} +{% block body %} {% include "@FOSUser/Resetting/request_content.html.twig" %} -{% endblock fos_user_content %} +{% endblock body %} diff --git a/app/Resources/FOSUserBundle/views/Security/login.html.twig b/app/Resources/FOSUserBundle/views/Security/login.html.twig index e565119..004cfd5 100644 --- a/app/Resources/FOSUserBundle/views/Security/login.html.twig +++ b/app/Resources/FOSUserBundle/views/Security/login.html.twig @@ -1,5 +1,5 @@ -{% extends "@FOSUser/layout.html.twig" %} +{% extends "base.html.twig" %} -{% block fos_user_content %} +{% block body %} {{ include('@FOSUser/Security/login_content.html.twig') }} -{% endblock fos_user_content %} +{% endblock body %} diff --git a/app/Resources/FOSUserBundle/views/Security/login_content.html.twig b/app/Resources/FOSUserBundle/views/Security/login_content.html.twig index 863e796..50a3c9c 100644 --- a/app/Resources/FOSUserBundle/views/Security/login_content.html.twig +++ b/app/Resources/FOSUserBundle/views/Security/login_content.html.twig @@ -4,19 +4,32 @@
{{ error.messageKey|trans(error.messageData, 'security') }}
{% endif %} -
+ {% if csrf_token %} {% endif %} +
+
+ +
+ + +
+
+
+ +
+ - - + +
+
+
+
+
+ +
+
+
- - - - - - -
diff --git a/app/Resources/HWIOAuthBundle/views/Connect/connect_confirm.html.twig b/app/Resources/HWIOAuthBundle/views/Connect/connect_confirm.html.twig index ba5c229..b68c38c 100644 --- a/app/Resources/HWIOAuthBundle/views/Connect/connect_confirm.html.twig +++ b/app/Resources/HWIOAuthBundle/views/Connect/connect_confirm.html.twig @@ -1,24 +1,27 @@ -{% extends 'HWIOAuthBundle::layout.html.twig' %} +{% extends 'base.html.twig' %} -{% block hwi_oauth_content %} +{% block body %}

{{ 'header.connecting' | trans({}, 'HWIOAuthBundle')}}

-
-
-

{{ 'connect.confirm.text' | trans({'%service%': service | trans({}, 'HWIOAuthBundle'), '%name%': userInformation.realName}, 'HWIOAuthBundle') }}

+
+ +

{{ 'connect.confirm.text' | trans({'%service%': service | trans({}, 'HWIOAuthBundle'), '%name%': userInformation.email}, 'HWIOAuthBundle') }}

{{ form_start(form, {'action': path('hwi_oauth_connect_service', {'service': service, 'key': key}), 'attr': {'class': 'fos_user_registration_register'}}) }} {{ form_widget(form) }} -

- - {{ 'connect.confirm.cancel' | trans({}, 'HWIOAuthBundle') }} -
+
+
+ +
+ +
{{ form_end(form) }}

-
{% if userInformation.profilePicture is defined and userInformation.profilePicture is not empty %} {% endif %}
-{% endblock hwi_oauth_content %} +{% endblock body %} diff --git a/app/Resources/HWIOAuthBundle/views/Connect/registration.html.twig b/app/Resources/HWIOAuthBundle/views/Connect/registration.html.twig index fc904c3..dd0aef8 100644 --- a/app/Resources/HWIOAuthBundle/views/Connect/registration.html.twig +++ b/app/Resources/HWIOAuthBundle/views/Connect/registration.html.twig @@ -1,22 +1,30 @@ -{% extends 'HWIOAuthBundle::layout.html.twig' %} +{% extends 'base.html.twig' %} -{% block hwi_oauth_content %} -

{{ 'header.register' | trans({'%name%': userInformation.realName}, 'HWIOAuthBundle') }}

-
-
- {{ form_start(form, {'action': path('hwi_oauth_connect_registration', {'key': key}), 'attr': {'class': 'hwi_oauth_registration_register'}}) }} +{% block body %} +
+ {{ dump(userInformation) }} +
+ {% if userInformation.resourceOwner.name == 'yahoo' %} + {% set name = userInformation.nickname %} + {% else %} + {% set name = userInformation.email %} + {% endif %} +

{{ 'header.register' | trans({'%name%': name }, 'HWIOAuthBundle') }}

+ + + {{ form_start(form, {'action': path('hwi_oauth_connect_registration', {'key': key}), 'attr': {'class': 'hwi_oauth_registration_register uk-form uk-form-horizontal'}}) }} {{ form_widget(form) }}
{{ 'connect.registration.cancel' | trans({}, 'HWIOAuthBundle') }}
{{ form_end(form) }} -
-
+ + {% if userInformation.profilePicture is not empty %} {% endif %} -
+
-{% endblock hwi_oauth_content %} +{% endblock body %} diff --git a/app/Resources/translations/SikofittDoughnutweddingBundle.en.yml b/app/Resources/translations/SikofittDoughnutweddingBundle.en.yml new file mode 100644 index 0000000..45f3b14 --- /dev/null +++ b/app/Resources/translations/SikofittDoughnutweddingBundle.en.yml @@ -0,0 +1,9 @@ +profile.yes: Yep! +profile.no: Nope! +profile.name: Name +profile.email: Email address +profile.family: Immediate Family Member +profile.family_side: Family Side +profile.family_side_data: You're here for %family_side%! +profile.rsvp: Current guests including yourself. +profile.member_since: You've been a user since %date%! \ No newline at end of file diff --git a/app/Resources/translations/default.en.yml b/app/Resources/translations/default.en.yml new file mode 100644 index 0000000..9778413 --- /dev/null +++ b/app/Resources/translations/default.en.yml @@ -0,0 +1 @@ +profile.name: Name \ No newline at end of file diff --git a/app/Resources/translations/messages.en.yml b/app/Resources/translations/messages.en.yml new file mode 100644 index 0000000..9778413 --- /dev/null +++ b/app/Resources/translations/messages.en.yml @@ -0,0 +1 @@ +profile.name: Name \ No newline at end of file diff --git a/app/Resources/views/base.html.twig b/app/Resources/views/base.html.twig index dd283b9..c50d679 100644 --- a/app/Resources/views/base.html.twig +++ b/app/Resources/views/base.html.twig @@ -8,6 +8,7 @@ Title + @@ -16,8 +17,17 @@ {% block debug %}{% endblock %}
+
+ +
{% include 'flash_messages.html.twig' %} {% block body %}{% endblock %} + check + check + check + {% include "social_login.html.twig" %} {% block footer %}{% endblock %}
diff --git a/app/Resources/views/default/index.html.twig b/app/Resources/views/default/index.html.twig index 94cb36f..3677789 100644 --- a/app/Resources/views/default/index.html.twig +++ b/app/Resources/views/default/index.html.twig @@ -4,16 +4,26 @@ {% block body %}
-
+
+ + +
+

About Us

+
+ +
+ +
+
+
+
Small2
Medium
-
-
Large
-
+
{% endblock %} diff --git a/app/Resources/views/social_login.html.twig b/app/Resources/views/social_login.html.twig index 31ed025..27c98e0 100644 --- a/app/Resources/views/social_login.html.twig +++ b/app/Resources/views/social_login.html.twig @@ -1,7 +1,11 @@ -{% if(is_granted('IS_AUTHENTICATED_ANONYMOUSLY') and hide_social is not defined ) %} +{% if(not is_granted('IS_AUTHENTICATED_FULLY')) %}
-

Login

+

+ + Login Register + +

  • diff --git a/app/autoload.php b/app/autoload.php index 31321fa..09ce039 100644 --- a/app/autoload.php +++ b/app/autoload.php @@ -1,7 +1,25 @@ . + */ + use Composer\Autoload\ClassLoader; +use Doctrine\Common\Annotations\AnnotationRegistry; /** @var ClassLoader $loader */ $loader = require __DIR__.'/../vendor/autoload.php'; diff --git a/app/config/config.yml b/app/config/config.yml index 2764085..185d203 100644 --- a/app/config/config.yml +++ b/app/config/config.yml @@ -149,15 +149,11 @@ hwi_oauth: type: twitter client_id: 'YmXGQN2Az0eTlkwJrnaO2wR9r' client_secret: 'c73cBI7uj562BU4bBSHfNDcKHgM5aVo8sousjgUdDNBZFXxFHI' - windows: - type: windows_live - client_id: 'f9dc3dd7-1b1c-4b8c-acdf-f40611ab550d' - client_secret: 'fy5prOcKeLKNTB616WinrPt' - scope: wl.signin yahoo: type: yahoo client_id: 'dj0yJmk9SndXWm05Tk5yME9MJmQ9WVdrOVRYTkVUVWRHTjJjbWNHbzlNQS0tJnM9Y29uc3VtZXJzZWNyZXQmeD1lMw--' client_secret: '4f837f738d6c4df38eaedc7babe4d8f405f8cc0f' + scope: 'sdps-r' fosub: # try 30 times to check if a username is available (foo, foo1, foo2 etc) username_iterations: 30 @@ -169,21 +165,33 @@ hwi_oauth: amazon: amazonId instagram: instagramId twitter: twitterId - windows_live: windowsId yahoo: yahooId # if you want to use 'connect' and do not use the FOSUB integration, configure these separately - connect: ~ + connect: + confirmation: false fos_user: db_driver: orm # other valid values are 'mongodb' and 'couchdb' firewall_name: secured_area user_class: Sikofitt\DoughnutWeddingBundle\Entity\User from_email: - address: noreply@doughnutwedding.com - sender_name: "No Reply" + address: 'noreply@doughnutwedding.com' + sender_name: "[Doughnut Wedding] No Reply" + profile: + form: + type: Sikofitt\DoughnutWeddingBundle\Form\ProfileEditType registration: form: type: Sikofitt\DoughnutWeddingBundle\Form\RegistrationType +swiftmailer: + #disable_delivery: true + transport: null #'%mailer_transport%' + host: '%mailer_host%' + username: '%mailer_user%' + password: '%mailer_password%' + spool: { type: memory } + delivery_addresses: ['info@doughnutwedding.com'] + sender_address: 'noreply@doughnutwedding.com' sikofitt_doughnut_wedding: max_rsvps: ~ \ No newline at end of file diff --git a/app/config/config_dev.yml b/app/config/config_dev.yml index 9b3c82b..7f0c1a2 100644 --- a/app/config/config_dev.yml +++ b/app/config/config_dev.yml @@ -38,4 +38,7 @@ monolog: # level: info #swiftmailer: -# delivery_addresses: ['me@example.com'] +# disable_delivery: true +# transport: smtp +# delivery_addresses: ['info@doughnutwedding.com'] +# sender_address: 'noreply@doughnutwedding.com' diff --git a/app/config/google-storage-key.json b/app/config/google-storage-key.json new file mode 100644 index 0000000..ea13507 --- /dev/null +++ b/app/config/google-storage-key.json @@ -0,0 +1,12 @@ +{ + "type": "service_account", + "project_id": "doughnut-wedding", + "private_key_id": "097ae8333fdb2ba046efe522e25cffda1163547a", + "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCpiZ7fjrZIBxIJ\nprUQdKA7ODlF698aOkJNBPr2tgV2X1Xb2SYObs3p3/nhR+4SijXU4yrQSfOdUBPS\nlyM+vbT1uEniRMNUqQWcJyZN4sT0MmG85wGh3zCGa6FbakKGC6nhH1DuT6o7T1v7\nxqR/Byp7/6rAUxy0Yhm2CmlWmrt0Oe1wx42N4m1t9865SrNzUNloRp0a9jUQWpew\nssoG3pYlbzv+KHE4BSTGJEu2ErpA5kOp+loIOlmveyb8ac+tHUHqozkzMQ5+Esyf\nnNCpzurq6hL/9piVhkd1Hyr947Vb3kz6dpDoeBZqCzXK/1n3d/VJjYpBvCVqq5xr\n34U7Bfa9AgMBAAECggEAdIY2QAlil5bkeuWtxSWji5BVLQ21Rd2M/ErUAwWQM4/K\n/1P8qCbYOErNAF3j77I21Z9dKdPqMNF9Dlz6yICzA8AqZ+5DIskZJf5ygU2/eOe3\n7ZIIuS0huQH44U/jcSZLGIPhqCnxItqkqiQZo4VVWeybe5ykOgbDDS+SvweSl4qq\ngILLaMsEzDSJZhwLnmAeRnd1REq1afrQtIF/aNo5vZj0WvcLIEkwkAHqcZAUy/ox\n5huswc3SiUA4ruJkEKTtHwUDqlQhQVGGrHV0tuFHCYfxUMu1/Zp5G6e4jUeAq7t6\nKCx4tFi6U1ETiZ8w18mhO/uWkDAa0A9qquo7v+xagQKBgQDV/1Zrzv1P09XztFaV\nmhueNLJ570Fy2MNa/gHIjWJFjJlknpfCXn4q0jFBfiKs2iReRTEni33mPtzdcONF\njps/zeGch+6Exp7I+zTji2JMtXs8CiAJfR388QLzDETg6jwSL4hLWadizlJzsVA8\n4PliLv7P1kJMhMswKrUazaaetQKBgQDK0FLOVuYhLPWP2RHu0nr5MSLneXRG+dKx\nNc4Dk00ms1O6NPdhWwmHcDfocJMmi0usDvs9XjxwCQHB4KrITODRpSq3M9fI3I+W\n/QUNZfRqf0bQFzRuiKOh5BAZub3Zil3h7htkcqP4TuLvXqoHs5z2mS1wFUdcukLv\nAN7nOI/06QKBgGY9Ur25K98Kt0py23coJI/GX4rQGzXSiCsd9h4qJkxSKysediT/\n3kl5GN1QdSKeKgf8CMr64xCw8fa+K2cdBeFK7MJLU1KOTmh5VEBuZG1/uzvpHntK\nEpy5TQ5vyyyl3ENYAEb3s3gKWOw7R7l+Rsd46nbDx/Mk8qq1jMccf8GNAoGAXhe6\nYxpz1+5o2tzlcfxaqyO9wtBZPtiGhEqnEoeTYqIN9TS/lH5M9HX+qisYSeiUKfYl\nX3pJ5dx34T/fW+A26WyMXcSClyCkyXMHlgi4FXSJIN+zJpjj+aa6RYUj7DpChiAW\nu0pogjnvFQjBL6OH7exw5TAqFH4hsYqg33shZokCgYBvYMEUN+ZtNlVkgMd6lPoG\noVxq/JwJZ8d48yQ8XP3N/8qmPiuMtD9JJi6ZV4S/qvlMt63KkmtRAACQFQyJSfYj\n9U4H3sJ13vzW2tuZ87d58fACnzgElpwxifKz9X/h9+9rrD8UHvdmzSHISh2E3I3T\nsOO36Is9YoCwwjNsN9BacA==\n-----END PRIVATE KEY-----\n", + "client_email": "doughnut-wedding-images@doughnut-wedding.iam.gserviceaccount.com", + "client_id": "108682906131804711525", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://accounts.google.com/o/oauth2/token", + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", + "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/doughnut-wedding-images%40doughnut-wedding.iam.gserviceaccount.com" +} diff --git a/app/config/routing.yml b/app/config/routing.yml index c3f82e5..2554e40 100644 --- a/app/config/routing.yml +++ b/app/config/routing.yml @@ -8,7 +8,7 @@ hwi_oauth_connect: hwi_oauth_login: resource: "@HWIOAuthBundle/Resources/config/routing/login.xml" - prefix: /login/oauth + prefix: /connect facebook_login: path: /login/callback/facebook @@ -16,8 +16,6 @@ google_login: path: /login/callback/google twitter_login: path: /login/callback/twitter -windows_login: - path: /login/callback/windows instagram_login: path: /login/callback/instagram amazon_login: @@ -25,7 +23,7 @@ amazon_login: yahoo_login: path: /login/callback/yahoo -os_user_security: +fos_user_security: resource: "@FOSUserBundle/Resources/config/routing/security.xml" #paths # /login diff --git a/app/config/security.yml b/app/config/security.yml index 01f13b8..7fdca2a 100644 --- a/app/config/security.yml +++ b/app/config/security.yml @@ -7,7 +7,7 @@ security: cost: 14 providers: fos_userbundle: - id: fos_user.user_provider.username_email + id: fos_user.user_provider.username firewalls: # disables authentication for assets and the profiler, adapt it according to your needs dev: @@ -28,20 +28,20 @@ security: facebook: /login/callback/facebook google: /login/callback/google twitter: /login/callback/twitter - windows: /login/callback/windows instagram: /login/callback/instagram amazon: /login/callback/amazon yahoo: /login/callback/yahoo - login_path: /login + login_path: /connect use_forward: false - failure_path: /login + failure_path: /connect oauth_user_provider: service: hwi_oauth.user.provider.fosub_bridge access_control: + - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY } - - { path: ^/user, role: ROLE_USER } + - { path: ^/user$, role: ROLE_USER } - { path: ^/gallery/upload, role: ROLE_USER } - { path: ^/gallery, role: IS_AUTHENTICATED_ANONYMOUSLY } - - { path: ^/admin/, role: ROLE_ADMIN } \ No newline at end of file + - { path: ^/admin$, role: ROLE_ADMIN } \ No newline at end of file diff --git a/app/config/services.yml b/app/config/services.yml index 47b5840..12ba0d1 100644 --- a/app/config/services.yml +++ b/app/config/services.yml @@ -10,5 +10,17 @@ services: doughnutwedding.form.registration: class: Sikofitt\DoughnutWeddingBundle\Form\RegistrationType + arguments: ['@fos_user.user_manager'] tags: - - { name: form.type, alias: app_user_registration } \ No newline at end of file + - { name: form.type, alias: app_user_registration } + doughnutwedding.event.redirect_user_logged_in_event: + class: Sikofitt\DoughnutWeddingBundle\EventListener\UserRedirectOnLoggedInListener + arguments: ['@security.token_storage', '@router'] + tags: + - { name: kernel.event_listener, event: kernel.request } + doughnutwedding.event.redirect_user_after_register_event: + class: Sikofitt\DoughnutWeddingBundle\EventListener\RedirectOnUserRegisterListener + arguments: ['@router'] + tags: + - { name: kernel.event_listener, event: fos_user.registration.confirmed } + - { name: kernel.event_listener, event: fos_user.registration.completed } \ No newline at end of file diff --git a/build/images/logo.png b/build/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..6160a3af03de613138684c627b748bbd0ef02a67 GIT binary patch literal 82555 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
  • xNj&AZWWqx~r_G&j&Zr*rrM;f&&^ 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

    elG8n-=DeD&VxJ@fg#w-IZ}Ur=bC)!rY(JXx{KV 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 0) { + if(null === document.querySelector('select') && document.querySelector('select').length > 0) { var selectPlaceholder = 'Choose an option.'; if(document.querySelector('select').hasAttribute('placeholder')) { selectPlaceholder = document.querySelector('select').getAttribute('placeholder'); @@ -9,5 +9,6 @@ jQuery(document).ready(function($) { minimumResultsForSearch: Infinity, theme: 'default' }); + } }); \ No newline at end of file diff --git a/build/less/doughnut.less b/build/less/doughnut.less index 8d5c02f..3b2f7fb 100644 --- a/build/less/doughnut.less +++ b/build/less/doughnut.less @@ -3,7 +3,10 @@ //@global-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; //@global-font-size: 16px; - +@base-body-font-family: 'Raleway', sans-serif; +@base-heading-font-family: 'Raleway', sans-serif; +@base-body-font-weight: 200; +@base-heading-font-weight: 300; @form-background: #ffffff; .uk-input, @@ -18,4 +21,10 @@ background: #f5fbfe; border:1px solid #99baca; color: #666; -} \ No newline at end of file +} +.uk-login-form #password { + border-top:0 !important; +} +.uk-login-form #password:focus { + border-top: 1px solid #99baca !important; +} diff --git a/composer.json b/composer.json index 20c30d3..8584295 100644 --- a/composer.json +++ b/composer.json @@ -19,6 +19,7 @@ "doctrine/orm": "^2.5", "egulias/email-validator": "^2.1", "friendsofsymfony/user-bundle": "^2.0", + "google/apiclient": "^2.1", "google/recaptcha": "^1.1", "hwi/oauth-bundle": "^0.5.3", "incenteev/composer-parameter-handler": "^2.0", @@ -26,6 +27,7 @@ "ircmaxell/security-lib": "^1.1", "j-ben87/parsley-bundle": "^1.4", "javiereguiluz/easyadmin-bundle": "^1.16", + "knplabs/knp-gaufrette-bundle": "^0.4.0", "lexik/translation-bundle": "^4.0", "lightsaml/sp-bundle": "^1.1", "moontoast/math": "^1.1", @@ -34,7 +36,7 @@ "paragonie/sodium_compat": "^0.6.0", "predis/predis": "^1.1", "psr/http-message": "^1.0", - "ramsey/uuid": "^3.5", + "ramsey/uuid": "^3.6", "ramsey/uuid-doctrine": "^1.2", "ravenberg/uikit-bundle": "^1.0", "sensio/distribution-bundle": "^5.0", diff --git a/docker/php/Dockerfile b/docker/php/Dockerfile index 0d8ee03..7fac4f8 100644 --- a/docker/php/Dockerfile +++ b/docker/php/Dockerfile @@ -1,5 +1,5 @@ -#FROM php:7.1-fpm-alpine -FROM php-7.1.4-fpm-alpine +FROM php:7.1-fpm-alpine +#FROM php-7.1.4-fpm-alpine ENV PHPIZE_DEPS \ autoconf \ diff --git a/src/Sikofitt/DoughnutWeddingBundle/Controller/DefaultController.php b/src/Sikofitt/DoughnutWeddingBundle/Controller/DefaultController.php index 8196be2..13c84be 100644 --- a/src/Sikofitt/DoughnutWeddingBundle/Controller/DefaultController.php +++ b/src/Sikofitt/DoughnutWeddingBundle/Controller/DefaultController.php @@ -1,33 +1,49 @@ . + */ + namespace Sikofitt\DoughnutWeddingBundle\Controller; -use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; -use Symfony\Component\DependencyInjection\ContainerAwareInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\HttpFoundation\Response; +use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; /** - * Class DefaultController + * Class DefaultController. */ class DefaultController extends Controller { - - /** + /** * @Route("/") * * @param Request $request + * * @return Response */ public function indexAction(Request $request) { - $parameters = []; - if(null !== $this->getUser()) { - $parameters['hide_social'] = true; - } - return $this->render('default/index.html.twig', $parameters); - } + $parameters = []; + if (null !== $this->getUser()) { + $parameters['hide_social'] = true; + } + return $this->render('default/index.html.twig', $parameters); + } } diff --git a/src/Sikofitt/DoughnutWeddingBundle/Controller/ImageController.php b/src/Sikofitt/DoughnutWeddingBundle/Controller/ImageController.php index 8b0e012..fdca419 100644 --- a/src/Sikofitt/DoughnutWeddingBundle/Controller/ImageController.php +++ b/src/Sikofitt/DoughnutWeddingBundle/Controller/ImageController.php @@ -1,14 +1,31 @@ . + */ + namespace Sikofitt\DoughnutWeddingBundle\Controller; -use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; +use Symfony\Bundle\FrameworkBundle\Controller\Controller; /** - * Class ImageController + * Class ImageController. * - * @package Sikofitt\DoughnutWeddingBundle\Controller * @Route("/gallery") */ class ImageController extends Controller @@ -18,9 +35,9 @@ class ImageController extends Controller */ public function indexAction() { - return $this->render('SikofittDoughnutWeddingBundle:Image:index.html.twig', array( + return $this->render('SikofittDoughnutWeddingBundle:Image:index.html.twig', [ // ... - )); + ]); } /** @@ -28,9 +45,9 @@ class ImageController extends Controller */ public function uploadAction() { - return $this->render('SikofittDoughnutWeddingBundle:Image:upload.html.twig', array( + return $this->render('SikofittDoughnutWeddingBundle:Image:upload.html.twig', [ // ... - )); + ]); } /** @@ -38,9 +55,9 @@ class ImageController extends Controller */ public function tagAction() { - return $this->render('SikofittDoughnutWeddingBundle:Image:tag.html.twig', array( + return $this->render('SikofittDoughnutWeddingBundle:Image:tag.html.twig', [ // ... - )); + ]); } /** @@ -48,9 +65,8 @@ class ImageController extends Controller */ public function categoryAction() { - return $this->render('SikofittDoughnutWeddingBundle:Image:category.html.twig', array( + return $this->render('SikofittDoughnutWeddingBundle:Image:category.html.twig', [ // ... - )); + ]); } - } diff --git a/src/Sikofitt/DoughnutWeddingBundle/Controller/RsvpController.php b/src/Sikofitt/DoughnutWeddingBundle/Controller/RsvpController.php index 85d4fff..e805961 100644 --- a/src/Sikofitt/DoughnutWeddingBundle/Controller/RsvpController.php +++ b/src/Sikofitt/DoughnutWeddingBundle/Controller/RsvpController.php @@ -25,7 +25,6 @@ use Doctrine\ORM\EntityManager; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\Form\FormFactory; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Validator\ConstraintViolationList; @@ -33,6 +32,7 @@ class RsvpController extends Controller { /** * @Route("/rsvp") + * * @param \Symfony\Component\HttpFoundation\Request $request * * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response diff --git a/src/Sikofitt/DoughnutWeddingBundle/Controller/UserController.php b/src/Sikofitt/DoughnutWeddingBundle/Controller/UserController.php deleted file mode 100644 index 30b4221..0000000 --- a/src/Sikofitt/DoughnutWeddingBundle/Controller/UserController.php +++ /dev/null @@ -1,215 +0,0 @@ -. - */ - -namespace Sikofitt\DoughnutWeddingBundle\Controller; - -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; -use Sikofitt\App\Form\UserLoginType; -use Sikofitt\App\Form\UserTokenType; -use Sikofitt\DoughnutWeddingBundle\Security\TokenGenerator; -use Symfony\Bundle\FrameworkBundle\Controller\Controller; -use Symfony\Component\Form\FormError; -use Symfony\Component\HttpFoundation\JsonResponse; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\StreamedResponse; - -/** - * Class UserController. - - */ -class UserController extends Controller -{ - - /** - * @Route("/logout", name="logout") - * @param \Symfony\Component\HttpFoundation\Request $request - * @return \Symfony\Component\HttpFoundation\Response - */ - public function logoutAction(Request $request) - { - if(null !== $request->getUser()) { - $request->getSession()->remove('user'); - } - return $this->render('user/logout.html.twig'); - } - - public function tokenLoginAction(Request $request, string $token = null) - { - if (null === $token) { - $tokenForm = $this->get('form.factory')->create(UserTokenType::class); - if ($request->isMethod('POST')) { - $tokenForm->handleRequest($request); - if ($tokenForm->isValid() && $tokenForm->isSubmitted()) { - if ($tokenForm->get('update_token')->isClicked()) { - if (null !== $tokenForm->get('email')->getData()) { - return $this->updateAndSendTokenLoginLink($this, - $tokenForm); - } else { - $tokenForm->get('email') - ->addError(new FormError('Email address is a required field to send a new login link.')); - - return $this->render('form/token.html.twig', - ['form' => $tokenForm->createView()]); - } - } else { - $userToken = $tokenForm->get('user_token')->getData(); - - $user = $this->getDoctrine() - ->getRepository('SikofittDoughnutWeddingBundle:User') - ->getUserByUserToken($userToken); - - if (null === $user) { - $tokenForm->get('user_token') - ->addError(new FormError('Token is invalid.')); - } else { - $request->getSession()->set('user', $user); - } - - return $this->render('form/token.html.twig', - ['form' => $tokenForm->createView()]); - } - } else { - return $this->render('form/token.html.twig', - ['form' => $tokenForm->createView()]); - } - } - - return $this->render('form/token.html.twig', ['form' => $tokenForm->createView()]); - } else { - // Token has been included. - $request->getSession()->remove('user'); - $tokenForm = $this->get('form.factory')->create(UserTokenType::class); - //$user = $app->getEntityManager()->getRepository('Sikofitt:User')->getUserByUserToken($token); - $user = $this->getDoctrine()->getRepository('SikofittDoughnutWeddingBundle:User')->findOneBy(['userToken' => $token]); - if (null !== $user) { - $request->getSession()->set('user', $user); - - return $this->render('user/index.html.twig'); - } else { - return new StreamedResponse(function () use ($tokenForm, $token) { - $tokenForm->get('user_token')->setData($token); - $tokenForm->get('user_token')->addError(new FormError('Invalid token.')); - print $this->renderView('form/token.html.twig', ['form' => $tokenForm->createView()]); - }); - } - } - } - - /** - * @Route("/user", name="user_index") - * @param \Symfony\Component\HttpFoundation\Request $request - * - * @return \Symfony\Component\HttpFoundation\JsonResponse - */ - public function indexAction(Request $request) - { - - //if ($request->getSession()->has('user')) { - return new JsonResponse( - [ - 'request' => $request->request->all(), - 'server' => $request->server->all(), - 'headers' => $request->headers->all(), - 'session' => $request->getSession()->all(), - 'token' => (string) new TokenGenerator(), - ] - ); - // } - } - - public function loginAction(Request $request) - { - if ($app->session()->has('user')) { - //return $app->redirect($app->url('rsvp_edit')); - } - $loginForm = $app->getFormFactory()->create(UserLoginType::class); - if ($request->isMethod('POST')) { - $loginForm->handleRequest($request); - if ($loginForm->isValid() && $loginForm->isSubmitted()) { - $user = $app->getEntityManager()->getRepository(User::class)->findByEmail($loginForm->get('email_username')->getData()); - if (null !== $user && true === password_verify($loginForm->get('password')->getData(), $user[0]->getPassword())) { - $userSession = [ - 'firstName' => $user[0]->getFirstName(), - 'lastName' => $user[0]->getLastName(), - 'fullName' => sprintf('%s %s', $user[0]->getFirstName(), $user[0]->getLastName()), - 'familySide' => $user[0]->getFamilySide(), - 'email' => $user[0]->getEmail(), - 'family' => $user[0]->getFamily(), - 'created' => $user[0]->getCreated()->format('U'), - 'updated' => $user[0]->getUpdated()->format('U'), - 'guests' => $user[0]->getRsvp()->getGuests(), - ]; - $app->getSession()->set('user', $userSession); - $app->redirect($app->url('rsvp')); - } else { - $error = new FormError('Your password or email is incorrect.'); - $error->setOrigin($loginForm); - $loginForm->get('password')->addError($error); - - return $app->render('login.html.twig', ['form' => $loginForm->createView()]); - } - } - } - - return $app->render('login.html.twig', ['form' => $loginForm->createView()]); - } - - public function resetAction(Request $request, \Kernel $app) - { - } - - public function tokenAction(Request $request, \Kernel $app) - { - } - - public function editAction(Request $request, \Kernel $app) - { - } - - private function tokenFormGenerator(\Kernel $app) - { - return; - } - - private function updateAndSendTokenLoginLink(\Kernel $app, \Symfony\Component\Form\FormInterface $tokenForm) - { - $email = $tokenForm->get('email')->getData(); - $user = $app->getEntityManager() - ->getRepository('Sikofitt:User') - ->findByEmail($email); - if (null === $user) { - $tokenForm->get('email')->addError(new FormError('Sorry we couldn\'t find your email address.')); - - return $app->render('form/token.html.twig', ['form' => $tokenForm->createView()]); - } - $newToken = $app->getEntityManager() - ->getRepository('Sikofitt:User') - ->setUserToken($email); - if (false !== $newToken) { - $user->setUserToken($newToken); - $app->session()->set('user', $user); - - return $app->render('form/token.html.twig', ['form' => $tokenForm->createView()]); - } - $tokenForm->get('email')->addError(new FormError('An Unknown error occured. Please try again.')); - - return $app->render('form/token.html.twig', ['form' => $tokenForm->createView()]); - } -} diff --git a/src/Sikofitt/DoughnutWeddingBundle/DependencyInjection/Configuration.php b/src/Sikofitt/DoughnutWeddingBundle/DependencyInjection/Configuration.php index 5efbb0c..d00a44b 100644 --- a/src/Sikofitt/DoughnutWeddingBundle/DependencyInjection/Configuration.php +++ b/src/Sikofitt/DoughnutWeddingBundle/DependencyInjection/Configuration.php @@ -1,5 +1,23 @@ . + */ + namespace Sikofitt\DoughnutWeddingBundle\DependencyInjection; use Symfony\Component\Config\Definition\Builder\TreeBuilder; @@ -14,6 +32,7 @@ class Configuration implements ConfigurationInterface { /** * {@inheritdoc} + * * @throws \RuntimeException */ public function getConfigTreeBuilder() @@ -25,8 +44,8 @@ class Configuration implements ConfigurationInterface ->scalarNode('max_rsvps') ->isRequired() ->validate() - ->ifEmpty()->then(function() {return 40;}) - ->ifNull()->then(function() { return 40;}) + ->ifEmpty()->then(function () {return 40; }) + ->ifNull()->then(function () { return 40; }) ->end() ->end(); // Here you should define the parameters that are allowed to diff --git a/src/Sikofitt/DoughnutWeddingBundle/DependencyInjection/SikofittDoughnutWeddingExtension.php b/src/Sikofitt/DoughnutWeddingBundle/DependencyInjection/SikofittDoughnutWeddingExtension.php index 69637e1..d58aef9 100644 --- a/src/Sikofitt/DoughnutWeddingBundle/DependencyInjection/SikofittDoughnutWeddingExtension.php +++ b/src/Sikofitt/DoughnutWeddingBundle/DependencyInjection/SikofittDoughnutWeddingExtension.php @@ -1,16 +1,34 @@ . + */ + namespace Sikofitt\DoughnutWeddingBundle\DependencyInjection; -use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Config\FileLocator; -use Symfony\Component\HttpKernel\DependencyInjection\Extension; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Loader; +use Symfony\Component\HttpKernel\DependencyInjection\Extension; /** * This is the class that loads and manages your bundle configuration. * - * @link http://symfony.com/doc/current/cookbook/bundles/extension.html + * @see http://symfony.com/doc/current/cookbook/bundles/extension.html */ class SikofittDoughnutWeddingExtension extends Extension { diff --git a/src/Sikofitt/DoughnutWeddingBundle/Entity/User.php b/src/Sikofitt/DoughnutWeddingBundle/Entity/User.php index 9e44699..ccbb9c6 100644 --- a/src/Sikofitt/DoughnutWeddingBundle/Entity/User.php +++ b/src/Sikofitt/DoughnutWeddingBundle/Entity/User.php @@ -21,7 +21,6 @@ namespace Sikofitt\DoughnutWeddingBundle\Entity; use Doctrine\ORM\Mapping as ORM; -use FOS\UserBundle\Model\UserInterface; use Symfony\Component\Validator\Constraints as Assert; /** @@ -46,50 +45,12 @@ class User extends \FOS\UserBundle\Model\User protected $id; /** - * @ORM\Column(name="first_name", type="string", length=255, nullable=false) + * @ORM\Column(name="fullname", type="string", length=255, nullable=false) * @Assert\NotBlank() * @Assert\Regex(pattern="/\w+/") */ - private $firstName; + private $name; - /** - * @ORM\Column(name="last_name", type="string", length=255, nullable=false) - * @Assert\NotBlank() - * @Assert\Regex(pattern="/\w+/") - */ - private $lastName; - - /** - * @ORM\Column(type="boolean", name="is_family", nullable=false) - * @Assert\Type(type="bool") - */ - private $family = false; - - //* @Assert\Choice(choices="{self::KATRINA_SIDE, self::ERIC_SIDE}", multiple=false) - /** - * @ORM\Column(type="string", name="family_side", nullable=true) - * - * @var null|string - */ - private $familySide = null; - - /* - * @ORM\Column(name="email", type="string", length=255) - * @Assert\Email(strict=true, checkHost=true, checkMX=true) - - protected $email; - */ - /* - * @var string - * @ORM\Column(name="password", type="string", length=255)) - * - protected $password; - */ - /* - * @var string - * - protected $plainPassword; - */ /** * @var string * @ORM\Column(name="reset_token", type="string", length=255, nullable=true) @@ -123,269 +84,38 @@ class User extends \FOS\UserBundle\Model\User */ private $facebookId; - private $facebookAccessToken; + private $facebookAccessToken; /** * @ORM\Column(name="google_id", type="string", length=255, nullable=true) */ private $googleId; - private $googleAccessToken; + private $googleAccessToken; /** * @ORM\Column(name="amazon_id", type="string", length=255, nullable=true) */ private $amazonId; - private $amazonAccessToken; + private $amazonAccessToken; /** * @ORM\Column(name="instagram_id", type="string", length=255, nullable=true) */ private $instagramId; - private $instagramAccessToken; + private $instagramAccessToken; /** * @ORM\Column(name="twitter_id", type="string", length=255, nullable=true) */ private $twitterId; - private $twitterAccessToken; - - /** - * @ORM\Column(name="windows_id", type="string", length=255, nullable=true) - */ - private $windowsId; - private $windowsAccessToken; + private $twitterAccessToken; /** * @ORM\Column(name="yahoo_id", type="string", length=255, nullable=true) */ private $yahooId; - private $yahooAccessToken; - - /** - * @return mixed - */ - public function getAmazonId() { - return $this->amazonId; - } - - /** - * @param mixed $amazonId - * @return User - */ - public function setAmazonId($amazonId) { - $this->amazonId = $amazonId; - return $this; - } - - /** - * @return mixed - */ - public function getAmazonAccessToken() { - return $this->amazonAccessToken; - } - - /** - * @param mixed $amazonAccessToken - * @return User - */ - public function setAmazonAccessToken($amazonAccessToken) { - $this->amazonAccessToken = $amazonAccessToken; - return $this; - } - - /** - * @return mixed - */ - public function getFacebookId() { - return $this->facebookId; - } - - /** - * @param mixed $facebookId - * @return User - */ - public function setFacebookId($facebookId) { - $this->facebookId = $facebookId; - return $this; - } - - /** - * @return mixed - */ - public function getFacebookAccessToken() { - return $this->facebookAccessToken; - } - - /** - * @param mixed $facebookAccessToken - * @return User - */ - public function setFacebookAccessToken($facebookAccessToken) { - $this->facebookAccessToken = $facebookAccessToken; - return $this; - } - - /** - * @return mixed - */ - public function getGoogleId() { - return $this->googleId; - } - - /** - * @param mixed $googleId - * @return User - */ - public function setGoogleId($googleId) { - $this->googleId = $googleId; - return $this; - } - - /** - * @return mixed - */ - public function getGoogleAccessToken() { - return $this->googleAccessToken; - } - - /** - * @param mixed $googleAccessToken - * @return User - */ - public function setGoogleAccessToken($googleAccessToken) { - $this->googleAccessToken = $googleAccessToken; - return $this; - } - - /** - * @return mixed - */ - public function getInstagramId() { - return $this->instagramId; - } - - /** - * @param mixed $instagramId - * @return User - */ - public function setInstagramId($instagramId) { - $this->instagramId = $instagramId; - return $this; - } - - /** - * @return mixed - */ - public function getInstagramAccessToken() { - return $this->instagramAccessToken; - } - - /** - * @param mixed $instagramAccessToken - * @return User - */ - public function setInstagramAccessToken($instagramAccessToken) { - $this->instagramAccessToken = $instagramAccessToken; - return $this; - } - - /** - * @return mixed - */ - public function getTwitterId() { - return $this->twitterId; - } - - /** - * @param mixed $twitterId - * @return User - */ - public function setTwitterId($twitterId) { - $this->twitterId = $twitterId; - return $this; - } - - /** - * @return mixed - */ - public function getTwitterAccessToken() { - return $this->twitterAccessToken; - } - - /** - * @param mixed $twitterAccessToken - * @return User - */ - public function setTwitterAccessToken($twitterAccessToken) { - $this->twitterAccessToken = $twitterAccessToken; - return $this; - } - - /** - * @return mixed - */ - public function getWindowsId() { - return $this->windowsId; - } - - /** - * @param mixed $windowsId - * @return User - */ - public function setWindowsId($windowsId) { - $this->windowsId = $windowsId; - return $this; - } - - /** - * @return mixed - */ - public function getWindowsAccessToken() { - return $this->windowsAccessToken; - } - - /** - * @param mixed $windowsAccessToken - * @return User - */ - public function setWindowsAccessToken($windowsAccessToken) { - $this->windowsAccessToken = $windowsAccessToken; - return $this; - } - - /** - * @return mixed - */ - public function getYahooId() { - return $this->yahooId; - } - - /** - * @param mixed $yahooId - * @return User - */ - public function setYahooId($yahooId) { - $this->yahooId = $yahooId; - return $this; - } - - /** - * @return mixed - */ - public function getYahooAccessToken() { - return $this->yahooAccessToken; - } - - /** - * @param mixed $yahooAccessToken - * @return User - */ - public function setYahooAccessToken($yahooAccessToken) { - $this->yahooAccessToken = $yahooAccessToken; - return $this; - } - + private $yahooAccessToken; public function __construct() { @@ -396,6 +126,247 @@ class User extends \FOS\UserBundle\Model\User parent::__construct(); } + /** + * @return mixed + */ + public function getAmazonId() + { + return $this->amazonId; + } + + /** + * @param mixed $amazonId + * + * @return User + */ + public function setAmazonId($amazonId) + { + $this->amazonId = $amazonId; + + return $this; + } + + /** + * @return mixed + */ + public function getAmazonAccessToken() + { + return $this->amazonAccessToken; + } + + /** + * @param mixed $amazonAccessToken + * + * @return User + */ + public function setAmazonAccessToken($amazonAccessToken) + { + $this->amazonAccessToken = $amazonAccessToken; + + return $this; + } + + /** + * @return mixed + */ + public function getFacebookId() + { + return $this->facebookId; + } + + /** + * @param mixed $facebookId + * + * @return User + */ + public function setFacebookId($facebookId) + { + $this->facebookId = $facebookId; + + return $this; + } + + /** + * @return mixed + */ + public function getFacebookAccessToken() + { + return $this->facebookAccessToken; + } + + /** + * @param mixed $facebookAccessToken + * + * @return User + */ + public function setFacebookAccessToken($facebookAccessToken) + { + $this->facebookAccessToken = $facebookAccessToken; + + return $this; + } + + /** + * @return mixed + */ + public function getGoogleId() + { + return $this->googleId; + } + + /** + * @param mixed $googleId + * + * @return User + */ + public function setGoogleId($googleId) + { + $this->googleId = $googleId; + + return $this; + } + + /** + * @return mixed + */ + public function getGoogleAccessToken() + { + return $this->googleAccessToken; + } + + /** + * @param mixed $googleAccessToken + * + * @return User + */ + public function setGoogleAccessToken($googleAccessToken) + { + $this->googleAccessToken = $googleAccessToken; + + return $this; + } + + /** + * @return mixed + */ + public function getInstagramId() + { + return $this->instagramId; + } + + /** + * @param mixed $instagramId + * + * @return User + */ + public function setInstagramId($instagramId) + { + $this->instagramId = $instagramId; + + return $this; + } + + /** + * @return mixed + */ + public function getInstagramAccessToken() + { + return $this->instagramAccessToken; + } + + /** + * @param mixed $instagramAccessToken + * + * @return User + */ + public function setInstagramAccessToken($instagramAccessToken) + { + $this->instagramAccessToken = $instagramAccessToken; + + return $this; + } + + /** + * @return mixed + */ + public function getTwitterId() + { + return $this->twitterId; + } + + /** + * @param mixed $twitterId + * + * @return User + */ + public function setTwitterId($twitterId) + { + $this->twitterId = $twitterId; + + return $this; + } + + /** + * @return mixed + */ + public function getTwitterAccessToken() + { + return $this->twitterAccessToken; + } + + /** + * @param mixed $twitterAccessToken + * + * @return User + */ + public function setTwitterAccessToken($twitterAccessToken) + { + $this->twitterAccessToken = $twitterAccessToken; + + return $this; + } + + + /** + * @return mixed + */ + public function getYahooId() + { + return $this->yahooId; + } + + /** + * @param mixed $yahooId + * + * @return User + */ + public function setYahooId($yahooId) + { + $this->yahooId = $yahooId; + + return $this; + } + + /** + * @return mixed + */ + public function getYahooAccessToken() + { + return $this->yahooAccessToken; + } + + /** + * @param mixed $yahooAccessToken + * + * @return User + */ + public function setYahooAccessToken($yahooAccessToken) + { + $this->yahooAccessToken = $yahooAccessToken; + + return $this; + } + /** * Get id. * @@ -407,51 +378,27 @@ class User extends \FOS\UserBundle\Model\User } /** - * Set firstName. + * Set Name. * - * @param string $firstName + * @param string $name * * @return User */ - public function setFirstName($firstName) + public function setName($name) { - $this->firstName = $firstName; + $this->name = $name; return $this; } /** - * Get firstName. + * Get Name. * * @return string */ - public function getFirstName() + public function getName() { - return $this->firstName; - } - - /** - * Set lastName. - * - * @param string $lastName - * - * @return User - */ - public function setLastName($lastName) - { - $this->lastName = $lastName; - - return $this; - } - - /** - * Get lastName. - * - * @return string - */ - public function getLastName() - { - return $this->lastName; + return $this->name; } /** @@ -462,53 +409,6 @@ class User extends \FOS\UserBundle\Model\User return $this->username; } - /** - * Set family. - * - * @param bool $family - * - * @return User - */ - public function setFamily($family) - { - $this->family = $family; - - return $this; - } - - /** - * Get family. - * - * @return bool - */ - public function getFamily() - { - return $this->family; - } - - /** - * Set familySide. - * - * @param string $familySide - * - * @return User - */ - public function setFamilySide($familySide) - { - $this->familySide = $familySide; - - return $this; - } - - /** - * Get familySide. - * - * @return string - */ - public function getFamilySide() - { - return $this->familySide; - } /** * Set email. @@ -582,7 +482,7 @@ class User extends \FOS\UserBundle\Model\User public function setUserToken($userToken) { $this->userToken = $userToken; - + return $this; } @@ -686,17 +586,4 @@ class User extends \FOS\UserBundle\Model\User return $this->rsvp; } - public function getRoles() - { - return ['ROLE_USER']; - } - - public function eraseCredentials() - { - } - - public function getSalt() - { - return null; - } } diff --git a/src/Sikofitt/DoughnutWeddingBundle/EventListener/RedirectOnUserRegisterListener.php b/src/Sikofitt/DoughnutWeddingBundle/EventListener/RedirectOnUserRegisterListener.php new file mode 100644 index 0000000..b15dd5c --- /dev/null +++ b/src/Sikofitt/DoughnutWeddingBundle/EventListener/RedirectOnUserRegisterListener.php @@ -0,0 +1,31 @@ +router = $router; + } + + public function onKernelRequest(FormEvent $event) + { + $url = $this->router->generate('sikofitt_doughnutwedding_default_index'); + $event->setResponse(new RedirectResponse($url)); + } +} \ No newline at end of file diff --git a/src/Sikofitt/DoughnutWeddingBundle/EventListener/UserRedirectOnLoggedInListener.php b/src/Sikofitt/DoughnutWeddingBundle/EventListener/UserRedirectOnLoggedInListener.php new file mode 100644 index 0000000..0797acb --- /dev/null +++ b/src/Sikofitt/DoughnutWeddingBundle/EventListener/UserRedirectOnLoggedInListener.php @@ -0,0 +1,113 @@ +. + */ + +namespace Sikofitt\DoughnutWeddingBundle\EventListener; + +use Symfony\Bundle\FrameworkBundle\Routing\Router; +use Symfony\Component\{ + EventDispatcher\EventDispatcherInterface, HttpFoundation\RedirectResponse, HttpKernel\Event\GetResponseEvent, Security\Core\Authentication\Token\Storage\TokenStorageInterface +}; + +class UserRedirectOnLoggedInListener +{ + /** + * @var TokenStorageInterface + */ + private $tokenStorage; + + /** + * @var Router + */ + private $router; + + /** + * UserRedirectOnLoggedInListener constructor. + * + * @param TokenStorageInterface $tokenStorage + * @param Router $router + */ + public function __construct( + TokenStorageInterface $tokenStorage, + Router $router + ) { + $this->tokenStorage = $tokenStorage; + $this->router = $router; + } + + /** + * Redirects logged in users to the profile page, from the login page. + * + * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event + * + * @throws \InvalidArgumentException + */ + public function onKernelRequest(GetResponseEvent $event): void + { + + $token = $this->tokenStorage->getToken(); + + if (null !== $token) { + $pathInfo = $event->getRequest()->getPathInfo(); + $routeInformation = $this->router->match($pathInfo); + $profile = $this->router->generate('fos_user_profile_show'); + + if ( + true === $this->shouldRedirectRoute($routeInformation) && + null !== $token->getUser() && + false === strpos($token->getUsername(), 'anon') + ) { + $event->setResponse(new RedirectResponse($profile)); + } + } + } + + /** + * Decides if we should redirect the current route + * depending on whether or not we are logged in. + * + * @param array $routeInformation + * + * @return bool + */ + private function shouldRedirectRoute(array $routeInformation): bool + { + + return true === in_array( + $routeInformation['_route'], + $this->getRedirectRoutes(), + true + ); + } + + /** + * @return array + * Routes that we should redirect + */ + private function getRedirectRoutes(): array + { + return [ + //'fos_user_security_login', + // 'fos_user_registration_confirmed', + //'hwi_oauth_connect' + ]; + } +} diff --git a/src/Sikofitt/DoughnutWeddingBundle/Form/ProfileEditType.php b/src/Sikofitt/DoughnutWeddingBundle/Form/ProfileEditType.php new file mode 100644 index 0000000..a7ef043 --- /dev/null +++ b/src/Sikofitt/DoughnutWeddingBundle/Form/ProfileEditType.php @@ -0,0 +1,84 @@ +get('email')->getOptions(); + + $builder->remove('current_password'); + //$builder->remove('username'); + $builder->remove('email'); + $emailOptions['attr'] = [ + 'class' => 'uk-input uk-form-large uk-padding-small uk-box-shadow-hover-small', + 'placeholder' => 'Email Address', + ]; + $emailOptions['label_attr'] = [ + 'class' => 'uk-form-label uk-text-primary', + ]; + $builder->add('email', EmailType::class, $emailOptions); + $builder->add('name', TextType::class, [ + 'attr' => [ + 'class' => 'uk-input uk-form-large uk-padding-small uk-box-shadow-hover-small', + 'placeholder' => 'Name', + ], + 'label' => 'Name', + 'label_attr' => [ + 'class' => 'uk-form-label uk-text-primary', + ], + ]); + $builder->add('rsvp', IntegerType::class, [ + 'attr' => [ + 'class' => 'uk-input uk-form-large uk-padding-small uk-box-shadow-hover-small', + 'placeholder' => 'Number of Guests (including yourself)', + ], + 'label' => 'Number of guests? (including yourself)', + 'label_attr' => [ + 'class' => 'uk-form-label uk-text-primary', + ], + ]); + + $builder->get('rsvp') + ->addModelTransformer(new CallbackTransformer( + function (?Rsvp $rsvp) { + if (null === $rsvp) { + return $rsvp; + } + + return $rsvp->getGuests(); + }, + function (Int $rsvpInt) { + $rsvp = new Rsvp(); + $rsvp->setGuests($rsvpInt); + + return $rsvp; + } + )); + } + + public function getParent() + { + return ProfileFormType::class; + } +} \ No newline at end of file diff --git a/src/Sikofitt/DoughnutWeddingBundle/Form/RegistrationType.php b/src/Sikofitt/DoughnutWeddingBundle/Form/RegistrationType.php index bfbda75..9f717a0 100644 --- a/src/Sikofitt/DoughnutWeddingBundle/Form/RegistrationType.php +++ b/src/Sikofitt/DoughnutWeddingBundle/Form/RegistrationType.php @@ -1,60 +1,57 @@ . + */ + namespace Sikofitt\DoughnutWeddingBundle\Form; +use HWI\Bundle\OAuthBundle\OAuth\Response\PathUserResponse; +use Symfony\Component\Form\FormEvent; use FOS\UserBundle\Form\Type\RegistrationFormType; +use FOS\UserBundle\Model\UserManager; use Sikofitt\DoughnutWeddingBundle\Entity\Rsvp; use Sikofitt\DoughnutWeddingBundle\Entity\User; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\CallbackTransformer; use Symfony\Component\Form\Extension\Core\Type\CheckboxType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; -use Symfony\Component\Form\Extension\Core\Type\EmailType; use Symfony\Component\Form\Extension\Core\Type\IntegerType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\OptionsResolver\OptionsResolver; class RegistrationType extends AbstractType { + private $userManger; + + public function __construct(UserManager $userManager) + { + $this->userManger = $userManager; + } + public function buildForm(FormBuilderInterface $builder, array $options) { - - - $builder->add('first_name', TextType::class) - ->add('last_name', TextType::class) - ->add('familyside', ChoiceType::class, [ - 'choices' => [ - User::ERIC_SIDE => User::ERIC_SIDE, - User::KATRINA_SIDE => User::KATRINA_SIDE, - ], - 'attr' => [ - 'class' => 'uk-select uk-form-large uk-box-shadow-hover-small', - 'style' => 'padding-left:16px;', - ], - 'label' => 'Who are you coming for?', - 'label_attr' => [ - 'class' => 'uk-form-label uk-text-primary', - 'style' => 'font-size:1.25rem; margin-left:15px;' - ], - ]) - ->add('family', CheckboxType::class, [ - 'label' => 'Are you an immediate family member?', - 'required' => false, - 'attr' => [ - 'class' => 'uk-checkbox uk-box-shadow-hover-small', - ], - 'label_attr' => [ - 'class' => 'uk-form-label uk-text-primary', - 'style' => 'font-size:1.25rem; margin-left:15px;' - ], - ]) - + $builder->add('name', TextType::class) ->add('rsvp', IntegerType::class, [ 'attr' => [ - 'class' => 'uk-input uk-form-large uk-padding-small uk-box-shadow-hover-small', 'placeholder' => 'Number of Guests (including yourself)', ], @@ -62,31 +59,41 @@ class RegistrationType extends AbstractType 'label_attr' => [ 'class' => 'uk-form-label uk-text-primary', ], - ]); + ])->remove('username'); - $builder->get('rsvp') + $builder->addEventListener(FormEvents::SUBMIT, function(FormEvent $event) { + + $user = $event->getData(); + $user->setUsername($user->getEmail()); + $this->userManger->updateCanonicalFields($user); + }); + + $builder->get('rsvp') ->addModelTransformer(new CallbackTransformer( function (?Rsvp $rsvp) { - if (null === $rsvp) { - return $rsvp; - } - return $rsvp->getGuests(); + if (null === $rsvp) { + return $rsvp; + } + + return $rsvp->getGuests(); }, function (Int $rsvpInt) { - $rsvp = new Rsvp(); - $rsvp->setGuests($rsvpInt); - return $rsvp; + $rsvp = new Rsvp(); + $rsvp->setGuests($rsvpInt); + + return $rsvp; } )); } public function configureOptions(OptionsResolver $resolver) { - $resolver->setDefault('attr', ['class' => 'uk-form uk-form-horizontal']); - + $resolver->setDefault('attr', ['class' => 'uk-form uk-form-horizontal']); } - public function getParent() { - return RegistrationFormType::class; + + public function getParent() + { + return RegistrationFormType::class; } public function finishView( @@ -94,11 +101,13 @@ class RegistrationType extends AbstractType FormInterface $form, array $options ) { - $view->children['email']->vars['attr']['class'] = 'uk-input'; - $view->children['email']->vars['label_attr']['class'] = 'uk-form-label'; + $view->children['email']->vars['attr']['class'] = 'uk-input'; + $view->children['email']->vars['label_attr']['class'] = 'uk-form-label'; + $p = new PathUserResponse(); + //$p->getResourceOwner()->getName(); } - public function getBlockPrefix() + public function getBlockPrefix() { return 'sikofitt_doughnut_wedding_bundle_registration_type'; } diff --git a/src/Sikofitt/DoughnutWeddingBundle/Form/RsvpType.php b/src/Sikofitt/DoughnutWeddingBundle/Form/RsvpType.php index 8e60d3b..c79f323 100644 --- a/src/Sikofitt/DoughnutWeddingBundle/Form/RsvpType.php +++ b/src/Sikofitt/DoughnutWeddingBundle/Form/RsvpType.php @@ -93,7 +93,6 @@ class RsvpType extends AbstractType ]) ->add('familyside', ChoiceType::class, [ 'choices' => [ - User::ERIC_SIDE => User::ERIC_SIDE, User::KATRINA_SIDE => User::KATRINA_SIDE, ], @@ -111,11 +110,10 @@ class RsvpType extends AbstractType 'required' => false, 'attr' => [ 'class' => 'uk-checkbox uk-box-shadow-hover-small', - 'style' => 'padding-left:16px;' + 'style' => 'padding-left:16px;', ], 'label_attr' => [ 'class' => 'uk-form-label uk-text-primary', - ], ]); $builder->get('rsvp') diff --git a/src/Sikofitt/DoughnutWeddingBundle/Resources/translations/SikofittDoughnutweddingBundle.en.yml b/src/Sikofitt/DoughnutWeddingBundle/Resources/translations/SikofittDoughnutweddingBundle.en.yml new file mode 100644 index 0000000..9778413 --- /dev/null +++ b/src/Sikofitt/DoughnutWeddingBundle/Resources/translations/SikofittDoughnutweddingBundle.en.yml @@ -0,0 +1 @@ +profile.name: Name \ No newline at end of file diff --git a/src/Sikofitt/DoughnutWeddingBundle/SikofittDoughnutWeddingBundle.php b/src/Sikofitt/DoughnutWeddingBundle/SikofittDoughnutWeddingBundle.php index 522a2e9..4e343f1 100644 --- a/src/Sikofitt/DoughnutWeddingBundle/SikofittDoughnutWeddingBundle.php +++ b/src/Sikofitt/DoughnutWeddingBundle/SikofittDoughnutWeddingBundle.php @@ -1,5 +1,23 @@ . + */ + namespace Sikofitt\DoughnutWeddingBundle; use Symfony\Component\HttpKernel\Bundle\Bundle; diff --git a/src/Sikofitt/DoughnutWeddingBundle/Tests/Controller/DefaultControllerTest.php b/src/Sikofitt/DoughnutWeddingBundle/Tests/Controller/DefaultControllerTest.php index c33ee11..fcbfd4b 100644 --- a/src/Sikofitt/DoughnutWeddingBundle/Tests/Controller/DefaultControllerTest.php +++ b/src/Sikofitt/DoughnutWeddingBundle/Tests/Controller/DefaultControllerTest.php @@ -1,5 +1,23 @@ . + */ + namespace Sikofitt\DoughnutWeddingBundle\Tests\Controller; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; @@ -12,5 +30,4 @@ class DefaultControllerTest extends WebTestCase $crawler = $client->request('GET', '/'); } - } diff --git a/src/Sikofitt/DoughnutWeddingBundle/Tests/Controller/ImageControllerTest.php b/src/Sikofitt/DoughnutWeddingBundle/Tests/Controller/ImageControllerTest.php index 72e45dd..f2aaf69 100644 --- a/src/Sikofitt/DoughnutWeddingBundle/Tests/Controller/ImageControllerTest.php +++ b/src/Sikofitt/DoughnutWeddingBundle/Tests/Controller/ImageControllerTest.php @@ -1,5 +1,23 @@ . + */ + namespace Sikofitt\DoughnutWeddingBundle\Tests\Controller; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; @@ -33,5 +51,4 @@ class ImageControllerTest extends WebTestCase $crawler = $client->request('GET', '/category'); } - } diff --git a/var/SymfonyRequirements.php b/var/SymfonyRequirements.php old mode 100644 new mode 100755 diff --git a/web/app_dev.php b/web/app_dev.php index e76fcac..10e556e 100644 --- a/web/app_dev.php +++ b/web/app_dev.php @@ -10,13 +10,13 @@ use Symfony\Component\Debug\Debug; // This check prevents access to debug front controllers that are deployed by accident to production servers. // Feel free to remove this, extend it, or make something more sophisticated. -if (isset($_SERVER['HTTP_CLIENT_IP']) +/*if (isset($_SERVER['HTTP_CLIENT_IP']) || isset($_SERVER['HTTP_X_FORWARDED_FOR']) || !(in_array(@$_SERVER['REMOTE_ADDR'], ['172.19.0.1','127.0.0.1', '::1']) || php_sapi_name() === 'cli-server') ) { header('HTTP/1.0 403 Forbidden'); exit('You are not allowed to access this file. Check '.basename(__FILE__).' for more information.'); -} +}*/ /** @var \Composer\Autoload\ClassLoader $loader */ $loader = require __DIR__.'/../app/autoload.php'; diff --git a/web/config.php b/web/config.php index 69df43c..b96786b 100644 --- a/web/config.php +++ b/web/config.php @@ -14,13 +14,13 @@ if (!isset($_SERVER['HTTP_HOST'])) { exit('This script cannot be run from the CLI. Run it from a browser.'); } -if (!in_array(@$_SERVER['REMOTE_ADDR'], array( - '127.0.0.1', - '::1', -))) { - header('HTTP/1.0 403 Forbidden'); - exit('This script is only accessible from localhost.'); -} +//if (!in_array(@$_SERVER['REMOTE_ADDR'], array( +// '127.0.0.1', +// '::1', +//))) { +// header('HTTP/1.0 403 Forbidden'); +// exit('This script is only accessible from localhost.'); +//} require_once dirname(__FILE__).'/../var/SymfonyRequirements.php';