Patching bug on portabase.config.ts about social providers.

This commit is contained in:
charlesgauthereau
2025-12-30 10:27:47 +01:00
parent ff175e1edd
commit 011120fdf9
9 changed files with 52 additions and 73 deletions
+3 -7
View File
@@ -24,18 +24,16 @@ export default async function SignInPage() {
</div>
</CardHeader>
<CardContent className="space-y-4">
<LoginForm />
<LoginForm/>
{SUPPORTED_PROVIDERS.filter((p) => !p.isManual).length > 0 && (
{SUPPORTED_PROVIDERS.filter((p) => !p.isManual && p.isActive).length > 0 && (
<>
<div className="relative my-4 flex items-center justify-center overflow-hidden">
<Separator/>
<div className="px-2 text-center text-sm">OR</div>
<Separator/>
</div>
<SocialAuthButtons />
<SocialAuthButtons providers={SUPPORTED_PROVIDERS}/>
</>
)}
@@ -50,7 +48,5 @@ export default async function SignInPage() {
</TooltipProvider>
)
}
+6 -4
View File
@@ -1,9 +1,9 @@
import {Chrome, KeyRound, LucideIcon} from "lucide-react";
export interface AuthProviderConfig {
id: "google" | "github" | "credential";
icon: LucideIcon;
isActive: boolean;
icon: string;
isManual?: boolean;
credentials?: {
clientId: string;
@@ -80,7 +80,8 @@ export const PORTABASE_DEFAULT_SETTINGS = {
export const SUPPORTED_PROVIDERS: AuthProviderConfig[] = [
{
id: "google",
icon: Chrome,
icon: "hugeicons:chrome",
isActive: Boolean(process.env.AUTH_GOOGLE_METHOD),
// isManual: true,
credentials: {
clientId: process.env.GOOGLE_CLIENT_ID || "",
@@ -100,7 +101,8 @@ export const SUPPORTED_PROVIDERS: AuthProviderConfig[] = [
},*/
{
id: "credential",
icon: KeyRound,
isActive: true,
icon: "proicons:key",
isManual: true,
credentials: {
clientId: "",
@@ -5,9 +5,12 @@ import { Button } from "@/components/ui/button";
import { authClient } from "@/lib/auth/auth-client";
import { Loader2 } from "lucide-react";
import { toast } from "sonner";
import {SUPPORTED_PROVIDERS} from "../../../../portabase.config";
import {AuthProviderConfig} from "../../../../portabase.config";
import {Icon} from "@iconify/react";
export function SocialAuthButtons({ providers }: { providers: AuthProviderConfig[] }) {
const socialProviders = providers.filter(p => p.isActive && !p.isManual);
export function SocialAuthButtons() {
const [isLoading, setIsLoading] = useState<string | null>(null);
const handleSocialSignIn = async (providerId: string) => {
@@ -30,16 +33,15 @@ export function SocialAuthButtons() {
}
};
const socialProviders = SUPPORTED_PROVIDERS.filter((p) => !p.isManual);
if (socialProviders.length === 0) return null;
return (
<div className="flex flex-col gap-2 w-full">
{socialProviders.map((provider) => (
<Button key={provider.id} variant="outline" className="w-full gap-2" onClick={() => handleSocialSignIn(provider.id)} disabled={!!isLoading}>
{isLoading === provider.id ? <Loader2 className="h-4 w-4 animate-spin" /> : <provider.icon className="h-4 w-4" />}
{isLoading === provider.id ? <Loader2 className="h-4 w-4 animate-spin" /> :
<Icon icon={provider.icon} className="h-4 w-4"/>
}
<span>{PROVIDERS_TEXT[provider.id].title}</span>
</Button>
))}
@@ -1,6 +1,7 @@
import {currentUser} from "@/lib/auth/current-user";
import {getAccounts, getSession, getSessions} from "@/lib/auth/auth";
import {LoggedInButtonClient} from "./logged-in-button";
import {SUPPORTED_PROVIDERS} from "../../../../../../portabase.config";
export const LoggedInButton = async () => {
const user = await currentUser();
@@ -18,6 +19,7 @@ export const LoggedInButton = async () => {
// @ts-ignore
currentSession={currentSession.session}
accounts={accounts}
providers={SUPPORTED_PROVIDERS.filter((p) => p.isActive)}
/>
);
};
@@ -1,46 +1,3 @@
// import { ChevronUp } from "lucide-react";
//
// import {Avatar, AvatarFallback, AvatarImage} from "@/components/ui/avatar";
// import { currentUser } from "@/lib/auth/current-user";
// import { SidebarMenuButton } from "@/components/ui/sidebar";
// import { getAccounts, getSession, getSessions } from "@/lib/auth/auth";
// import {LoggedInDropdown} from "@/components/wrappers/dashboard/common/logged-in/logged-in-dropdown";
//
// export const LoggedInButton = async () => {
// const user = await currentUser();
// const sessions = await getSessions();
// const currentSession = await getSession();
// const accounts = await getAccounts();
//
// if (!user) return null;
//
//
// return (
// <>
// <LoggedInDropdown
// // @ts-ignore
// user={user}
// // @ts-ignore
// sessions={sessions}
// // @ts-ignore
// currentSession={currentSession.session}
// // @ts-ignore
// accounts={accounts}
// >
// <SidebarMenuButton>
//
// <Avatar className="size-6">
// <AvatarFallback>{user?.name[0].toUpperCase()}</AvatarFallback>
// {user?.image ? <AvatarImage src={user?.image} alt={`${user.name ?? "-"}'s profile picture`} /> : null}
// </Avatar>
//
// <span className="first-letter:capitalize">{user?.name}</span>
// <ChevronUp className="ml-auto" />
// </SidebarMenuButton>
// </LoggedInDropdown>
// </>
// );
// };
"use client";
import {ChevronUp} from "lucide-react";
@@ -48,15 +5,23 @@ import {Avatar, AvatarFallback, AvatarImage} from "@/components/ui/avatar";
import {SidebarMenuButton} from "@/components/ui/sidebar";
import {LoggedInDropdown} from "./logged-in-dropdown";
import {Account, Session, User} from "better-auth";
import {AuthProviderConfig} from "../../../../../../portabase.config";
type LoggedInButtonClientProps = {
user: User;
sessions: Session[];
currentSession: Session;
accounts: Account[];
user: User,
sessions: Session[],
currentSession: Session,
accounts: Account[],
providers: AuthProviderConfig[]
}
export const LoggedInButtonClient = ({user, sessions, currentSession, accounts}: LoggedInButtonClientProps) => {
export const LoggedInButtonClient = ({
user,
sessions,
currentSession,
accounts,
providers
}: LoggedInButtonClientProps) => {
return (
<LoggedInDropdown
@@ -68,6 +33,7 @@ export const LoggedInButtonClient = ({user, sessions, currentSession, accounts}:
currentSession={currentSession}
// @ts-ignore
accounts={accounts}
providers={providers}
>
<SidebarMenuButton type="button">
<Avatar className="size-6">
@@ -7,6 +7,7 @@ import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigge
import { signOut } from "@/lib/auth/auth-client";
import {ProfileModal} from "@/components/wrappers/dashboard/common/profile/profile-modal";
import {Account, Session, User} from "@/db/schema/02_user";
import {AuthProviderConfig} from "../../../../../../portabase.config";
export type LoggedInDropdownProps = PropsWithChildren<{
user: User;
@@ -14,9 +15,11 @@ export type LoggedInDropdownProps = PropsWithChildren<{
currentSession: Session;
accounts: Account[];
children: ReactNode;
providers: AuthProviderConfig[]
}>;
export const LoggedInDropdown = ({ user, sessions, currentSession, accounts, children }: LoggedInDropdownProps) => {
export const LoggedInDropdown = ({ user, sessions, currentSession, accounts, children, providers }: LoggedInDropdownProps) => {
const router = useRouter();
const [isModalOpen, setIsModalOpen] = useState(false);
@@ -29,6 +32,7 @@ export const LoggedInDropdown = ({ user, sessions, currentSession, accounts, chi
accounts={accounts}
open={isModalOpen}
onOpenChange={setIsModalOpen}
providers={providers}
/>
<DropdownMenu>
@@ -10,6 +10,7 @@ import {ProfileAccount} from "@/components/wrappers/dashboard/profile/profile-ac
import {ProfileAppearance} from "@/components/wrappers/dashboard/profile/profile-apperance";
import {ProfileSecurity} from "@/components/wrappers/dashboard/profile/profile-security";
import {ProfileGeneral} from "@/components/wrappers/dashboard/profile/profile-general";
import {AuthProviderConfig} from "../../../../../../portabase.config";
type ProfileModalProps = {
open: boolean;
@@ -18,9 +19,11 @@ type ProfileModalProps = {
currentSession: Session;
accounts: Account[];
onOpenChange: (open: boolean) => void;
providers: AuthProviderConfig[]
};
export const ProfileModal = ({ user, sessions, currentSession, accounts, open, onOpenChange }: ProfileModalProps) => {
export const ProfileModal = ({ user, sessions, currentSession, accounts, open, onOpenChange, providers }: ProfileModalProps) => {
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="w-[95vw] h-[90vh] max-w-md lg:max-w-[1000px] lg:h-[800px] p-0 overflow-hidden flex flex-col outline-none gap-0 rounded-xl bg-background">
@@ -46,7 +49,7 @@ export const ProfileModal = ({ user, sessions, currentSession, accounts, open, o
</TabsContent>
<TabsContent value="providers" className="mt-0 h-full p-6 lg:p-10 outline-none focus-visible:ring-0">
<ProfileProviders accounts={accounts} />
<ProfileProviders accounts={accounts} providers={providers} />
</TabsContent>
<TabsContent value="account" className="mt-0 h-full p-6 lg:p-10 outline-none focus-visible:ring-0">
@@ -12,13 +12,16 @@ import {useRouter} from "next/navigation";
import {Tooltip, TooltipContent, TooltipProvider, TooltipTrigger} from "@/components/ui/tooltip";
import {Alert, AlertDescription} from "@/components/ui/alert";
import {SetPasswordProfileProviderModal} from "./modal/set-password-modal";
import {SUPPORTED_PROVIDERS} from "../../../../../portabase.config";
import {AuthProviderConfig} from "../../../../../portabase.config";
import {Icon} from "@iconify/react";
interface ProfileProviderProps {
accounts: Account[];
providers: AuthProviderConfig[]
}
export function ProfileProviders({accounts}: ProfileProviderProps) {
export function ProfileProviders({accounts, providers}: ProfileProviderProps) {
const router = useRouter();
const totalConnected = accounts.length;
const [loadingProvider, setLoadingProvider] = useState<string | null>(null);
@@ -70,7 +73,7 @@ export function ProfileProviders({accounts}: ProfileProviderProps) {
</div>
<div className="grid gap-4">
{SUPPORTED_PROVIDERS.map((provider) => {
{providers.map((provider) => {
const linkedAccount = accounts.find((acc) => acc.providerId === provider.id);
const isConnected = !!linkedAccount;
// const canUnlink = totalConnected > 1 || (totalConnected === 1 && !provider.isManual);
@@ -83,7 +86,7 @@ export function ProfileProviders({accounts}: ProfileProviderProps) {
className="flex items-center justify-between p-4 border rounded-lg hover:bg-muted/30 transition-colors">
<div className="flex items-center gap-4">
<div className="w-10 h-10 rounded-full bg-muted flex items-center justify-center">
<provider.icon className="w-5 h-5"/>
<Icon icon={provider.icon} className="w-5 h-5"/>
</div>
<div className="space-y-0.5">
<div className="font-medium flex items-center gap-2">
+2 -1
View File
@@ -11,7 +11,7 @@ import {count, eq} from "drizzle-orm";
import {MemberWithUser, OrganizationWithMembersAndUsers} from "@/db/schema/03_organization";
import {sendEmail} from "@/lib/email/email-helper";
import {render} from "@react-email/render";
import {SUPPORTED_PROVIDERS} from "../../../portabase.config";
import {AuthProviderConfig, SUPPORTED_PROVIDERS} from "../../../portabase.config";
import {withUpdatedAt} from "@/db/utils";
import EmailVerification from "@/components/emails/auth/email-verification";
import EmailForgotPassword from "@/components/emails/auth/email-forgot-password";
@@ -80,6 +80,7 @@ export const auth = betterAuth({
},
},
socialProviders: SUPPORTED_PROVIDERS.reduce((acc: any, provider: any) => {
if (!provider.isActive) return acc;
if (provider.id === "credential") return acc;
if (provider.id === "google") {
acc.google = {