mirror of
https://github.com/vercel/commerce.git
synced 2025-06-19 21:51:21 +00:00
saleor: refine the auth process
This commit is contained in:
parent
85d203e85c
commit
e98a9f4d6f
@ -45,8 +45,8 @@ export class Config {
|
||||
const config = new Config({
|
||||
locale: 'en-US',
|
||||
commerceUrl: API_URL,
|
||||
apiToken: "",
|
||||
cartCookie: "saleorCheckoutID",
|
||||
apiToken: "saleor.Token",
|
||||
cartCookie: "saleor.CheckoutID",
|
||||
cartCookieMaxAge: 60 * 60 * 24 * 30,
|
||||
fetch: fetchGraphqlApi,
|
||||
customerCookie: "",
|
||||
|
@ -4,6 +4,7 @@ import fetch from './fetch'
|
||||
import { API_URL } from '../../const'
|
||||
import { getError } from '../../utils/handle-fetch-response'
|
||||
import { getConfig } from '..'
|
||||
import { getToken } from '@framework/utils'
|
||||
|
||||
const fetchGraphqlApi: GraphQLFetcher = async (
|
||||
query: string,
|
||||
@ -12,11 +13,13 @@ const fetchGraphqlApi: GraphQLFetcher = async (
|
||||
) => {
|
||||
// FIXME @zaiste follow the bigcommerce example
|
||||
const config = getConfig()
|
||||
const token = getToken();
|
||||
|
||||
const res = await fetch(API_URL || '', {
|
||||
...fetchOptions,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
...fetchOptions?.headers,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
|
@ -1,31 +1,20 @@
|
||||
import { useCallback } from 'react'
|
||||
import type { MutationHook } from '@commerce/utils/types'
|
||||
import { CommerceError, ValidationError } from '@commerce/utils/errors'
|
||||
import { CommerceError } from '@commerce/utils/errors'
|
||||
import useCustomer from '../customer/use-customer'
|
||||
import createCustomerAccessTokenMutation from '../utils/mutations/customer-access-token-create'
|
||||
import tokenCreateMutation from '../utils/mutations/customer-access-token-create'
|
||||
import {
|
||||
CustomerAccessTokenCreateInput,
|
||||
CustomerUserError,
|
||||
Mutation,
|
||||
MutationCheckoutCreateArgs,
|
||||
MutationTokenCreateArgs,
|
||||
} from '../schema'
|
||||
import useLogin, { UseLogin } from '@commerce/auth/use-login'
|
||||
import { setCustomerToken, throwUserErrors } from '../utils'
|
||||
import { setCSRFToken, setToken, throwUserErrors } from '../utils'
|
||||
|
||||
export default useLogin as UseLogin<typeof handler>
|
||||
|
||||
const getErrorMessage = ({ code, message }: CustomerUserError) => {
|
||||
switch (code) {
|
||||
case 'UNIDENTIFIED_CUSTOMER':
|
||||
message = 'Cannot find an account that matches the provided credentials'
|
||||
break
|
||||
}
|
||||
return message
|
||||
}
|
||||
|
||||
export const handler: MutationHook<null, {}, CustomerAccessTokenCreateInput> = {
|
||||
export const handler: MutationHook<null, {}, MutationTokenCreateArgs> = {
|
||||
fetchOptions: {
|
||||
query: createCustomerAccessTokenMutation,
|
||||
query: tokenCreateMutation,
|
||||
},
|
||||
async fetcher({ input: { email, password }, options, fetch }) {
|
||||
if (!(email && password)) {
|
||||
@ -35,23 +24,21 @@ export const handler: MutationHook<null, {}, CustomerAccessTokenCreateInput> = {
|
||||
})
|
||||
}
|
||||
|
||||
const { customerAccessTokenCreate } = await fetch<
|
||||
const { tokenCreate } = await fetch<
|
||||
Mutation,
|
||||
MutationCheckoutCreateArgs
|
||||
MutationTokenCreateArgs
|
||||
>({
|
||||
...options,
|
||||
variables: {
|
||||
input: { email, password },
|
||||
},
|
||||
variables: { email, password },
|
||||
})
|
||||
|
||||
throwUserErrors(customerAccessTokenCreate?.customerUserErrors)
|
||||
throwUserErrors(tokenCreate?.errors)
|
||||
|
||||
const customerAccessToken = customerAccessTokenCreate?.customerAccessToken
|
||||
const accessToken = customerAccessToken?.accessToken
|
||||
const { token, csrfToken } = tokenCreate!;
|
||||
|
||||
if (accessToken) {
|
||||
setCustomerToken(accessToken)
|
||||
if (token && csrfToken) {
|
||||
setToken(token)
|
||||
setCSRFToken(csrfToken)
|
||||
}
|
||||
|
||||
return null
|
||||
|
@ -3,7 +3,7 @@ import type { MutationHook } from '@commerce/utils/types'
|
||||
import useLogout, { UseLogout } from '@commerce/auth/use-logout'
|
||||
import useCustomer from '../customer/use-customer'
|
||||
import customerAccessTokenDeleteMutation from '../utils/mutations/customer-access-token-delete'
|
||||
import { getCustomerToken, setCustomerToken } from '../utils/customer-token'
|
||||
import { setToken } from '../utils/customer-token'
|
||||
|
||||
export default useLogout as UseLogout<typeof handler>
|
||||
|
||||
@ -14,11 +14,9 @@ export const handler: MutationHook<null> = {
|
||||
async fetcher({ options, fetch }) {
|
||||
await fetch({
|
||||
...options,
|
||||
variables: {
|
||||
customerAccessToken: getCustomerToken(),
|
||||
},
|
||||
variables: {},
|
||||
})
|
||||
setCustomerToken(null)
|
||||
setToken()
|
||||
return null
|
||||
},
|
||||
useHook: ({ fetch }) => () => {
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { useCallback } from 'react'
|
||||
import type { MutationHook } from '@commerce/utils/types'
|
||||
import { CommerceError, ValidationError } from '@commerce/utils/errors'
|
||||
import { CommerceError } from '@commerce/utils/errors'
|
||||
import useSignup, { UseSignup } from '@commerce/auth/use-signup'
|
||||
import useCustomer from '../customer/use-customer'
|
||||
import {
|
||||
CustomerCreate,
|
||||
AccountRegisterInput,
|
||||
Mutation,
|
||||
MutationCustomerCreateArgs,
|
||||
MutationAccountRegisterArgs
|
||||
} from '../schema'
|
||||
|
||||
import { customerCreateMutation } from '../utils/mutations'
|
||||
@ -17,27 +17,18 @@ export default useSignup as UseSignup<typeof handler>
|
||||
export const handler: MutationHook<
|
||||
null,
|
||||
{},
|
||||
CustomerCreate,
|
||||
CustomerCreate
|
||||
AccountRegisterInput,
|
||||
AccountRegisterInput
|
||||
> = {
|
||||
fetchOptions: {
|
||||
query: customerCreateMutation,
|
||||
},
|
||||
async fetcher({
|
||||
input: { user },
|
||||
input: { email, password },
|
||||
options,
|
||||
fetch,
|
||||
}) {
|
||||
if (!user) {
|
||||
throw new CommerceError({
|
||||
message:
|
||||
'A first name, last name, email and password are required to signup',
|
||||
})
|
||||
}
|
||||
|
||||
const { firstName, lastName, email, password } = user;
|
||||
|
||||
if (!(firstName && lastName && email && password)) {
|
||||
if (!(email && password)) {
|
||||
throw new CommerceError({
|
||||
message:
|
||||
'A first name, last name, email and password are required to signup',
|
||||
@ -46,13 +37,11 @@ export const handler: MutationHook<
|
||||
|
||||
const { customerCreate } = await fetch<
|
||||
Mutation,
|
||||
MutationCustomerCreateArgs
|
||||
MutationAccountRegisterArgs
|
||||
>({
|
||||
...options,
|
||||
variables: {
|
||||
input: {
|
||||
firstName,
|
||||
lastName,
|
||||
email,
|
||||
password,
|
||||
},
|
||||
|
@ -1,7 +1,7 @@
|
||||
import useCustomer, { UseCustomer } from '@commerce/customer/use-customer'
|
||||
import { Customer } from '@commerce/types'
|
||||
import { SWRHook } from '@commerce/utils/types'
|
||||
import { getCustomerQuery, getCustomerToken } from '../utils'
|
||||
import { getCustomerQuery, getCSRFToken } from '../utils'
|
||||
|
||||
export default useCustomer as UseCustomer<typeof handler>
|
||||
|
||||
@ -12,7 +12,7 @@ export const handler: SWRHook<Customer | null> = {
|
||||
async fetcher({ options, fetch }) {
|
||||
const data = await fetch<any | null>({
|
||||
...options,
|
||||
variables: { customerAccessToken: getCustomerToken() },
|
||||
variables: { customerAccessToken: getCSRFToken() },
|
||||
})
|
||||
return data.customer ?? null
|
||||
},
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Fetcher } from '@commerce/utils/types'
|
||||
import { API_URL } from './const'
|
||||
import { handleFetchResponse } from './utils'
|
||||
import { getToken, handleFetchResponse } from './utils'
|
||||
|
||||
const fetcher: Fetcher = async ({
|
||||
url = API_URL,
|
||||
@ -8,11 +8,14 @@ const fetcher: Fetcher = async ({
|
||||
variables,
|
||||
query,
|
||||
}) => {
|
||||
const token = getToken();
|
||||
|
||||
return handleFetchResponse(
|
||||
await fetch(url!, {
|
||||
method,
|
||||
body: JSON.stringify({ query, variables }),
|
||||
headers: {
|
||||
Authorization: `JWT ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { Product } from '@commerce/types'
|
||||
import { getConfig, SaleorConfig } from '../api'
|
||||
import fetchAllProducts from '../api/utils/fetch-all-products'
|
||||
import { ProductCountableEdge } from '../schema'
|
||||
|
@ -1,20 +1,19 @@
|
||||
import Cookies, { CookieAttributes } from 'js-cookie'
|
||||
|
||||
export const getCustomerToken = () => Cookies.get('saleorAccessToken')
|
||||
export const getToken = () => Cookies.get('saleor.Token')
|
||||
export const setToken = (token?: string, options?: CookieAttributes) => {
|
||||
setCookie('saleor.Token', token, options)
|
||||
}
|
||||
|
||||
export const setCustomerToken = (
|
||||
token: string | null,
|
||||
options?: CookieAttributes
|
||||
) => {
|
||||
export const getCSRFToken = () => Cookies.get('saleor.CSRFToken')
|
||||
export const setCSRFToken = (token?: string, options?: CookieAttributes) => {
|
||||
setCookie('saleor.CSRFToken', token, options)
|
||||
}
|
||||
|
||||
const setCookie = (name: string, token?: string, options?: CookieAttributes) => {
|
||||
if (!token) {
|
||||
Cookies.remove('saleorAccessToken')
|
||||
Cookies.remove(name)
|
||||
} else {
|
||||
Cookies.set(
|
||||
'saleorAccessToken',
|
||||
token,
|
||||
options ?? {
|
||||
expires: 60 * 60 * 24 * 30,
|
||||
}
|
||||
)
|
||||
Cookies.set(name, token, options ?? { expires: 60 * 60 * 24 * 30 })
|
||||
}
|
||||
}
|
||||
|
@ -1,36 +1,38 @@
|
||||
import { FetcherOptions } from '@commerce/utils/types'
|
||||
import { CustomerAccessTokenCreateInput } from '../schema'
|
||||
import { setCustomerToken } from './customer-token'
|
||||
import { CreateToken, Mutation, MutationTokenCreateArgs } from '../schema'
|
||||
import { setToken, setCSRFToken } from './customer-token'
|
||||
import { customerAccessTokenCreateMutation } from './mutations'
|
||||
import throwUserErrors from './throw-user-errors'
|
||||
|
||||
const handleLogin = (data: any) => {
|
||||
const response = data.customerAccessTokenCreate
|
||||
throwUserErrors(response?.customerUserErrors)
|
||||
const handleLogin = (data: CreateToken) => {
|
||||
throwUserErrors(data?.errors)
|
||||
|
||||
const customerAccessToken = response?.customerAccessToken
|
||||
const accessToken = customerAccessToken?.accessToken
|
||||
const token = data?.token
|
||||
|
||||
if (accessToken) {
|
||||
setCustomerToken(accessToken)
|
||||
if (token) {
|
||||
setToken(token)
|
||||
setCSRFToken(token)
|
||||
}
|
||||
|
||||
return customerAccessToken
|
||||
return token
|
||||
}
|
||||
|
||||
export const handleAutomaticLogin = async (
|
||||
fetch: <T = any, B = Body>(options: FetcherOptions<B>) => Promise<T>,
|
||||
input: CustomerAccessTokenCreateInput
|
||||
input: MutationTokenCreateArgs
|
||||
) => {
|
||||
try {
|
||||
const loginData = await fetch({
|
||||
const { tokenCreate } = await fetch<
|
||||
Mutation,
|
||||
MutationTokenCreateArgs
|
||||
>({
|
||||
query: customerAccessTokenCreateMutation,
|
||||
variables: {
|
||||
input,
|
||||
},
|
||||
variables: { ...input },
|
||||
})
|
||||
handleLogin(loginData)
|
||||
} catch (error) {}
|
||||
handleLogin(tokenCreate!)
|
||||
} catch (error) {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
export default handleLogin
|
||||
|
@ -1,11 +1,10 @@
|
||||
const customerAccessTokenCreateMutation = /* GraphQL */ `
|
||||
mutation customerAccessTokenCreate($input: CustomerAccessTokenCreateInput!) {
|
||||
customerAccessTokenCreate(input: $input) {
|
||||
customerAccessToken {
|
||||
accessToken
|
||||
expiresAt
|
||||
}
|
||||
customerUserErrors {
|
||||
const tokenCreateMutation = /* GraphQL */ `
|
||||
mutation tokenCreate($email: String!, $password: String!) {
|
||||
tokenCreate(email: $email, password: $password) {
|
||||
token
|
||||
refreshToken
|
||||
csrfToken
|
||||
errors {
|
||||
code
|
||||
field
|
||||
message
|
||||
@ -13,4 +12,4 @@ const customerAccessTokenCreateMutation = /* GraphQL */ `
|
||||
}
|
||||
}
|
||||
`
|
||||
export default customerAccessTokenCreateMutation
|
||||
export default tokenCreateMutation;
|
||||
|
@ -1,9 +1,7 @@
|
||||
const customerAccessTokenDeleteMutation = /* GraphQL */ `
|
||||
mutation customerAccessTokenDelete($customerAccessToken: String!) {
|
||||
customerAccessTokenDelete(customerAccessToken: $customerAccessToken) {
|
||||
deletedAccessToken
|
||||
deletedCustomerAccessTokenId
|
||||
userErrors {
|
||||
mutation customerAccessTokenDelete {
|
||||
tokensDeactivateAll {
|
||||
errors {
|
||||
field
|
||||
message
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user