Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vue-Auth and Pinia #690

Open
alimuradov opened this issue Jul 23, 2022 · 10 comments
Open

Vue-Auth and Pinia #690

alimuradov opened this issue Jul 23, 2022 · 10 comments

Comments

@alimuradov
Copy link

Do I need additional settings to use this plugin with pinia storage? I tried to figure it out myself, but unfortunately I couldn't get this plugin to work with pinia.

@websanova
Copy link
Owner

I haven't used pinia yet, as long as you can import the library though, it should work I think?

Do you have some examples of anything you tried?

@alimuradov
Copy link
Author

After authorization, there is a request to update the user's data. But I get an authorization error because the request does not contain a token. The pinia repository is also empty, as is localstorage. The token received from the api is not saved anywhere

main.ts

import { createApp } from "vue";
import { createPinia } from "pinia";

import App from "./App.vue";
import router from "./router";
import auth from './plugins/auth.js';
import http from './http';

import DashboardLayout from "./layouts/DashboardLayout.vue";
import EmptyLayout from "./layouts/EmptyLayout.vue";
import PageLayout from "./layouts/PageLayout.vue";
import AuthLayout from "./layouts/AuthLayout.vue";

import "./assets/css/index.css";
import "./assets/css/tailwind.css";
import "@fortawesome/fontawesome-free/css/all.min.css";

const app = createApp(App);

app.component("default-layout", DashboardLayout);
app.component("empty-layout", EmptyLayout);
app.component("page-layout", PageLayout);
app.component("auth-layout", AuthLayout);

app.use(http);
app.use(createPinia());
app.use(router);
app.use(auth);

app.mount("#app");

plugins/auth.js

import { createAuth } from "@websanova/vue-auth/src/v3.js";
import driverAuthBearer from "@websanova/vue-auth/src/drivers/auth/bearer.js";
import driverHttpAxios from "@websanova/vue-auth/src/drivers/http/axios.1.x.js";
import driverRouterVueRouter from "@websanova/vue-auth/src/drivers/router/vue-router.2.x";
import router from "@/router";

export default (app) => {
  app.use(
    createAuth({
      plugins: {
        http: app.axios,
        router: app.router,
      },
      drivers: {
        http: driverHttpAxios,
        auth: driverAuthBearer,
        router: driverRouterVueRouter,
      },
      options: {
        loginData: {
          url: "users/login",
          method: "POST",
          redirect: "/dashboard",
          fetchUser: true,
          staySignedIn: true,
        },
        rolesKey: "type",
        notFoundRedirect: { name: "landing" },
        fetchData: { url: "users/me", method: "GET", enabled: true },
        rolesKey: "roles",
        tokenDefaultKey: "access_token",
        refreshTokenKey: "refresh_token",
        tokenExpiresKey: "expires_in",
      },
    })
  );
};

http/index.js


axios.defaults.baseURL = import.meta.env.VITE_APP_API_URL;

export default (app) => {
  app.axios = axios;
  app.$http = axios;

  app.config.globalProperties.axios = axios;
  app.config.globalProperties.$http = axios;
};

views\auth\Login.vue

