usebasejump / basejump Goto Github PK
View Code? Open in Web Editor NEWTeams, personal accounts, permissions and billing for your Supabase app
Home Page: https://usebasejump.com
License: MIT License
Teams, personal accounts, permissions and billing for your Supabase app
Home Page: https://usebasejump.com
License: MIT License
Hi, so I am confused how to use the RPC methods to get the account info. What I'm trying to do is just have a single function to get the account for me, and it automatically determines whether the account selector is on a team or not. Currently is what I have below, and basically, it just checks to see if there is a slug in the URL. Basically im wondering if theres a better way to do this, because its very sloppy and its a huge mess. A huge issue too is that the RPCs dont get types when generated with the supabase CLI. Basically I'd like advice on how to implement this with it being disaster. Thanks.
EDIT: Even more so, it seems like Supabase is trying to find these RPC on the public schema, where they dont exist. Dont know how to fix that either or something like that
Searched for the function public.get_account_by_slug without parameters or with a single unnamed json/jsonb parameter, but no matches were found in the schema cache
`import { createClient } from "@/utils/supabase/server";
export interface AccountData {
account_id: string;
account_role: string;
is_primary_owner: boolean;
name: string;
slug: string;
personal_account: boolean;
billing_enabled: boolean;
billing_status: string;
created_at: string; // Assuming timestamp is a string, adjust if it's a Date object
updated_at: string; // Same assumption as created_at
metadata: {
[key: string]: any; // Adjust according to the known structure or keep it flexible
};
}
export async function getAccountData({ params }: { params: { slug: string } }) {
const supabase = createClient();
if (params.slug === "personal") {
const { data, error } = await supabase.rpc("get_personal_account");
return { data: data as unknown as AccountData, error };
}
const { data, error } = await supabase.rpc("get_account_by_slug", {
slug: params.slug,
});
return { data: data as unknown as AccountData, error };
}
`
Hey! First thing, great work with basejump! I started on a similar project myself, but found that you have done a lot of the thing I was planning (but better), so I've decided to try and contribute to basejump instead.
I'm thinking about adapting https://github.com/supabase/supa_audit for the basejump multi tenancy setup and create a frontend-view for it. Would you be open for submission for such a feature?
The example on this page shows the page accessing data.email
from the get_personal_account
RPC response: https://usebasejump.com/docs/react/user-account-button. For context i'm using the RSC example.
When in fact the response does not contain email
. Here's an example response:
{
account_id: '3360b947-c0d2-4873-a145-64d5f6e399cf',
account_role: 'owner',
is_primary_owner: true,
name: 'ian',
slug: null,
personal_account: true,
billing_enabled: true,
billing_status: null,
created_at: '2024-01-11T00:02:55.986862+00:00',
updated_at: '2024-01-11T00:02:55.986862+00:00',
metadata: {}
}
Which matches the API docs: https://usebasejump.com/docs/accounts#retrieve-personal-account. My understanding is "Account" refers to a grouping of users, in which case it makes sense that email
isn't included.
thank you so much for such a great framework
Are you planning to upgrade the withApiAuth with createServerSupabaseClient?
After clonning i am trying supabase start
and have error that pg_tle not exist. How to fix it? I use wsl2 with ubuntu.
2023/07/01 10:54:38 PG Recv: {"Type":"BindComplete"}
2023/07/01 10:54:38 PG Recv: {"Type":"NoData"}
2023/07/01 10:54:38 PG Recv: {"Type":"CommandComplete","CommandTag":"DROP EXTENSION"}
2023/07/01 10:54:38 PG Recv: {"Type":"ParseComplete"}
2023/07/01 10:54:38 PG Recv: {"Type":"BindComplete"}
2023/07/01 10:54:38 PG Recv: {"Type":"NoData"}
2023/07/01 10:54:38 PG Recv: {"Type":"CommandComplete","CommandTag":"CREATE EXTENSION"}
2023/07/01 10:54:38 PG Recv: {"Type":"ParseComplete"}
2023/07/01 10:54:38 PG Recv: {"Type":"BindComplete"}
2023/07/01 10:54:38 PG Recv: {"Type":"NoData"}
2023/07/01 10:54:38 PG Recv: {"Type":"CommandComplete","CommandTag":"RESET"}
2023/07/01 10:54:38 PG Recv: {"Type":"ReadyForQuery","TxStatus":"I"}
Applying migration 00000000000000_dbdev_temp_install.sql...
2023/07/01 10:54:38 PG Send: {"Type":"Parse","Name":"","Query":"/**\n This should be automatically installed, but handling here manually until it is\n https://database.dev/installer\n */\ncreate extension if not exists http with schema extensions","ParameterOIDs":null}
2023/07/01 10:54:38 PG Send: {"Type":"Bind","DestinationPortal":"","PreparedStatement":"","ParameterFormatCodes":null,"Parameters":[],"ResultFormatCodes":[]}
2023/07/01 10:54:38 PG Send: {"Type":"Describe","ObjectType":"P","Name":""}
2023/07/01 10:54:38 PG Send: {"Type":"Execute","Portal":"","MaxRows":0}
2023/07/01 10:54:38 PG Send: {"Type":"Parse","Name":"","Query":"create extension if not exists pg_tle","ParameterOIDs":null}
2023/07/01 10:54:38 PG Send: {"Type":"Bind","DestinationPortal":"","PreparedStatement":"","ParameterFormatCodes":null,"Parameters":[],"ResultFormatCodes":[]}
2023/07/01 10:54:38 PG Send: {"Type":"Describe","ObjectType":"P","Name":""}
2023/07/01 10:54:38 PG Send: {"Type":"Execute","Portal":"","MaxRows":0}
2023/07/01 10:54:38 PG Send: {"Type":"Parse","Name":"","Query":"select pgtle.uninstall_extension_if_exists('supabase-dbdev')","ParameterOIDs":null}
2023/07/01 10:54:38 PG Send: {"Type":"Bind","DestinationPortal":"","PreparedStatement":"","ParameterFormatCodes":null,"Parameters":[],"ResultFormatCodes":[]}
2023/07/01 10:54:38 PG Send: {"Type":"Describe","ObjectType":"P","Name":""}
2023/07/01 10:54:38 PG Send: {"Type":"Execute","Portal":"","MaxRows":0}
2023/07/01 10:54:38 PG Send: {"Type":"Parse","Name":"","Query":"drop extension if exists \"supabase-dbdev\"","ParameterOIDs":null}
2023/07/01 10:54:38 PG Send: {"Type":"Bind","DestinationPortal":"","PreparedStatement":"","ParameterFormatCodes":null,"Parameters":[],"ResultFormatCodes":[]}
2023/07/01 10:54:38 PG Send: {"Type":"Describe","ObjectType":"P","Name":""}
2023/07/01 10:54:38 PG Send: {"Type":"Execute","Portal":"","MaxRows":0}
2023/07/01 10:54:38 PG Send: {"Type":"Parse","Name":"","Query":"select pgtle.install_extension(\n 'supabase-dbdev',\n resp.contents -\u003e\u003e 'version',\n 'PostgreSQL package manager',\n resp.contents -\u003e\u003e 'sql'\n )\nfrom http(\n (\n 'GET',\n 'https://api.database.dev/rest/v1/'\n || 'package_versions?select=sql,version'\n || '\u0026package_name=eq.supabase-dbdev'\n || '\u0026order=version.desc'\n || '\u0026limit=1',\n array [\n ('apiKey',\n 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InhtdXB0cHBsZnZpaWZyYndtbXR2Iiwicm9sZSI6ImFub24iLCJpYXQiOjE2ODAxMDczNzIsImV4cCI6MTk5NTY4MzM3Mn0.z2CN0mvO2No8wSi46Gw59DFGCTJrzM0AQKsu_5k134s')::http_header\n ],\n null,\n null\n )\n ) x,\n lateral (\n select ((row_to_json(x) -\u003e 'content') #\u003e\u003e '{}')::json -\u003e 0\n ) resp(contents)","ParameterOIDs":null}
2023/07/01 10:54:38 PG Send: {"Type":"Bind","DestinationPortal":"","PreparedStatement":"","ParameterFormatCodes":null,"Parameters":[],"ResultFormatCodes":[]}
2023/07/01 10:54:38 PG Send: {"Type":"Describe","ObjectType":"P","Name":""}
2023/07/01 10:54:38 PG Send: {"Type":"Execute","Portal":"","MaxRows":0}
2023/07/01 10:54:38 PG Send: {"Type":"Parse","Name":"","Query":"create extension \"supabase-dbdev\"","ParameterOIDs":null}
2023/07/01 10:54:38 PG Send: {"Type":"Bind","DestinationPortal":"","PreparedStatement":"","ParameterFormatCodes":null,"Parameters":[],"ResultFormatCodes":[]}
2023/07/01 10:54:38 PG Send: {"Type":"Describe","ObjectType":"P","Name":""}
2023/07/01 10:54:38 PG Send: {"Type":"Execute","Portal":"","MaxRows":0}
2023/07/01 10:54:38 PG Send: {"Type":"Parse","Name":"","Query":"select dbdev.install('supabase-dbdev')","ParameterOIDs":null}
2023/07/01 10:54:38 PG Send: {"Type":"Bind","DestinationPortal":"","PreparedStatement":"","ParameterFormatCodes":null,"Parameters":[],"ResultFormatCodes":[]}
2023/07/01 10:54:38 PG Send: {"Type":"Describe","ObjectType":"P","Name":""}
2023/07/01 10:54:38 PG Send: {"Type":"Execute","Portal":"","MaxRows":0}
2023/07/01 10:54:38 PG Send: {"Type":"Parse","Name":"","Query":"drop extension if exists \"supabase-dbdev\"","ParameterOIDs":null}
2023/07/01 10:54:38 PG Send: {"Type":"Bind","DestinationPortal":"","PreparedStatement":"","ParameterFormatCodes":null,"Parameters":[],"ResultFormatCodes":[]}
2023/07/01 10:54:38 PG Send: {"Type":"Describe","ObjectType":"P","Name":""}
2023/07/01 10:54:38 PG Send: {"Type":"Execute","Portal":"","MaxRows":0}
2023/07/01 10:54:38 PG Send: {"Type":"Parse","Name":"","Query":"create extension \"supabase-dbdev\"","ParameterOIDs":null}
2023/07/01 10:54:38 PG Send: {"Type":"Bind","DestinationPortal":"","PreparedStatement":"","ParameterFormatCodes":null,"Parameters":[],"ResultFormatCodes":[]}
2023/07/01 10:54:38 PG Send: {"Type":"Describe","ObjectType":"P","Name":""}
2023/07/01 10:54:38 PG Send: {"Type":"Execute","Portal":"","MaxRows":0}
2023/07/01 10:54:38 PG Send: {"Type":"Sync"}
2023/07/01 10:54:38 PG Recv: {"Type":"ParseComplete"}
2023/07/01 10:54:38 PG Recv: {"Type":"BindComplete"}
2023/07/01 10:54:38 PG Recv: {"Type":"NoData"}
2023/07/01 10:54:38 PG Recv: {"Type":"CommandComplete","CommandTag":"CREATE EXTENSION"}
2023/07/01 10:54:38 PG Recv: {"Type":"ParseComplete"}
2023/07/01 10:54:38 PG Recv: {"Type":"BindComplete"}
2023/07/01 10:54:38 PG Recv: {"Type":"NoData"}
2023/07/01 10:54:38 PG Recv: {"Type":"ErrorResponse","Severity":"ERROR","SeverityUnlocalized":"ERROR","Code":"0A000","Message":"extension \"pg_tle\" is not available","Detail":"Could not open extension control file \"/usr/share/postgresql/15/extension/pg_tle.control\": No such file or directory.","Hint":"The extension must first be installed on the system where PostgreSQL is running.","Position":0,"InternalPosition":0,"InternalQuery":"","Where":"","SchemaName":"","TableName":"","ColumnName":"","DataTypeName":"","ConstraintName":"","File":"extension.c","Line":539,"Routine":"parse_extension_control_file","UnknownFields":null}
2023/07/01 10:54:38 PG Recv: {"Type":"ReadyForQuery","TxStatus":"I"}
2023/07/01 10:54:38 PG Send: {"Type":"Terminate"}
Error: ERROR: extension "pg_tle" is not available (SQLSTATE 0A000)
At statement 1: create extension if not exists pg_tle
In an effort to make Basejump more useful to people and remove some of the dependency on Next, I'm looking at converting it into a selection of UI components and rpc functions that can be used in any language / framework.
appearance
prop as Supabase AuthUIInstead of a full starter template, Basejump would provide a set of UI components that make creating and managing accounts easy. As your startup scales, you could take control over the UI components by creating your own using the API endpoints in the next section.
All components are customized using the same appearance
prop as Supabase AuthUI. This allows you to customize the look and feel of the components to match your application.
import { AccountSwitcher } from '@usebasejump/account-ui-react';
const supabaseClient = useSupabaseClient();
<AccountSwitcher
supabaseClient={supabaseClient}
appearance={{{theme: ThemeSupa}}}
onAccountChange={(account) => router.push(`/accounts/${account.id}`)}
currentAccount={currentAccount}
/>
Shows an account overview, members and invitations. Let's you create new invitations
import { AccountSettings } from '@usebasejump/account-ui-react';
const supabaseClient = useSupabaseClient();
<AccountSettings
supabaseClient={supabaseClient}
appearance={{{theme: ThemeSupa}}}
currentAccount={currentAccount}
/>
Shows the current billing status and allows you to change the plan
import { AccountBilling } from '@usebasejump/account-ui-react';
const supabaseClient = useSupabaseClient();
<AccountBilling
supabaseClient={supabaseClient}
appearance={{{theme: ThemeSupa}}}
currentAccount={currentAccount}
/>
Shows a banner if account status is inactive or delinquent. Allows user to correct the issue.
import { AccountStatusBar } from '@usebasejump/account-ui-react';
const supabaseClient = useSupabaseClient();
<AccountStatusBar
supabaseClient={supabaseClient}
appearance={{{theme: ThemeSupa}}}
currentAccount={currentAccount}
/>
Shows a list of available pricing plans and allows user to select one
import { AccountPricingPlans } from '@usebasejump/account-ui-react';
const supabaseClient = useSupabaseClient();
<AccountPricingPlans
supabaseClient={supabaseClient}
appearance={{{theme: ThemeSupa}}}
currentAccount={currentAccount} // Optional field
onPlanClick={(plan) => router.push(`/accounts/${currentAccount.id}/billing`)}
/>
Proposing that we clean up the public
tables and move them into the basejump
schema. Only editable tables would remain, such as profiles
and a new table called account_settings
. This would allow us to hide away the accounts/members/invitations functionality.
accounts
, account_users
, invitations
, billing_subscriptions
, billing_customers
tables to basejump
schema and out of public
account_settings
table in public
schema for changeable account informationconst supabaseClient = useSupabaseClient();
const { data, error } = await supabaseClient
.rpc('get_accounts');
[
{
"account_id": "00000000-0000-0000-0000-000000000000",
"name": "My Account",
"personal_account": true,
"created_at": "2021-01-01T00:00:00.000000Z",
"updated_at": "2021-01-01T00:00:00.000000Z",
"role": "owner",
"is_primary_owner": true
},
{
"account_id": "00000000-0000-0000-0000-000000000000",
"name": "My Team Account",
"personal_account": false,
"created_at": "2021-01-01T00:00:00.000000Z",
"updated_at": "2021-01-01T00:00:00.000000Z",
"role": "member",
"is_primary_owner": false
}
]
const supabaseClient = useSupabaseClient();
const { data, error } = await supabaseClient
.rpc('get_account', { account_id: '00000000-0000-0000-0000-000000000000' });
{
"account_id": "00000000-0000-0000-0000-000000000000",
"name": "My Account",
"personal_account": true,
"created_at": "2021-01-01T00:00:00.000000Z",
"updated_at": "2021-01-01T00:00:00.000000Z",
"role": "owner",
"is_primary_owner": true,
"billing_status": "active",
"members": [
{
"user_id": "00000000-0000-0000-0000-000000000000",
"email": "[email protected]",
"role": "owner",
"is_primary_owner": true,
}
],
"invitations": [
{
"expiration": "2021-01-01T00:00:00.000000Z",
"email": "[email protected]",
"role": "owner"
}
]
}
Create a new account. The current user will be automatically added as the primary account owner
const supabaseClient = useSupabaseClient();
const { data, error } = await supabaseClient
.rpc('create_account', { name: 'Account 2', slug: 'account-2' });
{
"account_id": "00000000-0000-0000-0000-000000000000",
"name": "Account 2",
"personal_account": false,
"created_at": "2021-01-01T00:00:00.000000Z",
"updated_at": "2021-01-01T00:00:00.000000Z",
"role": "owner",
"billing_status": "active",
"is_primary_owner": true,
"members": [
{
"user_id": "00000000-0000-0000-0000-000000000000",
"email": "[email protected]",
"role": "owner",
"is_primary_owner": true
}
],
"invitations": []
}
Invite a new member to an existing account.
const supabaseClient = useSupabaseClient();
const { data, error } = await supabaseClient
.rpc('invite_account_member', { email: '[email protected]', role: 'member' });
{
"expiration": "2021-01-01T00:00:00.000000Z",
"email": "[email protected]",
"role": "member"
}
Allows a user to accept an invitation by providing their invitation token.
const supabaseClient = useSupabaseClient();
const { data, error } = await supabaseClient
.rpc('accept_account_invitation', { token: '00000000-0000-0000-0000-000000000000' });
{
"account_id": "00000000-0000-0000-0000-000000000000"
}
Allows an account owner to update the role of a member. If the current user is the primary owner, the owner can also transfer ownership to another member.
const supabaseClient = useSupabaseClient();
const { data, error } = await supabaseClient
.rpc('update_account_role', { user_id: '00000000-0000-0000-0000-000000000000', role: 'owner', make_primary_owner: true });
{
"user_id": "00000000-0000-0000-0000-000000000000",
"role": "owner",
"is_primary_owner": true
}
Returns the current billing status of an account
const supabaseClient = useSupabaseClient();
const { data, error } = await supabaseClient
.functions.invoke('account_billing_status', { account_id: '00000000-0000-0000-0000-000000000000' });
{
"subscription_id": "00000000-0000-0000-0000-000000000000",
"subscription_active": true,
"status": "active",
"is_primary_owner": true,
"billing_email": "[email protected]",
"account_role": "owner",
"billing_enabled": true
}
Returns available billing plans
const supabaseClient = useSupabaseClient();
const { data, error } = await supabaseClient
.functions.invoke('account_billing_plans', { account_id: '00000000-0000-0000-0000-000000000000' });
[
{
"product_name": "Monthly Basic",
"product_description": "Our most basic plan",
"currency": "usd",
"price": 1900,
"price_id": "price_00000000000000",
"interval": "monthly",
"active": true
},
{
"product_name": "Monthly Premium",
"product_description": "Our most premium plan",
"currency": "usd",
"price": 3900,
"price_id": "price_00000000000001",
"interval": "monthly",
"active": false
}
]
I've been using the new Basejump package since its release. First, I wanted to say that it's great work and I appreciate you built this to assess Supabase's needs for a native(ish) organization system. Tho I think, dbdev (and the project being a package) greatly limits the ability of it to be truly useful.
First, the maintainers are already unable to publish the first big update, due to an issue with dbdev.
Second, this makes local development impossible if you're not connected to the internet.
Third, is that the project provides an awesome starter set of functions and tables for a team system but makes it unnecessarily complex to extend it. I have to dig into the Basejump SQL file on GitHub, search for the relevant sections and copy-paste that part into a new migration in my project. This is way less productive than just a simple copy-paste when integrating Basejump.
A few examples that came up where I needed to extend:
auth.users
or in a custom public.profilesrun_new_user_setup()
on auth.users
) gets very confusing because of how postgres handles the function execution order. Especially if I want to have access to the Basejump account_id
in my function. It'd be way simpler if we could just extend the already existing Basejump function.So, I recommend making the core functionality copy-pastable and extensible by default, just as the UI components (as the shadcn/ui components). The command @usebasejump/cli@latest init
should create a migration file (or ideally multiple files by feature) with the chosen functionality, instead of a dbdev HTTP call.
After I signup or try to login I get this
: getStaticProps
Failed to parse cookie string: [Error: The edge runtime does not support Node.js 'buffer' module.
Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime]
When I deploy to vercel I get an error "ReferenceError: window is not defined".
next-translate - compiled page: /blog/[...slug] - locale: en - namespaces: content - used loader: getStaticProps
--
23:00:14.541 | next-translate - compiled page: /docs/[...slug] - locale: en - namespaces: content - used loader: getStaticProps
23:00:14.553 | ReferenceError: window is not defined
23:00:14.553 | at getFullRedirectUrl (/vercel/path0/.next/server/chunks/392.js:78:40)
23:00:14.554 | at ContentMeta (/vercel/path0/.next/server/chunks/392.js:54:115)
23:00:14.554 | at Wc (/vercel/path0/node_modules/react-dom/cjs/react-dom-server.browser.production.min.js:68:44)
23:00:14.554 | at Zc (/vercel/path0/node_modules/react-dom/cjs/react-dom-server.browser.production.min.js:70:253)
23:00:14.555 | at Z (/vercel/path0/node_modules/react-dom/cjs/react-dom-server.browser.production.min.js:76:89)
23:00:14.555 | at $c (/vercel/path0/node_modules/react-dom/cjs/react-dom-server.browser.production.min.js:78:98)
23:00:14.562 | at bd (/vercel/path0/node_modules/react-dom/cjs/react-dom-server.browser.production.min.js:77:404)
23:00:14.562 | at Z (/vercel/path0/node_modules/react-dom/cjs/react-dom-server.browser.production.min.js:76:217)
23:00:14.562 | at $c (/vercel/path0/node_modules/react-dom/cjs/react-dom-server.browser.production.min.js:78:98)
23:00:14.562 | at Zc (/vercel/path0/node_modules/react-dom/cjs/react-dom-server.browser.production.min.js:71:145)
It works fine on the my local machine.
I don't see a function in the documentation. Ideally a soft delete so that the history is maintained.
It would be good if the basejump.invitations
had a reference to the user who has been invited.
There are two reasons why this could be useful:
Can you create a demo with a pricing page? The link Update plan settings
inside Billing is redirecting to a 404 page
The project doesn't actually build out of the box, because the type check and lint tasks are failing.
Hello,
Running a local version, when attempting to sync strip products using yarn sync-stripe
i get the following error:
Error: supabaseUrl is required.
at SupabaseClient (c:\Users\Bureau\Desktop\BF-Next\BFBJ\BF\node_modules@supabase\supabase-js\dist\main\SupabaseClient.js:55:19)
at createClient (c:\Users\Bureau\Desktop\BF-Next\BFBJ\BF\node_modules@supabase\supabase-js\dist\main\index.js:35:12)
at (c:\Users\Bureau\Desktop\BF-Next\BFBJ\BF\src\utils\admin\supabase-admin-client.ts:4:30)
at Object. (c:\Users\Bureau\Desktop\BF-Next\BFBJ\BF\src\utils\admin\supabase-admin-client.ts:7:1)
at Module._compile (node:internal/modules/cjs/loader:1256:14)
at Object.F (C:\Users\Bureau\AppData\Local\npm-cache_npx\fd45a72a545557e9\node_modules@esbuild-kit\cjs-loader\dist\index.js:1:941)
at Module.load (node:internal/modules/cjs/loader:1119:32)
at Module._load (node:internal/modules/cjs/loader:960:12)
at Module.require (node:internal/modules/cjs/loader:1143:19)
at require (node:internal/modules/cjs/helpers:121:18)
We are currently building BaseJump legacy for our app. We find it incredibly limiting and it seems a lot of stuff have been upgraded.
Please share steps on how to upgrade to latest version from Legacy.
Just want to say thank you again for your amazing work. Wanted to see if I could get some feedback on an idea I have to extend the teams functionality. This might actually just be a SQL question... but figured it might help someone else.
My application is requiring an organization
feature. An organization
can have many teams
, and its purpose is for admin of the organization to view all data within a team. For example, a school (organization) would have many classes (teams), which would have many users (students/teachers). An organization would have admin users that wouldn't necessarily belong to any team.
I'm not sure if there would be a way to "bolt" this onto basejump.
One of the approaches I thought of is to keep the accounts and account_user tables as-is and create a new table called teams
. The teams table would have a foreign key account_id
to associate it with an account (organization). Doing so would keep the roles/permissions in place. I would only need to create similar roles/permissions for the teams table.
Appreciate any feedback, thank you.
Hey all, thanks for building this library! I'm currently doing something like this:
I'm stuck on step 3 right now. I'm currently debating on creating a bespoke provider to pass this account_id where needed to other client components in my application, but wasn't sure if there was a better way to do this. I'm essentially creating an app that has projects (folders) and documents that are owned by each project. Each project should be owned by only one account and each user should only be able to belong to one team account. Would appreciate any guidance on how to move forward!
Hello, thank you for this incredible work!!
I have a question, I am currently developing a web app where all the data from my various Supabase tables is linked to a user through a user_id that is found in almost all the tables.
I don't manage a team system yet, but I need to integrate one, which is why Basejump could save me a lot of time.
My question is, is it possible to create a Basejump account for each existing user so they can create teams?
I'm not sure if I should completely change everything, gradually integrate the Basejump system into my current database, or start from scratch (which would be a huge job).
If you could give me some advice, I would be very grateful.
Also, I would love to help develop features if there is a roadmap or something planned, I'm willing to help!
By the way, I've read in other issues that we're waiting on a blocking issue from Dbdev for version 2.1.0. Any updates on that?
At https://basejump-site.vercel.app/docs/accounts#update-an-account, the metadata field should be public_metadata.
Hey there, thanks so much for this awesome project!
We've released some official guidance around custom claims & RBAC using the new Auth Hooks approach: https://supabase.com/docs/guides/auth/custom-claims-and-role-based-access-control-rbac
Would love if you could review and see if that would make sense to adopt for this project?
Thanks 💚
Thank you for this project!! I was struggling to get teams management to work for my next app.
One small issue I found however, is scrolling on mobile:
OS: iOS 15.6.1
Browser: Safari
Current Behavior: Tapping the top of the page does not automatically scroll.
Expected Behavior: Tapping the top of the page on mobile should automatically scroll the page to the top.
Haven't looked too much into the tailwind utilities yet, so I wanted to see if anyone else was getting this bug as well.
Thank you!
Running supabase db reset --linked
fails with this error:
ERROR: cannot drop schema basejump because extension basejump-basejump_core requires it (SQLSTATE 2BP01)
At statement 0: DROP SCHEMA IF EXISTS basejump CASCADE
Try rerunning the command with --debug to troubleshoot the error.
It would be great to choose different BaaS....
Line 4 in da5b034
Struggled to figure out while my web hooks were failing but noticed that it was due to not having the STRIPE_WEBHOOK_SECRET
env set which isn't mention in the docs or referenced in the sample .env. Perhaps it makes since to add it.
Hi all, when installing @usebasejump/react in a project with vite, it looks like there's some issues with the npm package that causes the import to fail.
Error: (when importing anything with the package)
[ERROR] Failed to resolve entry for package "@usebasejump/react". The package may have incorrect main/module/exports specified in its package.json. [plugin vite:dep-scan]
Minimum Reproduction:
I tried figuring this issue out with the package, but wasn't quite able to. I ended up just taking the hooks and types and placing directly in my repo and it all works great for now in the meantime. Thanks for making this project, it's a huge timesaver.
Hitting Stripe takes a bit of time and leaves the user hanging, should add an account loading indicator at that step
Just had to do that. That is what I came up with :
create policy "Account members can insert" on storage.objects
for insert
to authenticated
with check (
bucket_id = '<your bucket name>'
AND (storage.foldername(name))[1] IN (SELECT (account)::text FROM basejump.get_accounts_with_role() AS account)
);
when i try to deploy the function to supabase, I get
Error: failed to load 'https://deno.land/x/[email protected]/billing-functions/lib/types/supabase.ts': Module not found "https://deno.land/x/[email protected]/billing-functions/lib/types/supabase.ts". error running container: exit 1
this error in
at https://deno.land/x/[email protected]/billing-functions/lib/create-supabase-client.ts:2:26
is trying to import file supabase.ts but it doesn't exist
Great project so far.
Found an edge case when I have a team member (not owner) that is able to access settings pages. Even though the sidebar hides the menu item Settings
, a member can simply enter the URLs for the settings.
RLS prevents a team member from updating settings, but they should not be able to view/interact with the pages at all.
Here is a screenshot of a team member that is able to view the the settings/members page:
If a member accesses a nested Settings page, they should be redirected to the Team Dashboard.
Even though RLS is taking care of the data, what is a good pattern to protect routes?
When I run this edge function, I get a 404 error.
These are the only Supabase edge function there are. Is this a mistake in the docs?
const {data, error} = await supabase.functions.invoke('current_user_account_role', {
body: {
action: "get_plans",
args: {
account_id: "uuid"
}
}
});
FunctionsHttpError {
name: 'FunctionsHttpError',
context: Response {
type: 'basic',
url: 'http://localhost:54321/functions/v1/current_user_account_role',
redirected: false,
status: 404,
ok: false,
statusText: 'Not Found',
When using created_by and updated_by columns, the relation points to auth.users table.
I would have liked to be able to retrieve the name of the account through this relation, but it is not possible to query relations across different schemas.
The same issue arises with account_id columns in public schema tables.
What approach do you recommand for this ?
I installed supabase v1.77.9
on windows, cloned the basejump repo and ran supabase start
but getting this error:
Applying migration 00000000000000_dbdev_temp_install.sql...
ERROR: Resolving timed out after 1000 milliseconds (SQLSTATE XX000)
At statement 5: create extension "supabase-dbdev"
I tried removing that 00000000000000_dbdev_temp_install.sql
file after reading some notes that perhaps dbdev already exists but get another error
Applying migration 00000000000001_utility_functions.sql...
ERROR: schema "dbdev" does not exist (SQLSTATE 3F000)
At statement 1: select dbdev.install('basejump-supabase_test_helpers')
Is there a version of superbase this no longer works with?
After generating a boilerplate project and setting up supabase to run locally, I get the following error when trying to create a team for a newly-created user:
If I understand correctly, this new user should be a primary account and therefore should be able to create a team according to the security policies.
I'm also struggling to figure out how to debug postgres issues when running locally. Tailing the logs doesn't really reveal much about why a security policy is failing. Any tips you have here would be greatly appreciated. Thanks!
Is there any plan to enable RLS at the billing level ?
E.g. Restrict row creation if billing status is not active ?
More generally, I was wondering how you handle restriction based on billing status ?
I'm looking into how to Default users into a free plan
. The docs for setting up stripe (https://usebasejump.com/docs/billing-stripe) suggest that this setting is in the basejump.config table but that table only has these columns:
The docs later link to an environment variables page that returns a 404 (https://usebasejump.com/docs/environment-variables). The .env file does have a var for STRIPE_DEFAULT_TRIAL_DAYS
. I'm guessing I could hack this default into a free plan by setting STRIPE_DEFAULT_TRIAL_DAYS
to 0 and setting the STRIPE_DEFAULT_PLAN_ID
to a free plan?
Either way some details on how to do that would be useful.
I would probably also change this:
Endpoint URL: https://<your-instance>.com/billing-webhooks
To:
Endpoint URL: https://<yourSupabaseProjRef>.supabase.co/functions/v1/billing-webhooks
Also, with my wsl setup, when I run supabase link, I get the warning:
Failed to save database password: Keyring is not supported on WSL
And as a result, I have to supply --project-ref flags for each of these commands to make the edge functions deploy correctly:
supabase secrets set --project-ref myrefid STRIPE_API_KEY=sk_test_mykey
supabase functions deploy --project-ref myrefid billing-webhooks --no-verify-jwt
Finally, I've tried clearing my npm cache with npm cache clean --force
and still, when I run:
npx @usebasejump/cli@latest init
It puts an index.ts file in supabase/functions/billing-functions that has this line in it:
import {billingFunctionsWrapper, stripeFunctionHandler} from "https://deno.land/x/[email protected]/billing-functions/mod.ts";
Which isn't the latest version of basejump and doesn't deploy correctly. The current main branch of this repo uses:
import {billingFunctionsWrapper, stripeFunctionHandler} from "../deno-packages/billing-functions/mod.ts";
Apologies for the lack of organization here or standard process. I'm a finance bro trying to hack together a web app and haven't gotten around to learning git/github yet so this is the best I could do for now!
Hello,
I have a problem with my deploy version.
On my local server when I sign up it automatically creates an 'account_user'
Yet when I deployed the project on Vercel and I sign up, I only have a profile user but no 'account-user associated'
(I have not setup Stripe, don't know if it has an impact on the deploy version, in addition, I 'enable_personal_accounts' in my db.
Could you help me with it? :)
Hi there,
First thank you for the great project!
While installing it, I think I found a typo in the documentation:
https://usebasejump.com/docs/accounts#retrieve-personal-account
In the response example:
"personal_account": false, --> true
The installation at https://usebasejump.com/docs/installation is a bit unclear on how to go about using basejump with hosted supabase.
Any pointers here?
I'm trying to add in a value to a table that I made by generating a table with Basejump npx command. But I can't figure out how to populate the account ID part. Do I just have to keep passing down the value from the slug through the components?
Hi,
I've just found the project and started playing around with it. Let me walk through my process of how I got here:
Right now blogs are displayed in full on a single page.
Need to swap to pagination with X articles per page (configurable).
Hello!
I am running a fresh copy of basejump
, trying to get Github Actions working for a full CI/CD flow.
Currently I am experiencing this error with the pg_tests
Supabase start
command:
Starting database...
Starting containers...
Setting up Edge Functions runtime...
Setting up local schema...
Applying migration 00000000000000_dbdev_temp_install.sql...
Error: ERROR: function pgtle.install_extension_version_sql(text, text, text) does not exist (SQLSTATE 42883)
At statement 7: drop extension if exists "supabase-dbdev"
Try rerunning the command with --debug to troubleshoot the error.
Error: Process completed with exit code 1.
It seems there is a function (pgtle.install_extension_version_sql
) that doesn't exist.
One thing worth noting, my local supabase
CLI is v1.88.0, whereas it looks like this action is hardcoded to an older 1.5 version. Going to try and upgrade the action to see if that helps, but figure I would ask here too.
Like not even a little bit.
One of the reasons I chose supabase is because at its core, it is just postgres. I want to build faster by leveraging a managed database, but I always want to preserve my ability to revert to plain old postgres if I need to. For example, if supabase goes out of business or if it becomes overpriced etc. So I want to build my app using protocols that will continue to work on a more standard installation of postgres. PostgREST and pg_graphql seem like good projects for achieving this. I'd like to suggest that you consider offering a version of basejump that demonstrates how to build a project based on supabase that doesn't rely on any supabase-specific features, like their js libraries.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.