saleor: refine the auth process

This commit is contained in:
Zaiste 2021-05-11 14:27:30 +02:00
parent 85d203e85c
commit e98a9f4d6f
No known key found for this signature in database
GPG Key ID: 15DF7EBC7F2FFE35
12 changed files with 78 additions and 101 deletions

View File

@ -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: "",

View File

@ -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',
},

View File

@ -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

View File

@ -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 }) => () => {

View File

@ -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,
},

View File

@ -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
},

View File

@ -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',
},
})

View File

@ -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'

View File

@ -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 })
}
}

View File

@ -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

View File

@ -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;

View File

@ -1,9 +1,7 @@
const customerAccessTokenDeleteMutation = /* GraphQL */ `
mutation customerAccessTokenDelete($customerAccessToken: String!) {
customerAccessTokenDelete(customerAccessToken: $customerAccessToken) {
deletedAccessToken
deletedCustomerAccessTokenId
userErrors {
mutation customerAccessTokenDelete {
tokensDeactivateAll {
errors {
field
message
}