From 6c29b298e2cfdc0f21ccdec2d92506c93093911c Mon Sep 17 00:00:00 2001
From: Ilham Firdausi Putra <ilhamfputra31@gmail.com>
Date: Fri, 30 Nov 2018 14:45:54 +0700
Subject: [PATCH] add token input to book detail

---
 app/controllers/Detail.php                    |   2 +-
 app/models/SoapHelper.php                     |   4 +-
 app/models/Token.php                          |   2 +
 app/views/detail.php                          |   7 +-
 composer.json                                 |   5 +
 composer.lock                                 |  75 +++
 example.php                                   |  41 ++
 index.php                                     |   1 +
 public/css/main.css                           |  70 +++
 public/images/profile/32                      | Bin 0 -> 21876 bytes
 public/js/detail.js                           |  14 +-
 public/js/profile.js                          |  11 +
 vendor/autoload.php                           |   7 +
 vendor/composer/ClassLoader.php               | 445 ++++++++++++++++++
 vendor/composer/LICENSE                       |  21 +
 vendor/composer/autoload_classmap.php         |   9 +
 vendor/composer/autoload_namespaces.php       |   9 +
 vendor/composer/autoload_psr4.php             |  11 +
 vendor/composer/autoload_real.php             |  52 ++
 vendor/composer/autoload_static.php           |  39 ++
 vendor/composer/installed.json                |  61 +++
 .../google-authenticator/LICENSE              |  21 +
 .../google-authenticator/Makefile             |  60 +++
 .../google-authenticator/composer.json        |  50 ++
 .../google-authenticator/phpunit.xml.dist     |  40 ++
 .../google-authenticator/sample/example.php   |  41 ++
 .../sample/tmpl/ask-for-otp.php               |  23 +
 .../sample/tmpl/loggedin.php                  |  19 +
 .../sample/tmpl/login-error.php               |   6 +
 .../sample/tmpl/login.php                     |   8 +
 .../sample/tmpl/show-qr.php                   |  11 +
 .../google-authenticator/sample/users.dat     |   1 +
 .../google-authenticator/sample/web/Users.php | 155 ++++++
 .../google-authenticator/sample/web/index.php | 119 +++++
 .../src/FixedBitNotation.php                  | 296 ++++++++++++
 .../src/GoogleAuthenticator.php               | 173 +++++++
 .../src/GoogleAuthenticatorInterface.php      |  44 ++
 .../google-authenticator/src/GoogleQrUrl.php  |  94 ++++
 .../src/RuntimeException.php                  |  46 ++
 39 files changed, 2088 insertions(+), 5 deletions(-)
 create mode 100644 composer.json
 create mode 100644 composer.lock
 create mode 100644 example.php
 create mode 100644 public/images/profile/32
 create mode 100644 public/js/profile.js
 create mode 100644 vendor/autoload.php
 create mode 100644 vendor/composer/ClassLoader.php
 create mode 100644 vendor/composer/LICENSE
 create mode 100644 vendor/composer/autoload_classmap.php
 create mode 100644 vendor/composer/autoload_namespaces.php
 create mode 100644 vendor/composer/autoload_psr4.php
 create mode 100644 vendor/composer/autoload_real.php
 create mode 100644 vendor/composer/autoload_static.php
 create mode 100644 vendor/composer/installed.json
 create mode 100644 vendor/sonata-project/google-authenticator/LICENSE
 create mode 100644 vendor/sonata-project/google-authenticator/Makefile
 create mode 100644 vendor/sonata-project/google-authenticator/composer.json
 create mode 100644 vendor/sonata-project/google-authenticator/phpunit.xml.dist
 create mode 100644 vendor/sonata-project/google-authenticator/sample/example.php
 create mode 100644 vendor/sonata-project/google-authenticator/sample/tmpl/ask-for-otp.php
 create mode 100644 vendor/sonata-project/google-authenticator/sample/tmpl/loggedin.php
 create mode 100644 vendor/sonata-project/google-authenticator/sample/tmpl/login-error.php
 create mode 100644 vendor/sonata-project/google-authenticator/sample/tmpl/login.php
 create mode 100644 vendor/sonata-project/google-authenticator/sample/tmpl/show-qr.php
 create mode 100644 vendor/sonata-project/google-authenticator/sample/users.dat
 create mode 100644 vendor/sonata-project/google-authenticator/sample/web/Users.php
 create mode 100644 vendor/sonata-project/google-authenticator/sample/web/index.php
 create mode 100644 vendor/sonata-project/google-authenticator/src/FixedBitNotation.php
 create mode 100644 vendor/sonata-project/google-authenticator/src/GoogleAuthenticator.php
 create mode 100644 vendor/sonata-project/google-authenticator/src/GoogleAuthenticatorInterface.php
 create mode 100644 vendor/sonata-project/google-authenticator/src/GoogleQrUrl.php
 create mode 100644 vendor/sonata-project/google-authenticator/src/RuntimeException.php

diff --git a/app/controllers/Detail.php b/app/controllers/Detail.php
index 2441e0d..6799ca9 100644
--- a/app/controllers/Detail.php
+++ b/app/controllers/Detail.php
@@ -66,7 +66,7 @@ class Detail extends Controller
         $entityBody = json_decode(file_get_contents('php://input'), true);
         //TODO MASUKKIN KARTU NASABAH ID
         $user = $model_user->readUserById($user_id);
-        $orderid = $soap->buyBook($_COOKIE['bookid'], $entityBody['total'], $user['no_kartu']);
+        $orderid = $soap->buyBook($_COOKIE['bookid'], $entityBody['total'], $user['no_kartu'], $entityBody['token']);
         if ($orderid != -1) {
             $model->createOrder($_COOKIE['bookid'], $user_id, $orderid);
         }
diff --git a/app/models/SoapHelper.php b/app/models/SoapHelper.php
index e391860..bac9da1 100644
--- a/app/models/SoapHelper.php
+++ b/app/models/SoapHelper.php
@@ -49,8 +49,8 @@ class SoapHelper {
         return $output;
     }
 
