share links

This commit is contained in:
Milo Schwartz
2024-12-20 22:24:44 -05:00
parent 72dc02ff2e
commit 845d65ad33
31 changed files with 1281 additions and 212 deletions

View File

@@ -0,0 +1,32 @@
"use client";
import { Button } from "@app/components/ui/button";
import {
Card,
CardContent,
CardFooter,
CardHeader,
CardTitle
} from "@app/components/ui/card";
import Link from "next/link";
export default function AccessTokenInvalid() {
return (
<Card className="w-full max-w-md">
<CardHeader>
<CardTitle className="text-center text-2xl font-bold">
Acess URL Invalid
</CardTitle>
</CardHeader>
<CardContent>
This shared access URL is invalid. Please contact the resource
owner for a new URL.
<div className="text-center mt-4">
<Button>
<Link href="/">Go Home</Link>
</Button>
</div>
</CardContent>
</Card>
);
}

View File

@@ -45,7 +45,7 @@ import { Alert, AlertDescription } from "@app/components/ui/alert";
import { formatAxiosError } from "@app/lib/utils";
import { AxiosResponse } from "axios";
import LoginForm from "@app/components/LoginForm";
import { AuthWithPasswordResponse, AuthWithAccessTokenResponse } from "@server/routers/resource";
import { AuthWithPasswordResponse, AuthWithAccessTokenResponse, AuthWithWhitelistResponse } from "@server/routers/resource";
import { redirect } from "next/dist/server/api-utils";
import ResourceAccessDenied from "./ResourceAccessDenied";
import { createApiClient } from "@app/api";
@@ -166,7 +166,7 @@ export default function ResourceAuthPortal(props: ResourceAuthPortalProps) {
const onWhitelistSubmit = (values: any) => {
setLoadingLogin(true);
api.post<AxiosResponse<AuthWithAccessTokenResponse>>(
api.post<AxiosResponse<AuthWithWhitelistResponse>>(
`/auth/resource/${props.resource.id}/whitelist`,
{ email: values.email, otp: values.otp }
)

View File

@@ -1,6 +1,7 @@
import {
AuthWithAccessTokenResponse,
GetResourceAuthInfoResponse,
GetResourceResponse,
GetResourceResponse
} from "@server/routers/resource";
import ResourceAuthPortal from "./components/ResourceAuthPortal";
import { internal, priv } from "@app/api";
@@ -13,10 +14,14 @@ import ResourceNotFound from "./components/ResourceNotFound";
import ResourceAccessDenied from "./components/ResourceAccessDenied";
import { cookies } from "next/headers";
import { CheckResourceSessionResponse } from "@server/routers/auth";
import AccessTokenInvalid from "./components/AccessTokenInvalid";
export default async function ResourceAuthPage(props: {
params: Promise<{ resourceId: number }>;
searchParams: Promise<{ redirect: string | undefined }>;
searchParams: Promise<{
redirect: string | undefined;
token: string | undefined;
}>;
}) {
const params = await props.params;
const searchParams = await props.searchParams;
@@ -43,18 +48,55 @@ export default async function ResourceAuthPage(props: {
);
}
const hasAuth = authInfo.password || authInfo.pincode || authInfo.sso || authInfo.whitelist;
const isSSOOnly = authInfo.sso && !authInfo.password && !authInfo.pincode && !authInfo.whitelist;
const redirectUrl = searchParams.redirect || authInfo.url;
if (searchParams.token) {
let doRedirect = false;
try {
const res = await internal.post<
AxiosResponse<AuthWithAccessTokenResponse>
>(
`/auth/resource/${params.resourceId}/access-token`,
{
accessToken: searchParams.token
},
await authCookieHeader()
);
if (res.data.data.session) {
doRedirect = true;
}
} catch (e) {
return (
<div className="w-full max-w-md">
<AccessTokenInvalid />
</div>
);
}
if (doRedirect) {
redirect(redirectUrl);
}
}
const hasAuth =
authInfo.password ||
authInfo.pincode ||
authInfo.sso ||
authInfo.whitelist;
const isSSOOnly =
authInfo.sso &&
!authInfo.password &&
!authInfo.pincode &&
!authInfo.whitelist;
if (
user &&
!user.emailVerified &&
process.env.FLAGS_EMAIL_VERIFICATION_REQUIRED === "true"
) {
redirect(
`/auth/verify-email?redirect=/auth/resource/${authInfo.resourceId}`,
`/auth/verify-email?redirect=/auth/resource/${authInfo.resourceId}`
);
}
@@ -91,7 +133,7 @@ export default async function ResourceAuthPage(props: {
try {
const res = await internal.get<AxiosResponse<GetResourceResponse>>(
`/resource/${params.resourceId}`,
await authCookieHeader(),
await authCookieHeader()
);
doRedirect = true;
@@ -121,7 +163,7 @@ export default async function ResourceAuthPage(props: {
}}
resource={{
name: authInfo.resourceName,
id: authInfo.resourceId,
id: authInfo.resourceId
}}
redirect={redirectUrl}
/>