Skip to content

Commit

Permalink
working verification, custom sms params, need to fix delete suborgs p…
Browse files Browse the repository at this point in the history
…atch
  • Loading branch information
moe-dev committed Dec 12, 2024
1 parent 3264f57 commit 72282ec
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 12 deletions.
52 changes: 44 additions & 8 deletions examples/react-components/src/app/dashboard/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
Import,
useTurnkey,
getSuborgs,
getVerifiedSuborgs,
OtpVerification,
TurnkeyThemeProvider,
} from "@turnkey/sdk-react";
Expand Down Expand Up @@ -59,6 +60,8 @@ export default function Dashboard() {
);
const [signature, setSignature] = useState<any>(null);
const [suborgId, setSuborgId] = useState<string>("");
const [isVerifiedEmail, setIsVerifiedEmail] = useState<boolean>(false);
const [isVerifiedPhone, setIsVerifiedPhone] = useState<boolean>(false);
const [user, setUser] = useState<any>("");
const [otpId, setOtpId] = useState("");
const [messageSigningResult, setMessageSigningResult] = useState<
Expand Down Expand Up @@ -92,6 +95,9 @@ export default function Dashboard() {
organizationId: suborgId,
otpType: "OTP_TYPE_SMS",
contact: phoneInput,
smsCustomization: {
template: "Your Turnkey Demo OTP is {{.OtpCode}}",
},
});
setOtpId(initAuthResponse?.otpId!);
};
Expand All @@ -110,11 +116,11 @@ export default function Dashboard() {
toast.error("Please enter a valid email address");
return;
}
const suborgs = await getSuborgs({
const suborgs = await getVerifiedSuborgs({
filterType: "EMAIL",
filterValue: emailInput,
}); //TODO change to get verified suborgs
if (suborgs!.organizationIds.length > 0) {
if (suborgs && suborgs!.organizationIds.length > 0) {
toast.error("Email is already connected to another account");
return;
}
Expand All @@ -139,11 +145,11 @@ export default function Dashboard() {
toast.error("Please enter a valid phone number.");
return;
}
const suborgs = await getSuborgs({
const suborgs = await getVerifiedSuborgs({
filterType: "PHONE_NUMBER",
filterValue: phoneInput,
}); //TODO change to get verified suborgs
if (suborgs!.organizationIds.length > 0) {
if (suborgs && suborgs!.organizationIds.length > 0) {
toast.error("Phone Number is already connected to another account");
return;
}
Expand All @@ -157,6 +163,9 @@ export default function Dashboard() {
organizationId: suborgId,
otpType: "OTP_TYPE_SMS",
contact: phoneInput,
smsCustomization: {
template: "Your Turnkey Demo OTP is {{.OtpCode}}",
},
});
setOtpId(initAuthResponse?.otpId!);
setIsEmailModalOpen(false);
Expand Down Expand Up @@ -296,6 +305,33 @@ export default function Dashboard() {
organizationId: suborgId!,
});
setWallets(walletsResponse.wallets);
if (userResponse.user.userEmail) {
const suborgs = await getVerifiedSuborgs({
filterType: "EMAIL",
filterValue: userResponse.user.userEmail,
});

if (
suborgs &&
suborgs!.organizationIds.length > 0 &&
suborgs!.organizationIds[0] == suborgId
) {
setIsVerifiedEmail(true);
}
}
if (userResponse.user.userPhoneNumber) {
const suborgs = await getVerifiedSuborgs({
filterType: "PHONE_NUMBER",
filterValue: userResponse.user.userPhoneNumber,
});
if (
suborgs &&
suborgs!.organizationIds.length > 0 &&
suborgs!.organizationIds[0] == suborgId
) {
setIsVerifiedPhone(true);
}
}

// Default to the first wallet if available
if (walletsResponse.wallets.length > 0) {
Expand Down Expand Up @@ -441,11 +477,11 @@ export default function Dashboard() {
<div className="labelContainer">
<img src="/mail.svg" className="iconSmall" />
<Typography>Email</Typography>
{user && user.userEmail && (
{user && user.userEmail && isVerifiedEmail && (
<span className="loginMethodDetails">{user.userEmail}</span>
)}
</div>
{user && user.userEmail ? (
{user && user.userEmail && isVerifiedEmail ? (
<CheckCircleIcon sx={{ color: "#4c48ff" }} />
) : (
<div onClick={handleOpenEmailModal}>
Expand All @@ -458,13 +494,13 @@ export default function Dashboard() {
<div className="labelContainer">
<img src="/phone.svg" className="iconSmall" />
<Typography>Phone</Typography>
{user && user.userPhoneNumber && (
{user && user.userPhoneNumber && isVerifiedPhone && (
<span className="loginMethodDetails">
{user.userPhoneNumber}
</span>
)}
</div>
{user && user.userPhoneNumber ? (
{user && user.userPhoneNumber && isVerifiedPhone ? (
<CheckCircleIcon sx={{ color: "#4c48ff" }} />
) : (
<div onClick={handleOpenPhoneModal}>
Expand Down
1 change: 1 addition & 0 deletions examples/react-components/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ export default function AuthPage() {
configOrder={configOrder}
onHandleAuthSuccess={handleAuthSuccess}
onError={(errorMessage: string) => toast.error(errorMessage)}
customSmsMessage={"Your Turnkey Demo OTP is {{.OtpCode}}"}
/>
</div>
<div>
Expand Down
38 changes: 38 additions & 0 deletions packages/sdk-react/src/actions/getVerifiedSuborgs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"use server";

import { Turnkey } from "@turnkey/sdk-server";

type GetSuborgsRequest = {
filterValue: string;
filterType: string;
};

type GetSuborgsResponse = {
organizationIds: string[];
};

export async function getVerifiedSuborgs(
request: GetSuborgsRequest
): Promise<GetSuborgsResponse | undefined> {
const turnkeyClient = new Turnkey({
apiBaseUrl: process.env.NEXT_PUBLIC_BASE_URL!,
defaultOrganizationId: process.env.NEXT_PUBLIC_ORGANIZATION_ID!,
apiPrivateKey: process.env.TURNKEY_API_PRIVATE_KEY!, // DO NOT EXPOSE THESE TO YOUR CLIENT SIDE CODE
apiPublicKey: process.env.TURNKEY_API_PUBLIC_KEY!, // DO NOT EXPOSE THESE TO YOUR CLIENT SIDE CODE
});
try {
const response = await turnkeyClient.apiClient().getVerifiedSubOrgIds({
organizationId: turnkeyClient.config.defaultOrganizationId,
filterType: request.filterType,
filterValue: request.filterValue,
});
if (!response || !response.organizationIds) {
throw new Error("Expected a non-null response with organizationIds.");
}

return { organizationIds: response.organizationIds };
} catch (e) {
console.error(e);
return;
}
}
1 change: 1 addition & 0 deletions packages/sdk-react/src/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

export { createSuborg } from "./createSuborg";
export { getSuborgs } from "./getSuborgs";
export { getVerifiedSuborgs } from "./getVerifiedSuborgs";
export { initOtpAuth } from "./initOtpAuth";
export { oauth } from "./oauth";
export { otpAuth } from "./otpAuth";
6 changes: 6 additions & 0 deletions packages/sdk-react/src/actions/initOtpAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ type InitOtpAuthRequest = {
suborgID: string;
otpType: string;
contact: string;
customSmsMessage?: string;
};

type InitOtpAuthResponse = {
Expand All @@ -27,6 +28,11 @@ export async function initOtpAuth(
contact: request.contact,
otpType: request.otpType,
organizationId: request.suborgID,
...(request.customSmsMessage && {
smsCustomization: {
template: request.customSmsMessage,
},
}),
});
const { otpId } = initOtpAuthResponse;

Expand Down
27 changes: 23 additions & 4 deletions packages/sdk-react/src/components/auth/Auth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import appleIcon from "assets/apple.svg";
import ChevronLeftIcon from "@mui/icons-material/ChevronLeft";
import OtpVerification from "./OtpVerification";
import { useTurnkey } from "../../hooks/use-turnkey";
import { getVerifiedSuborgs } from "../../actions/getVerifiedSuborgs";

const passkeyIcon = (
<svg xmlns="http://www.w3.org/2000/svg" width="43" height="48" fill="none">
Expand Down Expand Up @@ -59,13 +60,15 @@ interface AuthProps {
googleEnabled: boolean;
};
configOrder: string[];
customSmsMessage?: string;
}

const Auth: React.FC<AuthProps> = ({
onHandleAuthSuccess,
onError,
authConfig,
configOrder,
customSmsMessage,
}) => {
const { passkeyClient, authIframeClient } = useTurnkey();
const [email, setEmail] = useState<string>("");
Expand Down Expand Up @@ -116,11 +119,26 @@ const Auth: React.FC<AuthProps> = ({
filterValue: string,
additionalData = {}
) => {
const getSuborgsResponse = await getSuborgs({ filterType, filterValue });
if (!getSuborgsResponse || !getSuborgsResponse.organizationIds) {
onError("Failed to fetch account");
let suborgId;
if (filterType == "EMAIL" || filterType == "PHONE_NUMBER") {
const getVerifiedSuborgsResponse = await getVerifiedSuborgs({
filterType,
filterValue,
});
if (
!getVerifiedSuborgsResponse ||
!getVerifiedSuborgsResponse.organizationIds
) {
onError("Failed to fetch account");
}
suborgId = getVerifiedSuborgsResponse?.organizationIds[0];
} else {
const getSuborgsResponse = await getSuborgs({ filterType, filterValue });
if (!getSuborgsResponse || !getSuborgsResponse.organizationIds) {
onError("Failed to fetch account");
}
suborgId = getSuborgsResponse?.organizationIds[0];
}
let suborgId = getSuborgsResponse?.organizationIds[0];

if (!suborgId) {
const createSuborgData: Record<string, any> = { ...additionalData };
Expand Down Expand Up @@ -227,6 +245,7 @@ const Auth: React.FC<AuthProps> = ({
suborgID: suborgId,
otpType,
contact: value,
...(customSmsMessage && { customSmsMessage }),
});
if (initAuthResponse && initAuthResponse.otpId) {
setSuborgId(suborgId);
Expand Down

0 comments on commit 72282ec

Please sign in to comment.