spree/spree-api-v2-js-sdk

Cannot include logged-in user token when fetching product list

ddombrowsky opened this issue ยท 9 comments

Context

There appears to be no way to pass an auth token along with a call to list products. Because of this, the back end cannot determine which user is requesting the product list, preventing me from implementing members-only pricing or products.

e.g. this code

  const response = await spreeClient.products.list({
    include: "images",
    bearerToken: token ? token.access : undefined
  });

will not pass through the bearerToken.

Expected Behavior

The request should include the Authorize: header field, as it does with the cart operations.

Possible Fix

The API call should be updated to include the optional parameter.

Your Environment

  • Library version: 4.4.3
  • Node and yarn/npm version: node 14.15.4, npm 7.20.3

Some variant of this, perhaps? This changes the API though. Not sure if there's a way around that.

diff --git a/src/endpoints/Products.ts b/src/endpoints/Products.ts
index ca836e5..399ff06 100644
--- a/src/endpoints/Products.ts
+++ b/src/endpoints/Products.ts
@@ -1,14 +1,15 @@
 import Http from '../Http'
 import { IProductResult, IProductsResult } from '../interfaces/Product'
 import { IQuery } from '../interfaces/Query'
+import { IToken } from '../interfaces/Token'
 import routes from '../routes'
 
 export default class Products extends Http {
-  public async list(params: IQuery = {}): Promise<IProductsResult> {
-    return (await this.spreeResponse('get', routes.productsPath(), {}, params)) as IProductsResult
+  public async list(token: IToken, params: IQuery = {}): Promise<IProductsResult> {
+    return (await this.spreeResponse('get', routes.productsPath(), token, params)) as IProductsResult
   }
 
-  public async show(id: string, params: IQuery = {}): Promise<IProductResult> {
-    return (await this.spreeResponse('get', routes.productPath(id), {}, params)) as IProductResult
+  public async show(token: IToken, id: string, params: IQuery = {}): Promise<IProductResult> {
+    return (await this.spreeResponse('get', routes.productPath(id), token, params)) as IProductResult
   }
 }
diff --git a/types/endpoints/Products.d.ts b/types/endpoints/Products.d.ts
index 2481dd1..1c600b2 100644
--- a/types/endpoints/Products.d.ts
+++ b/types/endpoints/Products.d.ts
@@ -1,7 +1,8 @@
 import Http from '../Http';
 import { IProductResult, IProductsResult } from '../interfaces/Product';
 import { IQuery } from '../interfaces/Query';
+import { IToken } from '../interfaces/Token';
 export default class Products extends Http {
-    list(params?: IQuery): Promise<IProductsResult>;
-    show(id: string, params?: IQuery): Promise<IProductResult>;
+    list(token: IToken, params?: IQuery): Promise<IProductsResult>;
+    show(token: IToken, id: string, params?: IQuery): Promise<IProductResult>;
 }

The call would end up being

   const response = await spreeClient.products.list({
    bearerToken: token ? token.access_token : undefined
  }, {
    include: "images",
   });

Hey @ddombrowsky could you create a PR with these changes to this repo? :)

@damianlegawiec ๐Ÿ‘‹ Do you think an optional token should be added to the stock Spree SDK? Is it a common need to send a bearer token with list and show requests? These endpoints can be extended inside the project instead. For example:

class ExtendedProducts extends endpoints.Products {
  public list(params: IQuery = {}, token?: IToken): Promise<IProductsResult> {
    return this.spreeResponse('get', routes.productsPath(), token, params)
  }

  public show(id: string, params: IQuery = {}, token?: IToken): Promise<IProductResult> {
    return this.spreeResponse('get', routes.productPath(id), token, params)
  }
}

If we're going to allow sending a token with product requests, we must make it optional.

@damianlegawiec ๐Ÿ‘‹ Do you think an optional token should be added to the stock Spree SDK? Is it a common need to send a bearer token with list and show requests? These endpoints can be extended inside the project instead. For example:

class ExtendedProducts extends endpoints.Products {

  public list(params: IQuery = {}, token?: IToken): Promise<IProductsResult> {

    return this.spreeResponse('get', routes.productsPath(), token, params)

  }



  public show(id: string, params: IQuery = {}, token?: IToken): Promise<IProductResult> {

    return this.spreeResponse('get', routes.productPath(id), token, params)

  }

}

If we're going to allow sending a token with product requests, we must make it optional.

We need to add an option to send that token for all endpoints.

Hey @ddombrowsky could you create a PR with these changes to this repo? :)

PR created: #225

Thanks for the PR.

We'll have to update the README too.