<template>
  <div class="container mx-auto px-4 h-full">
    <div class="flex content-center items-center justify-center h-full">
      <div class="w-full lg:w-4/12 px-4">
        <div
          class="relative flex flex-col min-w-0 break-words w-full mb-6 shadow-lg rounded-lg bg-blueGray-200 border-0"
        >
          <div class="rounded-t mb-0 px-6 py-6">
            <div class="text-center mb-3">
              <h6 class="text-blueGray-500 text-sm font-bold">Войти через</h6>
            </div>
            <div class="btn-wrapper text-center">
              <button
                class="bg-white active:bg-blueGray-50 text-blueGray-700 font-normal px-4 py-2 rounded outline-none focus:outline-none mr-2 mb-1 uppercase shadow hover:shadow-md inline-flex items-center font-bold text-xs ease-linear transition-all duration-150"
                type="button"
              >
                <img alt="..." class="w-5 mr-1" :src="github" />
                Github
              </button>
              <button
                class="bg-white active:bg-blueGray-50 text-blueGray-700 font-normal px-4 py-2 rounded outline-none focus:outline-none mr-1 mb-1 uppercase shadow hover:shadow-md inline-flex items-center font-bold text-xs ease-linear transition-all duration-150"
                type="button"
              >
                <img alt="..." class="w-5 mr-1" :src="google" />
                Google
              </button>
            </div>
            <hr class="mt-6 border-b-1 border-blueGray-300" />
          </div>
          <div class="flex-auto px-4 lg:px-10 py-10 pt-0">
            <div class="text-blueGray-400 text-center mb-3 font-bold">
              <small>Или войти используя логин и пароль</small>
            </div>
            <form>
              <div class="relative w-full mb-3">
                <label
                  class="block uppercase text-blueGray-600 text-xs font-bold mb-2"
                  htmlFor="grid-password"
                >
                  Email
                </label>
                <input
                  type="email"
                  v-model="state.form.body.username"
                  class="border-0 px-3 py-3 placeholder-blueGray-300 text-blueGray-600 bg-white rounded text-sm shadow focus:outline-none focus:ring w-full ease-linear transition-all duration-150"
                  placeholder="Email"
                />
              </div>

              <div class="relative w-full mb-3">
                <label
                  class="block uppercase text-blueGray-600 text-xs font-bold mb-2"
                  htmlFor="grid-password"
                >
                  Пароль
                </label>
                <input
                  type="password"
                  v-model="state.form.body.password"
                  class="border-0 px-3 py-3 placeholder-blueGray-300 text-blueGray-600 bg-white rounded text-sm shadow focus:outline-none focus:ring w-full ease-linear transition-all duration-150"
                  placeholder="Password"
                />
              </div>
              <div>
                <label class="inline-flex items-center cursor-pointer">
                  <input
                    id="customCheckLogin"
                    type="checkbox"
                    class="form-checkbox border-0 rounded text-blueGray-700 ml-1 w-5 h-5 ease-linear transition-all duration-150"
                  />
                  <span class="ml-2 text-sm font-semibold text-blueGray-600">
                    Запомнить меня
                  </span>
                </label>
              </div>

              <div class="text-center mt-6">
                <button
                  @click="loginDefault"
                  class="bg-blueGray-800 text-white active:bg-blueGray-600 text-sm font-bold uppercase px-6 py-3 rounded shadow hover:shadow-lg outline-none focus:outline-none mr-1 mb-1 w-full ease-linear transition-all duration-150"
                  type="button"
                >
                  Войти
                </button>
              </div>
              <div
                v-if="state.form.errors.length"
                class="p-4 mt-6 text-center mb-4 text-sm text-red-700 bg-red-100 rounded-lg dark:bg-red-200 dark:text-red-800"
              >
                {{ state.form.errors.password }}
              </div>
            </form>
          </div>
        </div>
        <div class="flex flex-wrap mt-6 relative">
          <div class="w-1/2">
            <a href="javascript:void(0)" class="text-blueGray-200">
              <small>Забыли пароль?</small>
            </a>
          </div>
          <div class="w-1/2 text-right">
            <router-link to="/auth/register" class="text-blueGray-200">
              <small>Создать новый аккаунт</small>
            </router-link>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
import github from "@/assets/img/github.svg";
import google from "@/assets/img/google.svg";
import { reactive, onMounted } from "vue";
import { useRouter } from "vue-router";
import { useAuth } from "@websanova/vue-auth/src/v3.js";
import { useUsersStore } from "@/stores/users.store";

