diff --git a/packages/hoppscotch-common/src/components/http/OAuth2Authorization.vue b/packages/hoppscotch-common/src/components/http/OAuth2Authorization.vue index bdeed0e7e..326d2a878 100644 --- a/packages/hoppscotch-common/src/components/http/OAuth2Authorization.vue +++ b/packages/hoppscotch-common/src/components/http/OAuth2Authorization.vue @@ -302,7 +302,7 @@ const supportedGrantTypes = [ auth.value.grantTypeInfo = { ...auth.value.grantTypeInfo, - clientSecret: value, + clientSecret: value ?? "", } } ) diff --git a/packages/hoppscotch-common/src/services/oauth/flows/authCode.ts b/packages/hoppscotch-common/src/services/oauth/flows/authCode.ts index f46db7212..05c80cc1b 100644 --- a/packages/hoppscotch-common/src/services/oauth/flows/authCode.ts +++ b/packages/hoppscotch-common/src/services/oauth/flows/authCode.ts @@ -30,7 +30,6 @@ const AuthCodeOauthFlowParamsSchema = AuthCodeGrantTypeParams.pick({ params.authEndpoint.length >= 1 && params.tokenEndpoint.length >= 1 && params.clientID.length >= 1 && - params.clientSecret.length >= 1 && (!params.scopes || params.scopes.trim().length >= 1) ) }, @@ -85,7 +84,7 @@ const initAuthCodeOauthFlow = async ({ grant_type: "AUTHORIZATION_CODE" authEndpoint: string tokenEndpoint: string - clientSecret: string + clientSecret?: string clientID: string isPKCE: boolean codeVerifier?: string diff --git a/packages/hoppscotch-common/src/services/persistence/__tests__/__mocks__/index.ts b/packages/hoppscotch-common/src/services/persistence/__tests__/__mocks__/index.ts index 2cbf0d0be..1beaae9d9 100644 --- a/packages/hoppscotch-common/src/services/persistence/__tests__/__mocks__/index.ts +++ b/packages/hoppscotch-common/src/services/persistence/__tests__/__mocks__/index.ts @@ -25,7 +25,7 @@ export const REST_COLLECTIONS_MOCK: HoppCollection[] = [ folders: [], requests: [ { - v: "4", + v: "5", endpoint: "https://echo.hoppscotch.io", name: "Echo test", params: [], @@ -50,7 +50,7 @@ export const GQL_COLLECTIONS_MOCK: HoppCollection[] = [ folders: [], requests: [ { - v: 4, + v: 5, name: "Echo test", url: "https://echo.hoppscotch.io/graphql", headers: [], @@ -138,7 +138,7 @@ export const REST_HISTORY_MOCK: RESTHistoryEntry[] = [ preRequestScript: "", testScript: "", requestVariables: [], - v: "4", + v: "5", }, responseMeta: { duration: 807, statusCode: 200 }, star: false, @@ -150,7 +150,7 @@ export const GQL_HISTORY_MOCK: GQLHistoryEntry[] = [ { v: 1, request: { - v: 4, + v: 5, name: "Untitled", url: "https://echo.hoppscotch.io/graphql", query: "query Request { url }", @@ -171,7 +171,7 @@ export const GQL_TAB_STATE_MOCK: PersistableTabState = { tabID: "5edbe8d4-65c9-4381-9354-5f1bf05d8ccc", doc: { request: { - v: 4, + v: 5, name: "Untitled", url: "https://echo.hoppscotch.io/graphql", headers: [], @@ -194,7 +194,7 @@ export const REST_TAB_STATE_MOCK: PersistableTabState = { tabID: "e6e8d800-caa8-44a2-a6a6-b4765a3167aa", doc: { request: { - v: "4", + v: "5", endpoint: "https://echo.hoppscotch.io", name: "Echo test", params: [], diff --git a/packages/hoppscotch-data/src/graphql/index.ts b/packages/hoppscotch-data/src/graphql/index.ts index 52ff086a2..150aac4ba 100644 --- a/packages/hoppscotch-data/src/graphql/index.ts +++ b/packages/hoppscotch-data/src/graphql/index.ts @@ -4,6 +4,7 @@ import V1_VERSION from "./v/1" import V2_VERSION from "./v/2" import V3_VERSION from "./v/3" import V4_VERSION from "./v/4" +import V5_VERSION from "./v/5" export { GQLHeader } from "./v/1" export { @@ -13,23 +14,24 @@ export { HoppGQLAuthInherit, } from "./v/2" -export { HoppGQLAuth } from "./v/4" -export { HoppGQLAuthOAuth2 } from "./v/3" +export { HoppGQLAuthOAuth2, HoppGQLAuth } from "./v/5" + export { HoppGQLAuthAPIKey } from "./v/4" -export const GQL_REQ_SCHEMA_VERSION = 4 +export const GQL_REQ_SCHEMA_VERSION = 5 const versionedObject = z.object({ v: z.number(), }) export const HoppGQLRequest = createVersionedEntity({ - latestVersion: 4, + latestVersion: 5, versionMap: { 1: V1_VERSION, 2: V2_VERSION, 3: V3_VERSION, 4: V4_VERSION, + 5: V5_VERSION, }, getVersion(x) { const result = versionedObject.safeParse(x) diff --git a/packages/hoppscotch-data/src/graphql/v/5.ts b/packages/hoppscotch-data/src/graphql/v/5.ts new file mode 100644 index 000000000..3b390a06d --- /dev/null +++ b/packages/hoppscotch-data/src/graphql/v/5.ts @@ -0,0 +1,47 @@ +import { z } from "zod" + +import { defineVersion } from "verzod" + +import { HoppRESTAuthOAuth2 } from "../../rest/v/5" +import { + HoppGQLAuthBasic, + HoppGQLAuthBearer, + HoppGQLAuthInherit, + HoppGQLAuthNone, +} from "./2" +import { HoppGQLAuthAPIKey, V4_SCHEMA } from "./4" + +export { HoppRESTAuthOAuth2 as HoppGQLAuthOAuth2 } from "../../rest/v/5" + +export const HoppGQLAuth = z + .discriminatedUnion("authType", [ + HoppGQLAuthNone, + HoppGQLAuthInherit, + HoppGQLAuthBasic, + HoppGQLAuthBearer, + HoppGQLAuthAPIKey, + HoppRESTAuthOAuth2, // both rest and gql have the same auth type for oauth2 + ]) + .and( + z.object({ + authActive: z.boolean(), + }) + ) + +export type HoppGQLAuth = z.infer + +export const V5_SCHEMA = V4_SCHEMA.extend({ + v: z.literal(5), + auth: HoppGQLAuth, +}) + +export default defineVersion({ + initial: false, + schema: V5_SCHEMA, + up(old: z.infer) { + return { + ...old, + v: 5 as const, + } + }, +}) diff --git a/packages/hoppscotch-data/src/rest/index.ts b/packages/hoppscotch-data/src/rest/index.ts index aa4e728f1..d849ae5e5 100644 --- a/packages/hoppscotch-data/src/rest/index.ts +++ b/packages/hoppscotch-data/src/rest/index.ts @@ -6,12 +6,13 @@ import V1_VERSION from "./v/1" import V2_VERSION from "./v/2" import V3_VERSION from "./v/3" import V4_VERSION from "./v/4" +import V5_VERSION from "./v/5" import { createVersionedEntity, InferredEntity } from "verzod" import { lodashIsEqualEq, mapThenEq, undefinedEq } from "../utils/eq" import { HoppRESTReqBody, HoppRESTHeaders, HoppRESTParams } from "./v/1" -import { HoppRESTAuth } from "./v/4" +import { HoppRESTAuth } from "./v/5" import { HoppRESTRequestVariables } from "./v/2" import { z } from "zod" @@ -29,14 +30,18 @@ export { } from "./v/1" export { - HoppRESTAuthOAuth2, - AuthCodeGrantTypeParams, ClientCredentialsGrantTypeParams, ImplicitOauthFlowParams, PasswordGrantTypeParams, } from "./v/3" -export { HoppRESTAuth, HoppRESTAuthAPIKey } from "./v/4" +export { + AuthCodeGrantTypeParams, + HoppRESTAuthOAuth2, + HoppRESTAuth, +} from "./v/5" + +export { HoppRESTAuthAPIKey } from "./v/4" export { HoppRESTRequestVariables } from "./v/2" @@ -46,13 +51,14 @@ const versionedObject = z.object({ }) export const HoppRESTRequest = createVersionedEntity({ - latestVersion: 4, + latestVersion: 5, versionMap: { 0: V0_VERSION, 1: V1_VERSION, 2: V2_VERSION, 3: V3_VERSION, 4: V4_VERSION, + 5: V5_VERSION, }, getVersion(data) { // For V1 onwards we have the v string storing the number @@ -94,7 +100,7 @@ const HoppRESTRequestEq = Eq.struct({ ), }) -export const RESTReqSchemaVersion = "4" +export const RESTReqSchemaVersion = "5" export type HoppRESTParam = HoppRESTRequest["params"][number] export type HoppRESTHeader = HoppRESTRequest["headers"][number] @@ -189,7 +195,7 @@ export function makeRESTRequest( export function getDefaultRESTRequest(): HoppRESTRequest { return { - v: "4", + v: "5", endpoint: "https://echo.hoppscotch.io", name: "Untitled", params: [], diff --git a/packages/hoppscotch-data/src/rest/v/5.ts b/packages/hoppscotch-data/src/rest/v/5.ts new file mode 100644 index 000000000..f1c56806a --- /dev/null +++ b/packages/hoppscotch-data/src/rest/v/5.ts @@ -0,0 +1,66 @@ +import { z } from "zod" +import { defineVersion } from "verzod" +import { + HoppRESTAuthBasic, + HoppRESTAuthBearer, + HoppRESTAuthInherit, + HoppRESTAuthNone, +} from "./1" +import { HoppRESTAuthAPIKey, V4_SCHEMA } from "./4" +import { + AuthCodeGrantTypeParams as AuthCodeGrantTypeParamsOld, + ClientCredentialsGrantTypeParams, + HoppRESTAuthOAuth2 as HoppRESTAuthOAuth2Old, + ImplicitOauthFlowParams, + PasswordGrantTypeParams, +} from "./3" + +export const AuthCodeGrantTypeParams = AuthCodeGrantTypeParamsOld.extend({ + clientSecret: z.string().optional(), +}) + +export const HoppRESTAuthOAuth2 = HoppRESTAuthOAuth2Old.extend({ + grantTypeInfo: z.discriminatedUnion("grantType", [ + AuthCodeGrantTypeParams, + ClientCredentialsGrantTypeParams, + PasswordGrantTypeParams, + ImplicitOauthFlowParams, + ]), +}) + +export type HoppRESTAuthOAuth2 = z.infer + +export const HoppRESTAuth = z + .discriminatedUnion("authType", [ + HoppRESTAuthNone, + HoppRESTAuthInherit, + HoppRESTAuthBasic, + HoppRESTAuthBearer, + HoppRESTAuthOAuth2, + HoppRESTAuthAPIKey, + ]) + .and( + z.object({ + authActive: z.boolean(), + }) + ) + +export type HoppRESTAuth = z.infer + +export const V5_SCHEMA = V4_SCHEMA.extend({ + v: z.literal("5"), + auth: HoppRESTAuth, +}) + +export default defineVersion({ + schema: V5_SCHEMA, + initial: false, + up(old: z.infer) { + // v5 is not a breaking change in terms of migrations + // we're just making clientSecret in authcode + pkce flow optional + return { + ...old, + v: "5" as const, + } + }, +})