@redocly/redoc-reef 0.135.0-next.3 → 0.135.0-next.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/dist/api-schemas/search-facets.d.ts +41 -0
- package/dist/api-schemas/search-facets.js +1 -0
- package/dist/api-schemas/search.d.ts +66 -0
- package/dist/api-schemas/search.js +1 -0
- package/dist/client/app/Feedback/useSubmitFeedback.js +1 -1
- package/dist/client/app/UserMenu/useUserMenu.js +1 -1
- package/dist/client/app/pages/DevLogin/DevLogin.js +1 -1
- package/dist/client/app/pages/Invite/Invite.js +1 -1
- package/dist/client/app/search/useAiSearch.js +1 -1
- package/dist/client/app/search/useFacets.js +1 -1
- package/dist/client/app/search/useSearch.js +1 -1
- package/dist/client/app/utils/resolveRouteBySlug.js +1 -1
- package/dist/client/browser-entry.js +2 -2
- package/dist/client/providers/post-message/PostMessageProvider.js +1 -1
- package/dist/client/templates/asyncapi-docs/template.js +1 -1
- package/dist/client/templates/openapi-docs/helpers.js +2 -2
- package/dist/client/templates/openapi-docs/template.js +1 -1
- package/dist/client/types/post-message.d.ts +4 -0
- package/dist/constants/api.d.ts +49 -0
- package/dist/constants/api.js +1 -0
- package/dist/constants/common.d.ts +0 -48
- package/dist/constants/common.js +1 -1
- package/dist/server/config/env-config.d.ts +0 -2
- package/dist/server/config/env-schema.d.ts +0 -5
- package/dist/server/config/env-schemas/server-config.d.ts +0 -3
- package/dist/server/config/env-schemas/server-config.js +1 -1
- package/dist/server/constants/common.d.ts +0 -1
- package/dist/server/constants/common.js +1 -1
- package/dist/server/plugins/graphql-docs/template/GraphQLDocs.js +1 -1
- package/dist/server/plugins/markdown/attribute-resolvers/index.js +1 -1
- package/dist/server/plugins/markdown/attribute-resolvers/resolve-image-gallery.d.ts +4 -0
- package/dist/server/plugins/markdown/attribute-resolvers/resolve-image-gallery.js +1 -0
- package/dist/server/plugins/mcp/auth/auth-handlers.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/core/search.js +1 -1
- package/dist/server/plugins/search/engines/flexsearch/index.d.ts +3 -3
- package/dist/server/plugins/search/engines/flexsearch/index.js +1 -1
- package/dist/server/plugins/search/engines/search-engine.d.ts +3 -3
- package/dist/server/plugins/search/engines/search-engine.js +1 -1
- package/dist/server/plugins/search/engines/typesense/index.d.ts +3 -3
- package/dist/server/plugins/search/engines/typesense/index.js +1 -1
- package/dist/server/plugins/sitemap/index.js +1 -1
- package/dist/server/types/plugins/search.d.ts +2 -2
- package/dist/server/types/web-server.d.ts +8 -0
- package/dist/server/utils/rbac.js +1 -1
- package/dist/server/web-server/auth.js +3 -3
- package/dist/server/web-server/dev-server.js +1 -1
- package/dist/server/web-server/middleware/jsonValidatorMiddleware.d.ts +336 -0
- package/dist/server/web-server/middleware/jsonValidatorMiddleware.js +1 -0
- package/dist/server/web-server/routes/auth.d.ts +1 -1
- package/dist/server/web-server/routes/auth.js +1 -1
- package/dist/server/web-server/routes/catalog/bff-catalog-related-entities.js +1 -1
- package/dist/server/web-server/routes/catalog/bff-catalog.js +1 -1
- package/dist/server/web-server/routes/catalog/catalog-relations.js +1 -1
- package/dist/server/web-server/routes/catalog/catalog.js +1 -1
- package/dist/server/web-server/routes/cors-proxy.js +1 -1
- package/dist/server/web-server/routes/index.js +1 -1
- package/dist/server/web-server/routes/mcp-routes/mcp-oauth.js +1 -1
- package/dist/server/web-server/routes/mcp-routes/mcp-routes.js +1 -1
- package/dist/server/web-server/routes/page-data.js +1 -1
- package/dist/server/web-server/routes/search.d.ts +5 -3
- package/dist/server/web-server/routes/search.js +1 -1
- package/dist/types/api.d.ts +15 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/utils/auth/build-login-url.js +1 -1
- package/dist/utils/auth/is-auth-route-path.js +1 -1
- package/package.json +10 -9
- package/dist/types/search.d.ts +0 -29
- /package/dist/types/{search.js → api.js} +0 -0
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
import type { ZodSchema } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Same as `zValidator('json', schema)`, but exposes zod error details
|
|
4
|
+
* in the 400 response only in develop mode.
|
|
5
|
+
*/
|
|
6
|
+
export declare function jsonValidatorMiddleware<T extends ZodSchema>(schema: T): import("hono").MiddlewareHandler<import("hono").Env, string, {
|
|
7
|
+
in: (undefined extends (T extends ZodSchema<any, import("zod").ZodTypeDef, any> ? import("zod").input<T> : T extends import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>> ? import("zod/v4").input<T> : never) ? true : false) extends true ? {
|
|
8
|
+
json?: ([T extends ZodSchema<any, import("zod").ZodTypeDef, any> ? import("zod").input<T> : T extends import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>> ? import("zod/v4").input<T> : never] extends [any] ? T extends ZodSchema<any, import("zod").ZodTypeDef, any> ? import("zod").input<T> : T extends import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>> ? import("zod/v4").input<T> : never : [Exclude<T extends ZodSchema<any, import("zod").ZodTypeDef, any> ? import("zod").input<T> : T extends import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>> ? import("zod/v4").input<T> : never, undefined>] extends [never] ? {} : [Exclude<T extends ZodSchema<any, import("zod").ZodTypeDef, any> ? import("zod").input<T> : T extends import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>> ? import("zod/v4").input<T> : never, undefined>] extends [object] ? undefined extends (T extends ZodSchema<any, import("zod").ZodTypeDef, any> ? import("zod").input<T> : T extends import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>> ? import("zod/v4").input<T> : never) ? (((Exclude<T extends ZodSchema<any, import("zod").ZodTypeDef, any> ? import("zod").input<T> : T extends import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>> ? import("zod/v4").input<T> : never, (T extends ZodSchema<any, import("zod").ZodTypeDef, any> ? import("zod").input<T> : T extends import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>> ? import("zod/v4").input<T> : never) & undefined> extends infer T_3 ? { [K in keyof T_3]: ([Exclude<T_3[K], undefined>] extends [string] ? [string & Exclude<T_3[K], undefined>] extends [import("hono/utils/types").UnionToIntersection<string & Exclude<T_3[K], undefined>>] ? false : true : false) extends true ? T_3[K] : ([unknown] extends [T_3[K]] ? false : undefined extends T_3[K] ? true : false) extends true ? T_3[K] : Target extends "form" ? T$1 | T$1[] : Target extends "query" ? string | string[] : Target extends "param" ? string : Target extends "header" ? string : Target extends "cookie" ? string : unknown; } : never) extends infer T_2 ? { [K in keyof T_2]: T_2[K]; } : never) extends infer T_1 ? { [K in keyof T_1]: T_1[K]; } : never) | ((T extends ZodSchema<any, import("zod").ZodTypeDef, any> ? import("zod").input<T> : T extends import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>> ? import("zod/v4").input<T> : never) & undefined) : (((T extends ZodSchema<any, import("zod").ZodTypeDef, any> ? import("zod").input<T> : T extends import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>> ? import("zod/v4").input<T> : never) extends infer T_6 ? { [K in keyof T_6]: ([Exclude<T_6[K], undefined>] extends [string] ? [string & Exclude<T_6[K], undefined>] extends [import("hono/utils/types").UnionToIntersection<string & Exclude<T_6[K], undefined>>] ? false : true : false) extends true ? T_6[K] : ([unknown] extends [T_6[K]] ? false : undefined extends T_6[K] ? true : false) extends true ? T_6[K] : Target extends "form" ? T$1 | T$1[] : Target extends "query" ? string | string[] : Target extends "param" ? string : Target extends "header" ? string : Target extends "cookie" ? string : unknown; } : never) extends infer T_5 ? { [K in keyof T_5]: T_5[K]; } : never) extends infer T_4 ? { [K in keyof T_4]: T_4[K]; } : never : {}) | undefined;
|
|
9
|
+
} : {
|
|
10
|
+
json: [T extends ZodSchema<any, import("zod").ZodTypeDef, any> ? import("zod").input<T> : T extends import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>> ? import("zod/v4").input<T> : never] extends [any] ? T extends ZodSchema<any, import("zod").ZodTypeDef, any> ? import("zod").input<T> : T extends import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>> ? import("zod/v4").input<T> : never : [Exclude<T extends ZodSchema<any, import("zod").ZodTypeDef, any> ? import("zod").input<T> : T extends import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>> ? import("zod/v4").input<T> : never, undefined>] extends [never] ? {} : [Exclude<T extends ZodSchema<any, import("zod").ZodTypeDef, any> ? import("zod").input<T> : T extends import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>> ? import("zod/v4").input<T> : never, undefined>] extends [object] ? undefined extends (T extends ZodSchema<any, import("zod").ZodTypeDef, any> ? import("zod").input<T> : T extends import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>> ? import("zod/v4").input<T> : never) ? (((Exclude<T extends ZodSchema<any, import("zod").ZodTypeDef, any> ? import("zod").input<T> : T extends import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>> ? import("zod/v4").input<T> : never, (T extends ZodSchema<any, import("zod").ZodTypeDef, any> ? import("zod").input<T> : T extends import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>> ? import("zod/v4").input<T> : never) & undefined> extends infer T_3 ? { [K in keyof T_3]: ([Exclude<T_3[K], undefined>] extends [string] ? [string & Exclude<T_3[K], undefined>] extends [import("hono/utils/types").UnionToIntersection<string & Exclude<T_3[K], undefined>>] ? false : true : false) extends true ? T_3[K] : ([unknown] extends [T_3[K]] ? false : undefined extends T_3[K] ? true : false) extends true ? T_3[K] : Target extends "form" ? T$1 | T$1[] : Target extends "query" ? string | string[] : Target extends "param" ? string : Target extends "header" ? string : Target extends "cookie" ? string : unknown; } : never) extends infer T_2 ? { [K in keyof T_2]: T_2[K]; } : never) extends infer T_1 ? { [K in keyof T_1]: T_1[K]; } : never) | ((T extends ZodSchema<any, import("zod").ZodTypeDef, any> ? import("zod").input<T> : T extends import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>> ? import("zod/v4").input<T> : never) & undefined) : (((T extends ZodSchema<any, import("zod").ZodTypeDef, any> ? import("zod").input<T> : T extends import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>> ? import("zod/v4").input<T> : never) extends infer T_6 ? { [K in keyof T_6]: ([Exclude<T_6[K], undefined>] extends [string] ? [string & Exclude<T_6[K], undefined>] extends [import("hono/utils/types").UnionToIntersection<string & Exclude<T_6[K], undefined>>] ? false : true : false) extends true ? T_6[K] : ([unknown] extends [T_6[K]] ? false : undefined extends T_6[K] ? true : false) extends true ? T_6[K] : Target extends "form" ? T$1 | T$1[] : Target extends "query" ? string | string[] : Target extends "param" ? string : Target extends "header" ? string : Target extends "cookie" ? string : unknown; } : never) extends infer T_5 ? { [K in keyof T_5]: T_5[K]; } : never) extends infer T_4 ? { [K in keyof T_4]: T_4[K]; } : never : {};
|
|
11
|
+
};
|
|
12
|
+
out: {
|
|
13
|
+
json: T extends ZodSchema<any, import("zod").ZodTypeDef, any> ? import("zod").output<T> : T extends import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>> ? import("zod/v4").output<T> : never;
|
|
14
|
+
};
|
|
15
|
+
}, (Response & import("hono").TypedResponse<"Bad Request", 400, "text">) | (Response & import("hono").TypedResponse<{
|
|
16
|
+
success: boolean;
|
|
17
|
+
error: ({
|
|
18
|
+
path: (string | number)[];
|
|
19
|
+
message: string;
|
|
20
|
+
code: "custom";
|
|
21
|
+
params?: {
|
|
22
|
+
[x: string]: any;
|
|
23
|
+
} | undefined;
|
|
24
|
+
fatal?: boolean | undefined;
|
|
25
|
+
} | {
|
|
26
|
+
path: (string | number)[];
|
|
27
|
+
message: string;
|
|
28
|
+
code: "invalid_arguments";
|
|
29
|
+
argumentsError: {
|
|
30
|
+
name: string;
|
|
31
|
+
stack?: string;
|
|
32
|
+
cause?: import("hono/utils/types").JSONValue | undefined;
|
|
33
|
+
issues: ({
|
|
34
|
+
path: (string | number)[];
|
|
35
|
+
message: string;
|
|
36
|
+
code: "custom";
|
|
37
|
+
params?: {
|
|
38
|
+
[x: string]: any;
|
|
39
|
+
} | undefined;
|
|
40
|
+
fatal?: boolean | undefined;
|
|
41
|
+
} | /*elided*/ any | {
|
|
42
|
+
path: (string | number)[];
|
|
43
|
+
message: string;
|
|
44
|
+
code: "invalid_date";
|
|
45
|
+
fatal?: boolean | undefined;
|
|
46
|
+
} | {
|
|
47
|
+
path: (string | number)[];
|
|
48
|
+
message: string;
|
|
49
|
+
received: string | number;
|
|
50
|
+
code: "invalid_enum_value";
|
|
51
|
+
options: (string | number)[];
|
|
52
|
+
fatal?: boolean | undefined;
|
|
53
|
+
} | {
|
|
54
|
+
path: (string | number)[];
|
|
55
|
+
message: string;
|
|
56
|
+
code: "invalid_intersection_types";
|
|
57
|
+
fatal?: boolean | undefined;
|
|
58
|
+
} | {
|
|
59
|
+
path: (string | number)[];
|
|
60
|
+
message: string;
|
|
61
|
+
code: "invalid_literal";
|
|
62
|
+
expected: import("hono/utils/types").JSONValue;
|
|
63
|
+
received: import("hono/utils/types").JSONValue;
|
|
64
|
+
fatal?: boolean | undefined;
|
|
65
|
+
} | {
|
|
66
|
+
path: (string | number)[];
|
|
67
|
+
message: string;
|
|
68
|
+
code: "invalid_return_type";
|
|
69
|
+
returnTypeError: /*elided*/ any;
|
|
70
|
+
fatal?: boolean | undefined;
|
|
71
|
+
} | {
|
|
72
|
+
path: (string | number)[];
|
|
73
|
+
message: string;
|
|
74
|
+
code: "invalid_string";
|
|
75
|
+
validation: import("zod").StringValidation;
|
|
76
|
+
fatal?: boolean | undefined;
|
|
77
|
+
} | {
|
|
78
|
+
path: (string | number)[];
|
|
79
|
+
message: string;
|
|
80
|
+
code: "invalid_type";
|
|
81
|
+
expected: import("zod").ZodParsedType;
|
|
82
|
+
received: import("zod").ZodParsedType;
|
|
83
|
+
fatal?: boolean | undefined;
|
|
84
|
+
} | {
|
|
85
|
+
path: (string | number)[];
|
|
86
|
+
message: string;
|
|
87
|
+
code: "invalid_union_discriminator";
|
|
88
|
+
options: (string | number | boolean | null)[];
|
|
89
|
+
fatal?: boolean | undefined;
|
|
90
|
+
} | {
|
|
91
|
+
path: (string | number)[];
|
|
92
|
+
message: string;
|
|
93
|
+
code: "invalid_union";
|
|
94
|
+
unionErrors: /*elided*/ any[];
|
|
95
|
+
fatal?: boolean | undefined;
|
|
96
|
+
} | {
|
|
97
|
+
path: (string | number)[];
|
|
98
|
+
message: string;
|
|
99
|
+
code: "not_finite";
|
|
100
|
+
fatal?: boolean | undefined;
|
|
101
|
+
} | {
|
|
102
|
+
path: (string | number)[];
|
|
103
|
+
message: string;
|
|
104
|
+
code: "not_multiple_of";
|
|
105
|
+
multipleOf: number;
|
|
106
|
+
fatal?: boolean | undefined;
|
|
107
|
+
} | {
|
|
108
|
+
path: (string | number)[];
|
|
109
|
+
message: string;
|
|
110
|
+
code: "too_big";
|
|
111
|
+
maximum: number;
|
|
112
|
+
inclusive: boolean;
|
|
113
|
+
exact?: boolean;
|
|
114
|
+
type: "array" | "string" | "number" | "set" | "date" | "bigint";
|
|
115
|
+
fatal?: boolean | undefined;
|
|
116
|
+
} | {
|
|
117
|
+
path: (string | number)[];
|
|
118
|
+
message: string;
|
|
119
|
+
code: "too_small";
|
|
120
|
+
minimum: number;
|
|
121
|
+
inclusive: boolean;
|
|
122
|
+
exact?: boolean;
|
|
123
|
+
type: "array" | "string" | "number" | "set" | "date" | "bigint";
|
|
124
|
+
fatal?: boolean | undefined;
|
|
125
|
+
} | {
|
|
126
|
+
path: (string | number)[];
|
|
127
|
+
message: string;
|
|
128
|
+
code: "unrecognized_keys";
|
|
129
|
+
keys: string[];
|
|
130
|
+
fatal?: boolean | undefined;
|
|
131
|
+
})[];
|
|
132
|
+
readonly errors: ({
|
|
133
|
+
path: (string | number)[];
|
|
134
|
+
message: string;
|
|
135
|
+
code: "custom";
|
|
136
|
+
params?: {
|
|
137
|
+
[x: string]: any;
|
|
138
|
+
} | undefined;
|
|
139
|
+
fatal?: boolean | undefined;
|
|
140
|
+
} | /*elided*/ any | {
|
|
141
|
+
path: (string | number)[];
|
|
142
|
+
message: string;
|
|
143
|
+
code: "invalid_date";
|
|
144
|
+
fatal?: boolean | undefined;
|
|
145
|
+
} | {
|
|
146
|
+
path: (string | number)[];
|
|
147
|
+
message: string;
|
|
148
|
+
received: string | number;
|
|
149
|
+
code: "invalid_enum_value";
|
|
150
|
+
options: (string | number)[];
|
|
151
|
+
fatal?: boolean | undefined;
|
|
152
|
+
} | {
|
|
153
|
+
path: (string | number)[];
|
|
154
|
+
message: string;
|
|
155
|
+
code: "invalid_intersection_types";
|
|
156
|
+
fatal?: boolean | undefined;
|
|
157
|
+
} | {
|
|
158
|
+
path: (string | number)[];
|
|
159
|
+
message: string;
|
|
160
|
+
code: "invalid_literal";
|
|
161
|
+
expected: import("hono/utils/types").JSONValue;
|
|
162
|
+
received: import("hono/utils/types").JSONValue;
|
|
163
|
+
fatal?: boolean | undefined;
|
|
164
|
+
} | {
|
|
165
|
+
path: (string | number)[];
|
|
166
|
+
message: string;
|
|
167
|
+
code: "invalid_return_type";
|
|
168
|
+
returnTypeError: any;
|
|
169
|
+
fatal?: boolean | undefined;
|
|
170
|
+
} | {
|
|
171
|
+
path: (string | number)[];
|
|
172
|
+
message: string;
|
|
173
|
+
code: "invalid_string";
|
|
174
|
+
validation: import("zod").StringValidation;
|
|
175
|
+
fatal?: boolean | undefined;
|
|
176
|
+
} | {
|
|
177
|
+
path: (string | number)[];
|
|
178
|
+
message: string;
|
|
179
|
+
code: "invalid_type";
|
|
180
|
+
expected: import("zod").ZodParsedType;
|
|
181
|
+
received: import("zod").ZodParsedType;
|
|
182
|
+
fatal?: boolean | undefined;
|
|
183
|
+
} | {
|
|
184
|
+
path: (string | number)[];
|
|
185
|
+
message: string;
|
|
186
|
+
code: "invalid_union_discriminator";
|
|
187
|
+
options: (string | number | boolean | null)[];
|
|
188
|
+
fatal?: boolean | undefined;
|
|
189
|
+
} | {
|
|
190
|
+
path: (string | number)[];
|
|
191
|
+
message: string;
|
|
192
|
+
code: "invalid_union";
|
|
193
|
+
unionErrors: any[];
|
|
194
|
+
fatal?: boolean | undefined;
|
|
195
|
+
} | {
|
|
196
|
+
path: (string | number)[];
|
|
197
|
+
message: string;
|
|
198
|
+
code: "not_finite";
|
|
199
|
+
fatal?: boolean | undefined;
|
|
200
|
+
} | {
|
|
201
|
+
path: (string | number)[];
|
|
202
|
+
message: string;
|
|
203
|
+
code: "not_multiple_of";
|
|
204
|
+
multipleOf: number;
|
|
205
|
+
fatal?: boolean | undefined;
|
|
206
|
+
} | {
|
|
207
|
+
path: (string | number)[];
|
|
208
|
+
message: string;
|
|
209
|
+
code: "too_big";
|
|
210
|
+
maximum: number;
|
|
211
|
+
inclusive: boolean;
|
|
212
|
+
exact?: boolean;
|
|
213
|
+
type: "array" | "string" | "number" | "set" | "date" | "bigint";
|
|
214
|
+
fatal?: boolean | undefined;
|
|
215
|
+
} | {
|
|
216
|
+
path: (string | number)[];
|
|
217
|
+
message: string;
|
|
218
|
+
code: "too_small";
|
|
219
|
+
minimum: number;
|
|
220
|
+
inclusive: boolean;
|
|
221
|
+
exact?: boolean;
|
|
222
|
+
type: "array" | "string" | "number" | "set" | "date" | "bigint";
|
|
223
|
+
fatal?: boolean | undefined;
|
|
224
|
+
} | {
|
|
225
|
+
path: (string | number)[];
|
|
226
|
+
message: string;
|
|
227
|
+
code: "unrecognized_keys";
|
|
228
|
+
keys: string[];
|
|
229
|
+
fatal?: boolean | undefined;
|
|
230
|
+
})[];
|
|
231
|
+
readonly message: string;
|
|
232
|
+
readonly isEmpty: boolean;
|
|
233
|
+
addIssue: never;
|
|
234
|
+
addIssues: never;
|
|
235
|
+
readonly formErrors: {
|
|
236
|
+
formErrors: string[];
|
|
237
|
+
fieldErrors: {
|
|
238
|
+
[x: string]: string[] | undefined;
|
|
239
|
+
[x: number]: string[] | undefined;
|
|
240
|
+
};
|
|
241
|
+
};
|
|
242
|
+
};
|
|
243
|
+
fatal?: boolean | undefined;
|
|
244
|
+
} | {
|
|
245
|
+
path: (string | number)[];
|
|
246
|
+
message: string;
|
|
247
|
+
code: "invalid_date";
|
|
248
|
+
fatal?: boolean | undefined;
|
|
249
|
+
} | {
|
|
250
|
+
path: (string | number)[];
|
|
251
|
+
message: string;
|
|
252
|
+
received: string | number;
|
|
253
|
+
code: "invalid_enum_value";
|
|
254
|
+
options: (string | number)[];
|
|
255
|
+
fatal?: boolean | undefined;
|
|
256
|
+
} | {
|
|
257
|
+
path: (string | number)[];
|
|
258
|
+
message: string;
|
|
259
|
+
code: "invalid_intersection_types";
|
|
260
|
+
fatal?: boolean | undefined;
|
|
261
|
+
} | {
|
|
262
|
+
path: (string | number)[];
|
|
263
|
+
message: string;
|
|
264
|
+
code: "invalid_literal";
|
|
265
|
+
expected: import("hono/utils/types").JSONValue;
|
|
266
|
+
received: import("hono/utils/types").JSONValue;
|
|
267
|
+
fatal?: boolean | undefined;
|
|
268
|
+
} | {
|
|
269
|
+
path: (string | number)[];
|
|
270
|
+
message: string;
|
|
271
|
+
code: "invalid_return_type";
|
|
272
|
+
returnTypeError: any;
|
|
273
|
+
fatal?: boolean | undefined;
|
|
274
|
+
} | {
|
|
275
|
+
path: (string | number)[];
|
|
276
|
+
message: string;
|
|
277
|
+
code: "invalid_string";
|
|
278
|
+
validation: import("zod").StringValidation;
|
|
279
|
+
fatal?: boolean | undefined;
|
|
280
|
+
} | {
|
|
281
|
+
path: (string | number)[];
|
|
282
|
+
message: string;
|
|
283
|
+
code: "invalid_type";
|
|
284
|
+
expected: import("zod").ZodParsedType;
|
|
285
|
+
received: import("zod").ZodParsedType;
|
|
286
|
+
fatal?: boolean | undefined;
|
|
287
|
+
} | {
|
|
288
|
+
path: (string | number)[];
|
|
289
|
+
message: string;
|
|
290
|
+
code: "invalid_union_discriminator";
|
|
291
|
+
options: (string | number | boolean | null)[];
|
|
292
|
+
fatal?: boolean | undefined;
|
|
293
|
+
} | {
|
|
294
|
+
path: (string | number)[];
|
|
295
|
+
message: string;
|
|
296
|
+
code: "invalid_union";
|
|
297
|
+
unionErrors: any[];
|
|
298
|
+
fatal?: boolean | undefined;
|
|
299
|
+
} | {
|
|
300
|
+
path: (string | number)[];
|
|
301
|
+
message: string;
|
|
302
|
+
code: "not_finite";
|
|
303
|
+
fatal?: boolean | undefined;
|
|
304
|
+
} | {
|
|
305
|
+
path: (string | number)[];
|
|
306
|
+
message: string;
|
|
307
|
+
code: "not_multiple_of";
|
|
308
|
+
multipleOf: number;
|
|
309
|
+
fatal?: boolean | undefined;
|
|
310
|
+
} | {
|
|
311
|
+
path: (string | number)[];
|
|
312
|
+
message: string;
|
|
313
|
+
code: "too_big";
|
|
314
|
+
maximum: number;
|
|
315
|
+
inclusive: boolean;
|
|
316
|
+
exact?: boolean;
|
|
317
|
+
type: "array" | "string" | "number" | "set" | "date" | "bigint";
|
|
318
|
+
fatal?: boolean | undefined;
|
|
319
|
+
} | {
|
|
320
|
+
path: (string | number)[];
|
|
321
|
+
message: string;
|
|
322
|
+
code: "too_small";
|
|
323
|
+
minimum: number;
|
|
324
|
+
inclusive: boolean;
|
|
325
|
+
exact?: boolean;
|
|
326
|
+
type: "array" | "string" | "number" | "set" | "date" | "bigint";
|
|
327
|
+
fatal?: boolean | undefined;
|
|
328
|
+
} | {
|
|
329
|
+
path: (string | number)[];
|
|
330
|
+
message: string;
|
|
331
|
+
code: "unrecognized_keys";
|
|
332
|
+
keys: string[];
|
|
333
|
+
fatal?: boolean | undefined;
|
|
334
|
+
})[];
|
|
335
|
+
}, 400, "json">)>;
|
|
336
|
+
//# sourceMappingURL=jsonValidatorMiddleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{zValidator as s}from"@hono/zod-validator";import{envConfig as i}from"../../config/env-config.js";function a(o){return s("json",o,(e,r)=>{if(!e.success)return i.isDevelopMode?r.json({success:!1,error:e.error.issues},400):r.text("Bad Request",400)})}export{a as jsonValidatorMiddleware};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Context, Handler } from 'hono';
|
|
2
2
|
import type { Store } from '../../store.js';
|
|
3
|
-
import { ServerRoutes } from '../../../constants/
|
|
3
|
+
import { ServerRoutes } from '../../../constants/api.js';
|
|
4
4
|
export declare function authorizeHandler(ctx: Context): Promise<Response>;
|
|
5
5
|
export declare function redoclyLoginCallbackHandler(): Handler;
|
|
6
6
|
export declare function oidcCallbackHandler(store: Store): Handler;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{setCookie as y,deleteCookie as X}from"hono/cookie";import{AuthProviderType as W}from"@redocly/config";import{withPathPrefix as L,getPathPrefix as O}from"@redocly/theme/core/utils";import{compareURIs as Y}from"../../../utils/url/compare-uris.js";import{ensureArray as b}from"../../../utils/array/ensure-array.js";import{ALTERNATIVE_AUD_CLAIM_NAME as N,JWT_SECRET_KEY as v,ORG_SLUG as Q,ORG_ID as x}from"../../constants/common.js";import{AUTH_SEGMENT as ee,AuthCookieNames as A,DEFAULT_COOKIE_EXPIRATION as F,ServerRoutes as S}from"../../../constants/common.js";import{sanitizeRedirectPathname as H}from"../../../utils/url/sanitize-redirect-pathname.js";import{telemetry as T}from"../../telemetry/index.js";import{envConfig as B}from"../../config/env-config.js";import{clearAuthCookies as j}from"../../utils/cookie.js";import{getAuthProviderLoginParams as re,isOidcProviderConfig as $,isSaml2ProviderConfig as oe,oidcExchangeCodeForToken as ne,buildLoginUrl as te,decodeSamlResponse as se,extractUserClaims as ie,parseSamlResponse as ae,parseOidcState as de,verifySAMLResponse as ce,getUsernameFromPayload as le,buildOidcLogoutUrl as ue,getOidcMetadata as K,getRedoclyTokenPayload as pe,isRedoclySso as ge,rewritePreviewAuthRedirectUri as fe,parsePreviewBranch as z,buildOidcLoginUrl as me,createMcpSessionResource as D}from"../auth.js";import*as k from"../jwt/jwt.js";import{AlgorithmTypes as U}from"../jwt/types.js";import{handleErrorPageRender as he}from"../utils.js";import{encodeBase64URL as Ie}from"../jwt/encode.js";import{resolveUiLocalesForIdpLogin as we}from"./helpers/resolve-ui-locales-for-idp-login.js";async function Ee(s){if(B.isProductionEnv)return s.newResponse(null,404,{});const{password:e,...r}=await s.req.json(),a=await k.sign({...r,name:r.username||r.email||"Unknown"},v,U.HS256);return y(s,A.AUTHORIZATION,a,{path:O()||"/",httpOnly:!0,secure:!0,sameSite:"none"}),s.newResponse(null,200,{})}function be(){return async s=>{const e=s.get("logger"),r=encodeURIComponent(s.req.query("message")||"");e.error(`Login error: ${r}`);const a=`${S.LOGIN}/?error=${encodeURIComponent(r)}`;return s.newResponse(null,301,{Location:a})}}function G(s){if(!s||!s.includes(S.MCP_CALLBACK))return null;try{const e=s.split("/"),r=e[e.length-1];if(r){const a=Buffer.from(r,"base64url").toString("utf-8");return JSON.parse(a).mcpSessionId||null}}catch{}return null}function qe(s){return async e=>{const r=e.get("logger"),a=s.getConfig().ssoDirect,o=de(e.req.query("state")),m=o.idpId,t=o.source==="mcp"||o.redirectTo&&typeof o.redirectTo=="string"&&o.redirectTo.includes(S.MCP_CALLBACK),c=t?G(typeof o.redirectTo=="string"?o.redirectTo:void 0):null,i=a?.[m];if(!$(i))return r.error("OIDC login error: missing OIDC provider config"),e.text("Forbidden",403);const d=await K(m,i);if(a&&!d.token_endpoint){const p="Invalid OIDC configuration: token_endpoint is required";return r.error(`OIDC login error: ${p}`),e.text(p,500)}try{const p=d.token_endpoint,u=e.req.query("code"),h=e.req.query("error");if(h)return t&&T.sendMcpAuthorizationFailedMessage([{...D(c),error:`OIDC error: ${h}`,error_details:e.req.query("error_description")||null}]),he(e,s,{slug:"/"},403,"403OIDC");if(!u){const w="Code is expected but not present";return r.error(`OIDC login error: ${w}`),t&&T.sendMcpAuthorizationFailedMessage([{...D(c),error:w,error_details:null}]),new Response(`Forbidden: ${w}`,{status:403})}const R=typeof o.redirectUri=="string"?o.redirectUri:new URL(L(S.OIDC_CALLBACK),e.req.url).toString(),I=e.get("cookies")?.code_verifier,l=await ne(p,u,R,i,{...i.tokenRequestCustomParams,...I?{code_verifier:I}:{}});if(l.error)return r.error(`Error from OIDC provider: "${l.error}"`),t&&T.sendMcpAuthorizationFailedMessage([{...D(c),error:`Token exchange error: ${l.error}`,error_details:l.error_description||null}]),e.text(`Forbidden: ${l.error_description||l.error}`,403);if(!l?.id_token){const w="No id_token, please, add openid to scopes";return r.error(`OIDC login error: ${w}`),t&&T.sendMcpAuthorizationFailedMessage([{...D(c),error:w,error_details:null}]),new Response(`Forbidden: ${w}`,{status:403})}const{payload:f,header:M}=k.decode(l.id_token),n=M.alg===U.RS256;if(i.audience?.length&&![...b(f.aud||[]),...b(f[N]||[])].some(_=>i.audience?.includes(_))){const _="No valid audience found in id_token";return r.error(`OIDC login error: ${_}`),t&&T.sendMcpAuthorizationFailedMessage([{...D(c),error:_,error_details:null}]),new Response(`Forbidden: ${_}`)}const g=n?l.id_token:await k.sign({...f,idpId:m},v,U.HS256);le(f)||r.warn("To display your username, the required 'email' or 'full_profile' scope must be added to the identity provider configuration");const P=i?.tokenExpirationTime?Date.now()+i.tokenExpirationTime*1e3:f.exp*1e3||Date.now()+F*1e3;if(i.introspectEndpoint){const w=await fetch(i.introspectEndpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({access_token:l.access_token})});if(w.ok){const E=(await w.json()).ext?.federatedIdentity;E&&(y(e,A.FEDERATED_ACCESS_TOKEN,E.access_token||"",{path:O()||"/",httpOnly:!1,expires:new Date(P)}),y(e,A.FEDERATED_ID_TOKEN,E.id_token||"",{path:O()||"/",httpOnly:!1,expires:new Date(P)}))}else r.warn(`OIDC introspect error: ${w.statusText}`)}if(y(e,A.AUTHORIZATION,g,{path:O()||"/",httpOnly:!0,expires:new Date(P)}),g!==l.id_token&&y(e,A.IDP_ID_TOKEN,l.id_token||"",{path:O()||"/",httpOnly:!0,expires:new Date(P)}),y(e,A.IDP_ACCESS_TOKEN,l.access_token||"",{path:O()||"/",httpOnly:!0,expires:new Date(P)}),X(e,"code_verifier",{path:O()||"/"}),t&&o.redirectTo&&typeof o.redirectTo=="string"&&o.redirectTo.includes(S.MCP_CALLBACK)){const _=`${e.req.url.split("?")[0].replace(S.OIDC_CALLBACK,"")}${o.redirectTo}`;return e.newResponse(null,302,{Location:_})}const J=typeof o.redirectTo=="string"?o.redirectTo:void 0;let Z=H(new URL(J||"/",e.req.url).pathname);const V=e.newResponse(null,302,{Location:Z});return r.updateContext({email:f.email,subject:f.sub}),r.info("OIDC login successful"),V}catch(p){const u=p instanceof Error?p.message:String(p),h=p instanceof Error?p.stack:String(p);if(r.error(`OIDC login error: ${u}`),t&&T.sendMcpAuthorizationFailedMessage([{...D(c),error:u,error_details:h}]),p.error==="access_denied")return r.info("Access denied"),e.text("Forbidden",403)}const C="Something went wrong";return r.error(`OIDC login error: ${C}`),t&&T.sendMcpAuthorizationFailedMessage([{...D(c),error:C,error_details:null}]),e.text(C,500)}}function Ne(s){return async e=>{const r=e.get("logger"),o=e.get("auth").claims?.idpId,t=s.getConfig().ssoDirect?.[o];if(e.req.method==="POST")return $(t)||j(e),r.info("Logout successful"),e.newResponse(null,200,{});let c;if($(t)){const i=(await K(o,t)).end_session_endpoint;if(i){const d=new URL(e.req.url),C=e.req.header("x-forwarded-proto")||d.protocol.slice(0,-1)||"https",p=e.req.header("x-forwarded-host")||d.host,u=`${C}://${p}`,h=z(u),R=h?Ie(JSON.stringify({branch:z(u)})):void 0,I=h?`${fe(u)}/${ee}/logout`:`${u}${L(S.POST_LOGOUT)}`;c=ue(i,I,e.get("cookies")?.[A.IDP_ID_TOKEN]||e.get("cookies")?.[A.AUTHORIZATION]||"",R)}}return r.info("Logout successful"),j(e),e.newResponse(null,302,{Location:c||L("/")})}}function Fe(s){return async e=>{const r=s.getConfig().access?.logoutReturnUrl,a=r||L("/");return e.newResponse(null,302,{Location:a})}}function He(s){return async e=>{const r=e.get("logger"),a=e.req.param("code"),o=B.BH_API_URL,m=(t,c,i)=>t&&c?`${t} ${c.charAt(0)}`:i;try{if(!o)throw new Error("BH_API_URL is not set");const t=s.getConfig().ssoDirect;if(!t||!Object.keys(t).length)return r.warn("Invite no sso configured to handle"),e.redirect(L("/"));const c=await fetch(`${o}/user-invites/public/${a}`);if(!c.ok)return c.status===404?(r.warn(`Invite ${a} not found redirect to homepage`),e.redirect(L("/"))):(r.error("Invite error",await c.text()),e.redirect(L("/")));const i=await c.json(),d=new URL(L("/invite"),e.req.url);return d.searchParams.set("code",a),d.searchParams.set("org",i.organization.name),d.searchParams.set("invitedBy",m(i.invitedBy.firstName,i.invitedBy.lastName,i.invitedBy.name)),e.newResponse(null,302,{Location:d.toString()})}catch(t){return r.error("Error processing invite",{error:t,inviteCode:a}),e.text(t.message||"Failed to process invite",400)}}}function Be(s){return async e=>{const r=e.get("logger"),a=s.getConfig().ssoDirect,o=new URL(e.req.url),m=e.req.query("inviteCode"),t=e.req.header("x-forwarded-proto")||o.protocol.slice(0,-1)||"https",c=e.req.header("x-forwarded-host")||o.host,i=`${t}://${c}`;let d=o.searchParams.get("idpId");const C=o.searchParams.get("redirectTo"),p=Object.keys(a||{})[0];d=d||p;const u=o.searchParams.get("mcp_redirect_uri"),h=!!u;if(!a?.[d]){const g="Invalid idpId";if(r.error(`IdP login error: ${g}`),h){const q=G(C||void 0);T.sendMcpAuthorizationFailedMessage([{...D(q),error:g,error_details:null}])}return e.text(`Forbidden: ${g}`,403)}const I=we({localePrefixParam:o.searchParams.get("localePrefix"),l10n:s.getGlobalData()?.l10n}),l=d&&a?await re(d,a[d]):void 0,f={};for(const g of Object.keys(l?.extraParams||{}))f[g]=o.searchParams.get(g)||l?.extraParams?.[g]||void 0;let M,n={};if(h&&u&&l&&l.type===W.OIDC){r.info(`Building MCP OAuth login URL with redirect_uri: ${u}`);const g=me("",{...l,extraParams:f},C,m,{redirectUriOverride:u,sourceOverride:"mcp",branchOverride:void 0,uiLocales:I});M=g.loginUrl,n=g.cookies||{}}else if(l){const g=te({...l,extraParams:f},i,C,m,I);M=g.loginUrl,n=g.cookies||{}}return Object.keys(n).forEach(g=>{y(e,g,n[g].value,n[g].options)}),r.info(`IdP login initiated for ID '${d}'`),e.newResponse(null,302,{Location:M||new URL(e.req.url).pathname})}}function je(s){return async e=>{const r=e.get("logger"),a=await e.req.formData(),o=a.get("SAMLResponse"),m=a.get("RelayState");if(typeof o!="string"||typeof m!="string"){const n="SAMLResponse is required";return r.error(`SAML2 login error: ${n}`),e.text(`Bad request: ${n}`,400)}const t=se(o),{success:c,uid:i,nameFormat:d,attrs:C,issuerId:p,expiresAt:u}=ae(t),{idpId:h,redirectTo:R}=JSON.parse(m);if(!c){const n="SAML2 assertion is not successful";return r.error(`SAML2 login error: ${n}`),e.text(`Permission denied: ${n}`,401)}if(!u||Math.ceil(Date.now()/1e3)>=u){const n="SAML2 Token Expired";return r.error(`SAML2 login error: ${n}`),e.text(n,401)}const I=s.getConfig().ssoDirect?.[h];if(!I||!oe(I)){const n="Cannot find valid IdP";return r.error(`SAML2 login error: ${n}`),e.text(`Permission denied: ${n}`,401)}if(!(I.issuerId&&p&&Y(I.issuerId,p))){const n="IssuerID is misconfigured or untrusted assertions issuer received";return r.error(`SAML2 login error: ${n}`),e.text(`Permission denied: ${n}`,401)}if(!await ce(t,I.x509PublicCert)){const n="SAMLResponse signature invalid";return r.error(`SAML2 login error: ${n}`),e.text(n,401)}const f=ie(i,d,C,I.teamsAttributeName);if(!f.sub){const n="The provider did not return a valid user identity.";return r.error(`SAML2 login error: ${n}`),e.text(n,400)}if(!f.email){const n="The provider did not return a valid user email.";return r.error(`SAML2 login error: ${n}`),e.text(n,400)}const M=await k.sign({...f,idpId:h},v,U.HS256);return y(e,A.AUTHORIZATION,M,{path:O()||"/",httpOnly:!0,expires:new Date(u*1e3)}),r.updateContext({email:f.email,subject:f.sub}),r.info("SAML2 login successful"),e.newResponse(null,302,{Location:R||"/"})}}function Ke(s){return async e=>{const r=e.get("logger"),a=new URL(e.req.query("redirectTo")||"/",e.req.url),o=L(H(a.pathname)),m=s.getConfig().ssoDirect,t=Object.entries(m||{}).find(([,R])=>$(R)&&ge(R));if(!(m&&t))return e.newResponse(null,302,{Location:o});const i=e.req.query("token"),d=i&&await pe(i);if(!d)return e.newResponse(null,302,{Location:o});if(!b(d[N]||[]).some(R=>R===Q||R===x))return e.newResponse(null,302,{Location:o});const u=await k.sign({...d,idpId:t?.at(0)},v,U.HS256),h=Date.now()+F*1e3;return y(e,A.AUTHORIZATION,u,{path:O()||"/",httpOnly:!0,expires:new Date(h),sameSite:"None",secure:!0}),r.info("Token login successful"),e.newResponse(null,302,{Location:o})}}export{Ee as authorizeHandler,Be as idpLoginHandler,He as inviteHandler,Ne as logoutHandler,qe as oidcCallbackHandler,Fe as postLogoutHandler,be as redoclyLoginCallbackHandler,Ke as redoclyTokenLoginHandler,je as samlCallbackHandler};
|
|
1
|
+
import{setCookie as y,deleteCookie as X}from"hono/cookie";import{AuthProviderType as W}from"@redocly/config";import{withPathPrefix as L,getPathPrefix as O}from"@redocly/theme/core/utils";import{compareURIs as Y}from"../../../utils/url/compare-uris.js";import{ensureArray as b}from"../../../utils/array/ensure-array.js";import{ALTERNATIVE_AUD_CLAIM_NAME as N,JWT_SECRET_KEY as v,ORG_SLUG as Q,ORG_ID as x}from"../../constants/common.js";import{AUTH_SEGMENT as ee,ServerRoutes as S}from"../../../constants/api.js";import{AuthCookieNames as A,DEFAULT_COOKIE_EXPIRATION as F}from"../../../constants/common.js";import{sanitizeRedirectPathname as H}from"../../../utils/url/sanitize-redirect-pathname.js";import{telemetry as T}from"../../telemetry/index.js";import{envConfig as B}from"../../config/env-config.js";import{clearAuthCookies as j}from"../../utils/cookie.js";import{getAuthProviderLoginParams as re,isOidcProviderConfig as $,isSaml2ProviderConfig as oe,oidcExchangeCodeForToken as ne,buildLoginUrl as te,decodeSamlResponse as se,extractUserClaims as ie,parseSamlResponse as ae,parseOidcState as de,verifySAMLResponse as ce,getUsernameFromPayload as le,buildOidcLogoutUrl as ue,getOidcMetadata as K,getRedoclyTokenPayload as pe,isRedoclySso as ge,rewritePreviewAuthRedirectUri as fe,parsePreviewBranch as z,buildOidcLoginUrl as me,createMcpSessionResource as D}from"../auth.js";import*as k from"../jwt/jwt.js";import{AlgorithmTypes as U}from"../jwt/types.js";import{handleErrorPageRender as he}from"../utils.js";import{encodeBase64URL as Ie}from"../jwt/encode.js";import{resolveUiLocalesForIdpLogin as we}from"./helpers/resolve-ui-locales-for-idp-login.js";async function be(s){if(B.isProductionEnv)return s.newResponse(null,404,{});const{password:e,...r}=await s.req.json(),a=await k.sign({...r,name:r.username||r.email||"Unknown"},v,U.HS256);return y(s,A.AUTHORIZATION,a,{path:O()||"/",httpOnly:!0,secure:!0,sameSite:"none"}),s.newResponse(null,200,{})}function qe(){return async s=>{const e=s.get("logger"),r=encodeURIComponent(s.req.query("message")||"");e.error(`Login error: ${r}`);const a=`${S.LOGIN}/?error=${encodeURIComponent(r)}`;return s.newResponse(null,301,{Location:a})}}function G(s){if(!s||!s.includes(S.MCP_CALLBACK))return null;try{const e=s.split("/"),r=e[e.length-1];if(r){const a=Buffer.from(r,"base64url").toString("utf-8");return JSON.parse(a).mcpSessionId||null}}catch{}return null}function Ne(s){return async e=>{const r=e.get("logger"),a=s.getConfig().ssoDirect,o=de(e.req.query("state")),m=o.idpId,t=o.source==="mcp"||o.redirectTo&&typeof o.redirectTo=="string"&&o.redirectTo.includes(S.MCP_CALLBACK),c=t?G(typeof o.redirectTo=="string"?o.redirectTo:void 0):null,i=a?.[m];if(!$(i))return r.error("OIDC login error: missing OIDC provider config"),e.text("Forbidden",403);const d=await K(m,i);if(a&&!d.token_endpoint){const p="Invalid OIDC configuration: token_endpoint is required";return r.error(`OIDC login error: ${p}`),e.text(p,500)}try{const p=d.token_endpoint,u=e.req.query("code"),h=e.req.query("error");if(h)return t&&T.sendMcpAuthorizationFailedMessage([{...D(c),error:`OIDC error: ${h}`,error_details:e.req.query("error_description")||null}]),he(e,s,{slug:"/"},403,"403OIDC");if(!u){const w="Code is expected but not present";return r.error(`OIDC login error: ${w}`),t&&T.sendMcpAuthorizationFailedMessage([{...D(c),error:w,error_details:null}]),new Response(`Forbidden: ${w}`,{status:403})}const R=typeof o.redirectUri=="string"?o.redirectUri:new URL(L(S.OIDC_CALLBACK),e.req.url).toString(),I=e.get("cookies")?.code_verifier,l=await ne(p,u,R,i,{...i.tokenRequestCustomParams,...I?{code_verifier:I}:{}});if(l.error)return r.error(`Error from OIDC provider: "${l.error}"`),t&&T.sendMcpAuthorizationFailedMessage([{...D(c),error:`Token exchange error: ${l.error}`,error_details:l.error_description||null}]),e.text(`Forbidden: ${l.error_description||l.error}`,403);if(!l?.id_token){const w="No id_token, please, add openid to scopes";return r.error(`OIDC login error: ${w}`),t&&T.sendMcpAuthorizationFailedMessage([{...D(c),error:w,error_details:null}]),new Response(`Forbidden: ${w}`,{status:403})}const{payload:f,header:M}=k.decode(l.id_token),n=M.alg===U.RS256;if(i.audience?.length&&![...b(f.aud||[]),...b(f[N]||[])].some(_=>i.audience?.includes(_))){const _="No valid audience found in id_token";return r.error(`OIDC login error: ${_}`),t&&T.sendMcpAuthorizationFailedMessage([{...D(c),error:_,error_details:null}]),new Response(`Forbidden: ${_}`)}const g=n?l.id_token:await k.sign({...f,idpId:m},v,U.HS256);le(f)||r.warn("To display your username, the required 'email' or 'full_profile' scope must be added to the identity provider configuration");const P=i?.tokenExpirationTime?Date.now()+i.tokenExpirationTime*1e3:f.exp*1e3||Date.now()+F*1e3;if(i.introspectEndpoint){const w=await fetch(i.introspectEndpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({access_token:l.access_token})});if(w.ok){const E=(await w.json()).ext?.federatedIdentity;E&&(y(e,A.FEDERATED_ACCESS_TOKEN,E.access_token||"",{path:O()||"/",httpOnly:!1,expires:new Date(P)}),y(e,A.FEDERATED_ID_TOKEN,E.id_token||"",{path:O()||"/",httpOnly:!1,expires:new Date(P)}))}else r.warn(`OIDC introspect error: ${w.statusText}`)}if(y(e,A.AUTHORIZATION,g,{path:O()||"/",httpOnly:!0,expires:new Date(P)}),g!==l.id_token&&y(e,A.IDP_ID_TOKEN,l.id_token||"",{path:O()||"/",httpOnly:!0,expires:new Date(P)}),y(e,A.IDP_ACCESS_TOKEN,l.access_token||"",{path:O()||"/",httpOnly:!0,expires:new Date(P)}),X(e,"code_verifier",{path:O()||"/"}),t&&o.redirectTo&&typeof o.redirectTo=="string"&&o.redirectTo.includes(S.MCP_CALLBACK)){const _=`${e.req.url.split("?")[0].replace(S.OIDC_CALLBACK,"")}${o.redirectTo}`;return e.newResponse(null,302,{Location:_})}const J=typeof o.redirectTo=="string"?o.redirectTo:void 0;let Z=H(new URL(J||"/",e.req.url).pathname);const V=e.newResponse(null,302,{Location:Z});return r.updateContext({email:f.email,subject:f.sub}),r.info("OIDC login successful"),V}catch(p){const u=p instanceof Error?p.message:String(p),h=p instanceof Error?p.stack:String(p);if(r.error(`OIDC login error: ${u}`),t&&T.sendMcpAuthorizationFailedMessage([{...D(c),error:u,error_details:h}]),p.error==="access_denied")return r.info("Access denied"),e.text("Forbidden",403)}const C="Something went wrong";return r.error(`OIDC login error: ${C}`),t&&T.sendMcpAuthorizationFailedMessage([{...D(c),error:C,error_details:null}]),e.text(C,500)}}function Fe(s){return async e=>{const r=e.get("logger"),o=e.get("auth").claims?.idpId,t=s.getConfig().ssoDirect?.[o];if(e.req.method==="POST")return $(t)||j(e),r.info("Logout successful"),e.newResponse(null,200,{});let c;if($(t)){const i=(await K(o,t)).end_session_endpoint;if(i){const d=new URL(e.req.url),C=e.req.header("x-forwarded-proto")||d.protocol.slice(0,-1)||"https",p=e.req.header("x-forwarded-host")||d.host,u=`${C}://${p}`,h=z(u),R=h?Ie(JSON.stringify({branch:z(u)})):void 0,I=h?`${fe(u)}/${ee}/logout`:`${u}${L(S.POST_LOGOUT)}`;c=ue(i,I,e.get("cookies")?.[A.IDP_ID_TOKEN]||e.get("cookies")?.[A.AUTHORIZATION]||"",R)}}return r.info("Logout successful"),j(e),e.newResponse(null,302,{Location:c||L("/")})}}function He(s){return async e=>{const r=s.getConfig().access?.logoutReturnUrl,a=r||L("/");return e.newResponse(null,302,{Location:a})}}function Be(s){return async e=>{const r=e.get("logger"),a=e.req.param("code"),o=B.BH_API_URL,m=(t,c,i)=>t&&c?`${t} ${c.charAt(0)}`:i;try{if(!o)throw new Error("BH_API_URL is not set");const t=s.getConfig().ssoDirect;if(!t||!Object.keys(t).length)return r.warn("Invite no sso configured to handle"),e.redirect(L("/"));const c=await fetch(`${o}/user-invites/public/${a}`);if(!c.ok)return c.status===404?(r.warn(`Invite ${a} not found redirect to homepage`),e.redirect(L("/"))):(r.error("Invite error",await c.text()),e.redirect(L("/")));const i=await c.json(),d=new URL(L("/invite"),e.req.url);return d.searchParams.set("code",a),d.searchParams.set("org",i.organization.name),d.searchParams.set("invitedBy",m(i.invitedBy.firstName,i.invitedBy.lastName,i.invitedBy.name)),e.newResponse(null,302,{Location:d.toString()})}catch(t){return r.error("Error processing invite",{error:t,inviteCode:a}),e.text(t.message||"Failed to process invite",400)}}}function je(s){return async e=>{const r=e.get("logger"),a=s.getConfig().ssoDirect,o=new URL(e.req.url),m=e.req.query("inviteCode"),t=e.req.header("x-forwarded-proto")||o.protocol.slice(0,-1)||"https",c=e.req.header("x-forwarded-host")||o.host,i=`${t}://${c}`;let d=o.searchParams.get("idpId");const C=o.searchParams.get("redirectTo"),p=Object.keys(a||{})[0];d=d||p;const u=o.searchParams.get("mcp_redirect_uri"),h=!!u;if(!a?.[d]){const g="Invalid idpId";if(r.error(`IdP login error: ${g}`),h){const q=G(C||void 0);T.sendMcpAuthorizationFailedMessage([{...D(q),error:g,error_details:null}])}return e.text(`Forbidden: ${g}`,403)}const I=we({localePrefixParam:o.searchParams.get("localePrefix"),l10n:s.getGlobalData()?.l10n}),l=d&&a?await re(d,a[d]):void 0,f={};for(const g of Object.keys(l?.extraParams||{}))f[g]=o.searchParams.get(g)||l?.extraParams?.[g]||void 0;let M,n={};if(h&&u&&l&&l.type===W.OIDC){r.info(`Building MCP OAuth login URL with redirect_uri: ${u}`);const g=me("",{...l,extraParams:f},C,m,{redirectUriOverride:u,sourceOverride:"mcp",branchOverride:void 0,uiLocales:I});M=g.loginUrl,n=g.cookies||{}}else if(l){const g=te({...l,extraParams:f},i,C,m,I);M=g.loginUrl,n=g.cookies||{}}return Object.keys(n).forEach(g=>{y(e,g,n[g].value,n[g].options)}),r.info(`IdP login initiated for ID '${d}'`),e.newResponse(null,302,{Location:M||new URL(e.req.url).pathname})}}function Ke(s){return async e=>{const r=e.get("logger"),a=await e.req.formData(),o=a.get("SAMLResponse"),m=a.get("RelayState");if(typeof o!="string"||typeof m!="string"){const n="SAMLResponse is required";return r.error(`SAML2 login error: ${n}`),e.text(`Bad request: ${n}`,400)}const t=se(o),{success:c,uid:i,nameFormat:d,attrs:C,issuerId:p,expiresAt:u}=ae(t),{idpId:h,redirectTo:R}=JSON.parse(m);if(!c){const n="SAML2 assertion is not successful";return r.error(`SAML2 login error: ${n}`),e.text(`Permission denied: ${n}`,401)}if(!u||Math.ceil(Date.now()/1e3)>=u){const n="SAML2 Token Expired";return r.error(`SAML2 login error: ${n}`),e.text(n,401)}const I=s.getConfig().ssoDirect?.[h];if(!I||!oe(I)){const n="Cannot find valid IdP";return r.error(`SAML2 login error: ${n}`),e.text(`Permission denied: ${n}`,401)}if(!(I.issuerId&&p&&Y(I.issuerId,p))){const n="IssuerID is misconfigured or untrusted assertions issuer received";return r.error(`SAML2 login error: ${n}`),e.text(`Permission denied: ${n}`,401)}if(!await ce(t,I.x509PublicCert)){const n="SAMLResponse signature invalid";return r.error(`SAML2 login error: ${n}`),e.text(n,401)}const f=ie(i,d,C,I.teamsAttributeName);if(!f.sub){const n="The provider did not return a valid user identity.";return r.error(`SAML2 login error: ${n}`),e.text(n,400)}if(!f.email){const n="The provider did not return a valid user email.";return r.error(`SAML2 login error: ${n}`),e.text(n,400)}const M=await k.sign({...f,idpId:h},v,U.HS256);return y(e,A.AUTHORIZATION,M,{path:O()||"/",httpOnly:!0,expires:new Date(u*1e3)}),r.updateContext({email:f.email,subject:f.sub}),r.info("SAML2 login successful"),e.newResponse(null,302,{Location:R||"/"})}}function ze(s){return async e=>{const r=e.get("logger"),a=new URL(e.req.query("redirectTo")||"/",e.req.url),o=L(H(a.pathname)),m=s.getConfig().ssoDirect,t=Object.entries(m||{}).find(([,R])=>$(R)&&ge(R));if(!(m&&t))return e.newResponse(null,302,{Location:o});const i=e.req.query("token"),d=i&&await pe(i);if(!d)return e.newResponse(null,302,{Location:o});if(!b(d[N]||[]).some(R=>R===Q||R===x))return e.newResponse(null,302,{Location:o});const u=await k.sign({...d,idpId:t?.at(0)},v,U.HS256),h=Date.now()+F*1e3;return y(e,A.AUTHORIZATION,u,{path:O()||"/",httpOnly:!0,expires:new Date(h),sameSite:"None",secure:!0}),r.info("Token login successful"),e.newResponse(null,302,{Location:o})}}export{be as authorizeHandler,je as idpLoginHandler,Be as inviteHandler,Fe as logoutHandler,Ne as oidcCallbackHandler,He as postLogoutHandler,qe as redoclyLoginCallbackHandler,ze as redoclyTokenLoginHandler,Ke as samlCallbackHandler};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{telemetryTraceStep as o}from"../../../telemetry/helpers/trace-step.js";import{CATALOG_ENTITY_KEY as d}from"../../../../constants/
|
|
1
|
+
import{telemetryTraceStep as o}from"../../../telemetry/helpers/trace-step.js";import{CATALOG_ENTITY_KEY as d}from"../../../../constants/api.js";import{ALLOWED_CATALOG_QUERY_PARAMS as y}from"../../../constants/plugins/catalog-entities.js";import{allowlistObject as f}from"../../../../utils/object/allowlist-object.js";import{CatalogEntitiesService as g}from"../../../plugins/catalog-entities/database/catalog-entities-service.js";import{createPaginationParamsValidator as E}from"../../../providers/database/pagination/schemas.js";import{ENTITY_RELATION_TO_DATABASE as _}from"../../../plugins/catalog-entities/database/mappers/field-transformations.js";import{getRbacRestrictionsDataForCatalog as A}from"../helpers/get-rbac-restrictions-data-for-catalog.js";const b=["id","key","title","type","summary","source","source_file","created_at","updated_at","relation_type","version","revision"],p=async({catalogEntitiesService:i,store:a,ctx:e})=>o("catalog_entities.bff.related_entities.get_related_entities",async t=>{try{const r=e.req.param(d);if(!r)return t?.error(new Error("Entity key is required")),e.json({message:"Entity key is required"},400);t?.setAttribute("pathParams",JSON.stringify({entityKey:r}));const s=e.req.query();t?.setAttribute("queryParams",JSON.stringify(f(s,y)));const m=E(b,_).parse(s),{currentRbacTeamsForRead:l,excludedTypes:c,excludedEntities:u}=A({store:a,ctx:e}),n=await i.getRelatedEntities({entityKey:r,paginationParams:m,rbacTeams:l,excludedTypes:c,excludedEntities:u});return t?.setAttribute("relatedEntitiesCount",n.items.length),e.json(n)}catch(r){return console.error(r),t?.error(r),e.json({message:r.message},500)}});function v(i){return async a=>o("catalog_entities.bff.related_entities",async e=>{e?.setAttribute("method",a.req.method);const t=await g.getInstance({baseDbDir:i.serverOutDir});return p({catalogEntitiesService:t,ctx:a,store:i})})}export{v as bffCatalogRelatedEntitiesHandler};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{telemetryTraceStep as d}from"../../../telemetry/helpers/trace-step.js";import{CATALOG_ENTITY_KEY as g}from"../../../../constants/
|
|
1
|
+
import{telemetryTraceStep as d}from"../../../telemetry/helpers/trace-step.js";import{CATALOG_ENTITY_KEY as g}from"../../../../constants/api.js";import{ALLOWED_CATALOG_QUERY_PARAMS as p}from"../../../constants/plugins/catalog-entities.js";import{allowlistObject as E}from"../../../../utils/object/allowlist-object.js";import{CatalogEntitiesService as b}from"../../../plugins/catalog-entities/database/catalog-entities-service.js";import{createPaginationParamsValidator as v}from"../../../providers/database/pagination/schemas.js";import{isValidIsoDate as q}from"../../../utils/is-valid-iso-date.js";import{isValidSanitizedString as A}from"../../../utils/validate-and-sanitize-string.js";import{getRbacRestrictionsDataForCatalog as l}from"../helpers/get-rbac-restrictions-data-for-catalog.js";const _=["type","key","title","summary","tags","metadata","metadata.*","git","contact","links","id","source","source_file","version","revision","created_at","updated_at","domains","owners"],h=async({catalogEntitiesService:r,ctx:e,store:n})=>d("catalog_entities.bff.get_entities",async t=>{const i=e.req.query();t?.setAttribute("queryParams",JSON.stringify(E(i,p)));const a=v(_).parse(i),{currentRbacTeamsForRead:s,excludedTypes:o,excludedEntities:u}=l({store:n,ctx:e}),m=await r.getEntitiesWithRelations({paginationParams:a,rbacTeams:s,excludedTypes:o,excludedEntities:u});return t?.setAttribute("entitiesCount",m.items.length),e.json(m)}),w=async({catalogEntitiesService:r,ctx:e,store:n})=>d("catalog_entities.bff.get_entity",async t=>{const i=e.req.param(g);if(!i)return t?.error(new Error("Entity key is required")),e.json({message:"Entity key is required"},400);const a=e.req.query("revision");let s=null;if(a){if(!q(a))return t?.error(new Error("Invalid revision parameter")),e.json({message:"Invalid revision parameter: must be a valid ISO 8601 date-time string"},400);s=a}const o=e.req.query("version");if(!A(o,{pattern:/^[a-zA-Z0-9._-]+$/,maxLength:100,allowEmpty:!0}))return t?.error(new Error("Invalid version parameter")),e.json({message:"Invalid version parameter: version must contain only alphanumeric characters, dots, hyphens, and underscores, and must not exceed 100 characters"},400);const u=e.req.query();t?.setAttribute("queryParams",JSON.stringify(u)),t?.setAttribute("pathParams",JSON.stringify({entityKey:i}));const{currentRbacTeamsForRead:m,excludedTypes:c,excludedEntities:f}=l({store:n,ctx:e}),y=await r.getEntityWithRelationsByKey({entityKey:i,filter:{revision:s,version:o},rbacTeams:m,excludedTypes:c,excludedEntities:f});return y?(t?.setAttribute("entity",JSON.stringify(y)),e.json(y)):(t?.error(new Error("Entity not found")),e.json({message:"Entity not found"},404))});function L(r){return async e=>d("catalog_entities.bff",async n=>{n?.setAttribute("method",e.req.method);const t=await b.getInstance({baseDbDir:r.serverOutDir});return e.req.param("entityKey")?w({catalogEntitiesService:t,ctx:e,store:r}):h({catalogEntitiesService:t,ctx:e,store:r})})}export{L as bffCatalogHandler};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{telemetryTraceStep as l}from"../../../telemetry/helpers/trace-step.js";import{CATALOG_ENTITY_RELATION_ID as y}from"../../../../constants/
|
|
1
|
+
import{telemetryTraceStep as l}from"../../../telemetry/helpers/trace-step.js";import{CATALOG_ENTITY_RELATION_ID as y}from"../../../../constants/api.js";import{CATALOG_FILTERS_CACHE_NAMESPACE as m,ALLOWED_CATALOG_QUERY_PARAMS as c}from"../../../constants/plugins/catalog-entities.js";import{allowlistObject as E}from"../../../../utils/object/allowlist-object.js";import{CatalogEntitiesService as f}from"../../../plugins/catalog-entities/database/catalog-entities-service.js";import{createPaginationParamsValidator as R}from"../../../providers/database/pagination/schemas.js";import{ENTITY_RELATION_TO_DATABASE as w}from"../../../plugins/catalog-entities/database/mappers/field-transformations.js";import{CacheService as A}from"../../../persistence/cache/services/cache-service.js";import{parseEntityRelation as _}from"./parsers/relations/parse-entity-relation.js";import{parseEntitiesRelations as b}from"./parsers/relations/parse-entities-relations.js";import{parseEntityRelationUpdateData as j}from"./parsers/relations/parse-entity-relation-update-data.js";const h=["id","organizationId","projectId","sourceKey","targetKey","type","createdAt","updatedAt"],g=async a=>{await(await A.getInstance({baseDbDir:a,databaseType:"local"})).deleteByNamespace(m)},p=async({catalogEntitiesService:a,ctx:e})=>l("catalog_entities.relations.get_entity_relation",async n=>{const t=e.req.param(y);if(!t)return n?.error(new Error("Entity relation id is required")),e.json({message:"Entity relation id is required"},400);n?.setAttribute("pathParams",JSON.stringify({entityRelationId:t}));const i=await a.getEntityRelationById(t);return i?(n?.setAttribute("entityRelation",JSON.stringify(i)),e.json(i)):(n?.error(new Error("Entity relation not found")),e.json({message:"Entity relation not found"},404))}),O=async({catalogEntitiesService:a,ctx:e})=>l("catalog_entities.relations.get_entities_relations",async n=>{try{const t=e.req.query();n?.setAttribute("queryParams",JSON.stringify(E(t,c)));const i=R(h,w).parse(t),r=await a.getEntitiesRelations(i);return n?.setAttribute("entitiesRelationsCount",r.items.length),e.json(r)}catch(t){return console.error(t),n?.error(new Error("Failed to get entities relations")),e.json({message:"Failed to get entities relations"},500)}}),q=async({catalogEntitiesService:a,ctx:e,serverOutDir:n})=>l("catalog_entities.relations.create_entity_relation",async t=>{const i=e.get("logger");try{const r=await e.req.json();t?.setAttribute("requestBody",JSON.stringify(r));const o=_(r),s=await a.createEntityRelation(o);return s?(g(n),t?.setAttribute("entityRelation",JSON.stringify(s)),e.json(s)):(t?.error(new Error("Failed to create entity relation")),e.json({message:"Failed to create entity relation"},500))}catch(r){return i.error(r),r instanceof Error&&r.message.includes("validation failed")?(t?.error(new Error(r.message)),e.json({message:r.message},400)):(t?.error(r),e.json({message:"Failed to create entity relation"},500))}}),T=async({catalogEntitiesService:a,ctx:e,serverOutDir:n})=>l("catalog_entities.relations.bulk_upsert_entities_relations",async t=>{const i=e.get("logger");try{const r=await e.req.json();t?.setAttribute("requestBody",JSON.stringify(r));const o=b(r),s=await a.createEntitiesRelations(o);if(!s.length)return t?.error(new Error("Failed to create entity relations")),e.json({message:"Failed to create entity relations"},500);g(n);const u=s.filter(d=>d.status==="ok");return t?.setAttribute("totalSuccess",u.length),t?.setAttribute("totalFailed",s.length-u.length),e.json(s,207)}catch(r){return i.error(r),r instanceof Error&&r.message.includes("validation failed")?(t?.error(new Error(r.message)),e.json({message:r.message},400)):(t?.error(r),e.json({message:"Failed to create entity relations"},500))}}),N=async({catalogEntitiesService:a,ctx:e,serverOutDir:n})=>l("catalog_entities.relations.update_entity_relation",async t=>{const i=e.get("logger"),r=e.req.param(y);if(!r)return t?.error(new Error("Entity relation id is required")),e.json({message:"Entity relation id is required"},400);t?.setAttribute("pathParams",JSON.stringify({entityRelationId:r}));try{const o=await e.req.json();t?.setAttribute("requestBody",JSON.stringify(o));const s=await a.getEntityRelationById(r);if(!s)return t?.error(new Error(`Entity relation with id: ${r} not found`)),e.json({message:`Entity relation with id: ${r} not found`},404);const u=j(o),d=await a.updateEntityRelation(u,s);return d?(g(n),t?.setAttribute("entityRelation",JSON.stringify(d)),e.json(d)):(t?.error(new Error("Failed to update entity relation")),e.json({message:"Failed to update entity relation"},500))}catch(o){return i.error(o),o instanceof Error&&o.message.includes("validation failed")?(t?.error(new Error(o.message)),e.json({message:o.message},400)):(t?.error(o),e.json({message:o.message},500))}}),I=async({catalogEntitiesService:a,ctx:e,serverOutDir:n})=>l("catalog_entities.relations.delete_entity_relation",async t=>{const i=e.req.param(y);return i?(t?.setAttribute("pathParams",JSON.stringify({entityRelationId:i})),await a.deleteEntityRelation(i),g(n),new Response(null,{status:204})):(t?.error(new Error("Entity relation id is required")),e.json({message:"Entity relation id is required"},400))}),D={GET:O,POST:q,PUT:T},F={GET:p,DELETE:I,PATCH:N};function Y(a){return async e=>l("catalog_entities.relations",async n=>{n?.setAttribute("method",e.req.method);const t=await f.getInstance({baseDbDir:a.serverOutDir}),i=e.req.method,r=e.req.param(y)?F:D;return r[i]?await r[i]({catalogEntitiesService:t,ctx:e,serverOutDir:a.serverOutDir}):(n?.error(new Error("Method not allowed")),e.json({message:"Method not allowed"},405))})}export{Y as catalogRelationsHandler};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getCompleteCatalogConfig as j}from"../../../plugins/catalog-entities/get-complete-catalog-config.js";import{telemetryTraceStep as m}from"../../../telemetry/helpers/trace-step.js";import{CATALOG_FILTERS_CACHE_NAMESPACE as T,ALLOWED_CATALOG_QUERY_PARAMS as F}from"../../../constants/plugins/catalog-entities.js";import{CATALOG_ENTITY_ID as f}from"../../../../constants/
|
|
1
|
+
import{getCompleteCatalogConfig as j}from"../../../plugins/catalog-entities/get-complete-catalog-config.js";import{telemetryTraceStep as m}from"../../../telemetry/helpers/trace-step.js";import{CATALOG_FILTERS_CACHE_NAMESPACE as T,ALLOWED_CATALOG_QUERY_PARAMS as F}from"../../../constants/plugins/catalog-entities.js";import{CATALOG_ENTITY_ID as f}from"../../../../constants/api.js";import{allowlistObject as _}from"../../../../utils/object/allowlist-object.js";import{CatalogEntitiesService as R}from"../../../plugins/catalog-entities/database/catalog-entities-service.js";import{createPaginationParamsValidator as q}from"../../../providers/database/pagination/schemas.js";import{createEntityRelationDtoFromFileSchema as O}from"../../../plugins/catalog-entities/database/mappers/create-entity-relation-dto-from-file-schema.js";import{CacheService as C}from"../../../persistence/cache/services/cache-service.js";import{hasAccessToEntity as w}from"./helpers/has-access-to-entity.js";import{getRbacRestrictionsDataForCatalog as b}from"../helpers/get-rbac-restrictions-data-for-catalog.js";import{mapEntityReadModelSchemaToEntityReadDto as g}from"./mappers/map-entity-read-model-schema-to-entity-read-dto.js";import{parseEntity as I}from"./parsers/entities/parse-entity.js";import{parseEntityUpdateData as D}from"./parsers/entities/parse-entity-update-data.js";import{parseEntities as P}from"./parsers/entities/parse-entities.js";import{upsertPagesStats as h}from"./helpers/upsert-pages-stats.js";const k=["type","key","title","summary","tags","metadata","metadata.*","git","contact","links","id","source","sourceFile","createdAt","updatedAt"],A=async n=>{await(await C.getInstance({baseDbDir:n,databaseType:"local"})).deleteByNamespace(T)},N=async({catalogEntitiesService:n,ctx:e,store:u})=>m("catalog_entities.get_entities",async o=>{const i=e.get("logger");try{const r=e.req.query();o?.setAttribute("queryParams",JSON.stringify(_(r,F)));const{currentRbacTeamsForRead:d,excludedTypes:t,excludedEntities:s}=b({store:u,ctx:e}),l=q(k).parse(r),y=await n.getEntities({paginationParams:l,rbacTeams:d,excludedTypes:t,excludedEntities:s});return o?.setAttribute("entitiesCount",y.items.length),e.json({...y,items:y.items.map(g)})}catch(r){return i.error(r),o?.error(r),e.json({message:"Failed to get entities"},500)}}),W=async({catalogEntitiesService:n,ctx:e,store:u})=>m("catalog_entities.get_entity",async o=>{const i=e.req.param(f);if(!i)return o?.error(new Error("Entity id is required")),e.json({message:"Entity id is required"},400);o?.setAttribute("pathParams",JSON.stringify({entityId:i}));const{currentRbacTeamsForRead:r,excludedTypes:d,excludedEntities:t}=b({store:u,ctx:e}),s=await n.getEntityById(i,{rbacTeams:r,excludedTypes:d,excludedEntities:t});return s?(o?.setAttribute("entity",JSON.stringify(s)),e.json(g(s))):(o?.error(new Error("Entity not found")),e.json({message:"Entity not found"},404))}),L=async({catalogEntitiesService:n,ctx:e,catalogConfig:u,serverOutDir:o,store:i})=>m("catalog_entities.create_entity",async r=>{const d=e.get("logger");try{const t=await e.req.json();r?.setAttribute("requestBody",JSON.stringify(t));const s=I(t,u);if(!w({ctx:e,store:i,accessLevel:"WRITE",entityType:s.type,entityKey:s.key}))return r?.error(new Error("Access denied")),e.json({message:"Access denied"},403);const y=await n.transaction(async()=>{const a=await n.createEntity({entity:s,source:"remote",errorOnSkip:!0}),c=s.relations?.map(E=>O(s.key,E));return await n.createEntitiesRelations(c??[]),await h({ctx:e,catalogEntitiesService:n,addedEntities:a?[a]:void 0}),a});return y?(A(o),r?.setAttribute("entity",JSON.stringify(y)),e.json(g(y))):(r?.error(new Error("Failed to create entity")),e.json({message:"Failed to create entity"},500))}catch(t){return d.error(t),t instanceof Error&&t.message.includes("validation failed")?(r?.error(new Error(t.message)),e.json({message:t.message},400)):(r?.error(t),e.json({message:"Failed to create entity"},500))}}),J=async({catalogEntitiesService:n,ctx:e,catalogConfig:u,serverOutDir:o,store:i})=>m("catalog_entities.bulk_upsert_entities",async r=>{const d=e.get("logger");try{const t=await e.req.json();r?.setAttribute("requestBody",JSON.stringify(t));const s=P(t,u);for(const a of s)if(!w({ctx:e,store:i,accessLevel:"WRITE",entityType:a.type,entityKey:a.key}))return r?.error(new Error("Access denied")),e.json({message:"Access denied"},403);const l=await n.transaction(async()=>{const a=await n.createEntities(s,"remote"),c=a.reduce((E,p)=>(p.status==="ok"&&p.resource!=null&&E.push(p.resource),E),[]);return await h({ctx:e,catalogEntitiesService:n,addedEntities:c}),a});if(!l.length)return r?.error(new Error("Failed to create entities")),e.json({message:"Failed to create entities"},500);A(o);const y=l.filter(a=>a.status==="ok");return r?.setAttribute("totalSuccess",y.length),r?.setAttribute("totalFailed",l.length-y.length),e.json(y.map(a=>({...a,resource:g(a.resource)})),207)}catch(t){return d.error(t),t instanceof Error&&t.message.includes("validation failed")?(r?.error(new Error(t.message)),e.json({message:t.message},400)):(r?.error(t),e.json({message:"Failed to create entities"},500))}}),v=async({catalogEntitiesService:n,ctx:e,catalogConfig:u,serverOutDir:o,store:i})=>m("catalog_entities.update_entity",async r=>{const d=e.get("logger"),t=e.req.param(f);if(!t)return r?.error(new Error("Entity id is required")),e.json({message:"Entity id is required"},400);r?.setAttribute("pathParams",JSON.stringify({entityId:t}));try{const s=await e.req.json();r?.setAttribute("requestBody",JSON.stringify(s));const l=await n.getEntityById(t);if(!l)return r?.error(new Error(`Entity with id: ${t} not found`)),e.json({message:`Entity with id: ${t} not found`},404);if(l.source==="file")return r?.error(new Error("File entities cannot be updated")),e.json({message:"File entities cannot be updated"},400);if(!w({ctx:e,store:i,accessLevel:"WRITE",entityType:s.type??l.type,entityKey:s.key??l.key}))return r?.error(new Error("Access denied")),e.json({message:"Access denied"},403);const a=D(s,u,s?.type??l.type),c=await n.updateEntity(a,l);return c?(A(o),r?.setAttribute("entity",JSON.stringify(c)),e.json(g(c))):(r?.error(new Error("Failed to update entity")),e.json({message:"Failed to update entity"},500))}catch(s){return d.error(s),s instanceof Error&&s.message.includes("validation failed")?(r?.error(new Error(s.message)),e.json({message:s.message},400)):(r?.error(s),e.json({message:s.message},500))}}),B=async({catalogEntitiesService:n,ctx:e,serverOutDir:u,store:o})=>m("catalog_entities.delete_entity",async i=>{const r=e.get("logger"),d=e.req.param(f);if(!d)return i?.error(new Error("Entity id is required")),e.json({message:"Entity id is required"},400);i?.setAttribute("pathParams",JSON.stringify({entityId:d}));try{const t=await n.getEntityById(d);return t?t.source==="file"?(i?.error(new Error("File entities cannot be deleted")),e.json({message:"File entities cannot be deleted"},400)):w({ctx:e,store:o,accessLevel:"WRITE",entityType:t.type,entityKey:t.key})?await n.transaction(async()=>{const y=await n.deleteEntity(t);return y?(await h({ctx:e,catalogEntitiesService:n,removedEntities:t?[t]:void 0}),y):null})?(A(u),new Response(null,{status:204})):(i?.error(new Error("Failed to delete entity")),e.json({message:"Failed to delete entity"},500)):(i?.error(new Error("Access denied")),e.json({message:"Access denied"},403)):new Response(null,{status:204})}catch(t){return r.error(t),i?.error(t),e.json({message:"Failed to delete entity"},500)}}),U={GET:N,POST:L,PUT:J},G={GET:W,DELETE:B,PATCH:v};function ne(n){return async e=>m("catalog_entities",async u=>{const o=await R.getInstance({baseDbDir:n.serverOutDir}),i=e.req.method;u?.setAttribute("method",i);const r=e.req.param(f)?G:U,d=j(n.config.entitiesCatalog),t=r[i];return t?await t({catalogEntitiesService:o,ctx:e,catalogConfig:d,serverOutDir:n.serverOutDir,store:n}):(u?.error(new Error("Method not allowed")),e.json({message:"Method not allowed"},405))})}export{ne as catalogHandler};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import $ from"node:dns";import{isIP as E}from"node:net";import{withPathPrefix as L}from"@redocly/theme/core/utils";import{ServerRoutes as A}from"../../../constants/
|
|
1
|
+
import $ from"node:dns";import{isIP as E}from"node:net";import{withPathPrefix as L}from"@redocly/theme/core/utils";import{ServerRoutes as A}from"../../../constants/api.js";import{envConfig as H}from"../../config/env-config.js";import{getRequestOrigin as D}from"../utils/get-request-origin.js";const M=new Set(["connection","keep-alive","proxy-authenticate","proxy-connection","proxy-authorization","te","trailer","transfer-encoding","upgrade","host"]),k=new Set(["cookie","cookie2","accept-encoding"]),b=new Set(["set-cookie","set-cookie2","content-encoding","content-length"]),y="x-redocly-proxy-streaming",x="x-http-method-override",S="x-redocly-cookie";function oe(n,e=L(A.CORS_PROXY)){return async t=>{const o=new URL(t.req.url).pathname;if(o===e||o===`${e}/`)return t.text(`Realm CORS proxy endpoint.
|
|
2
2
|
Usage: ${e}/https://api.example.com/path`);const r=J(t.req.url,e);if(!r)return t.text("Invalid proxied URL",400);const a=n?.getConfig().corsProxy?.allowedTargets;if(a&&a.length>0&&!a.some(p=>V(r,p)))return t.text("Target URL is not in the allowed list for CORS proxy",403);const f=D(t),h=r.origin===f,m=r.pathname===e||r.pathname.startsWith(`${e}/`);if(h&&!m)return new Response("Please use a direct request",{status:308,headers:{Location:r.toString(),Vary:"origin","Cache-Control":"private"}});const u=await Y(r.hostname);if((!H.isDevelopMode||H.isReunite)&&u&&F(u))return t.text("Requests to private network addresses are not allowed",403);const i=new Headers,I=v(t.req.raw.headers);for(const[s,p]of t.req.raw.headers)I.has(s.toLowerCase())||k.has(s.toLowerCase())||i.append(s,p);const g=i.get(S);if(g){const s=t.req.raw.headers.get("cookie")||"";i.set("cookie",s?`${s}; ${g}`:g),i.delete(S)}const O=t.req.raw.headers.get("origin")||"";U(O)&&i.delete("origin");let l=t.req.method;const R=i.get(x);R&&(l=R.toUpperCase(),i.delete(x));const w={method:l,headers:i,redirect:"manual"};l!=="GET"&&l!=="HEAD"&&t.req.raw.body&&(w.body=t.req.raw.body,w.duplex="half");let c;try{c=await fetch(r,w)}catch(s){const p=s instanceof Error?s.message:"unknown error",_=s instanceof Error&&s.cause instanceof Error?`: ${s.cause.message}`:"";return t.text(`Failed to proxy request: ${p}${_}`,502)}const T=c.headers.get("content-type")||"";if(G(T)&&t.req.raw.headers.get("sec-fetch-mode")==="navigate")return t.text("Direct browser navigation to proxied HTML or JavaScript content is not allowed",403);const d=new Headers(c.headers),q=v(c.headers);for(const s of q)d.delete(s);for(const s of b)d.delete(s);return d.set(y,"1"),d.set("x-content-type-options","nosniff"),d.has("content-type")||d.set("content-type","text/plain"),new Response(c.body,{status:c.status,statusText:c.statusText,headers:d})}}function N(n){try{return decodeURIComponent(n)}catch{return n}}function W(n){return n.replace(/^(https?):\/(?!\/)/i,"$1://")}function z(n,e){return e?n.includes("?")?e==="?"?n:`${n.endsWith("?")||n.endsWith("&")?n:`${n}&`}${e.slice(1)}`:`${n}${e}`:n}function v(n){const e=new Set(M),t=n.get("connection");if(!t)return e;for(const o of t.split(",")){const r=o.trim().toLowerCase();r&&e.add(r)}return e}function U(n){const e=n.toLowerCase();return e.includes(".redocly.app")||e.includes("localhost")}async function Y(n){const e=P(n);if(E(e))return e;try{const{address:t}=await $.promises.lookup(e);return t}catch{return null}}function F(n){const e=P(n).toLowerCase();if(!E(e))return!0;const t=X(e);return t?C(t):e.includes(":")?j(e):C(e)}function P(n){return n.startsWith("[")&&n.endsWith("]")?n.slice(1,-1):n}function X(n){const e=n.match(/^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i);if(e){const o=parseInt(e[1],16),r=parseInt(e[2],16);return[o>>8&255,o&255,r>>8&255,r&255].join(".")}return n.match(/^::ffff:(\d+\.\d+\.\d+\.\d+)$/i)?.[1]??null}function C(n){const e=n.split(".").map(Number);if(e.length!==4||e.some(r=>isNaN(r)))return!0;const[t,o]=e;return t===0||t===10||t===127||t===172&&o>=16&&o<=31||t===192&&o===168||t===169&&o===254||t===100&&o>=64&&o<=127}function j(n){const e=B(n);return n==="::1"||n==="::"||e!==null&&(e&65024)===64512||e!==null&&(e&65472)===65152}function B(n){const[e]=n.split(":");if(!e)return null;const t=parseInt(e,16);return Number.isNaN(t)?null:t}function V(n,e){let t;try{t=new URL(e)}catch{return!1}if(n.origin!==t.origin)return!1;const o=t.pathname.endsWith("/")?t.pathname:`${t.pathname}/`;return n.pathname.startsWith(o)||n.pathname===t.pathname}function G(n){const e=n.toLowerCase();return e.includes("text/html")||e.includes("javascript")||e.includes("application/xhtml")||e.includes("application/xml")||e.includes("image/svg")}function J(n,e){const t=new URL(n),o=t.pathname===e,r=t.pathname.startsWith(`${e}/`);if(!o&&!r)return null;const a=t.pathname.slice(e.length).replace(/^\/+/,"");if(!a)return null;const f=[a,N(a)];for(const h of f){const m=W(h),u=z(m,t.search);try{const i=new URL(u);if(i.protocol==="http:"||i.protocol==="https:")return i}catch{continue}}return null}const re=y;export{re as CORS_PROXY_STREAM_HEADER,oe as corsProxyHandler,F as isPrivateIp,J as resolveCorsProxyTarget};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{serveStatic as
|
|
1
|
+
import{serveStatic as c}from"hono/serve-static";import{withPathPrefix as i,withoutPathPrefix as H}from"@redocly/theme/core/utils";import{ServerRoutes as l}from"../../../constants/api.js";import{PUBLIC_STATIC_FOLDER as L}from"../../constants/common.js";import{envConfig as S}from"../../config/env-config.js";import{authMiddleware as C}from"../middleware/authMiddleware.js";import{ensureSearchData as g}from"../middleware/ensureSearchData.js";import{dynamicMiddleware as h}from"../middleware/dynamic-middleware/dynamic-middleware.js";import{installRoutes as D}from"../../plugins/dev-onboarding/api/routes/index.js";import{authorizeHandler as I,oidcCallbackHandler as P,logoutHandler as f,postLogoutHandler as w,idpLoginHandler as M,redoclyLoginCallbackHandler as v,samlCallbackHandler as N,redoclyTokenLoginHandler as B,inviteHandler as G}from"./auth.js";import{appDataHandler as F}from"./app-data.js";import{searchFacetsHandler as U,searchHandler as y}from"./search.js";import{dynamicRouteHandler as Y}from"./dynamic-route.js";import{pageDataHandler as K,sharedPageDataHandler as k}from"./page-data.js";import{pathPrefixRedirectHandler as b}from"./path-prefix-redirect.js";import{getRoutesByLineHandler as A,resolvePathHandler as s,resolvePathsHandler as V,resolveSlugHandler as E}from"./resolve-route.js";import{feedbackHandler as x}from"./feedback.js";import{loggerMiddleware as q}from"../middleware/loggerMiddleware.js";import{responseHeadersMiddleware as u}from"../middleware/responseHeadersMiddleware.js";import{idleTimeoutMiddleware as X}from"../middleware/idleTimeoutMiddleware.js";import{otelTracesHandler as $}from"./otel/otel.js";import{healthCheckHandler as j}from"./health.js";import{askAiHandler as z}from"./ask-ai.js";import{semanticSearchHandler as W}from"./semantic-search.js";import{replayOauth2RedirectCallbackHandler as Z}from"./replay-oauth2-redirect.js";import{corsProxyHandler as O}from"./cors-proxy.js";import{corsMiddleware as d}from"../middleware/corsMiddleware.js";import{installApiRoutes as J}from"./api-routes/api-routes.js";import{cookieMiddleware as Q}from"../middleware/cookieMiddleware.js";import{staticContentHandler as aa}from"../routes/static-content.js";import{infoHandler as _}from"./info.js";import{catalogHandler as ea}from"./catalog/catalog.js";import{catalogRelationsHandler as ia}from"./catalog/catalog-relations.js";import{bffCatalogHandler as la}from"./catalog/bff-catalog.js";import{bffCatalogRevisionsHandler as ta}from"./catalog/bff-catalog-revisions.js";import{bffCatalogRelatedEntitiesHandler as ma}from"./catalog/bff-catalog-related-entities.js";import{catalogAuthMiddleware as t}from"../middleware/catalogAuthMiddleware.js";import{telemetryMiddleware as oa}from"../middleware/telemetry-middleware.js";import{errorHandler as da}from"./error.js";import{installMcpAuthRoutes as na}from"./mcp-routes/mcp-routes.js";import{jsonValidatorMiddleware as T}from"../middleware/jsonValidatorMiddleware.js";import{searchFacetsRequestSchema as pa}from"../../../api-schemas/search-facets.js";import{searchRequestSchema as ra}from"../../../api-schemas/search.js";function ee(a,e,m){const{resolveRouteData:n,readStaticAsset:p}=m;a.use("*",X()),a.use("*",Q()),a.use("*",h(e)),a.use("*",C(e)),a.use("*",q()),a.use("*",u(e)),a.use("*",oa()),a.use(i("*"),c({root:`./${L}`,getContent:(o,R)=>aa(o,R,e,p),rewriteRequestPath:o=>H(o)})),a.use(i(l.FEEDBACK),d({allowMethods:["POST"]})),a.use(i(l.ASK_AI),d({allowMethods:["POST"]})),a.use(i(l.SEMANTIC_SEARCH),d({allowMethods:["POST"]})),a.use("*",fa(e));const r=g(e);a.use(i(l.INFO),_()),S.NEW_CATALOG_ENABLED&&(a.use(i(l.CATALOG_ENTITIES),t({serverOutDir:e.serverOutDir}),ea(e)),a.use(i(l.CATALOG_ENTITIES_RELATIONS),t({serverOutDir:e.serverOutDir}),ia(e)),a.get(i(l.BFF_CATALOG_ENTITIES),t({serverOutDir:e.serverOutDir,protectReadMethods:!1}),la(e)),a.get(i(l.BFF_CATALOG_RELATED_ENTITIES),t({serverOutDir:e.serverOutDir,protectReadMethods:!1}),ma(e)),a.get(i(l.BFF_CATALOG_REVISIONS),t({serverOutDir:e.serverOutDir,protectReadMethods:!1}),ta(e))),a.get(i(l.SHARED_PAGE_DATA),k(e)),a.get(i(l.PAGE_DATA),K(e,n)),a.get(i(l.APP_DATA),F(e)),a.post(i(l.SEARCH),r,T(ra),y(e)),a.post(i(l.SEARCH_FACETS),r,T(pa),U(e)),a.post(i(l.AUTHORIZATION),I),a.post(i(l.LOGOUT),f(e)),a.get(i(l.LOGOUT),f(e)),a.get(i(l.POST_LOGOUT),w(e)),a.get(i(l.OIDC_CALLBACK),P(e)),a.get(i(l.REDOCLY_TOKEN_LOGIN),B(e)),a.get(i(l.REDOCLY_LOGIN_CALLBACK),v()),a.get(i(l.IDP_LOGIN),M(e)),a.post(i(l.SAML_CALLBACK),N(e)),a.get(i(l.INVITE),G(e)),a.get(i(l.HEALTH),j),na(a,e),D(a,e),a.all(i(l.CORS_PROXY),O(e)),a.all(i(`${l.CORS_PROXY}/*`),O(e)),J(a,e),a.post(i(l.FEEDBACK),x(e)),a.post(i(l.RESOLVE_ROUTE_BY_PATH),s(e)),a.post(i(l.RESOLVE_ROUTES_BY_PATHS),V(e)),a.post(i(l.RESOLVE_ROUTE_BY_SLUG),E(e)),a.post(i(l.ASK_AI),z(e)),a.post(i(l.SEMANTIC_SEARCH),W(e)),a.get(i(l.GET_ROUTES_BY_LINE),A(e)),a.post(i(l.OTEL_TRACES),$),a.get(i(l.REPLAY_OAUTH2_CALLBACK),Z),a.all(i("/*"),Y(e,n,p)),a.get("*",b),a.onError(da)}function fa(a){return async(e,m)=>{await a.waitForPluginsLifecycle(),await m()}}function ie(a,e){a.get(i(l.INFO),_()),a.post(i(l.RESOLVE_ROUTE_BY_PATH),s(e)),a.post(i(l.RESOLVE_ROUTE_BY_SLUG),E(e)),a.get(i(l.GET_ROUTES_BY_LINE),A(e))}export{ie as installDevRoutes,ee as installProdRoutes,fa as waitForPluginsLifecycle};
|