Skip to content

Commit

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

feat: add directive to validate auth token
  • Loading branch information
Rudge authored Dec 14, 2023
2 parents 4469f5f + e98efe3 commit ac63dcc
Show file tree
Hide file tree
Showing 11 changed files with 209 additions and 162 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](http://semver.org/spec/v2.0.0.

## [Unreleased]

### Added

- add directive to validate auth token for some operations

## [1.37.3] - 2023-12-07

### Fixed
Expand Down
33 changes: 17 additions & 16 deletions graphql/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ type Query {
@cacheControl(scope: PRIVATE)
@settings(settingsType: "workspace")
@withSender
@auditAccess

getRole(id: ID!): Role @cacheControl(scope: PRIVATE, maxAge: SHORT)

Expand All @@ -14,7 +13,6 @@ type Query {
@settings(settingsType: "workspace")
@withSession
@withSender
@auditAccess

getFeaturesByModule(module: String!): Feature
@settings(settingsType: "workspace")
Expand All @@ -24,31 +22,28 @@ type Query {
@settings(settingsType: "workspace")
@cacheControl(scope: PRIVATE, maxAge: SHORT)
@withSender
@auditAccess

getUser(id: ID!): User @cacheControl(scope: PRIVATE)
getUser(id: ID!): User @cacheControl(scope: PRIVATE) @checkUserAccess
getB2BUser(id: ID!): User @cacheControl(scope: PRIVATE)

checkCustomerSchema: Boolean
@cacheControl(scope: PRIVATE)
@withSender
@auditAccess
checkCustomerSchema: Boolean @cacheControl(scope: PRIVATE) @withSender

getUserByEmail(email: String!): [User]
@cacheControl(scope: PRIVATE)
@withSender
@auditAccess
@checkUserAccess

listAllUsers: [User]
@cacheControl(scope: PRIVATE, maxAge: SHORT)
@withSender
@auditAccess
@checkUserAccess

listUsers(organizationId: ID, costCenterId: ID, roleId: ID): [User]
@cacheControl(scope: PRIVATE, maxAge: SHORT)
@deprecated(
reason: "This query is deprecated, use listUsersPaginated query instead."
)
@checkUserAccess

listUsersPaginated(
organizationId: ID
Expand All @@ -59,7 +54,9 @@ type Query {
search: String
sortOrder: String
sortedBy: String
): UserPagination @cacheControl(scope: PRIVATE, maxAge: SHORT)
): UserPagination
@cacheControl(scope: PRIVATE, maxAge: SHORT)
@checkUserAccess

checkImpersonation: UserImpersonation
@settings(settingsType: "workspace")
Expand All @@ -74,12 +71,17 @@ type Query {

getSessionWatcher: Boolean @cacheControl(scope: PRIVATE)

getUsersByEmail(email: String!): [User] @cacheControl(scope: PRIVATE)
getUsersByEmail(email: String!): [User]
@cacheControl(scope: PRIVATE)
@checkUserAccess

getActiveUserByEmail(email: String!): User @cacheControl(scope: PRIVATE)
getActiveUserByEmail(email: String!): User
@cacheControl(scope: PRIVATE)
@checkUserAccess

getOrganizationsByEmail(email: String!): [Organization]
@cacheControl(scope: PRIVATE)
@checkUserAccess
}

type Mutation {
Expand All @@ -90,12 +92,12 @@ type Mutation {
name: String!
slug: String
features: [FeatureInput]
): MutationResponse @cacheControl(scope: PRIVATE) @withSender @auditAccess
): MutationResponse @cacheControl(scope: PRIVATE) @withSender @checkUserAccess

deleteRole(id: ID!): MutationResponse
@cacheControl(scope: PRIVATE)
@withSender
@auditAccess
@checkUserAccess

saveUser(
id: ID
Expand Down Expand Up @@ -159,7 +161,6 @@ type Mutation {
@withSession
@cacheControl(scope: PRIVATE)
@withSender
@auditAccess
}

type UserImpersonation {
Expand Down
24 changes: 0 additions & 24 deletions node/clients/GraphQLServer.ts

This file was deleted.

88 changes: 88 additions & 0 deletions node/clients/Organizations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import type { InstanceOptions, IOContext } from '@vtex/api'
import { AppClient, GraphQLClient } from '@vtex/api'

import { QUERIES } from '../resolvers/Routes/utils'
import { getTokenToHeader } from './index'

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

export class OrganizationsGraphQLClient extends AppClient {
protected graphql: GraphQLClient

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

public getOrganizationById = async (orgId: string): Promise<unknown> => {
return this.query({
extensions: getPersistedQuery(),
query: QUERIES.getOrganizationById,
variables: {
id: orgId,
},
})
}

public getB2BSettings = async (): Promise<unknown> => {
return this.query({
extensions: getPersistedQuery(),
query: QUERIES.getB2BSettings,
variables: {},
})
}

public getCostCenterById = async (costId: string): Promise<unknown> => {
return this.query({
extensions: getPersistedQuery(),
query: QUERIES.getCostCenterById,
variables: {
id: costId,
},
})
}

public getMarketingTags = async (costId: string): Promise<unknown> => {
return this.query({
extensions: getPersistedQuery(),
query: QUERIES.getMarketingTags,
variables: {
costId,
},
})
}

public getOrganizationsByEmail = async (email: string): Promise<unknown> => {
return this.query({
extensions: getPersistedQuery(),
query: QUERIES.getOrganizationsByEmail,
variables: { email },
})
}

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

Check warning on line 72 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 73 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(
{ query, variables, extensions },
{
params: {
headers: getTokenToHeader(this.context),
locale: this.context.locale,
},
url: '/graphql',
}
)
}
}
25 changes: 20 additions & 5 deletions node/clients/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,29 @@
import type { IOContext } from '@vtex/api'
import { IOClients } from '@vtex/api'

import { LMClient } from '../utils/LicenseManager'
import { ProfileSystemClient } from '../utils/ProfileSystem'
import { Checkout } from './checkout'
import { GraphQLServer } from './GraphQLServer'
import FullSessions from './FullSessions'
import IdentityClient from './IdentityClient'
import { OrganizationsGraphQLClient } from './Organizations'
import { SalesChannel } from './salesChannel'
import { Schema } from './schema'
import VtexId from './vtexId'
import { SalesChannel } from './salesChannel'
import FullSessions from './FullSessions'

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 All @@ -24,8 +39,8 @@ export class Clients extends IOClients {
return this.getOrSet('checkout', Checkout)
}

public get graphqlServer() {
return this.getOrSet('graphqlServer', GraphQLServer)
public get organizations() {
return this.getOrSet('organizations', OrganizationsGraphQLClient)
}

public get schema() {
Expand Down
6 changes: 3 additions & 3 deletions node/clients/schema.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import type { InstanceOptions, IOContext } from '@vtex/api'
import { JanusClient } from '@vtex/api'

import { getTokenToHeader } from './index'

const getRouteSchema = (dataEntity: string) =>
`/api/dataentities/${dataEntity}/schemas`

Expand All @@ -10,9 +12,7 @@ export class Schema extends JanusClient {
...options,
headers: {
...options?.headers,
...(ctx.storeUserAuthToken
? { VtexIdclientAutCookie: ctx.storeUserAuthToken }
: { VtexIdclientAutCookie: ctx.authToken }),
...getTokenToHeader(ctx),
'x-vtex-user-agent': ctx.userAgent,
},
})
Expand Down
Loading

0 comments on commit ac63dcc

Please sign in to comment.