Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Authorization header to OpenAPI docs #61

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions config.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,13 +217,9 @@ export interface AiWarpConfig {
prefix?: string;
path?: string;
};
plugins?:
| {
[k: string]: unknown;
}
| {
[k: string]: unknown;
};
plugins?: {
[k: string]: unknown;
};
}[];
};
module?: string;
Expand Down
22 changes: 22 additions & 0 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,28 @@ const stackable: Stackable<AiWarpConfig> = async function (fastify, opts) {
})
}

if (config.service === undefined) {
config.service = {}
}

const currentOpenApiConfig = typeof config.service.openapi === 'object' ? config.service.openapi : {}
if (config.auth?.jwt !== undefined) {
config.service.openapi = {
...currentOpenApiConfig,
components: {
...currentOpenApiConfig.components,
securitySchemes: {
...currentOpenApiConfig.components?.securitySchemes,
aiWarpJwtToken: {
type: 'apiKey',
in: 'header',
name: 'Authorization'
}
}
}
}
}

await fastify.register(platformaticService, opts)

await fastify.register(warpPlugin, opts) // needs to be registered here for fastify.ai to be decorated
Expand Down
7 changes: 7 additions & 0 deletions plugins/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,16 @@ function isAFastifyError (object: object): object is FastifyError {
const InternalServerError = createError('INTERNAL_SERVER_ERROR', 'Internal Server Error', 500)

const plugin: FastifyPluginAsyncTypebox = async (fastify) => {
let security: Array<Record<string, string[]>> | undefined
if (fastify.platformatic.config.auth?.jwt !== undefined) {
security = [{ aiWarpJwtToken: [] }]
}

fastify.route({
url: '/api/v1/prompt',
method: 'POST',
schema: {
security,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, this is not enough for platformatic openapi tools. They just don't check for the security schemas now. What you need to do it to add an "Authorization" header to the route headers schema.

And I think it's better to use the onRoute hook to intercept app routes that you want to update.

body: Type.Object({
prompt: Type.String(),
chatHistory: Type.Optional(Type.Array(Type.Object({
Expand Down Expand Up @@ -55,6 +61,7 @@ const plugin: FastifyPluginAsyncTypebox = async (fastify) => {
method: 'POST',
schema: {
produces: ['text/event-stream'],
security,
body: Type.Object({
prompt: Type.String(),
chatHistory: Type.Optional(Type.Array(Type.Object({
Expand Down
2 changes: 1 addition & 1 deletion schema.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$id": "ai-warp",
"version": "1.37.1",
"version": "1.39.0",
"title": "Ai Warp Config",
"type": "object",
"properties": {
Expand Down
41 changes: 41 additions & 0 deletions tests/e2e/api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,47 @@ it('provides all paths in OpenAPI', async () => {
await app.close()
})

it('provides header for jwt token in OpenAPI', async () => {
const [app, port] = await buildAiWarpApp({
aiProvider: {
openai: {
model: 'gpt-3.5-turbo',
apiKey: ''
}
},
auth: {
jwt: {
secret: 'asd'
}
}
})

await app.start()

const res = await fetch(`http://localhost:${port}/documentation/json`)
const body = await res.json()

assert.deepStrictEqual(body.components, {
securitySchemes: {
aiWarpJwtToken: {
type: 'apiKey',
in: 'header',
name: 'Authorization'
}
},
schemas: {}
})

const endpoints = ['/api/v1/prompt', '/api/v1/stream']
for (const endpoint of endpoints) {
assert.deepStrictEqual(body.paths[endpoint].post.security, [
{ aiWarpJwtToken: [] }
])
}

await app.close()
})

it('prompt with wrong JSON', async () => {
const [app, port] = await buildAiWarpApp({
aiProvider: {
Expand Down
Loading