Skip to content

Commit

Permalink
Merge pull request #45 from vtex-apps/feature/B2BTEAM-1286-add-token-…
Browse files Browse the repository at this point in the history
…validation

feat: add token validation and set token in graphql clients
  • Loading branch information
Rudge authored Dec 15, 2023
2 parents cfdfff0 + a44a641 commit b0fd132
Show file tree
Hide file tree
Showing 13 changed files with 219 additions and 145 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- Add token validation in graphql operations and token to call storefront-permission and b2b-organization

## [2.4.1] - 2023-11-09

### Fixed
Expand Down
1 change: 1 addition & 0 deletions graphql/directives.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ directive @withPermissions on FIELD | FIELD_DEFINITION
directive @withSegment on FIELD | FIELD_DEFINITION
directive @checkAdminAccess on FIELD | FIELD_DEFINITION
directive @auditAccess on FIELD | FIELD_DEFINITION
directive @checkUserAccess on FIELD | FIELD_DEFINITION
2 changes: 1 addition & 1 deletion graphql/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ type Mutation {
useQuote(id: String, orderFormId: String): String
@withPermissions
@withSession
clearCart(orderFormId: String): String @auditAccess
clearCart(orderFormId: String): String @checkUserAccess
saveAppSettings(input: AppSettingsInput!): AppSettings
@cacheControl(scope: PRIVATE)
@checkAdminAccess
Expand Down
7 changes: 3 additions & 4 deletions manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,10 @@
},
"dependencies": {
"vtex.storefront-permissions": "1.x",
"vtex.b2b-organizations-graphql": "0.x",
"vtex.orders-broadcast": "0.x"
},
"registries": [
"smartcheckout"
],
"registries": ["smartcheckout"],
"policies": [
{
"name": "vbase-read-write"
Expand Down Expand Up @@ -48,7 +47,7 @@
"name": "vtex.storefront-permissions:resolve-graphql"
},
{
"name": "vtex.graphql-server:resolve-graphql"
"name": "vtex.b2b-organizations-graphql:resolve-graphql"
},
{
"name": "Get_User_By_Identifier"
Expand Down
17 changes: 16 additions & 1 deletion node/clients/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import type { IOContext } from '@vtex/api'
import { IOClients } from '@vtex/api'

import RequestHub from '../utils/Hub'
import Identity from '../utils/Identity'
import { Scheduler } from '../utils/Scheduler'
import Checkout from './checkout'
import MailClient from './email'
Expand All @@ -9,7 +11,20 @@ import OrdersClient from './OrdersClient'
import Organizations from './organizations'
import StorefrontPermissions from './storefrontPermissions'
import VtexId from './vtexId'
import Identity from '../utils/Identity'

export const getTokenToHeader = (ctx: IOContext) => {
const token =
ctx.storeUserAuthToken ?? ctx.adminUserAuthToken ?? ctx.authToken

const { sessionToken } = ctx

return {
'x-vtex-credential': ctx.authToken,
VtexIdclientAutCookie: token,
cookie: `VtexIdclientAutCookie=${token}`,
'x-vtex-session': sessionToken,
}
}

// Extend the default IOClients implementation with our own custom clients.
export class Clients extends IOClients {
Expand Down
126 changes: 44 additions & 82 deletions node/clients/organizations.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,11 @@
import type { InstanceOptions, IOContext } from '@vtex/api'
import { AppClient, GraphQLClient } from '@vtex/api'
import { AppGraphQLClient } from '@vtex/api'

export default class Organizations extends AppClient {
protected graphql: GraphQLClient
import { getTokenToHeader } from './index'

export default class Organizations extends AppGraphQLClient {
constructor(ctx: IOContext, options?: InstanceOptions) {
super('[email protected]', ctx, options)
this.graphql = new GraphQLClient(this.http)
}

public getOrganizationIDs = async (search: string): Promise<any> => {
const graphQLQuery = `query GetOrganizations($search: String!) {
getOrganizations(search: $search) {
data {
id
}
}
}`

return this.graphql.query(
{
extensions: {
persistedQuery: {
provider: '[email protected]',
sender: '[email protected]',
},
},
query: graphQLQuery,
variables: {
search,
},
},
{ url: '/graphql' }
)
super('[email protected]', ctx, options)
}

public getOrganizationById = async (id: string): Promise<any> => {

Check warning on line 11 in node/clients/organizations.ts

View workflow job for this annotation

GitHub Actions / QE / Lint Node.js

Unexpected any. Specify a different type
Expand All @@ -43,47 +16,13 @@ export default class Organizations extends AppClient {
}
`

return this.graphql.query(
{
extensions: {
persistedQuery: {
provider: '[email protected]',
sender: '[email protected]',
},
},
query: graphQLQuery,
variables: {
id,
},
return this.query({
extensions: this.getPersistedQuery(),
query: graphQLQuery,
variables: {
id,
},
{ url: '/graphql' }
)
}

public getCostCenterIDs = async (search: string): Promise<any> => {
const graphQLQuery = `query GetCostCenters($search: String!) {
getCostCenters(search: $search) {
data {
id
}
}
}`

return this.graphql.query(
{
extensions: {
persistedQuery: {
provider: '[email protected]',
sender: '[email protected]',
},
},
query: graphQLQuery,
variables: {
search,
},
},
{ url: '/graphql' }
)
})
}

public getCostCenterById = async (id: string): Promise<any> => {

Check warning on line 28 in node/clients/organizations.ts

View workflow job for this annotation

GitHub Actions / QE / Lint Node.js

Unexpected any. Specify a different type
Expand All @@ -94,20 +33,43 @@ export default class Organizations extends AppClient {
}
`

return this.query({
extensions: this.getPersistedQuery(),
query: graphQLQuery,
variables: {
id,
},
})
}

private getPersistedQuery = () => {
return {
persistedQuery: {
provider: '[email protected]',
sender: '[email protected]',
},
}
}

private query = async (param: {
query: string
variables: any

Check warning on line 56 in node/clients/organizations.ts

View workflow job for this annotation

GitHub Actions / QE / Lint Node.js

Unexpected any. Specify a different type
extensions: any

Check warning on line 57 in node/clients/organizations.ts

View workflow job for this annotation

GitHub Actions / QE / Lint Node.js

Unexpected any. Specify a different type
}): Promise<any> => {

Check warning on line 58 in node/clients/organizations.ts

View workflow job for this annotation

GitHub Actions / QE / Lint Node.js

Unexpected any. Specify a different type
const { query, variables, extensions } = param

return this.graphql.query(
{
extensions: {
persistedQuery: {
provider: '[email protected]',
sender: '[email protected]',
},
},
query: graphQLQuery,
variables: {
id,
},
extensions,
query,
variables,
},
{ url: '/graphql' }
{
headers: getTokenToHeader(this.context),
params: {
locale: this.context.locale,
},
}
)
}
}
85 changes: 47 additions & 38 deletions node/clients/storefrontPermissions.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import type { InstanceOptions, IOContext } from '@vtex/api'
import { AppGraphQLClient } from '@vtex/api'

import { getTokenToHeader } from './index'

export const QUERIES = {
getPermission: `query permissions {
checkUserPermission {
Expand Down Expand Up @@ -60,35 +62,19 @@ export default class StorefrontPermissions extends AppGraphQLClient {
}

public checkUserPermission = async (): Promise<any> => {

Check warning on line 64 in node/clients/storefrontPermissions.ts

View workflow job for this annotation

GitHub Actions / QE / Lint Node.js

Unexpected any. Specify a different type
return this.graphql.query(
{
extensions: {
persistedQuery: {
provider: '[email protected]',
sender: '[email protected]',
},
},
query: QUERIES.getPermission,
variables: {},
},
{}
)
return this.query({
extensions: this.getPersistedQuery(),
query: QUERIES.getPermission,
variables: {},
})
}

public listRoles = async (): Promise<any> => {

Check warning on line 72 in node/clients/storefrontPermissions.ts

View workflow job for this annotation

GitHub Actions / QE / Lint Node.js

Unexpected any. Specify a different type
return this.graphql.query(
{
extensions: {
persistedQuery: {
provider: '[email protected]',
sender: '[email protected]',
},
},
query: QUERIES.listRoles,
variables: {},
},
{}
)
return this.query({
extensions: this.getPersistedQuery(),
query: QUERIES.listRoles,
variables: {},
})
}

public listUsers = async ({
Expand All @@ -98,21 +84,44 @@ export default class StorefrontPermissions extends AppGraphQLClient {
roleId: string
organizationId?: string
}): Promise<any> => {

Check warning on line 86 in node/clients/storefrontPermissions.ts

View workflow job for this annotation

GitHub Actions / QE / Lint Node.js

Unexpected any. Specify a different type
return this.query({
extensions: this.getPersistedQuery(),
query: QUERIES.listUsers,
variables: {
roleId,
...(organizationId && { organizationId }),
},
})
}

private getPersistedQuery = () => {
return {
persistedQuery: {
provider: '[email protected]',
sender: '[email protected]',
},
}
}

private query = async (param: {
query: string
variables: any

Check warning on line 108 in node/clients/storefrontPermissions.ts

View workflow job for this annotation

GitHub Actions / QE / Lint Node.js

Unexpected any. Specify a different type
extensions: any
}): Promise<any> => {
const { query, variables, extensions } = param

return this.graphql.query(
{
extensions: {
persistedQuery: {
provider: '[email protected]',
sender: '[email protected]',
},
},
query: QUERIES.listUsers,
variables: {
roleId,
...(organizationId && { organizationId }),
},
extensions,
query,
variables,
},
{}
{
headers: getTokenToHeader(this.context),
params: {
locale: this.context.locale,
},
}
)
}
}
4 changes: 2 additions & 2 deletions node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"jsonwebtoken": "^8.5.0",
"ramda": "^0.25.0",
"atob": "^2.1.2",
"axios": "0.27.2"
"axios": "0.27.2",
"@vtex/api": "6.46.0"
},
"devDependencies": {
"@types/atob": "^2.1.2",
Expand All @@ -17,7 +18,6 @@
"@types/jsonwebtoken": "^8.5.0",
"@types/node": "^12.0.0",
"@types/ramda": "types/npm-ramda#dist",
"@vtex/api": "6.45.20",
"@vtex/prettier-config": "^0.3.1",
"tslint": "^5.12.0",
"tslint-config-prettier": "^1.18.0",
Expand Down
8 changes: 5 additions & 3 deletions node/resolvers/directives.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { AuditAccess } from './directives/auditAccess'
import { CheckAdminAccess } from './directives/checkAdminAccess'
import { CheckUserAccess } from './directives/checkUserAccess'
import { WithPermissions } from './directives/withPermissions'
import { WithSession } from './directives/withSession'
import { WithSegment } from './directives/withSegment'
import { CheckAdminAccess } from './directives/checkAdminAccess'
import { AuditAccess } from './directives/auditAccess'
import { WithSession } from './directives/withSession'

export const schemaDirectives = {
withPermissions: WithPermissions as any,
withSession: WithSession as any,
withSegment: WithSegment as any,
checkAdminAccess: CheckAdminAccess as any,
auditAccess: AuditAccess as any,
checkUserAccess: CheckUserAccess as any,
}
Loading

0 comments on commit b0fd132

Please sign in to comment.