последний токен jwt не обновляется в vue - PullRequest
0 голосов
/ 29 марта 2020

У меня проблема с тем, что после входа пользователя в систему пользователь не обновляет последние данные, и я не вижу его в пользовательском интерфейсе.

Пользователь является частью последнего возвращенного объекта токена, и я могу см. в консоли, что vue загружает пользователя с его предыдущим состоянием, не загружая его снова с последним полученным токеном после того, как jwt был обновлен и установлен как постоянный.

Я думаю, что мне нужно создать вычисленный на функция, которая возвращает токен, или свойство токена, которое изменяется, я не уверен ...

следующий код:

root-component.vue

<template>
  <app v-bind:tokenInstance="tokenInstance" v-bind:saveUserLocales="saveUserLocales"></app>
</template>

<script>
const { getTokenInstance, getTokenInstanceFromStorage, fetchProtectedApi } = require('../auth/jwt.js');
const { onAkuoJwtChanged } = require('../jwt-akuo-token-listener.js');
const { sendToAllTabs } = require('../cross-environment-code/messaging');

const storedTokenInstance = getTokenInstanceFromStorage();

const rootComponent = {
  components: {
    'app': require('./app.vue')
  },
  data() {
    return {
      tokenInstance: storedTokenInstance
    };
  },
  created() {
    onAkuoJwtChanged(this.setTokenInstance);
    console.log('creation of function onAkuoJwtChanged with ');
  },
  methods: {
    setTokenInstance(jwt) {
      console.log('setTokenInstance:', jwt)
      this.tokenInstance = getTokenInstance(jwt);
    },
    // this could probably be ubstracted to a more generic `saveUser`. Maybe we will save user elsewhere too and we do not want to deal with seting token there as well
    saveUserLocales(userId, locales) {
      return fetchProtectedApi(`users/${userId}`, {
        method: 'PUT',
        body: { locales }
      }).then(
        ({ token }) => {
          this.setTokenInstance(token); // this could be removed if sending singedIn would trigger a local storage set and this in turn would trigger onAkuoJwtChanged that calls thissetTokenInstance
          // here -> engine.content -> background page (where we store the token)
          sendToAllTabs({
            fn: 'signedIn',
            message: token
          }); // this is fine since both options page and background page share the same localStorage! according to this stackoverflow post: https://stackoverflow.com/a/8790423
        },
        (error) => {
          // TODO notify user that it failed
          console.error(error);
        }
      );
    }
  }
};
app.vue
<template>
  <div>
    <no-token v-if="displaySignIn" v-bind:tokenInstance="tokenInstance"></no-token>
    <with-chosen-locales v-else v-bind:userLocales="user.locales" v-bind:saveUserLocales="saveUserLocales" v-bind:userId="userId"></with-chosen-locales>
  </div>
</template>

<script>
const { getUserIntance } = require('../models/user');
module.exports = {
  components: {
    'no-token': require('./no-token.vue'),
    'no-locales': require('./no-locales.vue'),
    'with-chosen-locales': require('./with-chosen-locales.vue')
  },
  props: ['tokenInstance', 'saveUserLocales'],
  data() {
    return {};
  },
  computed: {
    displaySignIn() {
      console.log('displaySignIn: ', (!this.tokenInstance || this.tokenInstance.isExpired()));
      return !this.tokenInstance || this.tokenInstance.isExpired();
    },
    hasNotChosenLocales() {
      console.log('hasNotChosenLocales: ', (this.userInstance && !this.userInstance.hasChosenLocales()))
      return this.userInstance && !this.userInstance.hasChosenLocales();
    },
    hasNotDetectedLocales() {
      console.log('hasNotDetectedLocales: ', (this.userInstance && !this.userInstance.detectedLocales()))
      return this.userInstance && !this.userInstance.detectedLocales();
    },
    user() {
      console.log('user: ', this.tokenInstance.getUser())
      return this.tokenInstance.getUser();
    },
    userInstance() {
      console.log('userInstance: ', this.user && getUserIntance(this.user))
      return this.user && getUserIntance(this.user);
    },
    userId() {
      console.log('userId: ', (this.userInstance && this.userInstance.getJson()._id))
      return this.userInstance && this.userInstance.getJson()._id;
    }
  }
};
</script>

с выбранными локалями. vue

<template>
<div v-if="isEditMode === false">
    <div>chosen locales</div>
    <template v-for="localeObj in chosenLocales">
      <div>{{localeObj.locale}}</div>
    </template>
    <button v-on:click="switchToEditMode">Edit</button>
</div>
<div v-else>
    <div>Edit locales</div>
    <template v-for="localeObj in availableLocales">
      <input type="checkbox" id="localeObj.locale" v-bind:checked="localeObj.chosen" v-on:click="localeObj.chosen = !localeObj.chosen">
      <label for="localeObj.locale">{{localeObj.locale}}</label>
    </template>
    <button v-on:click="save">Save</button>
</div>
</template>
<script>
const { fetchProtected } = require('../auth/jwt.js');
function cloneLocales(locales) {
  return locales.map(x => Object.assign({}, x));
}
module.exports = {
  props: ['userLocales', 'saveUserLocales', 'userId'],
  data() {
    return { 
      componentLocales: cloneLocales(this.userLocales),
      availableLocales: [],
      editMode: false };
  },
  computed: {
    chosenLocales() {
      return this.componentLocales.filter(x => x.chosen);
    },
    isEditMode()
    {
      console.log('this.userLocales:', this.userLocales);
      return this.editMode;
    }
  },
    methods: {
    switchToEditMode() {
      return fetchProtected(`data/list.json`, {
        method: 'GET'
      }).then(
        (v) => {
          this.availableLocales = v.map(l => {
            return {
              locale:l,
              chosen: this.chosenLocales.filter(x => x.locale === l).length > 0
            };});
          this.editMode = true;
        },
        (error) => {
          // TODO notify user that it failed
          console.error(error);
        }
      );
     },

    save() {
      this.saveUserLocales(this.userId, this.availableLocales.filter(x => x.chosen));
      this.componentLocales = this.availableLocales;
      this.editMode = false;
    },
}};
</script>

Ваша помощь, Ассаф

1 Ответ

0 голосов
/ 29 марта 2020

Вы явно должны использовать Vuex для этой задачи.

Вы отправляете свой токен от root дочерним компонентам - собираетесь ли вы добавить это свойство к каждому компоненту, который нуждается в нем? Вот почему Vuex нужен. Он синхронизирует данные по всему приложению.

Переместите все свои токены, получающие логи c, в модуль Vuex, например:

  1. Создайте токен в состоянии Vuex с начальным значением, извлеченным из хранилища
  2. Создайте мутацию который установит токен в хранилище и установит токен в состоянии
  3. Создайте действие, которое вызовет API и передаст токен мутации
  4. Создайте геттер для использования этого токена из Vuex

Это также объясняется здесь: https://scotch.io/tutorials/handling-authentication-in-vue-using-vuex

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