feat: allow registration disabling

This commit is contained in:
Aidan 2025-04-08 16:54:38 -04:00
parent 064b17fc88
commit 192e38cd67
5 changed files with 231 additions and 165 deletions

View File

@ -31,12 +31,19 @@ export default async function Login() {
<SiAuthentik /> <SiAuthentik />
Sign in with Authentik Sign in with Authentik
</Button> </Button>
<Link href="/account/signup" className="text-sm underline"> {process.env.SIGNUP_ENABLED === "true" ? (
<Link href="/account/signup">
<Button variant="outline" className="w-full"> <Button variant="outline" className="w-full">
<UserPlus /> <UserPlus />
Create an Account Create an Account
</Button> </Button>
</Link> </Link>
) : (
<Button variant="outline" className="w-full cursor-not-allowed" disabled>
<UserPlus />
Registration is Closed
</Button>
)}
</form> </form>
</CardContent> </CardContent>
<CardFooter className="justify-center"> <CardFooter className="justify-center">

View File

@ -0,0 +1,17 @@
import React from "react"
export default function SignupLayout({
children,
}: {
children: React.ReactNode
}) {
if (process.env.SIGNUP_ENABLED === "false") {
return <div>Signup is disabled</div>
} else if (process.env.SIGNUP_ENABLED === "true") {
return (
<div className="min-h-screen bg-background">{children}</div>
)
} else {
return <div>Invalid SIGNUP_ENABLED environment variable</div>
}
}

View File

@ -7,12 +7,15 @@ import { validateToken } from "@/lib/utils"
// (2) Migrate a p0ntus mail account to a LibreCloud account (creates/migrates Authentik/Email) // (2) Migrate a p0ntus mail account to a LibreCloud account (creates/migrates Authentik/Email)
async function createEmail(email: string, password: string, migrate: boolean) { async function createEmail(email: string, password: string, migrate: boolean) {
// Signup status check
if (process.env.SIGNUP_ENABLED === "false") {
return { success: false, message: "Signups are disabled" }
} else if (process.env.SIGNUP_ENABLED === "true") {
try { try {
if (!process.env.MAIL_CONNECT_API_URL) { if (!process.env.MAIL_CONNECT_API_URL) {
console.error("[!] Missing MAIL_CONNECT_API_URL environment variable") console.error("[!] Missing MAIL_CONNECT_API_URL environment variable")
return { success: false, message: "Server configuration error" } return { success: false, message: "Server configuration error" }
} } else {
const response = await axios.post(`${process.env.MAIL_CONNECT_API_URL}/accounts/add`, { const response = await axios.post(`${process.env.MAIL_CONNECT_API_URL}/accounts/add`, {
email, email,
password, password,
@ -29,6 +32,7 @@ async function createEmail(email: string, password: string, migrate: boolean) {
console.error("[!] Email creation failed with unknown error") console.error("[!] Email creation failed with unknown error")
return { success: false, message: "Failed to create email account" } return { success: false, message: "Failed to create email account" }
} }
}
} catch (error) { } catch (error) {
console.error("[!] Email creation error:", error) console.error("[!] Email creation error:", error)
if (axios.isAxiosError(error)) { if (axios.isAxiosError(error)) {
@ -39,9 +43,13 @@ async function createEmail(email: string, password: string, migrate: boolean) {
} }
return { success: false, message: "Failed to create email account" } return { success: false, message: "Failed to create email account" }
} }
} else {
return { success: false, message: "Account signup is not configured in your environment variables!" }
}
} }
export async function POST(request: Request) { export async function POST(request: Request) {
if (process.env.SIGNUP_ENABLED === "true") {
try { try {
const body = await request.json() const body = await request.json()
const { name, email, password, migrate, token } = body const { name, email, password, migrate, token } = body
@ -168,5 +176,10 @@ export async function POST(request: Request) {
console.error("[!] Unhandled error while creating user:", error) console.error("[!] Unhandled error while creating user:", error)
return NextResponse.json({ success: false, message: "An unexpected error occurred" }, { status: 500 }) return NextResponse.json({ success: false, message: "An unexpected error occurred" }, { status: 500 })
} }
} else if (process.env.SIGNUP_ENABLED === "false") {
return NextResponse.json({ success: false, message: "Signups are disabled" }, { status: 403 })
} else {
return NextResponse.json({ success: false, message: "Account signup is not configured in your environment variables!" }, { status: 500 })
}
} }

View File

@ -1,7 +1,7 @@
"use client" "use client"
import { Button } from "@/components/ui/button" import { Button } from "@/components/ui/button"
import { ArrowRight } from "lucide-react" import { ArrowRight, XCircle } from "lucide-react"
import { ReactTyped } from "react-typed" import { ReactTyped } from "react-typed"
import Link from "next/link"; import Link from "next/link";
@ -23,12 +23,19 @@ const Hero = () => {
</p> </p>
<div className="mt-10 max-w-md mx-auto sm:flex sm:justify-center"> <div className="mt-10 max-w-md mx-auto sm:flex sm:justify-center">
<div className="rounded-md shadow-sm"> <div className="rounded-md shadow-sm">
{process.env.SIGNUP_ENABLED === "true" ? (
<Link href="/account/login"> <Link href="/account/login">
<Button className="py-6 px-8"> <Button className="py-6 px-8">
Get started Get Started
<ArrowRight className="ml-2 h-5 w-5" /> <ArrowRight className="ml-2 h-5 w-5" />
</Button> </Button>
</Link> </Link>
) : (
<Button className="py-6 px-8 cursor-not-allowed" disabled>
<XCircle className="mr-2 h-5 w-5" />
Registration Closed
</Button>
)}
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,7 +1,7 @@
"use client" "use client"
import type React from "react" import type React from "react"
import { Check, ChevronRight, Clock } from "lucide-react" import { Check, ChevronRight, Clock, XCircle } from "lucide-react"
import { Separator } from "@/components/ui/separator" import { Separator } from "@/components/ui/separator"
import { Badge } from "@/components/ui/badge" import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button" import { Button } from "@/components/ui/button"
@ -145,6 +145,21 @@ const PricingCard: React.FC<PricingCardProps> = ({
)} )}
</div> </div>
<div> <div>
{title !== "Everything" ? (
<motion.span
variants={textVariants}
className="text-sm text-muted-foreground block mb-1 group-hover:text-muted-foreground/90 transition-colors duration-300"
>
Starting at
</motion.span>
) : (
<motion.span
variants={textVariants}
className="text-sm text-muted-foreground italic block mb-1 group-hover:text-muted-foreground/90 transition-colors duration-300"
>
Always
</motion.span>
)}
<motion.span <motion.span
variants={textVariants} variants={textVariants}
className="text-6xl font-bold text-foreground group-hover:text-foreground/90 transition-colors duration-300" className="text-6xl font-bold text-foreground group-hover:text-foreground/90 transition-colors duration-300"
@ -166,15 +181,22 @@ const PricingCard: React.FC<PricingCardProps> = ({
</motion.p> </motion.p>
{isComingSoon ? ( {isComingSoon ? (
<Button className="w-full" size="lg" variant="outline" disabled> <Button className="w-full" size="lg" variant="outline" disabled>
<Clock className="mr-2" /> Coming Soon <Clock /> Coming Soon
</Button> </Button>
) : buttonText ? ( ) : buttonText ? (
process.env.SIGNUP_ENABLED === "true" ? (
<Link href="/account/login" className="block"> <Link href="/account/login" className="block">
<Button className="w-full group" size="lg"> <Button className="w-full group" size="lg">
{buttonText} {buttonText}
{buttonIcon} {buttonIcon}
</Button> </Button>
</Link> </Link>
) : (
<Button className="w-full" size="lg" variant="outline" disabled>
<XCircle className="h-5 w-5" />
Registration Closed
</Button>
)
) : null} ) : null}
</div> </div>
<Separator className="bg-border" /> <Separator className="bg-border" />
@ -215,7 +237,7 @@ export default function Pricing(): React.ReactElement {
features={features.everything} features={features.everything}
badge="Most Popular" badge="Most Popular"
buttonText="Get Started" buttonText="Get Started"
buttonIcon={<ChevronRight className="ml-2 h-4 w-4" />} buttonIcon={<ChevronRight className="h-4 w-4" />}
/> />
<PricingCard <PricingCard