export default {
  data() {
    return {
      github,
      google,
    };
  },
  setup() {
    const auth = useAuth();
    const store = useUsersStore();
    const router = useRouter();

    const state = reactive({
      form: {
        body: {
          username: "tabarigen@mail.ru",
          password: "5vn63ys9",
        },
        remember: false,
        fetchUser: true,
        staySignedIn: false,
        errors: {},
      },
    });

    onMounted(() => {
      // console.log(auth);
    });

    function errors(res) {
      state.form.errors = Object.fromEntries(
        res.data.errors.map((item) => [item.field, item.msg])
      );
    }

    const form = new FormData();

    form.append("username", state.form.body.username);
    form.append("password", state.form.body.password);

    function loginDefault() {
      auth
        .login({
          data: form,
          remember: state.form.remember ? '{"name": "Default"}' : null,
          // fetchUser: state.form.fetchUser,
          staySignedIn: state.form.staySignedIn,
          redirect: "/",
        })
        .then(null, (res) => {
          errors(res.response);
        });
    }

    return {
      state,
      loginDefault,
    };
  },
};
</script>

stores/user.stores.js

import { defineStore } from "pinia";

export const useUsersStore = defineStore({
  id: "users",
  state: () => ({
    users: {},
    user: {},
  }),
});

@alimuradov
Copy link
Author

Please tell me, is it worth waiting for a demo project with pinia?

@websanova
Copy link
Owner

It's just a store, it shouldn't really have anything to do with vue-auth library.

Are you having issues importing the useAuth method in the stores?

Should be able to setup a basic example with some console calls.

@alimuradov
Copy link
Author

alimuradov commented Jul 28, 2022

Are you having issues importing the useAuth method in the stores?

There are no problems with using use Auth(). After the login() method, the token is not stored in the storage.

<template>
  <div class="container mx-auto px-4 h-full">
    <div class="flex content-center items-center justify-center h-full">
      <div class="w-full lg:w-4/12 px-4">
        <div
          class="relative flex flex-col min-w-0 break-words w-full mb-6 shadow-lg rounded-lg bg-blueGray-200 border-0"
        >
          <div class="rounded-t mb-0 px-6 py-6">
            <div class="text-center mb-3">
              <h6 class="text-blueGray-500 text-sm font-bold">Войти через</h6>
            </div>
            <div class="btn-wrapper text-center">
              <button
                class="bg-white active:bg-blueGray-50 text-blueGray-700 font-normal px-4 py-2 rounded outline-none focus:outline-none mr-2 mb-1 uppercase shadow hover:shadow-md inline-flex items-center font-bold text-xs ease-linear transition-all duration-150"
                type="button"
              >
                <img alt="..." class="w-5 mr-1" :src="github" />
                Github
              </button>
              <button
                class="bg-white active:bg-blueGray-50 text-blueGray-700 font-normal px-4 py-2 rounded outline-none focus:outline-none mr-1 mb-1 uppercase shadow hover:shadow-md inline-flex items-center font-bold text-xs ease-linear transition-all duration-150"
                type="button"
              >
                <img alt="..." class="w-5 mr-1" :src="google" />
                Google
              </button>
            </div>
            <hr class="mt-6 border-b-1 border-blueGray-300" />
          </div>
          <div class="flex-auto px-4 lg:px-10 py-10 pt-0">
            <div class="text-blueGray-400 text-center mb-3 font-bold">
              <small>Или войти используя логин и пароль</small>
            </div>
            <form>
              <div class="relative w-full mb-3">
                <label
                  class="block uppercase text-blueGray-600 text-xs font-bold mb-2"
                  htmlFor="grid-password"
                >
                  Email
                </label>
                <input
                  type="email"
                  v-model="state.form.body.username"
                  class="border-0 px-3 py-3 placeholder-blueGray-300 text-blueGray-600 bg-white rounded text-sm shadow focus:outline-none focus:ring w-full ease-linear transition-all duration-150"
                  placeholder="Email"
                />
              </div>

              <div class="relative w-full mb-3">
                <label
                  class="block uppercase text-blueGray-600 text-xs font-bold mb-2"
                  htmlFor="grid-password"
                >
                  Пароль
                </label>
                <input
                  type="password"
                  v-model="state.form.body.password"
                  class="border-0 px-3 py-3 placeholder-blueGray-300 text-blueGray-600 bg-white rounded text-sm shadow focus:outline-none focus:ring w-full ease-linear transition-all duration-150"
                  placeholder="Password"
                />
              </div>
              <div>
                <label class="inline-flex items-center cursor-pointer">
                  <input
                    id="customCheckLogin"
                    type="checkbox"
                    class="form-checkbox border-0 rounded text-blueGray-700 ml-1 w-5 h-5 ease-linear transition-all duration-150"
                  />
                  <span class="ml-2 text-sm font-semibold text-blueGray-600">
                    Запомнить меня
                  </span>
                </label>
              </div>

              <div class="text-center mt-6">
                <button
                  @click="loginDefault"
                  class="bg-blueGray-800 text-white active:bg-blueGray-600 text-sm font-bold uppercase px-6 py-3 rounded shadow hover:shadow-lg outline-none focus:outline-none mr-1 mb-1 w-full ease-linear transition-all duration-150"
                  type="button"
                >
                  Войти
                </button>
              </div>
              <div
                v-if="state.form.errors.length"
                class="p-4 mt-6 text-center mb-4 text-sm text-red-700 bg-red-100 rounded-lg dark:bg-red-200 dark:text-red-800"
              >
                {{ state.form.errors.password }}
              </div>
            </form>
          </div>
        </div>
        <div class="flex flex-wrap mt-6 relative">
          <div class="w-1/2">
            <a href="javascript:void(0)" class="text-blueGray-200">
              <small>Забыли пароль?</small>
            </a>
          </div>
          <div class="w-1/2 text-right">
            <router-link to="/auth/register" class="text-blueGray-200">
              <small>Создать новый аккаунт</small>
            </router-link>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
