Use RLS policies from Supabase with Plasmic

Hi there!
I have been testing Supabase integration with Plasmic, trying to write a table ONLY if the user is logged in. I am using Supabase auth system through Next.js SSR. No matter what, I can always INSERT into my Supabase table (I have a RLS policy avoiding that). Now I have realised that it could be because the direct connection made between Plasmic and Supabase, am I right?
So my question is: what are my options? I want only logged in users to be able to write my table. We were planning on doing it with Supabase auth but then I cannot use direct integration from Plasmic, right?
I fwe use Plasmic users, could I do that or not?
Is my only option hiding the page where the user inserts data to the table?
Thanks in advance,
P.S. Great work, I thing Plasmic is a really nice approach between a noCode tool and a React environment!

Hey Daniel (are you from Spain BTW? I am!),

I’m not from Plasmic team, just a new excited user of Plasmic, so I hope I don’t make any mistakes.

Yes, RLS is only available through the API/SDK. As Plasmic does a direct connection we have to treat it as a normal database (it’s a bit unfortunate tbh).

Apart from hiding it, you can limit who or which roles can perform the data operation. You can watch it in the final part of the “Users logins and permissions” video: https://youtu.be/hVzqjtkcEyk?t=206

As far as I’ve understood, when you use the Supabase auth integration with Plasmic from that template, what it does under the hood is it creates a “Plasmic auth” user for every user created in Supabase. That way you still use Supabase auth but you can use the normal User, Roles, Permissions… that Plasmic offers (this is my interpretation, take it with a pinch of salt and hopefully someone from the team can confirm/clarify).
You can learn more about how it works in this doc: Auth integration | Learn Plasmic (even though it explains what we would have to install and how if we didn’t clone the template, it also describes the internal inner workings of the solution).

I really really hope they step up their Supabase integration with the SDK and without having to create a custom project, etc. That and charts are their only weak spots for me that Plasmic has. But it is my favorite lowcode solution after extensive research.

Hope that helps. Cheers!

2 Likes

Hey Daniel,

I can’t comment directly on setting up and using Supabase as a Custom Auth Provider in Plasmic through the traditional means. I haven’t spent any significant time with it given I had an explicit requirements for Supabase RLS.

However, @callum_boase and I have been collaborating to develop three Supabase components (auth, data and storage provider) that all work together to provide Plasmic>Supabase integration, including RLS.

We are currently dogfooding the solution in our own app builds to resolve any technical, functional or usability issues. We plan to release soon once:

  • we are comfortable we have a quality solution, meeting most common scenarios with a good developer experience.
  • we have developed documentation, demos and communication channels for this to be manageable.

Would be open to demonstrating some of this to you to get feedback and see if it would meet your needs once released.

2 Likes

¡Hola Jacobo! Encantado de saludarte. Sí, yo también soy español :slight_smile:
Thanks a lot for the info. I had already read most of it but I gave it another try. What I finally did was using the demo from Plasmic’s Github and setting all the necessary files in my own project. Is kind of tricky because in order to get also the components created by them (Auth form and auth button), you need to make a copy of their Plasmic project and import it (previously auth must be disabled). There is more info about importing components through projects here.
After a while I have managed to have an auth system working seamlessly integrated in Plasmic but using Supabase. No RLS, of course, but both the pages and the requests requiring log in are protected in Plasmic through user auth. It works for me, for now at least.
Thanks a lot!!

1 Like

Hi Ryan!
Sounds really great, keep me posted. I am very interested in a better solution.
Cheers,

Hi @daniel_grau!

I am also studying this integration and was able to do something connecting my plasmic app with supabase following examples. I was also thinking about the RLS, but I am some steps behind.

I was able to make AuthForm, my supabase get the credendials and redirect, however my user (I have the same user in plasmic) didn’t work as expected, I can’t see non anonymous routes, just can see pages for the anonymous role.

I can navigate through my app (next app) but I don’t know how to handle some behaviors, like:

  1. After auth, if user try to access /auth again, I would like to check if user isLoggedIn then redirect to ‘some path’. So basically I would need to write some logic to the Auth (Plasmic) page. I don’t know exactly what could be done in plasmic or which would be the best approach.

  2. I am a bit confused about plasmic and supabase necessary files, I mean, my project settings are correct (components are loading through Plasmic API), supabase configs credentials are ok, but I am not sure if I am forgetting something and because of that plasmic permissions are not working with my components.

  3. Are you using SSR?
    I have seen diferent approachs, supabase tutorial uses it and the documentation consider another lib (@supase/SSR instead of supabase/next-js-helper)

Can you share your structure with me?
It really would help me a lot.

Thanks guys, plasmic is really awesome.

Hi @tchellos-mbt,
I’m afraid I cannot help you much since I am also learning by doing…
I had no problem with the Plasmic part. Have you set up Plasmic authentication? What I did was follow the Github link from my previous post and copy everything relevant from that rep to my codebase.

  1. Not sure about how to do that. You could do it with code, for sure.
  2. Again…Plasmic Auth? Have you checked everything is OK on that part? (Plasmic Studio, the three dots next to your project, where you set the App Host)
  3. I started using SSR following this tutorial but that is not written to be used with Plasmic Auth so I had all the problems that made me start this thread… :slight_smile:

Again, follow that tutorial from Github, my structure is exactly the same.
Good luck!

Thanks, man!

Well, I have copied as you did.
Inside AuthForm, for this line “await mutate(PLASMIC_AUTH_DATA_KEY);” I got ‘undefined’

I have configured plasmic studio to use custom auth, and added the secret inside the .env.local
This constant “PLASMIC_AUTH_DATA_KEY” which value may I initialize?

It’s inside cache-keys.ts

export const PLASMIC_AUTH_DATA_KEY = "plasmic-auth-data";

Form or Button? I have that code in Button, not Form
AuthButton:

import { PlasmicComponent } from "@plasmicapp/loader-nextjs";
import { createPagesBrowserClient } from "@supabase/auth-helpers-nextjs";
import { useRouter } from "next/router";
import { useState } from "react";
import { mutate } from "swr";
import { PLASMIC_AUTH_DATA_KEY } from "../utils/cache-keys";

export function AuthButton(): JSX.Element {
  const [supabaseClient] = useState(() => createPagesBrowserClient());
  const router = useRouter();
  return (
    <PlasmicComponent
      forceOriginal
      component="AuthButton"
      componentProps={{
        logoutBtn: {
          onClick: async () => {
            await supabaseClient.auth.signOut();
            await mutate(PLASMIC_AUTH_DATA_KEY);
            router.push("/");
            // router.reload();
          },
        },
      }}
    />
  );
}

AuthForm:

import { PlasmicComponent } from "@plasmicapp/loader-nextjs";
import { createPagesBrowserClient } from "@supabase/auth-helpers-nextjs";
import { useRouter } from "next/router";
import { useState } from "react";
import { mutate } from "swr";
import { PLASMIC_AUTH_DATA_KEY } from "../utils/cache-keys";

export function AuthForm(): JSX.Element {
  const [supabaseClient] = useState(() => createPagesBrowserClient());
  const router = useRouter();
  return (
    <PlasmicComponent
      forceOriginal
      component="AuthForm"
      componentProps={{
        handleSubmit: async (
          mode: "signIn" | "signUp",
          credentials: {
            email: string;
            password: string;
          }
        ) => {
          if (mode === "signIn") {
            await supabaseClient.auth.signInWithPassword(credentials);
          } else {
            await supabaseClient.auth.signUp(credentials);
          }
          await mutate(PLASMIC_AUTH_DATA_KEY);
          router.push("/");
        },
      }}
    />
  );
}