Используйте Vue. js плагин в js сервисном модуле - PullRequest
0 голосов
/ 16 марта 2020

Я создаю плагин $auth, который отлично работает с компонентом, используя this.$auth

main. js

import { Auth0Plugin } from "./auth";

Vue.use(Auth0Plugin, {
  domain: process.env.VUE_APP_AUTH0_DOMAIN,
  clientId: process.env.VUE_APP_AUTH0_CLIENT_ID,
  audience: process.env.VUE_APP_AUTH0_AUDIENCE,
  onRedirectCallback: () => {
    router.push("/signed-in");
  }
});

auth / index. js

import Vue from "vue";
import createAuth0Client from "@auth0/auth0-spa-js";

/** Define a default action to perform after authentication */
const DEFAULT_REDIRECT_CALLBACK = () =>
  window.history.replaceState({}, document.title, window.location.pathname);

let instance;

/** Returns the current instance of the SDK */
export const getInstance = () => instance;

/** Creates an instance of the Auth0 SDK. If one has already been created, it returns that instance */
export const useAuth0 = ({
  onRedirectCallback = DEFAULT_REDIRECT_CALLBACK,
  redirectUri = window.location.origin,
  ...options
}) => {
  if (instance) return instance;

  // The 'instance' is simply a Vue object
  instance = new Vue({
    data() {
      return {
        loading: true,
        isAuthenticated: false,
        user: {},
        auth0Client: null,
        popupOpen: false,
        error: null
      };
    },
    methods: {
      /** Returns the access token. If the token is invalid or missing, a new one is retrieved */
      getTokenSilently(o) {
        return this.auth0Client.getTokenSilently(o);
      },
    },
    /** Use this lifecycle method to instantiate the SDK client */
    async created() {
      // Create a new instance of the SDK client using members of the given options object
      this.auth0Client = await createAuth0Client({
        domain: options.domain,
        client_id: options.clientId,
        audience: options.audience,
        redirect_uri: redirectUri
      });

      try {
        // If the user is returning to the app after authentication..
        if (
          window.location.search.includes("code=") &&
          window.location.search.includes("state=")
        ) {
          // handle the redirect and retrieve tokens
          const { appState } = await this.auth0Client.handleRedirectCallback();

          // Notify subscribers that the redirect callback has happened, passing the appState
          // (useful for retrieving any pre-authentication state)
          onRedirectCallback(appState);
        }
      } catch (e) {
        this.error = e;
      } finally {
        // Initialize our internal authentication state
        this.isAuthenticated = await this.auth0Client.isAuthenticated();
        this.user = await this.auth0Client.getUser();
        this.loading = false;
      }
    }
  });

  return instance;
};

// Create a simple Vue plugin to expose the wrapper object throughout the application
export const Auth0Plugin = {
  install(Vue, options) {
    Vue.prototype.$auth = useAuth0(options);
  }
};

У меня есть класс обслуживания, который вызывает API. Мне нужно получить токен API от этого плагина $auth.getTokenSilently(). Как мне вызвать инстанцированный плагин из моего api-service.js файла?

Я знаю, что приведенный ниже код не работает. Но это всего лишь демонстрация того, что я пытаюсь сделать. Утилиты / API-сервис. js

export default {
  init() {
    this.lqdApi = axios.create({
      baseURL: process.env.lqdApiBaseUrl,
      headers: { Authorization: `Bearer ${$auth.getTokenSilently()}` }
    });
    return this;
  },
}

1 Ответ

1 голос
/ 17 марта 2020

Служба должна быть инициализирована внутри Vue. Он может быть просто внедрен с данными инициализации:

  init(token) {
    this.lqdApi = axios.create({
      baseURL: process.env.lqdApiBaseUrl,
      headers: { Authorization: `Bearer ${token}` }
    });
    return this;
  },

Проблема здесь в том, что async created является потенциальным антипаттерном, он не препятствует инициализации дочерних компонентов при auth0Client и, следовательно, api-service не готовы, но используются компонентами. Если это так, одно из возможных решений - сделать экземпляр Ax ios доступным на прототипе Vue, как показано здесь . Экземпляр необходимо создать немедленно, но ему может быть предоставлен токен асинхронно с перехватчиками, поскольку они поддерживают обещания. Он может быть записан в виде плагина и стать доступным для экземпляра Vue, например $auth:

  install(Vue, options) {
    Vue.prototype.$axios = axios.create();
  },
  created() {
    if (this.$root === this) {
      this.$axios.interceptors.request.use(async config => {
        let auth0Client = await this.auth0ClientPromise;
        config.headers.Authorization = `Bearer ${auth0Client.getTokenSilently()}`;
        return config;
    }
  }

. И обещание экземпляра клиента Auth0 должно быть доступно в экземпляре Vue, чтобы быть связанным Топор ios (и, возможно, другие вещи, которые могут от него зависеть):

  this.auth0ClientPromise = createAuth0Client(...);
  this.auth0Client = await auth0ClientPromise;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...