Добавьте дополнительные данные (ajax) к собственной аутентификации в Laravel - PullRequest
0 голосов
/ 19 января 2020

Я пытаюсь реализовать отслеживание пользователей в Laravel путем записи статистики после входа пользователя. Т.е. местоположение, часовой пояс и тому подобное. Мне почти повезло реализовать это.

Я использовал ajax, прикрепив прослушиватель событий для отправки кнопки в форму входа. После отправки формы вызывается метод ajax. Этот метод получает статистику пользователя с помощью вызова API. Затем этот запрос ajax отправляет эти данные в StatsController@store, который затем записывает эту запись в таблицу статистики.

Это достигается только с помощью e.preventDefault();, если я его не использую, записи не вставляются в БД и выдает ошибку, которая быстро исчезает после перенаправления на панель инструментов.

Ajax метод находится в файле js, который вызывается в файле макета.

Вот метод ajax:

function getCoords(){

    return fetch('https://ipinfo.io/geo')
    .then((response) => {
        if (!response.ok) {
            throw new Error('Network response was not ok');
        }
        else{

            return response.json();

        }

    })
    .then((response) => {

        let url = "/writeStats";
        let token = document.querySelector("meta[name='csrf-token']").getAttribute("content");
        let forma = document.getElementById("loginForm");

        let formElements = {};

        formElements.email = forma.elements[1].value;
        formElements.password = forma.elements[2].value;

        $.ajax({
            url: url,
            type: 'POST',
            data: {_token: token , message: "bravo", stats: response, formElements: formElements},
            dataType: 'JSON',
            success: (response) => { 
                console.log("success");
                console.log(response);
            },
            error: (response) => {
                console.log("error");
                console.log(response);
            }
        }); 

    })
    .catch((error) => {
        console.error('There has been a problem with your fetch operation:', error);
    });

}

window.addEventListener("click", (e) => {

    if(e.target.id==="loginBtn"){
        //e.preventDefault();
        getCoords();
    }

});

web. php:

Route::post('/writeStats','StatsController@store');

StatsController:

public function store(Request $request)
{
    if($request->ajax()){

        $email = $request->formElements["email"];
        $password = $request->formElements["password"];

        $user = DB::table('users')->where("email", "=", $email)->first();

        if(Hash::check($password, $user->password)) {   

            $stat = new Stats;
            $stat->ip = $request->stats["ip"];
            $stat->city = $request->stats["city"];
            $stat->region = $request->stats["region"];
            $stat->country = $request->stats["country"];
            $stat->coords = $request->stats["loc"];
            $stat->timezone = $request->stats["timezone"];
            $stat->user_id = $user->id;
            $stat->save();

            $response = array(
                "message" => "bravo",
                "request" => $request->all(),
                "stats" => $request->stats,
                "user" => $user,
                "stat" => $stat,
            );

            return response()->json($response);

        }

    }

}

php artisan --version показывает Laravel Framework 6.9.0

Мой вопрос: Как вставить в таблицу статистики сразу после входа пользователя ?

Edit1:

Сейчас я пробую несколько иной подход. Вместо какого-то пользовательского метода из StatsController я теперь использую метод authenticated в LoginController.

public function authenticated(Request $request)
    {
        $credentials = $request->only('email', 'password');

        $email = $request->input("email");
        $password = $request->input("password");

        $user = DB::table('users')->where("email", "=", $email)->first();
        if (Auth::attempt($credentials)) {

            $stat = new Stats;
            $stat->ip = $request->stats["ip"];
            $stat->city = $request->stats["city"];
            $stat->region = $request->stats["region"];
            $stat->country = $request->stats["country"];
            $stat->coords = $request->stats["loc"];
            $stat->timezone = $request->stats["timezone"];
            $stat->user_id = auth()->user()->id;
            $stat->save();

            $response = array(
                "stat" => $request->all(),
            );

            return redirect()->intended('dashboard');

        }
    }

и в Интернете. php:

Route::post('/login','Auth\LoginController@authenticated');

Все еще не повезло. Я просто не знаю, какой подход использовать. Это так близко, как будто я упустил что-то маленькое.

Edit2:

Позвольте мне перефразировать вопрос:

Как отправить вызов API ответ на контроллер входа, чтобы после аутентификации пользователя я мог вставить данные ответа API в другую таблицу (не в таблицу пользователей)? Могу ли я:

  1. Каким-то образом вставить ответ API в запрос аутентификации?
  2. Или как проверить подлинность при одновременной записи записей в таблицу stats?

Я испробовал оба подхода (см. Исходные данные и правки), но не уверен, что мне писать. ..

Ответы [ 2 ]

0 голосов
/ 20 января 2020

Я нашел решение, которое работает отлично. Чтобы объяснить лучше, у меня была пара ошибок:

Первая - dataType в ajax вызове, где ожидается ответ json. Никакого ответа не требуется, поскольку при входе в систему и последующей вставке данных из API пользователь отправляется на /dashboard.

Во-вторых, я использую e.preventDefault();, так как я хотел посмотреть, что я получу в случае представления. В этом нет необходимости, объяснение - последнее предложение в предыдущем абзаце.

И, кстати, возвращаемое значение - html код, так как пользователь перенаправлен на просмотр ...

Вот пересмотренный код:

LoginController:

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;

use Illuminate\Http\Request;
use Auth;
use App\Stats;

class LoginController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Login Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles authenticating users for the application and
    | redirecting them to your home screen. The controller uses a trait
    | to conveniently provide its functionality to your applications.
    |
    */

    use AuthenticatesUsers;

    /**
     * Where to redirect users after login.
     *
     * @var string
     */
    protected $redirectTo = '/dashboard';

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest')->except('logout');
    }

    public function authenticated(Request $request)
    {

        $email = $request->formElements["email"];
        $password = $request->formElements["password"];

        if (Auth::attempt(['email' => $email,'password' => $password])) {

            $stat = new Stats;
            $stat->ip = $request->stats["ip"];
            $stat->city = $request->stats["city"];
            $stat->region = $request->stats["region"];
            $stat->country = $request->stats["country"];
            $stat->coords = $request->stats["loc"];
            $stat->timezone = $request->stats["timezone"];
            $stat->user_id = auth()->user()->id;
            $stat->save();

            $response = array(
                "stat" => $request->all(),
            );

            return redirect()->intended('dashboard');
        }
    }
}

Код для ajax метода и прослушивателей событий внутри скрипта, вызываемого в файле макета:

function getCoords(){

    return fetch('https://ipinfo.io/geo')
    .then((response) => {
        if (!response.ok) {
            throw new Error('Network response was not ok');
        }
        else{

            return response.json();

        }

    })
    .then((response) => {

        let url = "/login";
        let token = document.querySelector("meta[name='csrf-token']").getAttribute("content");
        let forma = document.getElementById("loginForm");

        let formElements = {};

        formElements.email = forma.elements[1].value;
        formElements.password = forma.elements[2].value;
        console.log(formElements);
        $.ajax({
            url: url,
            type: 'POST',
            data: {_token: token , message: "bravo", stats: response, formElements: formElements},
            dataType: 'html',
            success: (response) => { 
                console.log("success");
                console.log(response);
                forma.submit();

            },
            error: (response) => {
                console.log("error");
                console.log(response);
            }
        }); 

    })
    .catch((error) => {
        console.error('There has been a problem with your fetch operation:', error);
    });

}

window.addEventListener("click", (e) => {

    if(e.target.id==="loginBtn"){
        getCoords();     
    }

});

window.addEventListener("keypress", (e) => {

    let forma = document.getElementById("loginForm");
    let isFocused = (document.activeElement === forma.elements[2]);

    if(forma.elements[1].value && forma.elements[2].value && e.key === 'Enter' && isFocused){

        getCoords();

    }

});

Итак, для "кого бы это ни интересовало" решение, если вы хотите добавить ajax вызов во время аутентификация в Laravel. Вероятно, может быть использовано и для чего-то еще ... например, пользовательской аутентификации или чего-то еще.

0 голосов
/ 19 января 2020

Это его предполагаемое поведение. Поскольку в вашем сценарии использования отправка формы зависит от асинхронных операций c, вы ХОТИТЕ такое поведение.

https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault

предотвращение интерфейса интерфейса Event ( ) сообщает агенту пользователя, что если событие не обрабатывается явно, его действие по умолчанию не должно выполняться, как обычно.

ОБНОВЛЕНИЕ: Ref: с использованием выборки внутри другого извлекать в javascript для вложенных асинхронных c операций.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...