Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] - VTEX LOGIN #913

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions shopify/utils/storefront/storefront.graphql.gen.ts
Original file line number Diff line number Diff line change
@@ -7704,6 +7704,8 @@ export type FilterFragment = { id: string, label: string, type: FilterType, valu

export type CartFragment = { id: string, checkoutUrl: any, totalQuantity: number, lines: { nodes: Array<{ id: string, quantity: number, merchandise: { id: string, title: string, image?: { url: any, altText?: string | null } | null, product: { title: string }, price: { amount: any, currencyCode: CurrencyCode } }, cost: { totalAmount: { amount: any, currencyCode: CurrencyCode }, subtotalAmount: { amount: any, currencyCode: CurrencyCode }, amountPerQuantity: { amount: any, currencyCode: CurrencyCode }, compareAtAmountPerQuantity?: { amount: any, currencyCode: CurrencyCode } | null } } | { id: string, quantity: number, merchandise: { id: string, title: string, image?: { url: any, altText?: string | null } | null, product: { title: string }, price: { amount: any, currencyCode: CurrencyCode } }, cost: { totalAmount: { amount: any, currencyCode: CurrencyCode }, subtotalAmount: { amount: any, currencyCode: CurrencyCode }, amountPerQuantity: { amount: any, currencyCode: CurrencyCode }, compareAtAmountPerQuantity?: { amount: any, currencyCode: CurrencyCode } | null } }> }, cost: { subtotalAmount: { amount: any, currencyCode: CurrencyCode }, totalAmount: { amount: any, currencyCode: CurrencyCode }, checkoutChargeAmount: { amount: any, currencyCode: CurrencyCode } }, discountCodes: Array<{ code: string, applicable: boolean }>, discountAllocations: Array<{ discountedAmount: { amount: any, currencyCode: CurrencyCode } } | { discountedAmount: { amount: any, currencyCode: CurrencyCode } } | { discountedAmount: { amount: any, currencyCode: CurrencyCode } }> };

export type CustomerFragment = { id: string, email?: string | null, firstName?: string | null, lastName?: string | null };

export type CreateCartMutationVariables = Exact<{ [key: string]: never; }>;


@@ -7767,6 +7769,13 @@ export type ProductRecommendationsQueryVariables = Exact<{

export type ProductRecommendationsQuery = { productRecommendations?: Array<{ availableForSale: boolean, createdAt: any, description: string, descriptionHtml: any, handle: string, id: string, isGiftCard: boolean, onlineStoreUrl?: any | null, productType: string, publishedAt: any, requiresSellingPlan: boolean, tags: Array<string>, title: string, totalInventory?: number | null, updatedAt: any, vendor: string, featuredImage?: { altText?: string | null, url: any } | null, images: { nodes: Array<{ altText?: string | null, url: any }> }, media: { nodes: Array<{ alt?: string | null, mediaContentType: MediaContentType, previewImage?: { altText?: string | null, url: any } | null } | { alt?: string | null, mediaContentType: MediaContentType, previewImage?: { altText?: string | null, url: any } | null } | { alt?: string | null, mediaContentType: MediaContentType, previewImage?: { altText?: string | null, url: any } | null } | { alt?: string | null, mediaContentType: MediaContentType, previewImage?: { altText?: string | null, url: any } | null }> }, options: Array<{ name: string, values: Array<string> }>, priceRange: { minVariantPrice: { amount: any, currencyCode: CurrencyCode }, maxVariantPrice: { amount: any, currencyCode: CurrencyCode } }, seo: { title?: string | null, description?: string | null }, variants: { nodes: Array<{ availableForSale: boolean, barcode?: string | null, currentlyNotInStock: boolean, id: string, quantityAvailable?: number | null, requiresShipping: boolean, sku?: string | null, title: string, weight?: number | null, weightUnit: WeightUnit, compareAtPrice?: { amount: any, currencyCode: CurrencyCode } | null, image?: { altText?: string | null, url: any } | null, price: { amount: any, currencyCode: CurrencyCode }, selectedOptions: Array<{ name: string, value: string }>, unitPrice?: { amount: any, currencyCode: CurrencyCode } | null, unitPriceMeasurement?: { measuredType?: UnitPriceMeasurementMeasuredType | null, quantityValue: number, referenceUnit?: UnitPriceMeasurementMeasuredUnit | null, quantityUnit?: UnitPriceMeasurementMeasuredUnit | null } | null }> }, collections: { nodes: Array<{ description: string, descriptionHtml: any, handle: string, id: string, title: string, updatedAt: any, image?: { altText?: string | null, url: any } | null }> } }> | null };

export type FetchCustomerInfoQueryVariables = Exact<{
customerAccessToken: Scalars['String']['input'];
}>;


export type FetchCustomerInfoQuery = { customer?: { id: string, email?: string | null, firstName?: string | null, lastName?: string | null } | null };

export type AddItemToCartMutationVariables = Exact<{
cartId: Scalars['ID']['input'];
lines: Array<CartLineInput> | CartLineInput;
@@ -7790,3 +7799,11 @@ export type UpdateItemsMutationVariables = Exact<{


export type UpdateItemsMutation = { payload?: { cart?: { id: string, checkoutUrl: any, totalQuantity: number, lines: { nodes: Array<{ id: string, quantity: number, merchandise: { id: string, title: string, image?: { url: any, altText?: string | null } | null, product: { title: string }, price: { amount: any, currencyCode: CurrencyCode } }, cost: { totalAmount: { amount: any, currencyCode: CurrencyCode }, subtotalAmount: { amount: any, currencyCode: CurrencyCode }, amountPerQuantity: { amount: any, currencyCode: CurrencyCode }, compareAtAmountPerQuantity?: { amount: any, currencyCode: CurrencyCode } | null } } | { id: string, quantity: number, merchandise: { id: string, title: string, image?: { url: any, altText?: string | null } | null, product: { title: string }, price: { amount: any, currencyCode: CurrencyCode } }, cost: { totalAmount: { amount: any, currencyCode: CurrencyCode }, subtotalAmount: { amount: any, currencyCode: CurrencyCode }, amountPerQuantity: { amount: any, currencyCode: CurrencyCode }, compareAtAmountPerQuantity?: { amount: any, currencyCode: CurrencyCode } | null } }> }, cost: { subtotalAmount: { amount: any, currencyCode: CurrencyCode }, totalAmount: { amount: any, currencyCode: CurrencyCode }, checkoutChargeAmount: { amount: any, currencyCode: CurrencyCode } }, discountCodes: Array<{ code: string, applicable: boolean }>, discountAllocations: Array<{ discountedAmount: { amount: any, currencyCode: CurrencyCode } } | { discountedAmount: { amount: any, currencyCode: CurrencyCode } } | { discountedAmount: { amount: any, currencyCode: CurrencyCode } }> } | null } | null };

export type SignInWithEmailAndPasswordMutationVariables = Exact<{
email: Scalars['String']['input'];
password: Scalars['String']['input'];
}>;


export type SignInWithEmailAndPasswordMutation = { customerAccessTokenCreate?: { customerAccessToken?: { accessToken: string, expiresAt: any } | null, customerUserErrors: Array<{ code?: CustomerErrorCode | null, message: string }> } | null };
99 changes: 99 additions & 0 deletions vtex/actions/login/classicSignIn.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { AuthResponse } from "../../utils/types.ts";
import { AppContext } from "../../mod.ts";
import { setCookie } from "std/http/mod.ts";

export interface Props {
email: string;
password: string;
}

/**
* @title VTEX Integration - Authenticate with Email and Password
* @description This function authenticates a user using their email and password.
*/
export default async function action(
props: Props,
_req: Request,
ctx: AppContext,
): Promise<AuthResponse | null> {
const { vcsDeprecated } = ctx;

console.log("executou a action");

if (!props.email || !props.password) {
console.error("Email and/or password is missing:", props);
return null;
}

try {
const startAuthentication = await ctx.invoke(
"vtex/loaders/login/startAuthentication.ts",
);

if (!startAuthentication?.authenticationToken) {
console.error("Error during startAuthentication", startAuthentication);
return null;
}

console.log({ startAuthentication });
const { authenticationToken } = startAuthentication;

const myHeaders = new Headers();
myHeaders.append("Accept", "application/json");
myHeaders.append("Content-Type", "application/x-www-form-urlencoded");

const urlencoded = new URLSearchParams();
urlencoded.append("email", props.email);
urlencoded.append("password", props.password);
urlencoded.append("authenticationToken", authenticationToken);

const response = await vcsDeprecated
["POST /api/vtexid/pub/authentication/classic/validate"](
{},
{
body: urlencoded,
headers: {
...myHeaders,
},
},
);

if (!response.ok) {
console.error(
"Authentication request failed",
response.status,
response.statusText,
);
return null;
}

const data: AuthResponse = await response.json();
console.log({ data });
if (data.authStatus === "Success") {
const VTEXID_EXPIRES = data.expiresIn;

setCookie(ctx.response.headers, {
name: data.authCookie.Name,
value: data.authCookie.Value,
httpOnly: true,
maxAge: VTEXID_EXPIRES,
path: "/",
secure: true,
});

setCookie(ctx.response.headers, {
name: data.accountAuthCookie.Name,
value: data.accountAuthCookie.Value,
httpOnly: true,
maxAge: VTEXID_EXPIRES,
path: "/",
secure: true,
});
}

return data;
} catch (error) {
console.error("Unexpected error during authentication", error);
return null;
}
}
Empty file added vtex/actions/login/session.ts
Empty file.
27 changes: 27 additions & 0 deletions vtex/loaders/login/startAuthentication.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { StartAuthentication } from "../../utils/types.ts";
import { AppContext } from "../../mod.ts";

/**
* @title VTEX Integration - Start Authentication
* @description
*/
export default async function loader(
_props: unknown,
_req: Request,
ctx: AppContext,
): Promise<StartAuthentication | null> {
const { vcsDeprecated } = ctx;

try {
const response = await vcsDeprecated
["GET /api/vtexid/pub/authentication/start"]({
locale: ctx.locale,
scope: ctx.account,
});

const data = await response.json();
return data;
} catch (_) {
return null;
}
}
108 changes: 56 additions & 52 deletions vtex/manifest.gen.ts
Original file line number Diff line number Diff line change
@@ -19,13 +19,14 @@ import * as $$$$$$$$$13 from "./actions/cart/updateItemPrice.ts";
import * as $$$$$$$$$14 from "./actions/cart/updateItems.ts";
import * as $$$$$$$$$15 from "./actions/cart/updateProfile.ts";
import * as $$$$$$$$$16 from "./actions/cart/updateUser.ts";
import * as $$$$$$$$$17 from "./actions/masterdata/createDocument.ts";
import * as $$$$$$$$$18 from "./actions/newsletter/subscribe.ts";
import * as $$$$$$$$$19 from "./actions/notifyme.ts";
import * as $$$$$$$$$20 from "./actions/review/submit.ts";
import * as $$$$$$$$$21 from "./actions/trigger.ts";
import * as $$$$$$$$$22 from "./actions/wishlist/addItem.ts";
import * as $$$$$$$$$23 from "./actions/wishlist/removeItem.ts";
import * as $$$$$$$$$17 from "./actions/login/classicSignIn.ts";
import * as $$$$$$$$$18 from "./actions/masterdata/createDocument.ts";
import * as $$$$$$$$$19 from "./actions/newsletter/subscribe.ts";
import * as $$$$$$$$$20 from "./actions/notifyme.ts";
import * as $$$$$$$$$21 from "./actions/review/submit.ts";
import * as $$$$$$$$$22 from "./actions/trigger.ts";
import * as $$$$$$$$$23 from "./actions/wishlist/addItem.ts";
import * as $$$$$$$$$24 from "./actions/wishlist/removeItem.ts";
import * as $$$$0 from "./handlers/sitemap.ts";
import * as $$$0 from "./loaders/cart.ts";
import * as $$$1 from "./loaders/categories/tree.ts";
@@ -44,25 +45,26 @@ import * as $$$13 from "./loaders/legacy/productList.ts";
import * as $$$14 from "./loaders/legacy/productListingPage.ts";
import * as $$$15 from "./loaders/legacy/relatedProductsLoader.ts";
import * as $$$16 from "./loaders/legacy/suggestions.ts";
import * as $$$17 from "./loaders/logistics/listPickupPoints.ts";
import * as $$$18 from "./loaders/logistics/listPickupPointsByLocation.ts";
import * as $$$19 from "./loaders/masterdata/searchDocuments.ts";
import * as $$$20 from "./loaders/navbar.ts";
import * as $$$21 from "./loaders/options/productIdByTerm.ts";
import * as $$$22 from "./loaders/orders/list.ts";
import * as $$$23 from "./loaders/paths/PDPDefaultPath.ts";
import * as $$$24 from "./loaders/paths/PLPDefaultPath.ts";
import * as $$$25 from "./loaders/product/extend.ts";
import * as $$$26 from "./loaders/product/extensions/detailsPage.ts";
import * as $$$27 from "./loaders/product/extensions/list.ts";
import * as $$$28 from "./loaders/product/extensions/listingPage.ts";
import * as $$$29 from "./loaders/product/extensions/suggestions.ts";
import * as $$$30 from "./loaders/product/wishlist.ts";
import * as $$$31 from "./loaders/proxy.ts";
import * as $$$32 from "./loaders/user.ts";
import * as $$$33 from "./loaders/wishlist.ts";
import * as $$$34 from "./loaders/workflow/product.ts";
import * as $$$35 from "./loaders/workflow/products.ts";
import * as $$$17 from "./loaders/login/startAuthentication.ts";
import * as $$$18 from "./loaders/logistics/listPickupPoints.ts";
import * as $$$19 from "./loaders/logistics/listPickupPointsByLocation.ts";
import * as $$$20 from "./loaders/masterdata/searchDocuments.ts";
import * as $$$21 from "./loaders/navbar.ts";
import * as $$$22 from "./loaders/options/productIdByTerm.ts";
import * as $$$23 from "./loaders/orders/list.ts";
import * as $$$24 from "./loaders/paths/PDPDefaultPath.ts";
import * as $$$25 from "./loaders/paths/PLPDefaultPath.ts";
import * as $$$26 from "./loaders/product/extend.ts";
import * as $$$27 from "./loaders/product/extensions/detailsPage.ts";
import * as $$$28 from "./loaders/product/extensions/list.ts";
import * as $$$29 from "./loaders/product/extensions/listingPage.ts";
import * as $$$30 from "./loaders/product/extensions/suggestions.ts";
import * as $$$31 from "./loaders/product/wishlist.ts";
import * as $$$32 from "./loaders/proxy.ts";
import * as $$$33 from "./loaders/user.ts";
import * as $$$34 from "./loaders/wishlist.ts";
import * as $$$35 from "./loaders/workflow/product.ts";
import * as $$$36 from "./loaders/workflow/products.ts";
import * as $$$$$$0 from "./sections/Analytics/Vtex.tsx";
import * as $$$$$$$$$$0 from "./workflows/events.ts";
import * as $$$$$$$$$$1 from "./workflows/product/index.ts";
@@ -86,25 +88,26 @@ const manifest = {
"vtex/loaders/legacy/productListingPage.ts": $$$14,
"vtex/loaders/legacy/relatedProductsLoader.ts": $$$15,
"vtex/loaders/legacy/suggestions.ts": $$$16,
"vtex/loaders/logistics/listPickupPoints.ts": $$$17,
"vtex/loaders/logistics/listPickupPointsByLocation.ts": $$$18,
"vtex/loaders/masterdata/searchDocuments.ts": $$$19,
"vtex/loaders/navbar.ts": $$$20,
"vtex/loaders/options/productIdByTerm.ts": $$$21,
"vtex/loaders/orders/list.ts": $$$22,
"vtex/loaders/paths/PDPDefaultPath.ts": $$$23,
"vtex/loaders/paths/PLPDefaultPath.ts": $$$24,
"vtex/loaders/product/extend.ts": $$$25,
"vtex/loaders/product/extensions/detailsPage.ts": $$$26,
"vtex/loaders/product/extensions/list.ts": $$$27,
"vtex/loaders/product/extensions/listingPage.ts": $$$28,
"vtex/loaders/product/extensions/suggestions.ts": $$$29,
"vtex/loaders/product/wishlist.ts": $$$30,
"vtex/loaders/proxy.ts": $$$31,
"vtex/loaders/user.ts": $$$32,
"vtex/loaders/wishlist.ts": $$$33,
"vtex/loaders/workflow/product.ts": $$$34,
"vtex/loaders/workflow/products.ts": $$$35,
"vtex/loaders/login/startAuthentication.ts": $$$17,
"vtex/loaders/logistics/listPickupPoints.ts": $$$18,
"vtex/loaders/logistics/listPickupPointsByLocation.ts": $$$19,
"vtex/loaders/masterdata/searchDocuments.ts": $$$20,
"vtex/loaders/navbar.ts": $$$21,
"vtex/loaders/options/productIdByTerm.ts": $$$22,
"vtex/loaders/orders/list.ts": $$$23,
"vtex/loaders/paths/PDPDefaultPath.ts": $$$24,
"vtex/loaders/paths/PLPDefaultPath.ts": $$$25,
"vtex/loaders/product/extend.ts": $$$26,
"vtex/loaders/product/extensions/detailsPage.ts": $$$27,
"vtex/loaders/product/extensions/list.ts": $$$28,
"vtex/loaders/product/extensions/listingPage.ts": $$$29,
"vtex/loaders/product/extensions/suggestions.ts": $$$30,
"vtex/loaders/product/wishlist.ts": $$$31,
"vtex/loaders/proxy.ts": $$$32,
"vtex/loaders/user.ts": $$$33,
"vtex/loaders/wishlist.ts": $$$34,
"vtex/loaders/workflow/product.ts": $$$35,
"vtex/loaders/workflow/products.ts": $$$36,
},
"handlers": {
"vtex/handlers/sitemap.ts": $$$$0,
@@ -130,13 +133,14 @@ const manifest = {
"vtex/actions/cart/updateItems.ts": $$$$$$$$$14,
"vtex/actions/cart/updateProfile.ts": $$$$$$$$$15,
"vtex/actions/cart/updateUser.ts": $$$$$$$$$16,
"vtex/actions/masterdata/createDocument.ts": $$$$$$$$$17,
"vtex/actions/newsletter/subscribe.ts": $$$$$$$$$18,
"vtex/actions/notifyme.ts": $$$$$$$$$19,
"vtex/actions/review/submit.ts": $$$$$$$$$20,
"vtex/actions/trigger.ts": $$$$$$$$$21,
"vtex/actions/wishlist/addItem.ts": $$$$$$$$$22,
"vtex/actions/wishlist/removeItem.ts": $$$$$$$$$23,
"vtex/actions/login/classicSignIn.ts": $$$$$$$$$17,
"vtex/actions/masterdata/createDocument.ts": $$$$$$$$$18,
"vtex/actions/newsletter/subscribe.ts": $$$$$$$$$19,
"vtex/actions/notifyme.ts": $$$$$$$$$20,
"vtex/actions/review/submit.ts": $$$$$$$$$21,
"vtex/actions/trigger.ts": $$$$$$$$$22,
"vtex/actions/wishlist/addItem.ts": $$$$$$$$$23,
"vtex/actions/wishlist/removeItem.ts": $$$$$$$$$24,
},
"workflows": {
"vtex/workflows/events.ts": $$$$$$$$$$0,
4 changes: 4 additions & 0 deletions vtex/mod.ts
Original file line number Diff line number Diff line change
@@ -42,6 +42,10 @@ export interface Props {
* @description VTEX Account name. For more info, read here: https://help.vtex.com/en/tutorial/o-que-e-account-name--i0mIGLcg3QyEy8OCicEoC.
*/
account: string;
/**
* @description The primary locale of your store, e.g. en-US, pt-BR
*/
locale?: string;
/**
* @title Public store URL
* @description Domain that is registered on License Manager (e.g: www.mystore.com.br)
16 changes: 16 additions & 0 deletions vtex/utils/client.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Userorderslist } from "./openapi/vcs.openapi.gen.ts";
import {
AuthResponse,
Brand,
Category,
CreateNewDocument,
@@ -16,6 +17,7 @@ import {
SimulationItem,
SimulationOrderForm,
SPEvent,
StartAuthentication,
Suggestion,
} from "./types.ts";

@@ -247,6 +249,20 @@ export interface VTEXCommerceStable {
"GET /api/oms/user/orders": {
response: Userorderslist;
};
"GET /api/vtexid/pub/authentication/start": {
searchParams: { scope?: string; locale?: string };
response: StartAuthentication;
};
"POST /api/vtexid/pub/authentication/classic/validate": {
body: URLSearchParams;
response: AuthResponse;
};
// "GET /api/sessions": {
// searchParams: {
// items: string
// },
// response: {}
// }
}

export interface SP {
36 changes: 36 additions & 0 deletions vtex/utils/types.ts
Original file line number Diff line number Diff line change
@@ -1339,3 +1339,39 @@ export interface Orders {
};
};
}

export interface StartAuthentication {
authenticationToken: string | null;
oauthProviders: AuthProvider[];
showClassicAuthentication: boolean;
showAccessKeyAuthentication: boolean;
showPasskeyAuthentication: boolean;
authCookie: string | null;
isAuthenticated: boolean;
selectedProvider: string | null;
samlProviders: unknown[];
}

export interface AuthProvider {
providerName: string;
className: string;
expectedContext: unknown[];
}

export interface AuthResponse {
authStatus: string;
promptMFA: boolean;
clientToken: string | null;
authCookie: {
Name: string;
Value: string;
};
accountAuthCookie: {
Name: string;
Value: string;
};
expiresIn: number;
userId: string;
phoneNumber: string | null;
scope: string | null;
}