Giter Club home page Giter Club logo

Comments (11)

Atinux avatar Atinux commented on July 20, 2024 1

Could you try to move the logic of checking the user + plan directly into a Nitro plugin, we have session hooks for this: https://github.com/Atinux/nuxt-auth-utils?tab=readme-ov-file#extend-session

// server/plugins/session.ts
export default defineNitroPlugin(() => {
  // Called when the session is fetched during SSR for the Vue composable (/api/_auth/session)
  sessionHooks.hook('fetch', async (session, event) => {
    const latestUserData = await findUserById(session.user.id);
    const { subscribed, isCanceled, proPlan } = await checkPlan(latestUserData);
    session.user.subscribed = subscribed;
    session.user.isCanceled = isCanceled;
    session.user..proPlan = proPlan;
  })
})

This should update the session before returning it to useUserSession() and will also work when running fetch from useSessionSession()

from nuxt-auth-utils.

fayazara avatar fayazara commented on July 20, 2024 1

Closing this, thank you for the help!

from nuxt-auth-utils.

fayazara avatar fayazara commented on July 20, 2024

As a workaround I am doing a hard reload - return window.location.replace("/dashboard");

from nuxt-auth-utils.

Atinux avatar Atinux commented on July 20, 2024

You need to call the fetch method to refresh the session on client-side @fayazara

const { fetch: refreshSession } = useUserSession()

async function onSubmit(event) {
  try {
    loading.value = true;
    await $fetch("/api/auth/login", {
      method: "POST",
      body: state,
    });
    await refreshSession()
    return navigateTo("/dashboard");
  } catch (error) {
    toast.add({
      title: "Error",
      description: error.statusMessage,
      color: "rose",
    });
    loading.value = false;
  }
}

from nuxt-auth-utils.

fayazara avatar fayazara commented on July 20, 2024

Worked perfectly, thank you!

from nuxt-auth-utils.

fayazara avatar fayazara commented on July 20, 2024

@Atinux reopening this for another question.

What is the right way to update the session after the user data has been updated and we want to update the session data? I saw there's replaceUserSession,

Use case:
I am using a webhook to update the users plan/subscription data after they pay on stripe. My db gets updated, but I am lost on a good way to update the session, because it wont happen unless I refresh the page or login again.

What I tried doing (but doesn't work properly)

<template>
  <AppContainer title="Settings">
    <div class="h-full p-4">
      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-4">
        <div>Current subscription: {{ user?.proPlan?.name || "Free" }}</div>
      </div>
      <div class="grid grid-cols-3 gap-4 mt-4">
        <div class="" v-for="plan in plans" :key="plan.id">
          <div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-4">
            <h2 class="text-xl font-semibold">{{ plan.name }}</h2>
            <p class="text-gray-500 dark:text-gray-400 text-sm">
              {{ plan.description }}
            </p>
            <ul class="mt-4">
              <li
                v-for="feature in plan.features"
                class="flex items-center gap-2"
              >
                <UIcon name="i-lucide-check" class="text-primary-500" />
                <span>{{ feature }}</span>
              </li>
            </ul>
            <div class="mt-4">
              <span class="text-3xl font-semibold">{{ plan.price }}</span>
              <span class="text-gray-500 dark:text-gray-400">/ month</span>
            </div>
            <UButton
              class="mt-4"
              variant="solid"
              color="white"
              size="lg"
              block
              label="Subscribe"
              @click="subscribe(plan.stripePriceId)"
            />
          </div>
        </div>
      </div>
    </div>
  </AppContainer>
</template>

<script setup>
const { user, fetch: refreshSession } = useUserSession();
const { data: plans } = await useFetch("/api/stripe/get-plans");
const route = useRoute();
const toast = useToast();
const subscribe = async (planId) => {
  const data = await $fetch(`/api/stripe/checkout?plan=${planId}`);
  if (data.url) window.location.href = data.url;
};

onMounted(async () => {
  await $fetch("/api/auth/update-session");
});
</script>

Created a api route called update-session

import { findUserById } from "@/server/utils/queries/users";

export default defineEventHandler(async (event) => {
  const session = await requireUserSession(event);
  const userId = session.user.id;
  const latestUserData = findUserById(userId);
  delete latestUserData.password;
  const newSessionData = {
    ...session,
    user: latestUserData,
  };
  await replaceUserSession(event, newSessionData);
  return { success: true };
});

Doesn't update the session with the new data for some reason

from nuxt-auth-utils.

Atinux avatar Atinux commented on July 20, 2024

I think for such use case where you update the session on server-side, I would use useDocumentVisibility in the mounted() hook of the page in order to refresh the session when the tab becomes active again ;)

from nuxt-auth-utils.

fayazara avatar fayazara commented on July 20, 2024

@Atinux I dont think the issue is related to updating the data in realtime, sorry if I was not clear, the session is not updated even after I get redirected from the stripe page or when the page is refreshed

Below video might explain my problem better.

  1. You can see the stripeId and other details are empty.
  2. Stripe flow is completed and data gets added in my db.
  3. We're redirected back to my billing page and I still see the "Plan as Free"
  4. You can see the stripe details in my db
  5. I refresh the page and still see the data not yet update.

The session get's updated only if I logout and login, probably because we're clearing repopulating the session data. I think my question probably is, does the session data not get updated when I refresh the page?

Screenshot.25-02.at.19.mp4

from nuxt-auth-utils.

fayazara avatar fayazara commented on July 20, 2024

Apologies I understand this is not an issue related to the module, rather an issue with my business logic. Just trying to understand how to get subscriptions working.

I now realise that we set the session only when the user logins and it's not mutated after that, so when the user is redirected from stripe the db is updated not the session.

So I thinking I will just set the session one more time once we land on this page.

from nuxt-auth-utils.

fayazara avatar fayazara commented on July 20, 2024

UPDATE:

I am now manually updating the session and it still won't update my session in the client 😅

billing.vue page

<template>
  <AppContainer title="Settings">
    <div class="h-full p-4">
      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-4">
        <div>Current subscription: {{ user?.proPlan?.name || "Free" }}</div>
      </div>
      <AppBillingPlanSelector />
    </div>
  </AppContainer>
</template>

<script setup>
const { user, fetch: refreshSession, session } = useUserSession();
await useAsyncData("session-manager", async () => {
  await useRequestFetch()("/api/auth/update-session");
  await refreshSession();
});
</script>

And this is the update-session api endpoint

import { findUserById } from "@/server/utils/queries/users";

export default defineEventHandler(async (event) => {
  try {
    console.log("I am here in update-session.js");
    const session = await requireUserSession(event);
    const userId = session.user.id;
    console.log("userId", userId);
    const latestUserData = await findUserById(userId);
    delete latestUserData.password;
    const { subscribed, isCanceled, proPlan } = await checkPlan(latestUserData);
    latestUserData.subscribed = subscribed;
    latestUserData.isCanceled = isCanceled;
    latestUserData.proPlan = proPlan;
    console.log(latestUserData);
    const updatedSession = await setUserSession(event, { user: latestUserData });
    console.log("updatedSession", updatedSession);
    return { success: true };
  } catch (error) {
    console.log(error)
    throw createError({statusCode: 500, statusMessage: "Error updating session"});
  }
});

I can see the logs getting printed in the console from the api and the updated session data, but it still wont get updated in the client side as I am calling the fetch: refreshSession method after I update my session in the server with my custom endpoint.

from nuxt-auth-utils.

fayazara avatar fayazara commented on July 20, 2024

Thank you 🫡

from nuxt-auth-utils.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.