import github from "@/assets/img/github.svg";
import google from "@/assets/img/google.svg";
import { reactive, onMounted } from "vue";
// import { useRouter } from "vue-router";
import router from "@/router";
import { useAuth } from "@websanova/vue-auth/src/v3.js";
import { useAuthStore } from "@/stores/auth.store.js";

export default {
  data() {
    return {
      github,
      google,
    };
  },
  setup() {
    const auth = useAuth();
    const store = useAuthStore();
    // const router = useRouter();

    const state = reactive({
      form: {
        body: {
          username: "tabarigen@mail.ru",
          password: "5vn63ys9",
        },
        remember: false,
        fetchUser: true,
        staySignedIn: false,
        errors: {},
      },
    });

    onMounted(() => {
      // console.log(auth);
    });

    function errors(res) {
      state.form.errors = Object.fromEntries(
        res.data.errors.map((item) => [item.field, item.msg])
      );
    }

    const form = new FormData();

    form.append("username", state.form.body.username);
    form.append("password", state.form.body.password);

    function loginDefault() {
      auth
        .login({
          data: form,
          remember: state.form.remember ? '{"name": "Default"}' : null,
          // fetchUser: state.form.fetchUser,
          staySignedIn: state.form.staySignedIn,
          redirect: "/",
        })
        .then(null, (res) => {
          errors(res.response);
        });
    }

    return {
      state,
      loginDefault,
      store,
    };
  },
};
</script>

@alimuradov
Copy link
Author

Снимок экрана от 2022-07-28 09-48-49
Снимок экрана от 2022-07-28 09-49-18

@websanova
Copy link
Owner

Hmm, so does the login call return a token?

@alimuradov
Copy link
Author

yes
image

@websanova
Copy link
Owner

Yea, so you're not using the correct auth driver it seems, you will just have to role a custom one to pick up the token from the response body.

@alimuradov
Copy link
Author

Thank you for advice.
Creating your own driver helped to pass authorization. But it has not been possible to sort out the storage yet, user data is not saved in it.
If you have the opportunity, please make a demo project using pinia.
vuex is not so popular anymore, and vue developers recommend using pinia

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants