feat: implement turnstile on signup (#13913)
* wip * feat: turnstile + removal of trpcState * fix: use react-turnstile * fix: i18n hydration errors * wip: server side validation for cf token * fix: hide in e2e tests * feat:throw on error of token * fix: set correct form values onVerify * fix: use getIp for remoteIp and use correct header for token input * chore: update .env.example * fix: Update .env.example * Update apps/web/pages/signup.tsx * chore: fix typo * fix: typo * feat: hide until error * feat: appearance interaction only * remove cloudflare from e2e * fix: legacyBehavior * fix links + wait for load * fix: signup tests * test: wait for load state --------- Co-authored-by: Keith Williams <keithwillcode@gmail.com> Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
This commit is contained in:
co-authored by
Keith Williams
Udit Takkar
parent
4a173c48b8
commit
89fe383c9f
@@ -212,6 +212,10 @@ E2E_TEST_MAILHOG_ENABLED=
|
||||
|
||||
# **********************************************************************************************************
|
||||
|
||||
# Cloudflare Turnstile
|
||||
NEXT_PUBLIC_CLOUDFLARE_SITEKEY=
|
||||
CLOUDFLARE_TURNSTILE_SECRET=
|
||||
|
||||
# Set the following value to true if you wish to enable Team Impersonation
|
||||
NEXT_PUBLIC_TEAM_IMPERSONATION=false
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import type { TurnstileProps } from "react-turnstile";
|
||||
import Turnstile from "react-turnstile";
|
||||
|
||||
import { CLOUDFLARE_SITE_ID } from "@calcom/lib/constants";
|
||||
|
||||
type Props = Omit<TurnstileProps, "sitekey">;
|
||||
|
||||
export default function TurnstileWidget(props: Props) {
|
||||
if (!CLOUDFLARE_SITE_ID || process.env.NEXT_PUBLIC_IS_E2E) return null;
|
||||
|
||||
return <Turnstile {...props} sitekey={CLOUDFLARE_SITE_ID} theme="auto" />;
|
||||
}
|
||||
@@ -24,8 +24,10 @@ const querySchema = z.object({
|
||||
|
||||
export const getServerSideProps = async (ctx: GetServerSidePropsContext) => {
|
||||
const prisma = await import("@calcom/prisma").then((mod) => mod.default);
|
||||
const emailVerificationEnabled = await getFeatureFlag(prisma, "email-verification");
|
||||
await ssrInit(ctx);
|
||||
const signupDisabled = await getFeatureFlag(prisma, "disable-signup");
|
||||
const ssr = await ssrInit(ctx);
|
||||
|
||||
const token = z.string().optional().parse(ctx.query.token);
|
||||
const redirectUrlData = z
|
||||
.string()
|
||||
@@ -42,8 +44,8 @@ export const getServerSideProps = async (ctx: GetServerSidePropsContext) => {
|
||||
redirectUrl,
|
||||
isGoogleLoginEnabled: IS_GOOGLE_LOGIN_ENABLED,
|
||||
isSAMLLoginEnabled,
|
||||
trpcState: ssr.dehydrate(),
|
||||
prepopulateFormValues: undefined,
|
||||
emailVerificationEnabled,
|
||||
};
|
||||
|
||||
// username + email prepopulated from query params
|
||||
|
||||
@@ -119,6 +119,7 @@
|
||||
"react-schemaorg": "^2.0.0",
|
||||
"react-select": "^5.7.0",
|
||||
"react-timezone-select": "^1.4.0",
|
||||
"react-turnstile": "^1.1.3",
|
||||
"react-use-intercom": "1.5.1",
|
||||
"remove-markdown": "^0.5.0",
|
||||
"rrule": "^2.7.1",
|
||||
|
||||
@@ -4,8 +4,10 @@ import calcomSignupHandler from "@calcom/feature-auth/signup/handlers/calcomHand
|
||||
import selfHostedSignupHandler from "@calcom/feature-auth/signup/handlers/selfHostedHandler";
|
||||
import { type RequestWithUsernameStatus } from "@calcom/features/auth/signup/username";
|
||||
import { IS_PREMIUM_USERNAME_ENABLED } from "@calcom/lib/constants";
|
||||
import getIP from "@calcom/lib/getIP";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import logger from "@calcom/lib/logger";
|
||||
import { checkCfTurnstileToken } from "@calcom/lib/server/checkCfTurnstileToken";
|
||||
import { signupSchema } from "@calcom/prisma/zod-utils";
|
||||
|
||||
function ensureSignupIsEnabled(req: RequestWithUsernameStatus) {
|
||||
@@ -36,8 +38,14 @@ function ensureReqIsPost(req: RequestWithUsernameStatus) {
|
||||
}
|
||||
|
||||
export default async function handler(req: RequestWithUsernameStatus, res: NextApiResponse) {
|
||||
const remoteIp = getIP(req);
|
||||
// Use a try catch instead of returning res every time
|
||||
try {
|
||||
await checkCfTurnstileToken({
|
||||
token: req.headers["cf-access-token"] as string,
|
||||
remoteIp,
|
||||
});
|
||||
|
||||
ensureReqIsPost(req);
|
||||
ensureSignupIsEnabled(req);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { signIn } from "next-auth/react";
|
||||
import { Trans } from "next-i18next";
|
||||
import dynamic from "next/dynamic";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/navigation";
|
||||
import Script from "next/script";
|
||||
@@ -16,9 +17,15 @@ import getStripe from "@calcom/app-store/stripepayment/lib/client";
|
||||
import { getPremiumPlanPriceValue } from "@calcom/app-store/stripepayment/lib/utils";
|
||||
import { getOrgUsernameFromEmail } from "@calcom/features/auth/signup/utils/getOrgUsernameFromEmail";
|
||||
import { getOrgFullOrigin } from "@calcom/features/ee/organizations/lib/orgDomains";
|
||||
import { useFlagMap } from "@calcom/features/flags/context/provider";
|
||||
import { classNames } from "@calcom/lib";
|
||||
import { APP_NAME, URL_PROTOCOL_REGEX, IS_CALCOM, WEBAPP_URL, WEBSITE_URL } from "@calcom/lib/constants";
|
||||
import {
|
||||
APP_NAME,
|
||||
URL_PROTOCOL_REGEX,
|
||||
IS_CALCOM,
|
||||
WEBAPP_URL,
|
||||
WEBSITE_URL,
|
||||
CLOUDFLARE_SITE_ID,
|
||||
} from "@calcom/lib/constants";
|
||||
import { fetchUsername } from "@calcom/lib/fetchUsername";
|
||||
import { pushGTMEvent } from "@calcom/lib/gtm";
|
||||
import { useCompatSearchParams } from "@calcom/lib/hooks/useCompatSearchParams";
|
||||
@@ -45,8 +52,11 @@ import PageWrapper from "@components/PageWrapper";
|
||||
|
||||
const signupSchema = apiSignupSchema.extend({
|
||||
apiError: z.string().optional(), // Needed to display API errors doesnt get passed to the API
|
||||
cfToken: z.string().optional(),
|
||||
});
|
||||
|
||||
const TurnstileCaptcha = dynamic(() => import("@components/auth/Turnstile"), { ssr: false });
|
||||
|
||||
type FormValues = z.infer<typeof signupSchema>;
|
||||
|
||||
export type SignupProps = inferSSRProps<typeof getServerSideProps>;
|
||||
@@ -171,6 +181,7 @@ export default function Signup({
|
||||
isSAMLLoginEnabled,
|
||||
orgAutoAcceptEmail,
|
||||
redirectUrl,
|
||||
emailVerificationEnabled,
|
||||
}: SignupProps) {
|
||||
const [premiumUsername, setPremiumUsername] = useState(false);
|
||||
const [usernameTaken, setUsernameTaken] = useState(false);
|
||||
@@ -179,7 +190,6 @@ export default function Signup({
|
||||
const telemetry = useTelemetry();
|
||||
const { t, i18n } = useLocale();
|
||||
const router = useRouter();
|
||||
const flags = useFlagMap();
|
||||
const formMethods = useForm<FormValues>({
|
||||
resolver: zodResolver(signupSchema),
|
||||
defaultValues: prepopulateFormValues satisfies FormValues,
|
||||
@@ -225,7 +235,8 @@ export default function Signup({
|
||||
|
||||
const isOrgInviteByLink = orgSlug && !prepopulateFormValues?.username;
|
||||
|
||||
const signUp: SubmitHandler<FormValues> = async (data) => {
|
||||
const signUp: SubmitHandler<FormValues> = async (_data) => {
|
||||
const { cfToken, ...data } = _data;
|
||||
await fetch("/api/auth/signup", {
|
||||
body: JSON.stringify({
|
||||
...data,
|
||||
@@ -234,6 +245,7 @@ export default function Signup({
|
||||
}),
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"cf-access-token": cfToken ?? "invalid-token",
|
||||
},
|
||||
method: "POST",
|
||||
})
|
||||
@@ -243,7 +255,7 @@ export default function Signup({
|
||||
pushGTMEvent("create_account", { email: data.email, user: data.username, lang: data.language });
|
||||
|
||||
telemetry.event(telemetryEventTypes.signup, collectPageParameters());
|
||||
const verifyOrGettingStarted = flags["email-verification"] ? "auth/verify-email" : "getting-started";
|
||||
const verifyOrGettingStarted = emailVerificationEnabled ? "auth/verify-email" : "getting-started";
|
||||
const callBackUrl = `${
|
||||
searchParams?.get("callbackUrl")
|
||||
? isOrgInviteByLink
|
||||
@@ -362,6 +374,16 @@ export default function Signup({
|
||||
{...register("password")}
|
||||
hintErrors={["caplow", "min", "num"]}
|
||||
/>
|
||||
{/* Cloudflare Turnstile Captcha */}
|
||||
{CLOUDFLARE_SITE_ID ? (
|
||||
<TurnstileCaptcha
|
||||
appearance="interaction-only"
|
||||
onVerify={(token) => {
|
||||
formMethods.setValue("cfToken", token);
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
<CheckboxField
|
||||
onChange={() => handleConsentChange(COOKIE_CONSENT)}
|
||||
description={t("cookie_consent_checkbox")}
|
||||
@@ -375,6 +397,9 @@ export default function Signup({
|
||||
!!formMethods.formState.errors.email ||
|
||||
!formMethods.getValues("email") ||
|
||||
!formMethods.getValues("password") ||
|
||||
(CLOUDFLARE_SITE_ID &&
|
||||
!process.env.NEXT_PUBLIC_IS_E2E &&
|
||||
!formMethods.getValues("cfToken")) ||
|
||||
isSubmitting ||
|
||||
usernameTaken
|
||||
}>
|
||||
@@ -497,14 +522,14 @@ export default function Signup({
|
||||
className="text-emphasis hover:underline"
|
||||
href={`${WEBSITE_URL}/terms`}
|
||||
target="_blank">
|
||||
<a>Terms</a>
|
||||
Terms
|
||||
</Link>{" "}
|
||||
and{" "}
|
||||
<Link
|
||||
className="text-emphasis hover:underline"
|
||||
href={`${WEBSITE_URL}/privacy`}
|
||||
target="_blank">
|
||||
<a>Privacy Policy</a>
|
||||
Privacy Policy
|
||||
</Link>
|
||||
.
|
||||
</Trans>
|
||||
|
||||
@@ -25,6 +25,7 @@ test.describe("Signup Flow Test", async () => {
|
||||
});
|
||||
|
||||
await page.goto("/signup");
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
const alertMessage = "Username or email is already taken";
|
||||
|
||||
@@ -51,6 +52,7 @@ test.describe("Signup Flow Test", async () => {
|
||||
});
|
||||
|
||||
await page.goto("/signup");
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
const alertMessage = "Username or email is already taken";
|
||||
|
||||
@@ -81,6 +83,7 @@ test.describe("Signup Flow Test", async () => {
|
||||
|
||||
// Signup with premium username name
|
||||
await page.goto("/signup");
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
// Fill form
|
||||
await page.locator('input[name="username"]').fill("rock");
|
||||
@@ -108,6 +111,7 @@ test.describe("Signup Flow Test", async () => {
|
||||
});
|
||||
|
||||
await page.goto("/signup");
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
// Fill form
|
||||
await page.locator('input[name="username"]').fill(userToCreate.username);
|
||||
@@ -115,10 +119,7 @@ test.describe("Signup Flow Test", async () => {
|
||||
await page.locator('input[name="password"]').fill(userToCreate.password);
|
||||
|
||||
await page.click('button[type="submit"]');
|
||||
await page.waitForLoadState("networkidle");
|
||||
// Find the newly created user and add it to the fixture store
|
||||
const newUser = await users.set(userToCreate.email);
|
||||
expect(newUser).not.toBeNull();
|
||||
await page.waitForURL("/auth/verify-email**");
|
||||
|
||||
// Check that the URL matches the expected URL
|
||||
expect(page.url()).toContain("/auth/verify-email");
|
||||
@@ -177,8 +178,8 @@ test.describe("Signup Flow Test", async () => {
|
||||
});
|
||||
|
||||
const signupUrlWithToken = `/signup?token=${token}`;
|
||||
|
||||
await page.goto(signupUrlWithToken);
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
const usernameField = page.locator('input[name="username"]');
|
||||
const emailField = page.locator('input[name="email"]');
|
||||
|
||||
@@ -146,5 +146,6 @@ export const BOOKER_NUMBER_OF_DAYS_TO_LOAD = parseInt(
|
||||
0
|
||||
);
|
||||
|
||||
export const CLOUDFLARE_SITE_ID = process.env.NEXT_PUBLIC_CLOUDFLARE_SITEKEY;
|
||||
export const MINIMUM_NUMBER_OF_ORG_SEATS = 30;
|
||||
export const ORG_SELF_SERVE_ENABLED = process.env.NEXT_PUBLIC_ORG_SELF_SERVE_ENABLED === "1";
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import { HttpError } from "../http-error";
|
||||
|
||||
const TURNSTILE_SECRET_ID = process.env.CLOUDFLARE_TURNSTILE_SECRET;
|
||||
|
||||
export async function checkCfTurnstileToken({ token, remoteIp }: { token?: string; remoteIp: string }) {
|
||||
// This means the instant doesnt have turnstile enabled - we skip the check and just return success.
|
||||
// OR the instance is running in CI so we skip these checks also
|
||||
if (!TURNSTILE_SECRET_ID || !!process.env.NEXT_PUBLIC_IS_E2E) {
|
||||
return {
|
||||
success: true,
|
||||
};
|
||||
}
|
||||
|
||||
if (!token) {
|
||||
throw new HttpError({ statusCode: 401, message: "Invalid cloudflare token" });
|
||||
}
|
||||
|
||||
const form = new URLSearchParams();
|
||||
form.append("secret", TURNSTILE_SECRET_ID);
|
||||
form.append("response", token);
|
||||
form.append("remoteip", remoteIp);
|
||||
|
||||
const result = await fetch("https://challenges.cloudflare.com/turnstile/v0/siteverify", {
|
||||
method: "POST",
|
||||
body: form,
|
||||
});
|
||||
|
||||
const data = await result.json();
|
||||
|
||||
if (!data["success"]) {
|
||||
throw new HttpError({ statusCode: 401, message: "Invalid cloudflare token" });
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
@@ -251,6 +251,7 @@
|
||||
"CLOSECOM_API_KEY",
|
||||
"CRON_API_KEY",
|
||||
"CRON_ENABLE_APP_SYNC",
|
||||
"CLOUDFLARE_TURNSTILE_SECRET",
|
||||
"DAILY_API_KEY",
|
||||
"DAILY_SCALE_PLAN",
|
||||
"DAILY_WEBHOOK_SECRET",
|
||||
@@ -321,6 +322,7 @@
|
||||
"NEXT_PUBLIC_SWAGGER_DOCS_URL",
|
||||
"NEXT_PUBLIC_TEAM_IMPERSONATION",
|
||||
"NEXT_PUBLIC_VERCEL_URL",
|
||||
"NEXT_PUBLIC_CLOUDFLARE_SITEKEY",
|
||||
"NEXT_PUBLIC_VERCEL_ENV",
|
||||
"NEXT_PUBLIC_VERCEL_BRANCH_URL",
|
||||
"NEXT_PUBLIC_GTM_ID",
|
||||
|
||||
@@ -290,25 +290,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@auth/core@npm:^0.1.4":
|
||||
version: 0.1.4
|
||||
resolution: "@auth/core@npm:0.1.4"
|
||||
dependencies:
|
||||
"@panva/hkdf": 1.0.2
|
||||
cookie: 0.5.0
|
||||
jose: 4.11.1
|
||||
oauth4webapi: 2.0.5
|
||||
preact: 10.11.3
|
||||
preact-render-to-string: 5.2.3
|
||||
peerDependencies:
|
||||
nodemailer: 6.8.0
|
||||
peerDependenciesMeta:
|
||||
nodemailer:
|
||||
optional: true
|
||||
checksum: 64854404ea1883e0deb5535b34bed95cd43fc85094aeaf4f15a79e14045020eb944f844defe857edfc8528a0a024be89cbb2a3069dedef0e9217a74ca6c3eb79
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@aw-web-design/x-default-browser@npm:1.4.126":
|
||||
version: 1.4.126
|
||||
resolution: "@aw-web-design/x-default-browser@npm:1.4.126"
|
||||
@@ -4050,41 +4031,6 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@calcom/auth@workspace:apps/auth":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@calcom/auth@workspace:apps/auth"
|
||||
dependencies:
|
||||
"@auth/core": ^0.1.4
|
||||
"@calcom/app-store": "*"
|
||||
"@calcom/app-store-cli": "*"
|
||||
"@calcom/config": "*"
|
||||
"@calcom/core": "*"
|
||||
"@calcom/dayjs": "*"
|
||||
"@calcom/embed-core": "workspace:*"
|
||||
"@calcom/embed-react": "workspace:*"
|
||||
"@calcom/embed-snippet": "workspace:*"
|
||||
"@calcom/features": "*"
|
||||
"@calcom/lib": "*"
|
||||
"@calcom/prisma": "*"
|
||||
"@calcom/trpc": "*"
|
||||
"@calcom/tsconfig": "*"
|
||||
"@calcom/types": "*"
|
||||
"@calcom/ui": "*"
|
||||
"@types/node": 16.9.1
|
||||
"@types/react": 18.0.26
|
||||
"@types/react-dom": ^18.0.9
|
||||
eslint: ^8.34.0
|
||||
eslint-config-next: ^13.2.1
|
||||
next: ^13.5.4
|
||||
next-auth: ^4.22.1
|
||||
postcss: ^8.4.18
|
||||
react: ^18.2.0
|
||||
react-dom: ^18.2.0
|
||||
tailwindcss: ^3.3.3
|
||||
typescript: ^4.9.4
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@calcom/base@workspace:packages/platform/examples/base":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@calcom/base@workspace:packages/platform/examples/base"
|
||||
@@ -4205,7 +4151,7 @@ __metadata:
|
||||
chart.js: ^3.7.1
|
||||
client-only: ^0.0.1
|
||||
eslint: ^8.34.0
|
||||
next: ^13.5.4
|
||||
next: ^13.4.6
|
||||
next-auth: ^4.22.1
|
||||
next-i18next: ^13.2.2
|
||||
postcss: ^8.4.18
|
||||
@@ -5345,6 +5291,7 @@ __metadata:
|
||||
react-schemaorg: ^2.0.0
|
||||
react-select: ^5.7.0
|
||||
react-timezone-select: ^1.4.0
|
||||
react-turnstile: ^1.1.3
|
||||
react-use-intercom: 1.5.1
|
||||
remove-markdown: ^0.5.0
|
||||
rrule: ^2.7.1
|
||||
@@ -9424,6 +9371,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@next/env@npm:13.5.6":
|
||||
version: 13.5.6
|
||||
resolution: "@next/env@npm:13.5.6"
|
||||
checksum: 5e8f3f6f987a15dad3cd7b2bcac64a6382c2ec372d95d0ce6ab295eb59c9731222017eebf71ff3005932de2571f7543bce7e5c6a8c90030207fb819404138dc2
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@next/env@npm:14.0.4":
|
||||
version: 14.0.4
|
||||
resolution: "@next/env@npm:14.0.4"
|
||||
@@ -9463,6 +9417,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@next/swc-darwin-arm64@npm:13.5.6":
|
||||
version: 13.5.6
|
||||
resolution: "@next/swc-darwin-arm64@npm:13.5.6"
|
||||
conditions: os=darwin & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@next/swc-darwin-arm64@npm:14.0.4":
|
||||
version: 14.0.4
|
||||
resolution: "@next/swc-darwin-arm64@npm:14.0.4"
|
||||
@@ -9484,6 +9445,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@next/swc-darwin-x64@npm:13.5.6":
|
||||
version: 13.5.6
|
||||
resolution: "@next/swc-darwin-x64@npm:13.5.6"
|
||||
conditions: os=darwin & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@next/swc-darwin-x64@npm:14.0.4":
|
||||
version: 14.0.4
|
||||
resolution: "@next/swc-darwin-x64@npm:14.0.4"
|
||||
@@ -9505,6 +9473,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@next/swc-linux-arm64-gnu@npm:13.5.6":
|
||||
version: 13.5.6
|
||||
resolution: "@next/swc-linux-arm64-gnu@npm:13.5.6"
|
||||
conditions: os=linux & cpu=arm64 & libc=glibc
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@next/swc-linux-arm64-gnu@npm:14.0.4":
|
||||
version: 14.0.4
|
||||
resolution: "@next/swc-linux-arm64-gnu@npm:14.0.4"
|
||||
@@ -9526,6 +9501,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@next/swc-linux-arm64-musl@npm:13.5.6":
|
||||
version: 13.5.6
|
||||
resolution: "@next/swc-linux-arm64-musl@npm:13.5.6"
|
||||
conditions: os=linux & cpu=arm64 & libc=musl
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@next/swc-linux-arm64-musl@npm:14.0.4":
|
||||
version: 14.0.4
|
||||
resolution: "@next/swc-linux-arm64-musl@npm:14.0.4"
|
||||
@@ -9547,6 +9529,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@next/swc-linux-x64-gnu@npm:13.5.6":
|
||||
version: 13.5.6
|
||||
resolution: "@next/swc-linux-x64-gnu@npm:13.5.6"
|
||||
conditions: os=linux & cpu=x64 & libc=glibc
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@next/swc-linux-x64-gnu@npm:14.0.4":
|
||||
version: 14.0.4
|
||||
resolution: "@next/swc-linux-x64-gnu@npm:14.0.4"
|
||||
@@ -9568,6 +9557,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@next/swc-linux-x64-musl@npm:13.5.6":
|
||||
version: 13.5.6
|
||||
resolution: "@next/swc-linux-x64-musl@npm:13.5.6"
|
||||
conditions: os=linux & cpu=x64 & libc=musl
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@next/swc-linux-x64-musl@npm:14.0.4":
|
||||
version: 14.0.4
|
||||
resolution: "@next/swc-linux-x64-musl@npm:14.0.4"
|
||||
@@ -9589,6 +9585,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@next/swc-win32-arm64-msvc@npm:13.5.6":
|
||||
version: 13.5.6
|
||||
resolution: "@next/swc-win32-arm64-msvc@npm:13.5.6"
|
||||
conditions: os=win32 & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@next/swc-win32-arm64-msvc@npm:14.0.4":
|
||||
version: 14.0.4
|
||||
resolution: "@next/swc-win32-arm64-msvc@npm:14.0.4"
|
||||
@@ -9610,6 +9613,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@next/swc-win32-ia32-msvc@npm:13.5.6":
|
||||
version: 13.5.6
|
||||
resolution: "@next/swc-win32-ia32-msvc@npm:13.5.6"
|
||||
conditions: os=win32 & cpu=ia32
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@next/swc-win32-ia32-msvc@npm:14.0.4":
|
||||
version: 14.0.4
|
||||
resolution: "@next/swc-win32-ia32-msvc@npm:14.0.4"
|
||||
@@ -9631,6 +9641,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@next/swc-win32-x64-msvc@npm:13.5.6":
|
||||
version: 13.5.6
|
||||
resolution: "@next/swc-win32-x64-msvc@npm:13.5.6"
|
||||
conditions: os=win32 & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@next/swc-win32-x64-msvc@npm:14.0.4":
|
||||
version: 14.0.4
|
||||
resolution: "@next/swc-win32-x64-msvc@npm:14.0.4"
|
||||
@@ -10273,13 +10290,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@panva/hkdf@npm:1.0.2":
|
||||
version: 1.0.2
|
||||
resolution: "@panva/hkdf@npm:1.0.2"
|
||||
checksum: 75183b4d5ea816ef516dcea70985c610683579a9e2ac540c2d59b9a3ed27eedaff830a43a1c43c1683556a457c92ac66e09109ee995ab173090e4042c4c4bb03
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@panva/hkdf@npm:^1.0.2":
|
||||
version: 1.0.4
|
||||
resolution: "@panva/hkdf@npm:1.0.4"
|
||||
@@ -30855,13 +30865,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"jose@npm:4.11.1":
|
||||
version: 4.11.1
|
||||
resolution: "jose@npm:4.11.1"
|
||||
checksum: cd15cba258d0fd20f6168631ce2e94fda8442df80e43c1033c523915cecdf390a1cc8efe0eab0c2d65935ca973d791c668aea80724d2aa9c2879d4e70f3081d7
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"jose@npm:5.2.1":
|
||||
version: 5.2.1
|
||||
resolution: "jose@npm:5.2.1"
|
||||
@@ -35179,6 +35182,61 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"next@npm:^13.4.6":
|
||||
version: 13.5.6
|
||||
resolution: "next@npm:13.5.6"
|
||||
dependencies:
|
||||
"@next/env": 13.5.6
|
||||
"@next/swc-darwin-arm64": 13.5.6
|
||||
"@next/swc-darwin-x64": 13.5.6
|
||||
"@next/swc-linux-arm64-gnu": 13.5.6
|
||||
"@next/swc-linux-arm64-musl": 13.5.6
|
||||
"@next/swc-linux-x64-gnu": 13.5.6
|
||||
"@next/swc-linux-x64-musl": 13.5.6
|
||||
"@next/swc-win32-arm64-msvc": 13.5.6
|
||||
"@next/swc-win32-ia32-msvc": 13.5.6
|
||||
"@next/swc-win32-x64-msvc": 13.5.6
|
||||
"@swc/helpers": 0.5.2
|
||||
busboy: 1.6.0
|
||||
caniuse-lite: ^1.0.30001406
|
||||
postcss: 8.4.31
|
||||
styled-jsx: 5.1.1
|
||||
watchpack: 2.4.0
|
||||
peerDependencies:
|
||||
"@opentelemetry/api": ^1.1.0
|
||||
react: ^18.2.0
|
||||
react-dom: ^18.2.0
|
||||
sass: ^1.3.0
|
||||
dependenciesMeta:
|
||||
"@next/swc-darwin-arm64":
|
||||
optional: true
|
||||
"@next/swc-darwin-x64":
|
||||
optional: true
|
||||
"@next/swc-linux-arm64-gnu":
|
||||
optional: true
|
||||
"@next/swc-linux-arm64-musl":
|
||||
optional: true
|
||||
"@next/swc-linux-x64-gnu":
|
||||
optional: true
|
||||
"@next/swc-linux-x64-musl":
|
||||
optional: true
|
||||
"@next/swc-win32-arm64-msvc":
|
||||
optional: true
|
||||
"@next/swc-win32-ia32-msvc":
|
||||
optional: true
|
||||
"@next/swc-win32-x64-msvc":
|
||||
optional: true
|
||||
peerDependenciesMeta:
|
||||
"@opentelemetry/api":
|
||||
optional: true
|
||||
sass:
|
||||
optional: true
|
||||
bin:
|
||||
next: dist/bin/next
|
||||
checksum: c869b0014ae921ada3bf22301985027ec320aebcd6aa9c16e8afbded68bb8def5874cca034c680e8c351a79578f1e514971d02777f6f0a5a1d7290f25970ac0d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"next@npm:^13.5.4":
|
||||
version: 13.5.5
|
||||
resolution: "next@npm:13.5.5"
|
||||
@@ -35833,13 +35891,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"oauth4webapi@npm:2.0.5":
|
||||
version: 2.0.5
|
||||
resolution: "oauth4webapi@npm:2.0.5"
|
||||
checksum: 32d0cb7b1cca42d51dfb88075ca2d69fe33172a807e8ea50e317d17cab3bc80588ab8ebcb7eb4600c371a70af4674595b4b341daf6f3a655f1efa1ab715bb6c9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"oauth@npm:^0.9.15":
|
||||
version: 0.9.15
|
||||
resolution: "oauth@npm:0.9.15"
|
||||
@@ -37970,17 +38021,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"preact-render-to-string@npm:5.2.3":
|
||||
version: 5.2.3
|
||||
resolution: "preact-render-to-string@npm:5.2.3"
|
||||
dependencies:
|
||||
pretty-format: ^3.8.0
|
||||
peerDependencies:
|
||||
preact: ">=10"
|
||||
checksum: 6e46288d8956adde35b9fe3a21aecd9dea29751b40f0f155dea62f3896f27cb8614d457b32f48d33909d2da81135afcca6c55077520feacd7d15164d1371fb44
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"preact-render-to-string@npm:^5.1.19":
|
||||
version: 5.2.6
|
||||
resolution: "preact-render-to-string@npm:5.2.6"
|
||||
@@ -37992,7 +38032,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"preact@npm:10.11.3, preact@npm:^10.6.3":
|
||||
"preact@npm:^10.6.3":
|
||||
version: 10.11.3
|
||||
resolution: "preact@npm:10.11.3"
|
||||
checksum: 9387115aa0581e8226309e6456e9856f17dfc0e3d3e63f774de80f3d462a882ba7c60914c05942cb51d51e23e120dcfe904b8d392d46f29ad15802941fe7a367
|
||||
@@ -39772,6 +39812,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-turnstile@npm:^1.1.3":
|
||||
version: 1.1.3
|
||||
resolution: "react-turnstile@npm:1.1.3"
|
||||
peerDependencies:
|
||||
react: ">= 16.13.1"
|
||||
react-dom: ">= 16.13.1"
|
||||
checksum: 1bb040eca9a4b24078dc21ee70947442ad97c7bc6507ba530974c4e5730769af0168e9b221e2835f20ea194282fc7a377eeb102084509f636fab322e95314201
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-twemoji@npm:^0.3.0":
|
||||
version: 0.3.0
|
||||
resolution: "react-twemoji@npm:0.3.0"
|
||||
|
||||
Reference in New Issue
Block a user