mirror of
https://github.com/Graylog2/graylog2-server.git
synced 2026-03-13 09:32:21 +08:00
* Initial working state of OpenAPI spec generation Generates an OpenAPI spec but still has lots of issues * Fix wrong import * Add NoAuditEvent annotation to test resource methods * Add OpenAPI browser frontend (POC) Add basic OpenAPI browser UI using Redoc loaded from CDN. This is a proof of concept implementation not yet ready for production use. - Loads Redoc from CDN to avoid webpack bundling complexity - Displays OpenAPI spec from /api/openapi.yaml endpoint - Accessible via Help menu → "OpenAPI browser" - Route: /openapi-browser 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * Make both json & yaml formats work * Implement plugin path prefixing + configure the openAPI context directly to be able to use dependency injection * Remove logging * Migrate REST resources from Swagger to OpenAPI 3.x annotations Migrated ~150 REST resource files from old Swagger annotations (io.swagger.annotations.*) to OpenAPI 3.x annotations (io.swagger.v3.oas.annotations.*). Migration performed using OpenRewrite and manual fixes: - @Api → @Tag - @ApiOperation → @Operation - @ApiParam → @Parameter - @ApiResponse code → responseCode - @ApiResponse message → description - Removed invalid attributes (allowableValues, defaultValue, tags) - Fixed nickname → operationId - Removed response= attribute (needs manual restoration) Note: Some information was intentionally lost and needs restoration: - Response type schemas (33 instances) - Parameter allowableValues constraints (58 instances) - CLOUD_VISIBLE tags (82 instances) 🤖 Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * Restore response type information to OpenAPI annotations Adds @ApiResponses with @Content and @Schema to restore the 33 instances of response type information that were lost during the OpenAPI 3.x migration. - Automated script restored 20 instances - Manual additions for 8 instances with multi-line annotations - 5 instances already fixed in previous commit - All response codes verified against actual implementation - Total: 33 response types restored with accurate HTTP status codes Co-Authored-By: Claude <noreply@anthropic.com> * Restore parameter allowableValues constraints for OpenAPI 3.x migration Restore allowableValues constraints that were lost during OpenAPI 3.x migration by converting from @ApiParam(allowableValues) to @Parameter with @Schema(allowableValues). This restores API documentation for parameter value constraints across 22 REST resource files, covering ~58 parameter instances. Changes: - Migrated allowableValues from Swagger 2.x @ApiParam to OpenAPI 3.x @Parameter with @Schema(allowableValues = {...}) - Added missing Schema imports where needed - Fixed several bugs and inconsistencies from master branch Summary of Semantic Differences (11 files): Bug Fixes: - AuthzRolesResource.getUsersForRole(): Fixed incorrect field list that had user fields (username,full_name,email) instead of role fields (id,name,description) - DatanodeResource: Fixed completely wrong field list (title,description, type) to actual DataNodeDto fields (hostname,data_node_status, transport_address,cert_valid_until,datanode_version) - IndexSetTemplateResource: Fixed "name" to "title" (correct field name) Added Missing Valid Fields: - DashboardsResource, SavedSearchesResource, ViewsResource: Added "last_updated_at" which exists in SEARCH_FIELD_MAPPING - ViewsResource: Added "owner", "description", "summary" (was very incomplete in master) - AuthzRolesResource (getList, getListForUser): Added "id" field - GrokResource, IndexFieldTypeProfileResource: Added "id" and other valid fields from SEARCH_FIELD_MAPPING Removed Invalid Fields: - StreamResource: Removed "updated_at", "status" (not in SEARCH_FIELD_MAPPING, didn't work) - GrokResource: Removed "pattern" (not in search mapping) - IndexSetsMappingResource: Reduced to "field_name" only (other fields not implemented) Fixed Constraint Type: - ClusterLoggersResource: Removed inappropriate allowableValues range constraint for numeric limit parameter (already has @Min validation) Files with Identical Field Lists (13 files): EventDefinitionsResource, EventNotificationsResource, PipelineResource, RuleResource, CollectorResource, ConfigurationResource, SidecarResource, ScriptingApiResource, AuthServiceBackendsResource, UsersResource, TokenUsageResource, LookupTableResource - all have identical semantics, just migrated annotation syntax. Rationale: All semantic differences were introduced to correct API documentation to match actual backend implementation. Changes ensure that: 1. All advertised sort fields actually work 2. All functional sort fields are advertised 3. API spec accurately reflects backend capabilities 4. Bugs in master branch are fixed 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * Add replacement for CLOUD_VISIBLE tag * Add @PublicCloudAPI annotation to cloud-visible REST resources Add @PublicCloudAPI annotation to 82 REST resources that were previously marked with tags = {CLOUD_VISIBLE} in Swagger 2.x @Api annotations. This annotation is used by CustomOpenAPIScanner to filter resources when IS_CLOUD=true, ensuring only cloud-appropriate APIs are exposed in the OpenAPI specification for cloud deployments. Resources annotated: - Events (4 resources): EventDefinitionsResource, EventNotificationsResource, etc. - Pipeline Processor (5 resources): PipelineResource, RuleResource, SimulatorResource, etc. - Sidecar (6 resources): SidecarResource, CollectorResource, ConfigurationResource, etc. - Views/Search (15 resources): DashboardsResource, SavedSearchesResource, ViewsResource, etc. - Security (6 resources): AuthzRolesResource, CAResource, ClientCertResource, etc. - System (30+ resources): StreamResource, InputsResource, NotificationsResource, etc. - Other resources (15+): MessageResource, EntitySuggestionResource, ContentPackResource, etc. The @PublicCloudAPI annotation: - Marks resources as available in public cloud deployments - Does not appear in the generated OpenAPI specification - Filters resources during OpenAPI generation when isCloud=true - Replaces the old tags = {CLOUD_VISIBLE} approach from Swagger 2.x 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * Migrate McpRestResource from Swagger 2.x to OpenAPI 3.x Updates the MCP REST resource to use OpenAPI 3.x annotations, completing the migration of all REST resources in the project. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * WIP: add TODOS and subtype resolver prototype * Add OpenAPI browser to help menu after merge conflict resolution The OpenAPI browser menu item was lost during the merge when the help menu was refactored from hardcoded items to a plugin-based registration system. This restores the menu item in the new bindings.ts format. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * Make legacy generator work with new annotations * Remove unused CLOUD_VISIBLE flag * Temporarily make test pass * Use @RequestBody annotation instead of @Parameter * Synchronize our not thread-safe custom reader * Add discriminator mapping based on jackson annotations * WIP command to generate a spec without a running server * Add output file argument * Don't hardcode any config parameters * Add spec generation to maven build * Move spec generation into profile * Add generated spec to resources * Attempt to stabilize spec format * Adjust test to openapi 3.1 schema * Resolve registered subtypes * bind object mapper to provider * don't skip empty subtype names * update spec * Revert extraction of ObjectMapperConfiguration With the latest changes, it didn't have an effect anymore. * Expose OpenAPIContext to not hide the caching behavior * Apply sorting for both web and command context * use fully qualified type names in schema * Fix broken discriminator mapping * Add custom handling for ImmutableMap * Split event expression types Swagger can't deal with the generic type hierarchy. It would generate faulty allOf's with refs to both Expression<Boolean> and Expression<Number> in one schema, e.g. for `org.graylog.events.conditions.Expr.And`. * Prevent duplicate operation IDs * Skip NonApiResource annotated resources * Add validation to spec command * Replace terms "spec"/"specification" with "description" * Update openapi description * Switch to swagger-ui-react * Serve description at openapi.yaml / openapi.json again * Add missing license headers * Add security schemes but hide them in swagger ui * Update openapi description * configure swagger ui * add changelog * qualify url to openapi.yaml * Remove old api browser * Rudimentary styling for swagger ui * Fix broken handling of duplicate paths * update openapi description * fix changelog * Remove swagger CSP group & deprecate DocumentationResource * Update graylog2-server/src/main/java/org/graylog/api/GenerateOpenApiDescriptionCommand.java Co-authored-by: Kay Roepke <kroepke@googlemail.com> * create parent path if non-existent * Polish print statements * Remove term "Graylog" * adjust RequestBody annotations to include schema ref in each case * Update graylog2-server/src/main/java/org/graylog/api/GenerateOpenApiDescriptionCommand.java Co-authored-by: Kay Roepke <kroepke@googlemail.com> * Add annotations for success responses with declared response types * treat Immutable(List|Set) as the java.util equivalents * semver Version is serialized as a String in our api * extract helper method and add overrides for joda-time and threeten classes * HostAndPort is a string in openapi * for ImmutableMap treat keys with GRN or joda-time DateTime types as strings for schema generation * Add more missing response schemas * Remove swagger annotations from datanode resource * Add forbidden-apis rule for io.swagger.annotations.* * Get rid of remaining ImmutableMap instances * Remove openapi.yaml from VCS * Execute OpenAPI desc generation in separate JVM to avoid classloader issues due to bouncycastle registration during command startup * Add handling for java.time.Duration and simplify scalar type mapping * More custom handling for various types * `yarn format` * Add special handling for FormDataContentDisposition in old swagger specs --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Kay Roepke <kroepke@googlemail.com>
166 lines
4.6 KiB
TypeScript
166 lines
4.6 KiB
TypeScript
/*
|
|
* Copyright (C) 2020 Graylog, Inc.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the Server Side Public License, version 1,
|
|
* as published by MongoDB, Inc.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* Server Side Public License for more details.
|
|
*
|
|
* You should have received a copy of the Server Side Public License
|
|
* along with this program. If not, see
|
|
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
|
*/
|
|
const path = require('path');
|
|
|
|
const webpack = require('webpack');
|
|
const AssetsPlugin = require('assets-webpack-plugin');
|
|
const { merge } = require('webpack-merge');
|
|
const { EsbuildPlugin } = require('esbuild-loader');
|
|
const { CycloneDxWebpackPlugin } = require('@cyclonedx/webpack-plugin');
|
|
|
|
const ROOT_PATH = path.resolve(__dirname);
|
|
const BUILD_PATH = path.resolve(ROOT_PATH, 'target/web/build');
|
|
const MANIFESTS_PATH = path.resolve(ROOT_PATH, 'manifests');
|
|
|
|
const vendorModules = require('./vendor.modules');
|
|
const supportedBrowsers = require('./supportedBrowsers');
|
|
|
|
const TARGET = process.env.npm_lifecycle_event || 'build';
|
|
process.env.BABEL_ENV = TARGET;
|
|
|
|
export const DEFAULT_API_URL = 'http://localhost:9000';
|
|
const apiUrl = process.env.GRAYLOG_API_URL ?? DEFAULT_API_URL;
|
|
|
|
// eslint-disable-next-line no-console
|
|
console.error('Building vendor bundle.');
|
|
|
|
const webpackConfig = {
|
|
mode: 'development',
|
|
name: 'vendor',
|
|
entry: {
|
|
vendor: vendorModules,
|
|
},
|
|
output: {
|
|
publicPath: '',
|
|
path: BUILD_PATH,
|
|
filename: '[name].js',
|
|
library: '__[name]',
|
|
clean: {
|
|
keep: /vendor-module\.json/,
|
|
},
|
|
},
|
|
plugins: [
|
|
new webpack.DllPlugin({
|
|
path: path.resolve(MANIFESTS_PATH, '[name]-manifest.json'),
|
|
name: '__[name]',
|
|
}),
|
|
new AssetsPlugin({
|
|
filename: 'vendor-module.json',
|
|
useCompilerPath: true,
|
|
processOutput(assets) {
|
|
const jsfiles = [];
|
|
const cssfiles = [];
|
|
const chunks = {};
|
|
|
|
Object.keys(assets).forEach((chunk) => {
|
|
if (assets[chunk].js) {
|
|
jsfiles.push(assets[chunk].js);
|
|
}
|
|
|
|
if (assets[chunk].css) {
|
|
jsfiles.push(assets[chunk].css);
|
|
}
|
|
|
|
chunks[chunk] = {
|
|
size: 0,
|
|
entry: assets[chunk].js,
|
|
css: assets[chunk].css || [],
|
|
};
|
|
});
|
|
|
|
return JSON.stringify({
|
|
files: {
|
|
js: jsfiles,
|
|
css: cssfiles,
|
|
chunks: chunks,
|
|
},
|
|
});
|
|
},
|
|
}),
|
|
],
|
|
recordsPath: path.resolve(ROOT_PATH, 'webpack/vendor-module-ids.json'),
|
|
};
|
|
|
|
// eslint-disable-next-line import/no-mutable-exports
|
|
let defaultExport = webpackConfig;
|
|
|
|
if (TARGET === 'start') {
|
|
defaultExport = merge(webpackConfig, {
|
|
devServer: {
|
|
hot: false,
|
|
liveReload: true,
|
|
compress: true,
|
|
historyApiFallback: {
|
|
disableDotRule: true,
|
|
},
|
|
proxy: [
|
|
{
|
|
context: ['/api', '/config.js', '/sso'],
|
|
target: apiUrl,
|
|
// Skip proxying for /api-browser - it's a frontend route, not an API endpoint
|
|
bypass: (req) => (req.path.startsWith('/api-browser') ? req.path : null),
|
|
onProxyReq: (proxyReq, req) => {
|
|
const existingHeader = proxyReq.getHeader('X-Graylog-Server-URL');
|
|
if (!existingHeader?.trim()) {
|
|
const serverUrl = `${req.protocol}://${req.get('host')}`;
|
|
proxyReq.setHeader('X-Graylog-Server-URL', serverUrl);
|
|
}
|
|
},
|
|
},
|
|
],
|
|
},
|
|
});
|
|
}
|
|
|
|
if (TARGET.startsWith('build')) {
|
|
defaultExport = merge(webpackConfig, {
|
|
mode: 'production',
|
|
optimization: {
|
|
concatenateModules: false,
|
|
sideEffects: false,
|
|
minimizer: [
|
|
new EsbuildPlugin({
|
|
format: 'cjs',
|
|
target: supportedBrowsers,
|
|
}),
|
|
],
|
|
},
|
|
plugins: [
|
|
new webpack.DefinePlugin({
|
|
'process.env.NODE_ENV': JSON.stringify('production'),
|
|
}),
|
|
new webpack.LoaderOptionsPlugin({
|
|
minimize: true,
|
|
}),
|
|
// Create SBOM files for graylog-server frontend dependencies.
|
|
new CycloneDxWebpackPlugin({
|
|
specVersion: '1.5',
|
|
rootComponentAutodetect: false,
|
|
rootComponentType: 'application',
|
|
rootComponentName: 'graylog-server',
|
|
outputLocation: '../cyclonedx-vendor',
|
|
includeWellknown: false,
|
|
}),
|
|
],
|
|
output: {
|
|
filename: '[name].[chunkhash].js',
|
|
},
|
|
});
|
|
}
|
|
|
|
export default defaultExport;
|