-
Notifications
You must be signed in to change notification settings - Fork 6
Add anonymous/guest authentication with Bitcoin-only payment enforcement #288
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
0891ec3
Add anonymous/guest authentication with Bitcoin-only payment enforcement
AnthonyRonning 600e123
Fix: Skip email verification modal for guest users
AnthonyRonning 0c882ae
Add clarifying text about Account ID display in signup flow
github-actions[bot] f69a07a
Clarify anonymous account activation status in payment warning
AnthonyRonning File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,147 @@ | ||
| import { useState } from "react"; | ||
| import { Button } from "@/components/ui/button"; | ||
| import { | ||
| Dialog, | ||
| DialogContent, | ||
| DialogDescription, | ||
| DialogFooter, | ||
| DialogHeader, | ||
| DialogTitle | ||
| } from "@/components/ui/dialog"; | ||
| import { Input } from "@/components/ui/input"; | ||
| import { Label } from "@/components/ui/label"; | ||
| import { AlertTriangle, Copy, CheckCircle } from "lucide-react"; | ||
| import { Checkbox } from "@/components/ui/checkbox"; | ||
|
|
||
| interface GuestCredentialsDialogProps { | ||
| open: boolean; | ||
| onOpenChange: (open: boolean) => void; | ||
| uuid: string; | ||
| onContinue: () => void; | ||
| } | ||
|
|
||
| export function GuestCredentialsDialog({ | ||
| open, | ||
| onOpenChange, | ||
| uuid, | ||
| onContinue | ||
| }: GuestCredentialsDialogProps) { | ||
| const [hasBackedUp, setHasBackedUp] = useState(false); | ||
| const [uuidCopied, setUuidCopied] = useState(false); | ||
|
|
||
| const handleCopyUuid = async () => { | ||
| try { | ||
| await navigator.clipboard.writeText(uuid); | ||
| setUuidCopied(true); | ||
| setTimeout(() => setUuidCopied(false), 2000); | ||
| } catch (error) { | ||
| console.error("Failed to copy UUID:", error); | ||
| } | ||
| }; | ||
|
|
||
| const handleContinue = () => { | ||
| if (hasBackedUp) { | ||
| setHasBackedUp(false); | ||
| setUuidCopied(false); | ||
| onContinue(); | ||
| } | ||
| }; | ||
|
|
||
| return ( | ||
| <Dialog open={open} onOpenChange={onOpenChange}> | ||
| <DialogContent | ||
| className="sm:max-w-[500px] [&>button]:hidden" | ||
| onInteractOutside={(e) => e.preventDefault()} | ||
| onEscapeKeyDown={(e) => e.preventDefault()} | ||
| > | ||
| <DialogHeader> | ||
| <DialogTitle className="flex items-center gap-2 text-amber-600 dark:text-amber-500"> | ||
| <AlertTriangle className="w-5 h-5" /> | ||
| Save Your Anonymous Account ID | ||
| </DialogTitle> | ||
| <DialogDescription className="text-base font-medium"> | ||
| This is your ONLY chance to see your Account ID. Save it now! | ||
| </DialogDescription> | ||
| </DialogHeader> | ||
|
|
||
| <div className="space-y-4 py-4"> | ||
| {/* Critical Warning Banner */} | ||
| <div className="rounded-lg border-2 border-red-500 bg-red-500/10 p-4"> | ||
| <div className="flex items-start gap-3"> | ||
| <AlertTriangle className="w-5 h-5 text-red-500 flex-shrink-0 mt-0.5" /> | ||
| <div className="space-y-2 text-sm"> | ||
| <p className="font-semibold text-red-600 dark:text-red-500"> | ||
| Critical: Save your Account ID immediately! | ||
| </p> | ||
| <p> | ||
| Your Account ID will <strong>never be shown again</strong> after you close this | ||
| dialog. If you lose it, you will <strong>permanently lose access</strong> to your | ||
| account. We cannot recover it for you. | ||
| </p> | ||
| </div> | ||
| </div> | ||
| </div> | ||
|
|
||
| {/* UUID Display */} | ||
| <div className="space-y-2"> | ||
| <Label htmlFor="uuid" className="text-base font-medium"> | ||
| Your Account ID | ||
| </Label> | ||
| <div className="flex gap-2"> | ||
| <Input id="uuid" value={uuid} readOnly className="font-mono text-sm" /> | ||
| <Button | ||
| type="button" | ||
| variant="outline" | ||
| size="icon" | ||
| onClick={handleCopyUuid} | ||
| className="flex-shrink-0" | ||
| > | ||
| {uuidCopied ? ( | ||
| <CheckCircle className="w-4 h-4 text-green-500" /> | ||
| ) : ( | ||
| <Copy className="w-4 h-4" /> | ||
| )} | ||
| </Button> | ||
| </div> | ||
| <p className="text-xs text-muted-foreground"> | ||
| You will need this Account ID along with your password to sign in. | ||
| </p> | ||
| </div> | ||
|
|
||
| {/* Backup Instructions */} | ||
| <div className="rounded-lg border border-border bg-muted/50 p-4 space-y-2"> | ||
| <p className="text-sm font-medium">How to save your Account ID:</p> | ||
| <ul className="text-sm space-y-1 list-disc list-inside text-muted-foreground"> | ||
| <li>Copy it to a password manager (recommended)</li> | ||
| <li>Write it down on paper and store it safely</li> | ||
| <li>Save it in a secure note or encrypted file</li> | ||
| <li>Take a screenshot and store it securely</li> | ||
| </ul> | ||
| </div> | ||
|
|
||
| {/* Confirmation Checkbox */} | ||
| <div className="flex items-start space-x-3 pt-2"> | ||
| <Checkbox | ||
| id="backed-up" | ||
| checked={hasBackedUp} | ||
| onCheckedChange={(checked: boolean) => setHasBackedUp(checked === true)} | ||
AnthonyRonning marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| /> | ||
| <Label | ||
| htmlFor="backed-up" | ||
| className="text-sm font-medium leading-relaxed cursor-pointer" | ||
| > | ||
| I have securely saved my Account ID and understand I cannot recover my account without | ||
| it | ||
| </Label> | ||
| </div> | ||
| </div> | ||
|
|
||
| <DialogFooter> | ||
| <Button onClick={handleContinue} disabled={!hasBackedUp} className="w-full sm:w-auto"> | ||
| Continue to Payment | ||
| </Button> | ||
| </DialogFooter> | ||
| </DialogContent> | ||
| </Dialog> | ||
| ); | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| import { Button } from "@/components/ui/button"; | ||
| import { | ||
| Dialog, | ||
| DialogContent, | ||
| DialogDescription, | ||
| DialogHeader, | ||
| DialogTitle | ||
| } from "@/components/ui/dialog"; | ||
| import { useNavigate } from "@tanstack/react-router"; | ||
| import { useOpenSecret } from "@opensecret/react"; | ||
| import { AlertTriangle, LogOut, CreditCard } from "lucide-react"; | ||
|
|
||
| interface GuestPaymentWarningDialogProps { | ||
| open: boolean; | ||
| onOpenChange: (open: boolean) => void; | ||
| } | ||
|
|
||
| export function GuestPaymentWarningDialog({ open, onOpenChange }: GuestPaymentWarningDialogProps) { | ||
| const navigate = useNavigate(); | ||
| const os = useOpenSecret(); | ||
|
|
||
| const handleGoToPricing = () => { | ||
| navigate({ to: "/pricing" }); | ||
| }; | ||
|
|
||
| const handleLogout = async () => { | ||
| await os.signOut(); | ||
| }; | ||
|
|
||
| return ( | ||
| <Dialog open={open} onOpenChange={onOpenChange}> | ||
| <DialogContent | ||
| className="sm:max-w-[425px] [&>button]:hidden" | ||
| onInteractOutside={(e) => e.preventDefault()} | ||
| onEscapeKeyDown={(e) => e.preventDefault()} | ||
| > | ||
| <DialogHeader> | ||
| <DialogTitle className="flex items-center gap-2 text-amber-600 dark:text-amber-500"> | ||
| <AlertTriangle className="w-5 h-5" /> | ||
| Subscription Required | ||
| </DialogTitle> | ||
| <DialogDescription> | ||
| Anonymous accounts require a paid subscription to use Maple AI. | ||
| </DialogDescription> | ||
| </DialogHeader> | ||
|
|
||
| <div className="space-y-4 py-4"> | ||
| <div className="rounded-lg border border-amber-500/50 bg-amber-500/10 p-4 space-y-3"> | ||
| <p className="text-sm font-medium"> | ||
| Your anonymous account is not activated yet and cannot use the chat feature. | ||
| </p> | ||
| <p className="text-sm text-muted-foreground"> | ||
| To start chatting with Maple AI, you need to subscribe to a paid plan. Anonymous | ||
| accounts must pay for a full year using Bitcoin. | ||
| </p> | ||
| </div> | ||
|
|
||
| <div className="space-y-2"> | ||
| <Button onClick={handleGoToPricing} className="w-full gap-2"> | ||
| <CreditCard className="w-4 h-4" /> | ||
| View Pricing & Subscribe | ||
| </Button> | ||
| <Button variant="outline" onClick={handleLogout} className="w-full gap-2"> | ||
| <LogOut className="w-4 h-4" /> | ||
| Log Out | ||
| </Button> | ||
| </div> | ||
| </div> | ||
| </DialogContent> | ||
| </Dialog> | ||
| ); | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.