Skip to content

Commit

Permalink
Feat: disconnect alby account in auth code form (#833)
Browse files Browse the repository at this point in the history
* feat: disconnect from Alby Account in OAuth form

* fix: always show confirmation dialog when disconnecting alby account
  • Loading branch information
rolznz authored Nov 29, 2024
1 parent 8addcd4 commit 6981e00
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 129 deletions.
5 changes: 3 additions & 2 deletions alby/alby_oauth_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -554,8 +554,9 @@ func (svc *albyOAuthService) UnlinkAccount(ctx context.Context) error {
return errors.New("alby account cannot be unlinked while VSS is activated")
}

err = svc.destroyAlbyAccountNWCNode(ctx)
if err != nil {
destroyAlbyAccountErr := svc.destroyAlbyAccountNWCNode(ctx)
if destroyAlbyAccountErr != nil {
// non-critical error - we still want to disconnect
logger.Logger.WithError(err).Error("Failed to destroy Alby Account NWC node")
}
svc.deleteAlbyAccountApps()
Expand Down
13 changes: 12 additions & 1 deletion frontend/src/components/AuthCodeForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Input } from "src/components/ui/input";
import { Label } from "src/components/ui/label";
import { LoadingButton } from "src/components/ui/loading-button";
import { useToast } from "src/components/ui/use-toast";
import { UnlinkAlbyAccount } from "src/components/UnlinkAlbyAccount";

import { useInfo } from "src/hooks/useInfo";
import { handleRequestError } from "src/utils/handleRequestError";
Expand All @@ -23,7 +24,7 @@ function AuthCodeForm({ url }: AuthCodeFormProps) {
const navigate = useNavigate();
const { toast } = useToast();

const { mutate: refetchInfo } = useInfo();
const { data: info, mutate: refetchInfo } = useInfo();

const [hasRequestedCode, setRequestedCode] = React.useState(false);
const [isLoading, setLoading] = React.useState(false);
Expand Down Expand Up @@ -103,6 +104,16 @@ function AuthCodeForm({ url }: AuthCodeFormProps) {
</div>
</>
)}
{info?.albyUserIdentifier && (
<div className="flex flex-col justify-center items-center mt-15 gap-5">
<p className="text-muted-foreground">or</p>
<UnlinkAlbyAccount>
<Button variant="outline" size="sm">
Disconnect Alby Account
</Button>
</UnlinkAlbyAccount>
</div>
)}
</div>
</form>
</Container>
Expand Down
78 changes: 78 additions & 0 deletions frontend/src/components/UnlinkAlbyAccount.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import React from "react";
import { useNavigate } from "react-router-dom";
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "src/components/ui/alert-dialog";
import { useToast } from "src/components/ui/use-toast";
import { useInfo } from "src/hooks/useInfo";
import { request } from "src/utils/request";

type UnlinkAlbyAccountProps = {
navigateTo?: string;
successMessage?: string;
};

export function UnlinkAlbyAccount({
children,
navigateTo = "/",
successMessage = "Your hub is no longer connected to an Alby Account.",
}: React.PropsWithChildren<UnlinkAlbyAccountProps>) {
const { toast } = useToast();
const navigate = useNavigate();
const { mutate: refetchInfo } = useInfo();

const unlinkAccount = React.useCallback(async () => {
try {
await request("/api/alby/unlink-account", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
});
await refetchInfo();
navigate(navigateTo);
toast({
title: "Alby Account Disconnected",
description: successMessage,
});
} catch (error) {
toast({
title: "Disconnect account failed",
description: (error as Error).message,
variant: "destructive",
});
}
}, [refetchInfo, navigate, navigateTo, toast, successMessage]);

return (
<AlertDialog>
<AlertDialogTrigger asChild>{children}</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Disconnect Alby Account</AlertDialogTitle>
<AlertDialogDescription>
<div>
<p>Are you sure you want to disconnect your Alby Account?</p>
<p className="text-destructive font-medium mt-4">
Your Alby Account will be disconnected and all Alby Account
features such as your lightning address will stop working.
</p>
</div>
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction onClick={unlinkAccount}>Confirm</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
);
}
153 changes: 27 additions & 126 deletions frontend/src/screens/settings/AlbyAccount.tsx
Original file line number Diff line number Diff line change
@@ -1,77 +1,17 @@
import { ExitIcon } from "@radix-ui/react-icons";
import { ExternalLinkIcon } from "lucide-react";
import { useNavigate } from "react-router-dom";

