121 lines
3.7 KiB
TypeScript
121 lines
3.7 KiB
TypeScript
import { useEffect, useState } from "react";
|
|
import { useDebounce } from "use-debounce";
|
|
import { ThemeToggle } from "@/components/theme-toggle";
|
|
import {
|
|
Card,
|
|
CardContent,
|
|
CardDescription,
|
|
CardFooter,
|
|
CardHeader,
|
|
CardTitle,
|
|
} from "@/components/ui/card";
|
|
import { Input } from "@/components/ui/input";
|
|
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
|
import { GitSocialLink, SelfSocialLink } from "@/components/social-links";
|
|
import "@/App.css";
|
|
const uri =
|
|
"https://login.microsoft.com/{tenant}/.well-known/openid-configuration";
|
|
|
|
function App() {
|
|
const [input, setInput] = useState<string>(location.hash.replace("#", ""));
|
|
const [tenantId, setTenantId] = useState<string | null>(null);
|
|
const [isLoading, setIsLoading] = useState<boolean>(false);
|
|
const [error, setError] = useState<string | null>(null);
|
|
const [domain, setDomain] = useDebounce<string>(input, 500);
|
|
const onChange = async (event: React.ChangeEvent<HTMLInputElement>) =>
|
|
setInput(event.target.value);
|
|
|
|
useEffect(() => {
|
|
location.hash = domain;
|
|
if (
|
|
(!domain.includes("@") && !domain.includes(".")) ||
|
|
domain.includes(" ") ||
|
|
domain.endsWith(".") ||
|
|
domain.length < 3 ||
|
|
domain.length > 254
|
|
) {
|
|
setTenantId(null);
|
|
setIsLoading(false);
|
|
setError("Please enter a valid email address or domain.");
|
|
return;
|
|
}
|
|
if (domain.includes("@")) {
|
|
const parts = domain.split("@");
|
|
setIsLoading(false);
|
|
setDomain(parts[parts.length - 1]);
|
|
return;
|
|
}
|
|
setIsLoading(true);
|
|
setError(null);
|
|
(async function () {
|
|
const response = await fetch(uri.replace("{tenant}", domain));
|
|
const body = await response.json();
|
|
if (!response.ok) {
|
|
setTenantId(null);
|
|
setIsLoading(false);
|
|
setError(body.error_description.split(". ")[0]);
|
|
return;
|
|
}
|
|
const myTenantId = body.authorization_endpoint.split("/")[3];
|
|
setTenantId(myTenantId);
|
|
setIsLoading(false);
|
|
})();
|
|
}, [domain, setDomain]);
|
|
|
|
return (
|
|
<>
|
|
<div className="absolute top-0 right-0 p-8">
|
|
<ThemeToggle />
|
|
</div>
|
|
<div className="flex py-32">
|
|
<Card className="grow">
|
|
<CardHeader>
|
|
<div className="grid grid-cols-12">
|
|
<SelfSocialLink />
|
|
<CardTitle className="col-span-10">
|
|
What's my Tenant Id?
|
|
</CardTitle>
|
|
<GitSocialLink />
|
|
</div>
|
|
<CardDescription>
|
|
Enter any email address or domain that your organization uses in
|
|
Microsoft365/Azure.
|
|
</CardDescription>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<Input
|
|
placeholder="Enter your email address or domain"
|
|
onChange={onChange}
|
|
value={input}
|
|
/>
|
|
</CardContent>
|
|
<CardFooter>
|
|
{input && !isLoading && error && (
|
|
<Alert variant="destructive">
|
|
<AlertTitle>Error!</AlertTitle>
|
|
<AlertDescription>{error}</AlertDescription>
|
|
</Alert>
|
|
)}
|
|
{isLoading && (
|
|
<Alert variant="destructive">
|
|
<AlertTitle>Loading...</AlertTitle>
|
|
<AlertDescription>Querying Microsoft land...</AlertDescription>
|
|
</Alert>
|
|
)}
|
|
{!isLoading && tenantId && (
|
|
<Alert variant="default">
|
|
<AlertTitle>Tenant Found</AlertTitle>
|
|
<AlertDescription>
|
|
Your Tenant Id is {tenantId}
|
|
</AlertDescription>
|
|
</Alert>
|
|
)}
|
|
</CardFooter>
|
|
</Card>
|
|
</div>
|
|
</>
|
|
);
|
|
}
|
|
|
|
export default App;
|