-
Notifications
You must be signed in to change notification settings - Fork 89
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
792 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/** | ||
* @description Safely parses a value to a JSON object. It doesn't validates the object, it just tries to parse it. | ||
* @param value - The value to parse | ||
* @returns The parsed value or null if the value is not a string | ||
*/ | ||
export default function safeParse<T>(value: string): T | null { | ||
if (typeof value !== "string") { | ||
return null; | ||
} | ||
|
||
try { | ||
return JSON.parse(value) as T; | ||
} catch (_e) { | ||
return null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
import { getCookies } from "std/http/cookie.ts"; | ||
import { setCookie } from "std/http/mod.ts"; | ||
import safeParse from "../../../utils/safeParse.ts"; | ||
import { AppContext } from "../../mod.ts"; | ||
import { AuthResponse } from "../../utils/types.ts"; | ||
|
||
export interface Props { | ||
email: string; | ||
accessKey: string; | ||
} | ||
|
||
/** | ||
* @title VTEX Integration - Authenticate with Email and AcessKey | ||
* @description Return authStatus that show if user is logged or something wrong happens. | ||
*/ | ||
export default async function action( | ||
props: Props, | ||
req: Request, | ||
ctx: AppContext, | ||
): Promise<AuthResponse | null> { | ||
const { vcsDeprecated } = ctx; | ||
|
||
if (!props.email || !props.accessKey) { | ||
console.error("Email and/or password is missing:", props); | ||
return null; | ||
} | ||
|
||
try { | ||
const cookies = getCookies(req.headers); | ||
const VtexSessionToken = cookies?.["VtexSessionToken"] ?? null; | ||
|
||
if (!VtexSessionToken) { | ||
console.error("VtexSessionToken cookie is missing", VtexSessionToken); | ||
return null; | ||
} | ||
|
||
const body = new URLSearchParams(); | ||
body.append("login", props.email); | ||
body.append("accessKey", props.accessKey); | ||
body.append("authenticationToken", VtexSessionToken); | ||
|
||
const response = await vcsDeprecated | ||
["POST /api/vtexid/pub/authentication/accesskey/validate"]( | ||
{}, | ||
{ | ||
body, | ||
headers: { | ||
"Content-Type": "application/x-www-form-urlencoded", | ||
"Accept": "application/json", | ||
}, | ||
}, | ||
); | ||
|
||
if (!response.ok) { | ||
console.error( | ||
"Authentication request failed", | ||
response.status, | ||
response.statusText, | ||
); | ||
return null; | ||
} | ||
|
||
const data: AuthResponse = await response.json(); | ||
if (data.authStatus === "Success") { | ||
const VTEXID_EXPIRES = data.expiresIn; | ||
|
||
if (data.authCookie) { | ||
setCookie(ctx.response.headers, { | ||
name: data.authCookie.Name, | ||
value: data.authCookie.Value, | ||
httpOnly: true, | ||
maxAge: VTEXID_EXPIRES, | ||
path: "/", | ||
secure: true, | ||
}); | ||
} | ||
|
||
if (data.accountAuthCookie) { | ||
setCookie(ctx.response.headers, { | ||
name: data.accountAuthCookie.Name, | ||
value: data.accountAuthCookie.Value, | ||
httpOnly: true, | ||
maxAge: VTEXID_EXPIRES, | ||
path: "/", | ||
secure: true, | ||
}); | ||
} | ||
} | ||
|
||
await ctx.invoke.vtex.actions.session.editSession({}); | ||
|
||
return data; | ||
} catch (error) { | ||
console.error("Unexpected error during authentication", error); | ||
if (error instanceof Error) { | ||
return safeParse<AuthResponse>(error.message); | ||
} | ||
return null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import { setCookie } from "std/http/mod.ts"; | ||
import safeParse from "../../../utils/safeParse.ts"; | ||
import { AppContext } from "../../mod.ts"; | ||
import { AuthResponse } from "../../utils/types.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; | ||
|
||
if (!props.email || !props.password) { | ||
console.error("Email and/or password is missing:", props); | ||
return null; | ||
} | ||
|
||
try { | ||
const startAuthentication = await ctx.invoke.vtex.actions.authentication | ||
.startAuthentication({}); | ||
|
||
if (!startAuthentication?.authenticationToken) { | ||
console.error( | ||
"No authentication token returned from startAuthentication.", | ||
); | ||
return null; | ||
} | ||
|
||
const authenticationToken = startAuthentication.authenticationToken; | ||
|
||
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: { | ||
"Content-Type": "application/x-www-form-urlencoded", | ||
"Accept": "application/json", | ||
}, | ||
}, | ||
); | ||
|
||
if (!response.ok) { | ||
console.error( | ||
"Authentication request failed", | ||
response.status, | ||
response.statusText, | ||
); | ||
return null; | ||
} | ||
|
||
const data: AuthResponse = await response.json(); | ||
if (data.authStatus === "Success") { | ||
const VTEXID_EXPIRES = data.expiresIn; | ||
|
||
if (data.authCookie) { | ||
setCookie(ctx.response.headers, { | ||
name: data.authCookie.Name, | ||
value: data.authCookie.Value, | ||
httpOnly: true, | ||
maxAge: VTEXID_EXPIRES, | ||
path: "/", | ||
secure: true, | ||
}); | ||
} | ||
|
||
if (data.accountAuthCookie) { | ||
setCookie(ctx.response.headers, { | ||
name: data.accountAuthCookie.Name, | ||
value: data.accountAuthCookie.Value, | ||
httpOnly: true, | ||
maxAge: VTEXID_EXPIRES, | ||
path: "/", | ||
secure: true, | ||
}); | ||
} | ||
} | ||
|
||
await ctx.invoke.vtex.actions.session.editSession({}); | ||
|
||
return data; | ||
} catch (error) { | ||
console.error("Unexpected error during authentication", error); | ||
if (error instanceof Error) { | ||
return safeParse<AuthResponse>(error.message); | ||
} | ||
return null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { getCookies, setCookie } from "std/http/mod.ts"; | ||
import { AppContext } from "../../mod.ts"; | ||
import { parseCookie } from "../../utils/vtexId.ts"; | ||
|
||
export default async function logout( | ||
_: unknown, | ||
req: Request, | ||
ctx: AppContext, | ||
) { | ||
const cookies = getCookies(req.headers); | ||
const { payload } = parseCookie(req.headers, ctx.account); | ||
|
||
for (const cookieName in cookies) { | ||
if (cookieName.startsWith("VtexIdclientAutCookie")) { | ||
setCookie(ctx.response.headers, { | ||
name: cookieName, | ||
value: "", | ||
expires: new Date(0), | ||
path: "/", | ||
}); | ||
} | ||
} | ||
|
||
try { | ||
if (payload?.sess) { | ||
await ctx.invoke.vtex.actions.session.deleteSession({ | ||
sessionId: payload?.sess, | ||
}); | ||
} | ||
} catch (error) { | ||
console.error("Error deleting session", error); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
import { getCookies } from "std/http/cookie.ts"; | ||
import { setCookie } from "std/http/mod.ts"; | ||
import safeParse from "../../../utils/safeParse.ts"; | ||
import { AppContext } from "../../mod.ts"; | ||
import { getSegmentFromBag } from "../../utils/segment.ts"; | ||
import { AuthResponse } from "../../utils/types.ts"; | ||
|
||
export interface Props { | ||
email: string; | ||
newPassword: string; | ||
accessKey: string; | ||
} | ||
|
||
/** | ||
* @title VTEX Integration - Recovery password | ||
* @description | ||
*/ | ||
export default async function action( | ||
props: Props, | ||
req: Request, | ||
ctx: AppContext, | ||
): Promise<AuthResponse | null> { | ||
const { vcsDeprecated, account } = ctx; | ||
const segment = getSegmentFromBag(ctx); | ||
|
||
if (!props.email || !props.accessKey || !props.newPassword) { | ||
console.error("Email, accessKey and/or newPassword is missing:", props); | ||
return null; | ||
} | ||
|
||
try { | ||
const cookies = getCookies(req.headers); | ||
const VtexSessionToken = cookies?.["VtexSessionToken"] ?? null; | ||
|
||
if (!VtexSessionToken) { | ||
console.error("VtexSessionToken is missing"); | ||
return null; | ||
} | ||
|
||
const urlencoded = new URLSearchParams(); | ||
urlencoded.append("login", props.email); | ||
urlencoded.append("accessKey", props.accessKey); | ||
urlencoded.append("newPassword", props.newPassword); | ||
urlencoded.append("authenticationToken", VtexSessionToken); | ||
|
||
const response = await vcsDeprecated | ||
["POST /api/vtexid/pub/authentication/classic/setpassword"]( | ||
{ | ||
locale: segment?.payload.cultureInfo || "pt-BR", | ||
scope: account, | ||
}, | ||
{ | ||
body: urlencoded, | ||
headers: { | ||
"Accept": "application/json", | ||
"Content-Type": "application/x-www-form-urlencoded", | ||
}, | ||
}, | ||
); | ||
|
||
if (!response.ok) { | ||
console.error( | ||
"Authentication request failed", | ||
response.status, | ||
response.statusText, | ||
); | ||
return null; | ||
} | ||
|
||
const data: AuthResponse = await response.json(); | ||
if (data.authStatus === "Success") { | ||
const VTEXID_EXPIRES = data.expiresIn; | ||
|
||
if (data.authCookie) { | ||
setCookie(ctx.response.headers, { | ||
name: data.authCookie.Name, | ||
value: data.authCookie.Value, | ||
httpOnly: true, | ||
maxAge: VTEXID_EXPIRES, | ||
path: "/", | ||
secure: true, | ||
}); | ||
} | ||
|
||
if (data.accountAuthCookie) { | ||
setCookie(ctx.response.headers, { | ||
name: data.accountAuthCookie.Name, | ||
value: data.accountAuthCookie.Value, | ||
httpOnly: true, | ||
maxAge: VTEXID_EXPIRES, | ||
path: "/", | ||
secure: true, | ||
}); | ||
} | ||
} | ||
|
||
await ctx.invoke.vtex.actions.session.editSession({}); | ||
|
||
return data; | ||
} catch (error) { | ||
console.error("Unexpected error during authentication", error); | ||
if (error instanceof Error) { | ||
return safeParse<AuthResponse>(error.message); | ||
} | ||
return null; | ||
} | ||
} |
Oops, something went wrong.