-    public function buyBook($id, $quantity, $no_rek) {
-        $data = $this->conn->buyBook($id, $quantity, $no_rek);
+    public function buyBook($id, $quantity, $no_rek, $token) {
+        $data = $this->conn->buyBook($id, $quantity, $no_rek, $token);
         $array = json_decode(json_encode($data), True);
         return $array;
     }
diff --git a/app/models/Token.php b/app/models/Token.php
index 5828e97..0bbed2b 100644
--- a/app/models/Token.php
+++ b/app/models/Token.php
@@ -24,6 +24,8 @@ class Token extends Model
         $ip_address = $_SERVER['REMOTE_ADDR'];
         $result = $this->conn->query($sql)->fetch_assoc();
         if ($result['id'] && $result['browser'] == $browser && $result['ip_address'] == $ip_address && time() < (int)$result['time']) {
+            $sql = "UPDATE access_token SET time = " . (time() + (int)1200) . " WHERE token = '" . $token . "';" ;
+            $this->conn->query($sql);
             return $result['id'];
         } else {
             return null;
diff --git a/app/views/detail.php b/app/views/detail.php
index 6ca7e33..ca4457c 100644
--- a/app/views/detail.php
+++ b/app/views/detail.php
@@ -52,6 +52,11 @@
                     <?php } ?>
                 </select>
             </div>
+                <label for="token" class="inp">
+                  <input type="text" id="token" placeholder="&nbsp;">
+                  <span class="label">Token</span>
+                  <span class="border"></span>
+                </label>
             <button onclick="order()" <?php if ($data['book']['price'] == -1) {echo "disabled";}?>>Order</button>
         </section>
         <section id="reviews">
@@ -98,7 +103,7 @@
         <div id="dialog-msg">
             <img id="check-notif" src="/public/images/check.png">
             <div id="msg-detail">
-                <p>Pemesanan Berhasil!</p>
+                <p id="text-msg-detail">Pemesanan Berhasil!</p>
                 <p>Nomor Transaksi : <span id="transaction-number">3<span></p>
             </div>
             <img id="close-notif" onclick="close_notif()" src="/public/images/close.png">
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..707632d
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,5 @@
+{
+    "require": {
+        "sonata-project/google-authenticator": "^2.2"
+    }
+}
diff --git a/composer.lock b/composer.lock
new file mode 100644
index 0000000..f36ec21
--- /dev/null
+++ b/composer.lock
@@ -0,0 +1,75 @@
+{
+    "_readme": [
+        "This file locks the dependencies of your project to a known state",
+        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
+        "This file is @generated automatically"
+    ],
+    "content-hash": "e2df69fcfa963bd7ffe8e358d7e93d70",
+    "packages": [
+        {
+            "name": "sonata-project/google-authenticator",
+            "version": "2.2.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sonata-project/GoogleAuthenticator.git",
+                "reference": "feda53899b26af24e3db2fe7a3e5f053ca483762"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sonata-project/GoogleAuthenticator/zipball/feda53899b26af24e3db2fe7a3e5f053ca483762",
+                "reference": "feda53899b26af24e3db2fe7a3e5f053ca483762",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.1"
+            },
+            "require-dev": {
+                "symfony/phpunit-bridge": "^4.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Google\\Authenticator\\": "src/",
+                    "Sonata\\GoogleAuthenticator\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Christian Stocker",
+                    "email": "me@chregu.tv"
+                },
+                {
+                    "name": "Andre DeMarre",
+                    "homepage": "http://www.devnetwork.net/viewtopic.php?f=50&t=94989"
+                },
+                {
+                    "name": "Thomas Rabaix",
+                    "email": "thomas.rabaix@gmail.com"
+                }
+            ],
+            "description": "Library to integrate Google Authenticator into a PHP project",
+            "homepage": "https://github.com/sonata-project/GoogleAuthenticator",
+            "keywords": [
+                "google authenticator"
+            ],
+            "time": "2018-07-18T22:08:02+00:00"
+        }
+    ],
+    "packages-dev": [],
+    "aliases": [],
+    "minimum-stability": "stable",
+    "stability-flags": [],
+    "prefer-stable": false,
+    "prefer-lowest": false,
+    "platform": [],
+    "platform-dev": []
+}
diff --git a/example.php b/example.php
new file mode 100644
index 0000000..50366d2
--- /dev/null
+++ b/example.php
@@ -0,0 +1,41 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the Sonata Project package.
+ *
+ * (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+include_once __DIR__.'/../src/FixedBitNotation.php';
+include_once __DIR__.'/../src/GoogleAuthenticator.php';
+include_once __DIR__.'/../src/GoogleQrUrl.php';
+
+$secret = 'XVQ2UIGO75XRUKJO';
+$code = '846474';
+
+$g = new \Sonata\GoogleAuthenticator\GoogleAuthenticator();
+
+echo 'Current Code is: ';
+echo $g->getCode($secret);
+
+echo "\n";
+
+echo "Check if $code is valid: ";
+
+if ($g->checkCode($secret, $code)) {
+    echo "YES \n";
+} else {
+    echo "NO \n";
+}
+
+$secret = $g->generateSecret();
+echo "Get a new Secret: $secret \n";
+echo "The QR Code for this secret (to scan with the Google Authenticator App: \n";
+
+echo \Sonata\GoogleAuthenticator\GoogleQrUrl::generate('chregu', $secret, 'GoogleAuthenticatorExample');
+echo "\n";
diff --git a/index.php b/index.php
index afa4a1a..996aa32 100644
--- a/index.php
+++ b/index.php
@@ -1,5 +1,6 @@
 <?php
 
 ini_set('display_errors', 0);
+require_once 'vendor/autoload.php';
 require_once 'app/init.php';
 
diff --git a/public/css/main.css b/public/css/main.css
index 7bfd34b..c9ce394 100644
--- a/public/css/main.css
+++ b/public/css/main.css
@@ -1034,4 +1034,74 @@ body {
     height: 200px !important;
     -webkit-transform: translate(-100px, -100px) scale(1) translate(100px, 100px);
     transform: translate(-100px, -100px) scale(1) translate(100px, 100px);
+}
+
+.qr-code{
+    display: block;
+    text-align: center; 
+    width: 100%;
+    height: 100%;
+    margin: auto;
+    border-radius: 3px;
+}
+
+* .inp {
+    position: relative;
+    margin: auto;
+    width: 100%;
+    max-width: 280px;
+}
+* .inp .label {
+    position: absolute;
+    top: 16px;
+    left: 0;
+    font-size: 16px;
+    color: #9098a9;
+    font-weight: 500;
+    transform-origin: 0 0;
+    transition: all 0.2s ease;
+}
+* .inp .border {
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    height: 2px;
+    width: 100%;
+    background: #07f;
+    transform: scaleX(0);
+    transform-origin: 0 0;
+    transition: all 0.15s ease;
+}
+* .inp input {
+    -webkit-appearance: none;
+    width: 100%;
+    border: 0;
+    font-family: inherit;
+    padding: 12px 0;
+    height: 48px;
+    font-size: 16px;
+    font-weight: 500;
+    border-bottom: 2px solid #c8ccd4;
+    background: none;
+    border-radius: 0;
+    color: #223254;
+    transition: all 0.15s ease;
+}
+* .inp input:hover {
+    background: rgba(34,50,84,0.03);
+}
+* .inp input:not(:placeholder-shown) + span {
+    color: #5a667f;
+    transform: translateY(-26px) scale(0.75);
+}
+* .inp input:focus {
+    background: none;
+    outline: none;
+}
+* .inp input:focus + span {
+    color: #07f;
+    transform: translateY(-26px) scale(0.75);
+}
+* .inp input:focus + span + .border {
+    transform: scaleX(1);
 }
\ No newline at end of file
diff --git a/public/images/profile/32 b/public/images/profile/32
new file mode 100644
index 0000000000000000000000000000000000000000..27cac80db760b8d73f20e7d0401ee5f3b1e5e530
GIT binary patch
literal 21876
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

literal 0
HcmV?d00001

diff --git a/public/js/detail.js b/public/js/detail.js
index f3d3a3c..c0ddcce 100644
--- a/public/js/detail.js
+++ b/public/js/detail.js
@@ -1,5 +1,7 @@
 function order() {
     var total_order_element = document.getElementById("total-order");
+    var token = document.getElementById("token").value;
+    console.log("token: "+token);
     var sum_order = total_order_element.options[total_order_element.selectedIndex].value;
     var xhttp = new XMLHttpRequest();
     xhttp.open("POST", "/detail/order");
@@ -7,11 +9,21 @@ function order() {
     xhttp.onreadystatechange = function() {
         console.log(this.responseText);
         if (this.readyState == 4 && this.status == 200 && this.responseText != -1) {
+            document.getElementById("text-msg-detail").innerHTML = "Pemesanan Berhasil!";
             document.getElementById("transaction-number").innerHTML = this.responseText;
             document.getElementById("notif").setAttribute("style", "display: flex");
+            document.getElementById("check-notif").src = "/public/images/check.png";
+        } else {
+            document.getElementById("text-msg-detail").innerHTML = "Pemesanan Gagal!";
+            document.getElementById("transaction-number").innerHTML = -1;
+            document.getElementById("notif").setAttribute("style", "display: flex");
+            document.getElementById("check-notif").src = "/public/images/close.png";
+
         }
     }
-    xhttp.send(JSON.stringify({total : sum_order}));
+    xhttp.send(JSON.stringify({
+        total : sum_order,
+        token : token}));
 }
 
 function close_notif() {
diff --git a/public/js/profile.js b/public/js/profile.js
new file mode 100644
index 0000000..d26153e
--- /dev/null
+++ b/public/js/profile.js
@@ -0,0 +1,11 @@
+// console.log("No kartu: " + document.getElementById("no-kartu").value);
+var xhttp = new XMLHttpRequest();
+xhttp.onreadystatechange = function() {
+    if (this.readyState == 4 && this.status == 200) {
+        var response = JSON.parse(this.responseText);
+        document.getElementById("qr-img").src = response.values
+    }
+}
+xhttp.open("POST", "http://localhost:3000/qrcode", true);
+xhttp.setRequestHeader("Content-type", "application/json");
+xhttp.send(JSON.stringify({ "no_kartu": document.getElementById("no-kartu").value }));
diff --git a/vendor/autoload.php b/vendor/autoload.php
new file mode 100644
index 0000000..46ffb4c
--- /dev/null
+++ b/vendor/autoload.php
@@ -0,0 +1,7 @@
+<?php
+
+// autoload.php @generated by Composer
+
+require_once __DIR__ . '/composer/autoload_real.php';
+
+return ComposerAutoloaderInitae14d3cd7eb3d58ce5dbc9a906ade70c::getLoader();
diff --git a/vendor/composer/ClassLoader.php b/vendor/composer/ClassLoader.php
new file mode 100644
index 0000000..fce8549
--- /dev/null
+++ b/vendor/composer/ClassLoader.php
@@ -0,0 +1,445 @@
+<?php
+
+/*
+ * This file is part of Composer.
+ *
+ * (c) Nils Adermann <naderman@naderman.de>
+ *     Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Composer\Autoload;
+
+/**
+ * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
+ *
+ *     $loader = new \Composer\Autoload\ClassLoader();
+ *
+ *     // register classes with namespaces
+ *     $loader->add('Symfony\Component', __DIR__.'/component');
+ *     $loader->add('Symfony',           __DIR__.'/framework');
+ *
+ *     // activate the autoloader
+ *     $loader->register();
+ *
+ *     // to enable searching the include path (eg. for PEAR packages)
+ *     $loader->setUseIncludePath(true);
+ *
+ * In this example, if you try to use a class in the Symfony\Component
+ * namespace or one of its children (Symfony\Component\Console for instance),
+ * the autoloader will first look for the class under the component/
+ * directory, and it will then fallback to the framework/ directory if not
+ * found before giving up.
+ *
+ * This class is loosely based on the Symfony UniversalClassLoader.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Jordi Boggiano <j.boggiano@seld.be>
+ * @see    http://www.php-fig.org/psr/psr-0/
+ * @see    http://www.php-fig.org/psr/psr-4/
+ */
+class ClassLoader
+{
+    // PSR-4
+    private $prefixLengthsPsr4 = array();
+    private $prefixDirsPsr4 = array();
+    private $fallbackDirsPsr4 = array();
+
+    // PSR-0
+    private $prefixesPsr0 = array();
+    private $fallbackDirsPsr0 = array();
+
+    private $useIncludePath = false;
+    private $classMap = array();
+    private $classMapAuthoritative = false;
+    private $missingClasses = array();
+    private $apcuPrefix;
+
+    public function getPrefixes()
+    {
+        if (!empty($this->prefixesPsr0)) {
+            return call_user_func_array('array_merge', $this->prefixesPsr0);
+        }
+
+        return array();
+    }
+
+    public function getPrefixesPsr4()
+    {
+        return $this->prefixDirsPsr4;
+    }
+
+    public function getFallbackDirs()
+    {
+        return $this->fallbackDirsPsr0;
+    }
+
+    public function getFallbackDirsPsr4()
+    {
+        return $this->fallbackDirsPsr4;
+    }
+
+    public function getClassMap()
+    {
+        return $this->classMap;
+    }
+
+    /**
+     * @param array $classMap Class to filename map
+     */
+    public function addClassMap(array $classMap)
+    {
+        if ($this->classMap) {
+            $this->classMap = array_merge($this->classMap, $classMap);
+        } else {
+            $this->classMap = $classMap;
+        }
+    }
+
+    /**
+     * Registers a set of PSR-0 directories for a given prefix, either
+     * appending or prepending to the ones previously set for this prefix.
+     *
+     * @param string       $prefix  The prefix
+     * @param array|string $paths   The PSR-0 root directories
+     * @param bool         $prepend Whether to prepend the directories
+     */
+    public function add($prefix, $paths, $prepend = false)
+    {
+        if (!$prefix) {
+            if ($prepend) {
+                $this->fallbackDirsPsr0 = array_merge(
+                    (array) $paths,
+                    $this->fallbackDirsPsr0
+                );
+            } else {
+                $this->fallbackDirsPsr0 = array_merge(
+                    $this->fallbackDirsPsr0,
+                    (array) $paths
+                );
+            }
+
+            return;
+        }
+
+        $first = $prefix[0];
+        if (!isset($this->prefixesPsr0[$first][$prefix])) {
+            $this->prefixesPsr0[$first][$prefix] = (array) $paths;
+
+            return;
+        }
+        if ($prepend) {
+            $this->prefixesPsr0[$first][$prefix] = array_merge(
+                (array) $paths,
+                $this->prefixesPsr0[$first][$prefix]
+            );
+        } else {
+            $this->prefixesPsr0[$first][$prefix] = array_merge(
+                $this->prefixesPsr0[$first][$prefix],
+                (array) $paths
+            );
+        }
+    }
+
+    /**
+     * Registers a set of PSR-4 directories for a given namespace, either
+     * appending or prepending to the ones previously set for this namespace.
+     *
+     * @param string       $prefix  The prefix/namespace, with trailing '\\'
+     * @param array|string $paths   The PSR-4 base directories
+     * @param bool         $prepend Whether to prepend the directories
+     *
+     * @throws \InvalidArgumentException
+     */
+    public function addPsr4($prefix, $paths, $prepend = false)
+    {
+        if (!$prefix) {
+            // Register directories for the root namespace.
+            if ($prepend) {
+                $this->fallbackDirsPsr4 = array_merge(
+                    (array) $paths,
+                    $this->fallbackDirsPsr4
+                );
+            } else {
+                $this->fallbackDirsPsr4 = array_merge(
+                    $this->fallbackDirsPsr4,
+                    (array) $paths
+                );
+            }
+        } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
+            // Register directories for a new namespace.
+            $length = strlen($prefix);
+            if ('\\' !== $prefix[$length - 1]) {
+                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+            }
+            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
+            $this->prefixDirsPsr4[$prefix] = (array) $paths;
+        } elseif ($prepend) {
+            // Prepend directories for an already registered namespace.
+            $this->prefixDirsPsr4[$prefix] = array_merge(
+                (array) $paths,
+                $this->prefixDirsPsr4[$prefix]
+            );
+        } else {
+            // Append directories for an already registered namespace.
+            $this->prefixDirsPsr4[$prefix] = array_merge(
+                $this->prefixDirsPsr4[$prefix],
+                (array) $paths
+            );
+        }
+    }
+
+    /**
+     * Registers a set of PSR-0 directories for a given prefix,
+     * replacing any others previously set for this prefix.
+     *
+     * @param string       $prefix The prefix
+     * @param array|string $paths  The PSR-0 base directories
+     */
+    public function set($prefix, $paths)
+    {
+        if (!$prefix) {
+            $this->fallbackDirsPsr0 = (array) $paths;
+        } else {
+            $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
+        }
+    }
+
+    /**
+     * Registers a set of PSR-4 directories for a given namespace,
+     * replacing any others previously set for this namespace.
+     *
+     * @param string       $prefix The prefix/namespace, with trailing '\\'
+     * @param array|string $paths  The PSR-4 base directories
+     *
+     * @throws \InvalidArgumentException
+     */
+    public function setPsr4($prefix, $paths)
+    {
+        if (!$prefix) {
+            $this->fallbackDirsPsr4 = (array) $paths;
+        } else {
+            $length = strlen($prefix);
+            if ('\\' !== $prefix[$length - 1]) {
+                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+            }
+            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
+            $this->prefixDirsPsr4[$prefix] = (array) $paths;
+        }
+    }
+
+    /**
+     * Turns on searching the include path for class files.
+     *
+     * @param bool $useIncludePath
+     */
+    public function setUseIncludePath($useIncludePath)
+    {
+        $this->useIncludePath = $useIncludePath;
+    }
+
+    /**
+     * Can be used to check if the autoloader uses the include path to check
+     * for classes.
+     *
+     * @return bool
+     */
+    public function getUseIncludePath()
+    {
+        return $this->useIncludePath;
+    }
+
+    /**
+     * Turns off searching the prefix and fallback directories for classes
+     * that have not been registered with the class map.
+     *
+     * @param bool $classMapAuthoritative
+     */
+    public function setClassMapAuthoritative($classMapAuthoritative)
+    {
+        $this->classMapAuthoritative = $classMapAuthoritative;
+    }
+
+    /**
+     * Should class lookup fail if not found in the current class map?
+     *
+     * @return bool
+     */
+    public function isClassMapAuthoritative()
+    {
+        return $this->classMapAuthoritative;
+    }
+
+    /**
+     * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
+     *
+     * @param string|null $apcuPrefix
+     */
+    public function setApcuPrefix($apcuPrefix)
+    {
+        $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
+    }
+
+    /**
+     * The APCu prefix in use, or null if APCu caching is not enabled.
+     *
+     * @return string|null
+     */
+    public function getApcuPrefix()
+    {
+        return $this->apcuPrefix;
+    }
+
+    /**
+     * Registers this instance as an autoloader.
+     *
+     * @param bool $prepend Whether to prepend the autoloader or not
+     */
+    public function register($prepend = false)
+    {
+        spl_autoload_register(array($this, 'loadClass'), true, $prepend);
+    }
+
+    /**
+     * Unregisters this instance as an autoloader.
+     */
+    public function unregister()
+    {
+        spl_autoload_unregister(array($this, 'loadClass'));
+    }
+
+    /**
+     * Loads the given class or interface.
+     *
+     * @param  string    $class The name of the class
+     * @return bool|null True if loaded, null otherwise
+     */
+    public function loadClass($class)
+    {
+        if ($file = $this->findFile($class)) {
+            includeFile($file);
+
+            return true;
+        }
+    }
+
+    /**
+     * Finds the path to the file where the class is defined.
+     *
+     * @param string $class The name of the class
+     *
+     * @return string|false The path if found, false otherwise
+     */
+    public function findFile($class)
+    {
+        // class map lookup
+        if (isset($this->classMap[$class])) {
+            return $this->classMap[$class];
+        }
+        if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
+            return false;
+        }
+        if (null !== $this->apcuPrefix) {
+            $file = apcu_fetch($this->apcuPrefix.$class, $hit);
+            if ($hit) {
+                return $file;
+            }
+        }
+
+        $file = $this->findFileWithExtension($class, '.php');
+
+        // Search for Hack files if we are running on HHVM
+        if (false === $file && defined('HHVM_VERSION')) {
+            $file = $this->findFileWithExtension($class, '.hh');
+        }
+
+        if (null !== $this->apcuPrefix) {
+            apcu_add($this->apcuPrefix.$class, $file);
+        }
+
+        if (false === $file) {
+            // Remember that this class does not exist.
+            $this->missingClasses[$class] = true;
+        }
+
+        return $file;
+    }
+
+    private function findFileWithExtension($class, $ext)
+    {
+        // PSR-4 lookup
+        $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
+
+        $first = $class[0];
+        if (isset($this->prefixLengthsPsr4[$first])) {
+            $subPath = $class;
+            while (false !== $lastPos = strrpos($subPath, '\\')) {
+                $subPath = substr($subPath, 0, $lastPos);
+                $search = $subPath . '\\';
+                if (isset($this->prefixDirsPsr4[$search])) {
+                    $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
+                    foreach ($this->prefixDirsPsr4[$search] as $dir) {
+                        if (file_exists($file = $dir . $pathEnd)) {
+                            return $file;
+                        }
+                    }
+                }
+            }
+        }
+
+        // PSR-4 fallback dirs
+        foreach ($this->fallbackDirsPsr4 as $dir) {
+            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
+                return $file;
+            }
+        }
+
+        // PSR-0 lookup
+        if (false !== $pos = strrpos($class, '\\')) {
+            // namespaced class name
+            $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
+                . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
+        } else {
+            // PEAR-like class name
+            $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
+        }
+
+        if (isset($this->prefixesPsr0[$first])) {
+            foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
+                if (0 === strpos($class, $prefix)) {
+                    foreach ($dirs as $dir) {
+                        if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
+                            return $file;
+                        }
+                    }
+                }
+            }
+        }
+
+        // PSR-0 fallback dirs
+        foreach ($this->fallbackDirsPsr0 as $dir) {
+            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
+                return $file;
+            }
+        }
+
+        // PSR-0 include paths.
+        if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
+            return $file;
+        }
+
+        return false;
+    }
+}
+
+/**
+ * Scope isolated include.
+ *
+ * Prevents access to $this/self from included files.
+ */
+function includeFile($file)
+{
+    include $file;
+}
diff --git a/vendor/composer/LICENSE b/vendor/composer/LICENSE
new file mode 100644
index 0000000..f27399a
--- /dev/null
+++ b/vendor/composer/LICENSE
@@ -0,0 +1,21 @@
+
+Copyright (c) Nils Adermann, Jordi Boggiano
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php
new file mode 100644
index 0000000..7a91153
--- /dev/null
+++ b/vendor/composer/autoload_classmap.php
@@ -0,0 +1,9 @@
+<?php
+
+// autoload_classmap.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = dirname($vendorDir);
+
+return array(
+);
diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php
new file mode 100644
index 0000000..b7fc012
--- /dev/null
+++ b/vendor/composer/autoload_namespaces.php
@@ -0,0 +1,9 @@
+<?php
+
+// autoload_namespaces.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = dirname($vendorDir);
+
+return array(
+);
diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php
new file mode 100644
index 0000000..c57cc2d
--- /dev/null
+++ b/vendor/composer/autoload_psr4.php
@@ -0,0 +1,11 @@
+<?php
+
+// autoload_psr4.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = dirname($vendorDir);
+
+return array(
+    'Sonata\\GoogleAuthenticator\\' => array($vendorDir . '/sonata-project/google-authenticator/src'),
+    'Google\\Authenticator\\' => array($vendorDir . '/sonata-project/google-authenticator/src'),
+);
diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php
new file mode 100644
index 0000000..6cd5c1f
--- /dev/null
+++ b/vendor/composer/autoload_real.php
@@ -0,0 +1,52 @@
+<?php
+
+// autoload_real.php @generated by Composer
+
+class ComposerAutoloaderInitae14d3cd7eb3d58ce5dbc9a906ade70c
+{
+    private static $loader;
+
+    public static function loadClassLoader($class)
+    {
+        if ('Composer\Autoload\ClassLoader' === $class) {
+            require __DIR__ . '/ClassLoader.php';
+        }
+    }
+
+    public static function getLoader()
+    {
+        if (null !== self::$loader) {
+            return self::$loader;
+        }
+
+        spl_autoload_register(array('ComposerAutoloaderInitae14d3cd7eb3d58ce5dbc9a906ade70c', 'loadClassLoader'), true, true);
+        self::$loader = $loader = new \Composer\Autoload\ClassLoader();
+        spl_autoload_unregister(array('ComposerAutoloaderInitae14d3cd7eb3d58ce5dbc9a906ade70c', 'loadClassLoader'));
+
+        $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
+        if ($useStaticLoader) {
+            require_once __DIR__ . '/autoload_static.php';
+
+            call_user_func(\Composer\Autoload\ComposerStaticInitae14d3cd7eb3d58ce5dbc9a906ade70c::getInitializer($loader));
+        } else {
+            $map = require __DIR__ . '/autoload_namespaces.php';
+            foreach ($map as $namespace => $path) {
+                $loader->set($namespace, $path);
+            }
+
+            $map = require __DIR__ . '/autoload_psr4.php';
+            foreach ($map as $namespace => $path) {
+                $loader->setPsr4($namespace, $path);
+            }
+
+            $classMap = require __DIR__ . '/autoload_classmap.php';
+            if ($classMap) {
+                $loader->addClassMap($classMap);
+            }
+        }
+
+        $loader->register(true);
+
+        return $loader;
+    }
+}
diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php
new file mode 100644
index 0000000..20899b7
--- /dev/null
+++ b/vendor/composer/autoload_static.php
@@ -0,0 +1,39 @@
+<?php
+
+// autoload_static.php @generated by Composer
+
+namespace Composer\Autoload;
+
+class ComposerStaticInitae14d3cd7eb3d58ce5dbc9a906ade70c
+{
+    public static $prefixLengthsPsr4 = array (
+        'S' => 
+        array (
+            'Sonata\\GoogleAuthenticator\\' => 27,
+        ),
+        'G' => 
+        array (
+            'Google\\Authenticator\\' => 21,
+        ),
+    );
+
+    public static $prefixDirsPsr4 = array (
+        'Sonata\\GoogleAuthenticator\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/sonata-project/google-authenticator/src',
+        ),
+        'Google\\Authenticator\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/sonata-project/google-authenticator/src',
+        ),
+    );
+
+    public static function getInitializer(ClassLoader $loader)
+    {
+        return \Closure::bind(function () use ($loader) {
+            $loader->prefixLengthsPsr4 = ComposerStaticInitae14d3cd7eb3d58ce5dbc9a906ade70c::$prefixLengthsPsr4;
+            $loader->prefixDirsPsr4 = ComposerStaticInitae14d3cd7eb3d58ce5dbc9a906ade70c::$prefixDirsPsr4;
+
+        }, null, ClassLoader::class);
+    }
+}
diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json
new file mode 100644
index 0000000..b6b2711
--- /dev/null
+++ b/vendor/composer/installed.json
@@ -0,0 +1,61 @@
+[
+    {
+        "name": "sonata-project/google-authenticator",
+        "version": "2.2.0",
+        "version_normalized": "2.2.0.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/sonata-project/GoogleAuthenticator.git",
+            "reference": "feda53899b26af24e3db2fe7a3e5f053ca483762"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/sonata-project/GoogleAuthenticator/zipball/feda53899b26af24e3db2fe7a3e5f053ca483762",
+            "reference": "feda53899b26af24e3db2fe7a3e5f053ca483762",
+            "shasum": ""
+        },
+        "require": {
+            "php": "^7.1"
+        },
+        "require-dev": {
+            "symfony/phpunit-bridge": "^4.0"
+        },
+        "time": "2018-07-18T22:08:02+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "2.x-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-4": {
+                "Google\\Authenticator\\": "src/",
+                "Sonata\\GoogleAuthenticator\\": "src/"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Christian Stocker",
+                "email": "me@chregu.tv"
+            },
+            {
+                "name": "Andre DeMarre",
+                "homepage": "http://www.devnetwork.net/viewtopic.php?f=50&t=94989"
+            },
+            {
+                "name": "Thomas Rabaix",
+                "email": "thomas.rabaix@gmail.com"
+            }
+        ],
+        "description": "Library to integrate Google Authenticator into a PHP project",
+        "homepage": "https://github.com/sonata-project/GoogleAuthenticator",
+        "keywords": [
+            "google authenticator"
+        ]
+    }
+]
diff --git a/vendor/sonata-project/google-authenticator/LICENSE b/vendor/sonata-project/google-authenticator/LICENSE
new file mode 100644
index 0000000..0135e0b
--- /dev/null
+++ b/vendor/sonata-project/google-authenticator/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2010 Thomas Rabaix
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/sonata-project/google-authenticator/Makefile b/vendor/sonata-project/google-authenticator/Makefile
new file mode 100644
index 0000000..4ae0c63
--- /dev/null
+++ b/vendor/sonata-project/google-authenticator/Makefile
@@ -0,0 +1,60 @@
+# DO NOT EDIT THIS FILE!
+#
+# It's auto-generated by sonata-project/dev-kit package.
+
+all:
+	@echo "Please choose a task."
+.PHONY: all
+
+lint: lint-composer lint-yaml lint-composer lint-xml lint-php
+.PHONY: lint
+
+lint-composer:
+	composer validate
+.PHONY: lint-composer
+
+lint-yaml:
+	yaml-lint --ignore-non-yaml-files --quiet --exclude vendor .
+
+.PHONY: lint-yaml
+
+lint-xml:
+	find . \( -name '*.xml' -or -name '*.xliff' \) \
+		-not -path './vendor/*' \
+		-not -path './src/Resources/public/vendor/*' \
+		| while read xmlFile; \
+	do \
+		XMLLINT_INDENT='    ' xmllint --encode UTF-8 --format "$$xmlFile"|diff - "$$xmlFile"; \
+		if [ $$? -ne 0 ] ;then exit 1; fi; \
+	done
+
+.PHONY: lint-xml
+
+lint-php:
+	php-cs-fixer fix --ansi --verbose --diff --dry-run
+.PHONY: lint-php
+
+cs-fix: cs-fix-php cs-fix-xml
+.PHONY: cs-fix
+
+cs-fix-php:
+	php-cs-fixer fix --verbose
+.PHONY: cs-fix-php
+
+cs-fix-xml:
+	find . \( -name '*.xml' -or -name '*.xliff' \) \
+		-not -path './vendor/*' \
+		-not -path './src/Resources/public/vendor/*' \
+		| while read xmlFile; \
+	do \
+		XMLLINT_INDENT='    ' xmllint --encode UTF-8 --format "$$xmlFile" --output "$$xmlFile"; \
+	done
+.PHONY: cs-fix-xml
+
+test:
+	phpunit -c phpunit.xml.dist --coverage-clover build/logs/clover.xml
+.PHONY: test
+
+docs:
+	cd docs && sphinx-build -W -b html -d _build/doctrees . _build/html
+.PHONY: docs
diff --git a/vendor/sonata-project/google-authenticator/composer.json b/vendor/sonata-project/google-authenticator/composer.json
new file mode 100644
index 0000000..4fbb160
--- /dev/null
+++ b/vendor/sonata-project/google-authenticator/composer.json
@@ -0,0 +1,50 @@
+{
+    "name": "sonata-project/google-authenticator",
+    "type": "library",
+    "description": "Library to integrate Google Authenticator into a PHP project",
+    "keywords": [
+        "google authenticator"
+    ],
+    "homepage": "https://github.com/sonata-project/GoogleAuthenticator",
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Thomas Rabaix",
+            "email": "thomas.rabaix@gmail.com"
+        },
+        {
+            "name": "Christian Stocker",
+            "email": "me@chregu.tv"
+        },
+        {
+            "name": "Andre DeMarre",
+            "homepage": "http://www.devnetwork.net/viewtopic.php?f=50&t=94989"
+        }
+    ],
+    "require": {
+        "php": "^7.1"
+    },
+    "require-dev": {
+        "symfony/phpunit-bridge": "^4.0"
+    },
+    "config": {
+        "sort-packages": true
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "2.x-dev"
+        }
+    },
+    "autoload": {
+        "psr-4": {
+            "Google\\Authenticator\\": "src/",
+            "Sonata\\GoogleAuthenticator\\": "src/"
+        }
+    },
+    "autoload-dev": {
+        "psr-4": {
+            "Google\\Authenticator\\Tests\\": "tests/",
+            "Sonata\\GoogleAuthenticator\\Tests\\": "tests/"
+        }
+    }
+}
diff --git a/vendor/sonata-project/google-authenticator/phpunit.xml.dist b/vendor/sonata-project/google-authenticator/phpunit.xml.dist
new file mode 100644
index 0000000..492b036
--- /dev/null
+++ b/vendor/sonata-project/google-authenticator/phpunit.xml.dist
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+DO NOT EDIT THIS FILE!
+
+It's auto-generated by sonata-project/dev-kit package.
+-->
+
+<phpunit backupGlobals="false"
+         backupStaticAttributes="false"
+         colors="true"
+         convertErrorsToExceptions="true"
+         convertNoticesToExceptions="true"
+         convertWarningsToExceptions="true"
+         processIsolation="false"
+         stopOnFailure="false"
+         syntaxCheck="false"
+         bootstrap="tests/bootstrap.php"
+>
+    <testsuites>
+        <testsuite name="Sonata Google Authenticator Test Suite">
+            <directory suffix="Test.php">./tests/</directory>
+        </testsuite>
+    </testsuites>
+
+    <listeners>
+       <listener class="Symfony\Bridge\PhpUnit\SymfonyTestsListener" />
+    </listeners>
+
+    <filter>
+        <whitelist>
+            <directory suffix=".php">./src/</directory>
+        </whitelist>
+    </filter>
+
+    <php>
+        <ini name="precision" value="8"/>
+    </php>
+
+</phpunit>
diff --git a/vendor/sonata-project/google-authenticator/sample/example.php b/vendor/sonata-project/google-authenticator/sample/example.php
new file mode 100644
index 0000000..50366d2
--- /dev/null
+++ b/vendor/sonata-project/google-authenticator/sample/example.php
@@ -0,0 +1,41 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the Sonata Project package.
+ *
+ * (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+include_once __DIR__.'/../src/FixedBitNotation.php';
+include_once __DIR__.'/../src/GoogleAuthenticator.php';
+include_once __DIR__.'/../src/GoogleQrUrl.php';
+
+$secret = 'XVQ2UIGO75XRUKJO';
+$code = '846474';
+
+$g = new \Sonata\GoogleAuthenticator\GoogleAuthenticator();
+
+echo 'Current Code is: ';
+echo $g->getCode($secret);
+
+echo "\n";
+
+echo "Check if $code is valid: ";
+
+if ($g->checkCode($secret, $code)) {
+    echo "YES \n";
+} else {
+    echo "NO \n";
+}
+
+$secret = $g->generateSecret();
+echo "Get a new Secret: $secret \n";
+echo "The QR Code for this secret (to scan with the Google Authenticator App: \n";
+
+echo \Sonata\GoogleAuthenticator\GoogleQrUrl::generate('chregu', $secret, 'GoogleAuthenticatorExample');
+echo "\n";
diff --git a/vendor/sonata-project/google-authenticator/sample/tmpl/ask-for-otp.php b/vendor/sonata-project/google-authenticator/sample/tmpl/ask-for-otp.php
new file mode 100644
index 0000000..f3e06d4
--- /dev/null
+++ b/vendor/sonata-project/google-authenticator/sample/tmpl/ask-for-otp.php
@@ -0,0 +1,23 @@
+
+<h1>please otp</h1>
+<p>
+<form method="post" action="./">
+<?php if ($debug) {
+    ?>
+    <br/>
+    (Set $debug in index.php to false, if you don't want to have the OTP prefilled (for real life application, for example ;))<br/>
+<?php
+}
+?>
+
+otp: <input name="otp"
+value="<?php
+if ($debug) {
+    $g = new GoogleAuthenticator();
+    echo $g->getCode($user->getSecret());
+}
+?>"/><br/>
+<input type="checkbox" name="remember" id="remember" /><label for="remember"> Remember verification for this computer for 1 day.</label> <br/>
+<input type="submit"/>
+
+</form>
diff --git a/vendor/sonata-project/google-authenticator/sample/tmpl/loggedin.php b/vendor/sonata-project/google-authenticator/sample/tmpl/loggedin.php
new file mode 100644
index 0000000..2a19032
--- /dev/null
+++ b/vendor/sonata-project/google-authenticator/sample/tmpl/loggedin.php
@@ -0,0 +1,19 @@
+
+<p>
+Hello <?php echo $user->getUsername(); ?>
+</p>
+<?php
+if (!isset($_GET['showqr'])) {
+    ?>
+
+<p>
+<a href="?showqr=1">Show QR Code</a>
+</p>
+
+<?php
+}
+?>
+
+<p>
+<a href="?logout=1">Logout</a>
+</p>
diff --git a/vendor/sonata-project/google-authenticator/sample/tmpl/login-error.php b/vendor/sonata-project/google-authenticator/sample/tmpl/login-error.php
new file mode 100644
index 0000000..8d23fd3
--- /dev/null
+++ b/vendor/sonata-project/google-authenticator/sample/tmpl/login-error.php
@@ -0,0 +1,6 @@
+<p>
+Wrong username or password or token.
+</p>
+<p>
+<a href="./">try again</a>
+</p>
diff --git a/vendor/sonata-project/google-authenticator/sample/tmpl/login.php b/vendor/sonata-project/google-authenticator/sample/tmpl/login.php
new file mode 100644
index 0000000..fd81623
--- /dev/null
+++ b/vendor/sonata-project/google-authenticator/sample/tmpl/login.php
@@ -0,0 +1,8 @@
+
+<h1>please login</h1>
+<p>
+<form method="post" action="./">
+username: <input name="username"/><br/>
+password: <input name="password" type="password"/><br/>
+<input type="submit"/>
+</form>
diff --git a/vendor/sonata-project/google-authenticator/sample/tmpl/show-qr.php b/vendor/sonata-project/google-authenticator/sample/tmpl/show-qr.php
new file mode 100644
index 0000000..774a298
--- /dev/null
+++ b/vendor/sonata-project/google-authenticator/sample/tmpl/show-qr.php
@@ -0,0 +1,11 @@
+<h1>Please scan this </h1>
+
+<p> with <a href="http://www.google.com/support/a/bin/answer.py?hl=en&answer=1037451">the Google Authenticator App</a></p>
+
+<p>
+<?php
+$link = \Sonata\GoogleAuthenticator\GoogleQrUrl::generate($user->getUsername(), $secret, 'GoogleAuthenticatorExample');
+?>
+
+<a  href="<?php echo $link; ?>"><img style="border: 0; padding:10px" src="<?php echo $link; ?>"/></a>
+</p>
diff --git a/vendor/sonata-project/google-authenticator/sample/users.dat b/vendor/sonata-project/google-authenticator/sample/users.dat
new file mode 100644
index 0000000..fdcc130
--- /dev/null
+++ b/vendor/sonata-project/google-authenticator/sample/users.dat
@@ -0,0 +1 @@
+{"chregu":{"password":"foobar"}}
\ No newline at end of file
diff --git a/vendor/sonata-project/google-authenticator/sample/web/Users.php b/vendor/sonata-project/google-authenticator/sample/web/Users.php
new file mode 100644
index 0000000..fb169de
--- /dev/null
+++ b/vendor/sonata-project/google-authenticator/sample/web/Users.php
@@ -0,0 +1,155 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the Sonata Project package.
+ *
+ * (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+class Users
+{
+    public function __construct(string $file = '../users.dat')
+    {
+        $this->userFile = $file;
+
+        $this->users = json_decode(file_get_contents($file), true);
+    }
+
+    public function hasSession()
+    {
+        session_start();
+        if (isset($_SESSION['username'])) {
+            return $_SESSION['username'];
+        }
+
+        return false;
+    }
+
+    public function storeData(User $user): void
+    {
+        $this->users[$user->getUsername()] = $user->getData();
+        file_put_contents($this->userFile, json_encode($this->users));
+    }
+
+    public function loadUser($name)
+    {
+        if (isset($this->users[$name])) {
+            return new User($name, $this->users[$name]);
+        }
+
+        return false;
+    }
+}
+
+class User
+{
+    public function __construct($user, $data)
+    {
+        $this->data = $data;
+        $this->user = $user;
+    }
+
+    public function auth($pass)
+    {
+        if ($this->data['password'] === $pass) {
+            return true;
+        }
+
+        return false;
+    }
+
+    public function startSession(): void
+    {
+        $_SESSION['username'] = $this->user;
+    }
+
+    public function doLogin(): void
+    {
+        session_regenerate_id();
+        $_SESSION['loggedin'] = true;
+        $_SESSION['ua'] = $_SERVER['HTTP_USER_AGENT'];
+    }
+
+    public function doOTP(): void
+    {
+        $_SESSION['OTP'] = true;
+    }
+
+    public function isOTP()
+    {
+        if (isset($_SESSION['OTP']) && true == $_SESSION['OTP']) {
+            return true;
+        }
+
+        return false;
+    }
+
+    public function isLoggedIn()
+    {
+        if (isset($_SESSION['loggedin']) && true == $_SESSION['loggedin'] &&
+            isset($_SESSION['ua']) && $_SESSION['ua'] == $_SERVER['HTTP_USER_AGENT']
+        ) {
+            return $_SESSION['username'];
+        }
+
+        return false;
+    }
+
+    public function getUsername()
+    {
+        return $this->user;
+    }
+
+    public function getSecret()
+    {
+        if (isset($this->data['secret'])) {
+            return $this->data['secret'];
+        }
+
+        return false;
+    }
+
+    public function generateSecret()
+    {
+        $g = new \Sonata\GoogleAuthenticator\GoogleAuthenticator();
+        $secret = $g->generateSecret();
+        $this->data['secret'] = $secret;
+
+        return $secret;
+    }
+
+    public function getData()
+    {
+        return $this->data;
+    }
+
+    public function setOTPCookie(): void
+    {
+        $time = floor(time() / (3600 * 24)); // get day number
+        //about using the user agent: It's easy to fake it, but it increases the barrier for stealing and reusing cookies nevertheless
+        // and it doesn't do any harm (except that it's invalid after a browser upgrade, but that may be even intented)
+        $cookie = $time.':'.hash_hmac('sha1', $this->getUsername().':'.$time.':'.$_SERVER['HTTP_USER_AGENT'], $this->getSecret());
+        setcookie('otp', $cookie, time() + (30 * 24 * 3600), null, null, null, true);
+    }
+
+    public function hasValidOTPCookie()
+    {
+        // 0 = tomorrow it is invalid
+        $daysUntilInvalid = 0;
+        $time = (string) floor((time() / (3600 * 24))); // get day number
+        if (isset($_COOKIE['otp'])) {
+            list($otpday, $hash) = explode(':', $_COOKIE['otp']);
+
+            if ($otpday >= $time - $daysUntilInvalid && $hash == hash_hmac('sha1', $this->getUsername().':'.$otpday.':'.$_SERVER['HTTP_USER_AGENT'], $this->getSecret())) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+}
diff --git a/vendor/sonata-project/google-authenticator/sample/web/index.php b/vendor/sonata-project/google-authenticator/sample/web/index.php
new file mode 100644
index 0000000..c039674
--- /dev/null
+++ b/vendor/sonata-project/google-authenticator/sample/web/index.php
@@ -0,0 +1,119 @@
+<?php declare(strict_types=1);
+ob_start(); //i'm too lazy to check when is sent what ;)
+//set session cookie to be read only via http and not by JavaScript
+ini_set('session.cookie_httponly', '1');
+
+include_once __DIR__.'/../../src/GoogleAuthenticator.php';
+include_once __DIR__.'/../../src/GoogleQrUrl.php';
+include_once __DIR__.'/../../src/FixedBitNotation.php';
+include_once 'Users.php';
+
+?>
+<!DOCTYPE HTML>
+<html>
+<head>
+    <title>Google Authenticator in PHP demo</title>
+</head>
+<body>
+<?php
+
+//set this to false, if you don't want the token prefilled
+$debug = true;
+
+$users = new Users();
+//check if the user has a session, if not, show the login screen
+if ($username = $users->hasSession()) {
+    //load the user data from the json storage.
+    $user = $users->loadUser($username);
+    //if he clicked logout, destroy the session and redirect to the startscreen.
+    if (isset($_GET['logout'])) {
+        session_destroy();
+        header('Location: ./');
+    }
+    // check if the user is logged in.
+    if ($user->isLoggedIn()) {
+        include __DIR__.'/../tmpl/loggedin.php';
+        //show the QR code if whished so
+        if (isset($_GET['showqr'])) {
+            $secret = $user->getSecret();
+            include __DIR__.'/../tmpl/show-qr.php';
+        }
+    }
+    //if the user is in the OTP phase and submit the OTP.
+    else {
+        if ($user->isOTP() && isset($_POST['otp'])) {
+            $g = new \Google\Authenticator\GoogleAuthenticator();
+            // check if the submitted token is the right one and log in
+            if ($g->checkCode($user->getSecret(), $_POST['otp'])) {
+                // do log-in the user
+                $user->doLogin();
+                //if the user clicked the "remember the token" checkbox, set the cookie
+                if (isset($_POST['remember']) && $_POST['remember']) {
+                    $user->setOTPCookie();
+                }
+                include __DIR__.'/../tmpl/loggedin.php';
+            }
+            //if the OTP is wrong, destroy the session and tell the user to try again
+            else {
+                session_destroy();
+                include __DIR__.'/../tmpl/login-error.php';
+            }
+        }
+        // if the user is neither logged in nor in the OTP phase, show the login form
+        else {
+            session_destroy();
+            include __DIR__.'/../tmpl/login.php';
+        }
+    }
+    die();
+}
+    //if the username is set in _POST, then we assume the user filled in the login form.
+
+    if (isset($_POST['username'])) {
+        // check if we can load the user (ie. the user exists in our db)
+        $user = $users->loadUser($_POST['username']);
+        if ($user) {
+            //try to authenticate the password and start the session if it's correct.
+            if ($user->auth($_POST['password'])) {
+                $user->startSession();
+                //check if the user has a valid OTP cookie, so we don't have to
+                // ask for the current token and can directly log in
+                if ($user->hasValidOTPCookie()) {
+                    include __DIR__.'/../tmpl/loggedin.php';
+                    $user->doLogin();
+                }
+                // try to get the users' secret from the db,
+                //  if he doesn't have one, generate one, store it and show it.
+                else {
+                    if (!$user->getSecret()) {
+                        include __DIR__.'/../tmpl/loggedin.php';
+
+                        $secret = $user->generateSecret();
+                        $users->storeData($user);
+                        $user->doLogin();
+                        include __DIR__.'/../tmpl/show-qr.php';
+                    }
+                    // if the user neither has a valid OTP cookie nor it's the first login
+                    //  ask for the OTP
+                    else {
+                        $user->doOTP();
+                        include __DIR__.'/../tmpl/ask-for-otp.php';
+                    }
+                }
+
+                die();
+            }
+        }
+        // if we're here, something went wrong, destroy the session and show a login error
+        session_destroy();
+
+        include __DIR__.'/../tmpl/login-error.php';
+        die();
+    }
+
+// if neither a session nor tried to submit the login credentials -> login screen
+include __DIR__.'/../tmpl/login.php';
+
+?>
+</body>
+</html>
diff --git a/vendor/sonata-project/google-authenticator/src/FixedBitNotation.php b/vendor/sonata-project/google-authenticator/src/FixedBitNotation.php
new file mode 100644
index 0000000..3f5ff55
--- /dev/null
+++ b/vendor/sonata-project/google-authenticator/src/FixedBitNotation.php
@@ -0,0 +1,296 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the Sonata Project package.
+ *
+ * (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Sonata\GoogleAuthenticator;
+
+/**
+ * FixedBitNotation.
+ *
+ * The FixedBitNotation class is for binary to text conversion. It
+ * can handle many encoding schemes, formally defined or not, that
+ * use a fixed number of bits to encode each character.
+ *
+ * @author Andre DeMarre
+ */
+final class FixedBitNotation
+{
+    /**
+     * @var string
+     */
+    private $chars;
+
+    /**
+     * @var int
+     */
+    private $bitsPerCharacter;
+
+    /**
+     * @var int
+     */
+    private $radix;
+
+    /**
+     * @var bool
+     */
+    private $rightPadFinalBits;
+
+    /**
+     * @var bool
+     */
+    private $padFinalGroup;
+
+    /**
+     * @var string
+     */
+    private $padCharacter;
+
+    /**
+     * @var string[]
+     */
+    private $charmap;
+
+    /**
+     * @param int    $bitsPerCharacter  Bits to use for each encoded character
+     * @param string $chars             Base character alphabet
+     * @param bool   $rightPadFinalBits How to encode last character
+     * @param bool   $padFinalGroup     Add padding to end of encoded output
+     * @param string $padCharacter      Character to use for padding
+     */
+    public function __construct(int $bitsPerCharacter, string $chars = null, bool $rightPadFinalBits = false, bool $padFinalGroup = false, string $padCharacter = '=')
+    {
+        // Ensure validity of $chars
+        if (!is_string($chars) || ($charLength = strlen($chars)) < 2) {
+            $chars =
+            '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-,';
+            $charLength = 64;
+        }
+
+        // Ensure validity of $bitsPerCharacter
+        if ($bitsPerCharacter < 1) {
+            // $bitsPerCharacter must be at least 1
+            $bitsPerCharacter = 1;
+            $radix = 2;
+        } elseif ($charLength < 1 << $bitsPerCharacter) {
+            // Character length of $chars is too small for $bitsPerCharacter
+            // Set $bitsPerCharacter to greatest acceptable value
+            $bitsPerCharacter = 1;
+            $radix = 2;
+
+            while ($charLength >= ($radix <<= 1) && $bitsPerCharacter < 8) {
+                ++$bitsPerCharacter;
+            }
+
+            $radix >>= 1;
+        } elseif ($bitsPerCharacter > 8) {
+            // $bitsPerCharacter must not be greater than 8
+            $bitsPerCharacter = 8;
+            $radix = 256;
+        } else {
+            $radix = 1 << $bitsPerCharacter;
+        }
+
+        $this->chars = $chars;
+        $this->bitsPerCharacter = $bitsPerCharacter;
+        $this->radix = $radix;
+        $this->rightPadFinalBits = $rightPadFinalBits;
+        $this->padFinalGroup = $padFinalGroup;
+        $this->padCharacter = $padCharacter[0];
+    }
+
+    /**
+     * Encode a string.
+     *
+     * @param string $rawString Binary data to encode
+     *
+     * @return string
+     */
+    public function encode($rawString): string
+    {
+        // Unpack string into an array of bytes
+        $bytes = unpack('C*', $rawString);
+        $byteCount = count($bytes);
+
+        $encodedString = '';
+        $byte = array_shift($bytes);
+        $bitsRead = 0;
+
+        $chars = $this->chars;
+        $bitsPerCharacter = $this->bitsPerCharacter;
+        $rightPadFinalBits = $this->rightPadFinalBits;
+        $padFinalGroup = $this->padFinalGroup;
+        $padCharacter = $this->padCharacter;
+
+        // Generate encoded output;
+        // each loop produces one encoded character
+        for ($c = 0; $c < $byteCount * 8 / $bitsPerCharacter; ++$c) {
+            // Get the bits needed for this encoded character
+            if ($bitsRead + $bitsPerCharacter > 8) {
+                // Not enough bits remain in this byte for the current
+                // character
+                // Save the remaining bits before getting the next byte
+                $oldBitCount = 8 - $bitsRead;
+                $oldBits = $byte ^ ($byte >> $oldBitCount << $oldBitCount);
+                $newBitCount = $bitsPerCharacter - $oldBitCount;
+
+                if (!$bytes) {
+                    // Last bits; match final character and exit loop
+                    if ($rightPadFinalBits) {
+                        $oldBits <<= $newBitCount;
+                    }
+                    $encodedString .= $chars[$oldBits];
+
+                    if ($padFinalGroup) {
+                        // Array of the lowest common multiples of
+                        // $bitsPerCharacter and 8, divided by 8
+                        $lcmMap = [1 => 1, 2 => 1, 3 => 3, 4 => 1, 5 => 5, 6 => 3, 7 => 7, 8 => 1];
+                        $bytesPerGroup = $lcmMap[$bitsPerCharacter];
+                        $pads = $bytesPerGroup * 8 / $bitsPerCharacter
+                        - ceil((strlen($rawString) % $bytesPerGroup)
+                        * 8 / $bitsPerCharacter);
+                        $encodedString .= str_repeat($padCharacter[0], $pads);
+                    }
+
+                    break;
+                }
+
+                // Get next byte
+                $byte = array_shift($bytes);
+                $bitsRead = 0;
+            } else {
+                $oldBitCount = 0;
+                $newBitCount = $bitsPerCharacter;
+            }
+
+            // Read only the needed bits from this byte
+            $bits = $byte >> 8 - ($bitsRead + $newBitCount);
+            $bits ^= $bits >> $newBitCount << $newBitCount;
+            $bitsRead += $newBitCount;
+
+            if ($oldBitCount) {
+                // Bits come from seperate bytes, add $oldBits to $bits
+                $bits = ($oldBits << $newBitCount) | $bits;
+            }
+
+            $encodedString .= $chars[$bits];
+        }
+
+        return $encodedString;
+    }
+
+    /**
+     * Decode a string.
+     *
+     * @param string $encodedString Data to decode
+     * @param bool   $caseSensitive
+     * @param bool   $strict        Returns null if $encodedString contains
+     *                              an undecodable character
+     *
+     * @return string
+     */
+    public function decode($encodedString, $caseSensitive = true, $strict = false): string
+    {
+        if (!$encodedString || !is_string($encodedString)) {
+            // Empty string, nothing to decode
+            return '';
+        }
+
+        $chars = $this->chars;
+        $bitsPerCharacter = $this->bitsPerCharacter;
+        $radix = $this->radix;
+        $rightPadFinalBits = $this->rightPadFinalBits;
+        $padCharacter = $this->padCharacter;
+
+        // Get index of encoded characters
+        if ($this->charmap) {
+            $charmap = $this->charmap;
+        } else {
+            $charmap = [];
+
+            for ($i = 0; $i < $radix; ++$i) {
+                $charmap[$chars[$i]] = $i;
+            }
+
+            $this->charmap = $charmap;
+        }
+
+        // The last encoded character is $encodedString[$lastNotatedIndex]
+        $lastNotatedIndex = strlen($encodedString) - 1;
+
+        // Remove trailing padding characters
+        while ($encodedString[$lastNotatedIndex] == $padCharacter[0]) {
+            $encodedString = substr($encodedString, 0, $lastNotatedIndex);
+            --$lastNotatedIndex;
+        }
+
+        $rawString = '';
+        $byte = 0;
+        $bitsWritten = 0;
+
+        // Convert each encoded character to a series of unencoded bits
+        for ($c = 0; $c <= $lastNotatedIndex; ++$c) {
+            if (!isset($charmap[$encodedString[$c]]) && !$caseSensitive) {
+                // Encoded character was not found; try other case
+                if (isset($charmap[$cUpper = strtoupper($encodedString[$c])])) {
+                    $charmap[$encodedString[$c]] = $charmap[$cUpper];
+                } elseif (isset($charmap[$cLower = strtolower($encodedString[$c])])) {
+                    $charmap[$encodedString[$c]] = $charmap[$cLower];
+                }
+            }
+
+            if (isset($charmap[$encodedString[$c]])) {
+                $bitsNeeded = 8 - $bitsWritten;
+                $unusedBitCount = $bitsPerCharacter - $bitsNeeded;
+
+                // Get the new bits ready
+                if ($bitsNeeded > $bitsPerCharacter) {
+                    // New bits aren't enough to complete a byte; shift them
+                    // left into position
+                    $newBits = $charmap[$encodedString[$c]] << $bitsNeeded
+                    - $bitsPerCharacter;
+                    $bitsWritten += $bitsPerCharacter;
+                } elseif ($c != $lastNotatedIndex || $rightPadFinalBits) {
+                    // Zero or more too many bits to complete a byte;
+                    // shift right
+                    $newBits = $charmap[$encodedString[$c]] >> $unusedBitCount;
+                    $bitsWritten = 8; //$bitsWritten += $bitsNeeded;
+                } else {
+                    // Final bits don't need to be shifted
+                    $newBits = $charmap[$encodedString[$c]];
+                    $bitsWritten = 8;
+                }
+
+                $byte |= $newBits;
+
+                if (8 == $bitsWritten || $c == $lastNotatedIndex) {
+                    // Byte is ready to be written
+                    $rawString .= pack('C', $byte);
+
+                    if ($c != $lastNotatedIndex) {
+                        // Start the next byte
+                        $bitsWritten = $unusedBitCount;
+                        $byte = ($charmap[$encodedString[$c]]
+                        ^ ($newBits << $unusedBitCount)) << 8 - $bitsWritten;
+                    }
+                }
+            } elseif ($strict) {
+                // Unable to decode character; abort
+                return null;
+            }
+        }
+
+        return $rawString;
+    }
+}
+
+// NEXT_MAJOR: Remove class alias
+class_alias('Sonata\GoogleAuthenticator\FixedBitNotation', 'Google\Authenticator\FixedBitNotation', false);
diff --git a/vendor/sonata-project/google-authenticator/src/GoogleAuthenticator.php b/vendor/sonata-project/google-authenticator/src/GoogleAuthenticator.php
new file mode 100644
index 0000000..145739c
--- /dev/null
+++ b/vendor/sonata-project/google-authenticator/src/GoogleAuthenticator.php
@@ -0,0 +1,173 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the Sonata Project package.
+ *
+ * (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Sonata\GoogleAuthenticator;
+
+/**
+ * @see https://github.com/google/google-authenticator/wiki/Key-Uri-Format
+ */
+final class GoogleAuthenticator implements GoogleAuthenticatorInterface
+{
+    /**
+     * @var int
+     */
+    private $passCodeLength;
+
+    /**
+     * @var int
+     */
+    private $secretLength;
+
+    /**
+     * @var int
+     */
+    private $pinModulo;
+
+    /**
+     * @var \DateTimeInterface
+     */
+    private $now;
+
+    /**
+     * @var int
+     */
+    private $codePeriod = 30;
+
+    /**
+     * @param int                     $passCodeLength
+     * @param int                     $secretLength
+     * @param \DateTimeInterface|null $now
+     */
+    public function __construct(int $passCodeLength = 6, int $secretLength = 10, \DateTimeInterface $now = null)
+    {
+        $this->passCodeLength = $passCodeLength;
+        $this->secretLength = $secretLength;
+        $this->pinModulo = 10 ** $passCodeLength;
+        $this->now = $now ?? new \DateTimeImmutable();
+    }
+
+    /**
+     * @param string $secret
+     * @param string $code
+     */
+    public function checkCode($secret, $code): bool
+    {
+        /**
+         * The result of each comparison is accumulated here instead of using a guard clause
+         * (https://refactoring.com/catalog/replaceNestedConditionalWithGuardClauses.html). This is to implement
+         * constant time comparison to make side-channel attacks harder. See
+         * https://cryptocoding.net/index.php/Coding_rules#Compare_secret_strings_in_constant_time for details.
+         * Each comparison uses hash_equals() instead of an operator to implement constant time equality comparison
+         * for each code.
+         */
+        $result = 0;
+
+        // current period
+        $result += hash_equals($this->getCode($secret, $this->now), $code);
+
+        // previous period, happens if the user was slow to enter or it just crossed over
+        $dateTime = new \DateTimeImmutable('@'.($this->now->getTimestamp() - $this->codePeriod));
+        $result += hash_equals($this->getCode($secret, $dateTime), $code);
+
+        // next period, happens if the user is not completely synced and possibly a few seconds ahead
+        $dateTime = new \DateTimeImmutable('@'.($this->now->getTimestamp() + $this->codePeriod));
+        $result += hash_equals($this->getCode($secret, $dateTime), $code);
+
+        return $result > 0;
+    }
+
+    /**
+     * NEXT_MAJOR: add the interface typehint to $time and remove deprecation.
+     *
+     * @param string                                   $secret
+     * @param float|string|int|null|\DateTimeInterface $time
+     */
+    public function getCode($secret, /* \DateTimeInterface */$time = null): string
+    {
+        if (null === $time) {
+            $time = $this->now;
+        }
+
+        if ($time instanceof \DateTimeInterface) {
+            $timeForCode = floor($time->getTimestamp() / $this->codePeriod);
+        } else {
+            @trigger_error(
+                'Passing anything other than null or a DateTimeInterface to $time is deprecated as of 2.0 '.
+                'and will not be possible as of 3.0.',
+                E_USER_DEPRECATED
+            );
+            $timeForCode = $time;
+        }
+
+        $base32 = new FixedBitNotation(5, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', true, true);
+        $secret = $base32->decode($secret);
+
+        $timeForCode = str_pad(pack('N', $timeForCode), 8, chr(0), STR_PAD_LEFT);
+
+        $hash = hash_hmac('sha1', $timeForCode, $secret, true);
+        $offset = ord(substr($hash, -1));
+        $offset &= 0xF;
+
+        $truncatedHash = $this->hashToInt($hash, $offset) & 0x7FFFFFFF;
+
+        return str_pad((string) ($truncatedHash % $this->pinModulo), $this->passCodeLength, '0', STR_PAD_LEFT);
+    }
+
+    /**
+     * NEXT_MAJOR: Remove this method.
+     *
+     * @param string $user
+     * @param string $hostname
+     * @param string $secret
+     *
+     * @deprecated deprecated as of 2.1 and will be removed in 3.0. Use Sonata\GoogleAuthenticator\GoogleQrUrl::generate() instead.
+     */
+    public function getUrl($user, $hostname, $secret): string
+    {
+        @trigger_error(sprintf(
+            'Using %s() is deprecated as of 2.1 and will be removed in 3.0. '.
+            'Use Sonata\GoogleAuthenticator\GoogleQrUrl::generate() instead.',
+            __METHOD__
+        ), E_USER_DEPRECATED);
+
+        $issuer = func_get_args()[3] ?? null;
+        $accountName = sprintf('%s@%s', $user, $hostname);
+
+        // manually concat the issuer to avoid a change in URL
+        $url = GoogleQrUrl::generate($accountName, $secret);
+
+        if ($issuer) {
+            $url .= '%26issuer%3D'.$issuer;
+        }
+
+        return $url;
+    }
+
+    public function generateSecret(): string
+    {
+        return (new FixedBitNotation(5, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', true, true))
+            ->encode(random_bytes($this->secretLength));
+    }
+
+    /**
+     * @param string $bytes
+     * @param int    $start
+     */
+    private function hashToInt(string $bytes, int $start): int
+    {
+        return unpack('N', substr(substr($bytes, $start), 0, 4))[1];
+    }
+}
+
+// NEXT_MAJOR: Remove class alias
+class_alias('Sonata\GoogleAuthenticator\GoogleAuthenticator', 'Google\Authenticator\GoogleAuthenticator', false);
diff --git a/vendor/sonata-project/google-authenticator/src/GoogleAuthenticatorInterface.php b/vendor/sonata-project/google-authenticator/src/GoogleAuthenticatorInterface.php
new file mode 100644
index 0000000..70219f2
--- /dev/null
+++ b/vendor/sonata-project/google-authenticator/src/GoogleAuthenticatorInterface.php
@@ -0,0 +1,44 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the Sonata Project package.
+ *
+ * (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Sonata\GoogleAuthenticator;
+
+interface GoogleAuthenticatorInterface
+{
+    /**
+     * @param string $secret
+     * @param string $code
+     */
+    public function checkCode($secret, $code): bool;
+
+    /**
+     * NEXT_MAJOR: add the interface typehint to $time and remove deprecation.
+     *
+     * @param string                                   $secret
+     * @param float|string|int|null|\DateTimeInterface $time
+     */
+    public function getCode($secret, /* \DateTimeInterface */$time = null): string;
+
+    /**
+     * NEXT_MAJOR: Remove this method.
+     *
+     * @param string $user
+     * @param string $hostname
+     * @param string $secret
+     *
+     * @deprecated deprecated as of 2.1 and will be removed in 3.0. Use Sonata\GoogleAuthenticator\GoogleQrUrl::generate() instead.
+     */
+    public function getUrl($user, $hostname, $secret): string;
+
+    public function generateSecret(): string;
+}
diff --git a/vendor/sonata-project/google-authenticator/src/GoogleQrUrl.php b/vendor/sonata-project/google-authenticator/src/GoogleQrUrl.php
new file mode 100644
index 0000000..7e9a537
--- /dev/null
+++ b/vendor/sonata-project/google-authenticator/src/GoogleQrUrl.php
@@ -0,0 +1,94 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the Sonata Project package.
+ *
+ * (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Sonata\GoogleAuthenticator;
+
+/**
+ * Responsible for QR image url generation.
+ *
+ * @see https://developers.google.com/chart/infographics/docs/qr_codes
+ * @see https://github.com/google/google-authenticator/wiki/Key-Uri-Format
+ *
+ * @author Iltar van der Berg <kjarli@gmail.com>
+ */
+final class GoogleQrUrl
+{
+    /**
+     * Private by design.
+     */
+    private function __construct()
+    {
+    }
+
+    /**
+     * Generates a URL that is used to show a QR code.
+     *
+     * Account names may not contain a double colon (:). Valid account name
+     * examples:
+     *  - "John.Doe@gmail.com"
+     *  - "John Doe"
+     *  - "John_Doe_976"
+     *
+     * The Issuer may not contain a double colon (:). The issuer is recommended
+     * to pass along. If used, it will also be appended before the accountName.
+     *
+     * The previous examples with the issuer "Acme inc" would result in label:
+     *  - "Acme inc:John.Doe@gmail.com"
+     *  - "Acme inc:John Doe"
+     *  - "Acme inc:John_Doe_976"
+     *
+     * The contents of the label, issuer and secret will be encoded to generate
+     * a valid URL.
+     *
+     * @param string      $accountName The account name to show and identify
+     * @param string      $secret      The secret is the generated secret unique to that user
+     * @param string|null $issuer      Where you log in to
+     * @param int         $size        Image size in pixels, 200 will make it 200x200
+     *
+     * @return string
+     */
+    public static function generate(string $accountName, string $secret, string $issuer = null, int $size = 200): string
+    {
+        if ('' === $accountName || false !== strpos($accountName, ':')) {
+            throw RuntimeException::InvalidAccountName($accountName);
+        }
+
+        if ('' === $secret) {
+            throw RuntimeException::InvalidSecret();
+        }
+
+        $label = $accountName;
+        $otpauthString = 'otpauth://totp/%s?secret=%s';
+
+        if (null !== $issuer) {
+            if ('' === $issuer || false !== strpos($issuer, ':')) {
+                throw RuntimeException::InvalidIssuer($issuer);
+            }
+
+            // use both the issuer parameter and label prefix as recommended by Google for BC reasons
+            $label = $issuer.':'.$label;
+            $otpauthString .= '&issuer=%s';
+        }
+
+        $otpauthString = rawurlencode(sprintf($otpauthString, $label, $secret, $issuer));
+
+        return sprintf(
+            'https://chart.googleapis.com/chart?chs=%1$dx%1$d&chld=M|0&cht=qr&chl=%2$s',
+            $size,
+            $otpauthString
+        );
+    }
+}
+
+// NEXT_MAJOR: Remove class alias
+class_alias('Sonata\GoogleAuthenticator\GoogleQrUrl', 'Google\Authenticator\GoogleQrUrl', false);
diff --git a/vendor/sonata-project/google-authenticator/src/RuntimeException.php b/vendor/sonata-project/google-authenticator/src/RuntimeException.php
new file mode 100644
index 0000000..4d3cf5f
--- /dev/null
+++ b/vendor/sonata-project/google-authenticator/src/RuntimeException.php
@@ -0,0 +1,46 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the Sonata Project package.
+ *
+ * (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Sonata\GoogleAuthenticator;
+
+/**
+ * Contains runtime exception templates.
+ *
+ * @author Iltar van der Berg <kjarli@gmail.com>
+ */
+final class RuntimeException extends \RuntimeException
+{
+    public static function InvalidAccountName(string $accountName): self
+    {
+        return new self(sprintf(
+            'The account name may not contain a double colon (:) and may not be an empty string. Given "%s".',
+            $accountName
+        ));
+    }
+
+    public static function InvalidIssuer(string $issuer): self
+    {
+        return new self(sprintf(
+            'The issuer name may not contain a double colon (:) and may not be an empty string. Given "%s".',
+            $issuer
+        ));
+    }
+
+    public static function InvalidSecret(): self
+    {
+        return new self('The secret name may not be an empty string.');
+    }
+}
+
+// NEXT_MAJOR: Remove class alias
+class_alias('Sonata\GoogleAuthenticator\RuntimeException', 'Google\Authenticator\RuntimeException', false);
-- 
GitLab