import ExternalLink from "src/components/ExternalLink";
import SettingsHeader from "src/components/SettingsHeader";
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "src/components/ui/alert-dialog";
import {
Card,
CardDescription,
CardHeader,
CardTitle,
} from "src/components/ui/card";
import { useToast } from "src/components/ui/use-toast";

import { request } from "src/utils/request";
import { UnlinkAlbyAccount } from "src/components/UnlinkAlbyAccount";

export function AlbyAccount() {
const { toast } = useToast();
const navigate = useNavigate();

const disconnect = async () => {
try {
await request("/api/alby/unlink-account", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
});
navigate("/");
toast({
title: "Alby Account Disconnected",
description: "Your hub is no longer connected to an Alby Account.",
});
} catch (error) {
toast({
title: "Disconnect account failed",
description: (error as Error).message,
variant: "destructive",
});
}
};
const unlink = async () => {
try {
await request("/api/alby/unlink-account", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
});
navigate("/alby/auth?force_login=true");
toast({
title: "Alby Account Unlinked",
description: "Please login with another Alby Account",
});
} catch (error) {
toast({
title: "Unlink account failed",
description: (error as Error).message,
variant: "destructive",
});
}
};

return (
<>
<SettingsHeader
Expand All @@ -92,71 +32,32 @@ export function AlbyAccount() {
</CardHeader>
</Card>
</ExternalLink>
<AlertDialog>
<AlertDialogTrigger asChild>
<Card className="w-full cursor-pointer">
<CardHeader>
<CardTitle>Change Alby Account</CardTitle>
<CardDescription className="flex gap-2 items-center">
<ExitIcon className="w-4 h-4" /> Link your Hub to a different
Alby Account
</CardDescription>
</CardHeader>
</Card>
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Unlink Alby Account</AlertDialogTitle>
<AlertDialogDescription>
<div>
<p>
Are you sure you want to change the Alby Account for your hub?
</p>
<p className="text-primary font-medium mt-4">
Your Alby Account will be disconnected from your hub and
you'll need to login with a new Alby Account to access your
hub.
</p>
</div>
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction onClick={unlink}>Confirm</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
<AlertDialog>
<AlertDialogTrigger asChild>
<Card className="w-full cursor-pointer">
<CardHeader>
<CardTitle>Disconnect Alby Account</CardTitle>
<CardDescription className="flex gap-2 items-center">
<ExitIcon className="w-4 h-4" /> Use Alby Hub without an Alby
Account
</CardDescription>
</CardHeader>
</Card>
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Disconnect Alby Account</AlertDialogTitle>
<AlertDialogDescription>
<div>
<p>Are you sure you want to disconnect your Alby Account?</p>
<p className="text-destructive font-medium mt-4">
Your Alby Account will be disconnected and all Alby Account
features such as your lightning address will stop working.
</p>
</div>
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction onClick={disconnect}>Confirm</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
<UnlinkAlbyAccount
navigateTo="/alby/auth?force_login=true"
successMessage="Please login with another Alby Account"
>
<Card className="w-full cursor-pointer">
<CardHeader>
<CardTitle>Change Alby Account</CardTitle>
<CardDescription className="flex gap-2 items-center">
<ExitIcon className="w-4 h-4" /> Link your Hub to a different Alby
Account
</CardDescription>
</CardHeader>
</Card>
</UnlinkAlbyAccount>

<UnlinkAlbyAccount>
<Card className="w-full cursor-pointer">
<CardHeader>
<CardTitle>Disconnect Alby Account</CardTitle>
<CardDescription className="flex gap-2 items-center">
<ExitIcon className="w-4 h-4" /> Use Alby Hub without an Alby
Account
</CardDescription>
</CardHeader>
</Card>
</UnlinkAlbyAccount>
</>
);
}

0 comments on commit 6981e00

Please sign in to comment.