pull/715/head
Travis Fischer 2025-05-15 15:53:44 +07:00
rodzic b28b333b36
commit f2c4d2442e
21 zmienionych plików z 151 dodań i 128 usunięć

Wyświetl plik

@ -4,11 +4,11 @@ import type { AuthenticatedEnv } from '@/lib/types'
import { db, eq, schema } from '@/db' import { db, eq, schema } from '@/db'
import { aclAdmin } from '@/lib/acl-admin' import { aclAdmin } from '@/lib/acl-admin'
import { import {
assert, openapiAuthenticatedSecuritySchemas,
openapiErrorResponse404, openapiErrorResponse404,
openapiErrorResponses, openapiErrorResponses
parseZodSchema } from '@/lib/openapi-utils'
} from '@/lib/utils' import { assert, parseZodSchema } from '@/lib/utils'
import { consumerTokenParamsSchema, populateConsumerSchema } from './schemas' import { consumerTokenParamsSchema, populateConsumerSchema } from './schemas'
@ -18,7 +18,7 @@ const route = createRoute({
operationId: 'getConsumer', operationId: 'getConsumer',
method: 'get', method: 'get',
path: 'admin/consumers/tokens/{token}', path: 'admin/consumers/tokens/{token}',
security: [{ bearerAuth: [] }], security: openapiAuthenticatedSecuritySchemas,
request: { request: {
params: consumerTokenParamsSchema, params: consumerTokenParamsSchema,
query: populateConsumerSchema query: populateConsumerSchema

Wyświetl plik

@ -4,11 +4,11 @@ import type { AuthenticatedEnv } from '@/lib/types'
import { db, eq, schema } from '@/db' import { db, eq, schema } from '@/db'
import { acl } from '@/lib/acl' import { acl } from '@/lib/acl'
import { import {
assert, openapiAuthenticatedSecuritySchemas,
openapiErrorResponse404, openapiErrorResponse404,
openapiErrorResponses, openapiErrorResponses
parseZodSchema } from '@/lib/openapi-utils'
} from '@/lib/utils' import { assert, parseZodSchema } from '@/lib/utils'
import { consumerIdParamsSchema, populateConsumerSchema } from './schemas' import { consumerIdParamsSchema, populateConsumerSchema } from './schemas'
@ -18,7 +18,7 @@ const route = createRoute({
operationId: 'getConsumer', operationId: 'getConsumer',
method: 'get', method: 'get',
path: 'consumers/{consumersId}', path: 'consumers/{consumersId}',
security: [{ bearerAuth: [] }], security: openapiAuthenticatedSecuritySchemas,
request: { request: {
params: consumerIdParamsSchema, params: consumerIdParamsSchema,
query: populateConsumerSchema query: populateConsumerSchema

Wyświetl plik

@ -4,11 +4,11 @@ import type { AuthenticatedEnv } from '@/lib/types'
import { db, eq, schema } from '@/db' import { db, eq, schema } from '@/db'
import { acl } from '@/lib/acl' import { acl } from '@/lib/acl'
import { import {
assert, openapiAuthenticatedSecuritySchemas,
openapiErrorResponse404, openapiErrorResponse404,
openapiErrorResponses, openapiErrorResponses
parseZodSchema } from '@/lib/openapi-utils'
} from '@/lib/utils' import { assert, parseZodSchema } from '@/lib/utils'
import { projectIdParamsSchema } from '../projects/schemas' import { projectIdParamsSchema } from '../projects/schemas'
import { paginationAndPopulateConsumerSchema } from './schemas' import { paginationAndPopulateConsumerSchema } from './schemas'
@ -19,7 +19,7 @@ const route = createRoute({
operationId: 'listConsumers', operationId: 'listConsumers',
method: 'get', method: 'get',
path: 'projects/{projectId}/consumers', path: 'projects/{projectId}/consumers',
security: [{ bearerAuth: [] }], security: openapiAuthenticatedSecuritySchemas,
request: { request: {
params: projectIdParamsSchema, params: projectIdParamsSchema,
query: paginationAndPopulateConsumerSchema query: paginationAndPopulateConsumerSchema

Wyświetl plik

@ -8,14 +8,13 @@ import { upsertStripeCustomer } from '@/lib/billing/upsert-stripe-customer'
import { upsertStripePricingPlans } from '@/lib/billing/upsert-stripe-pricing-plans' import { upsertStripePricingPlans } from '@/lib/billing/upsert-stripe-pricing-plans'
import { upsertStripeSubscription } from '@/lib/billing/upsert-stripe-subscription' import { upsertStripeSubscription } from '@/lib/billing/upsert-stripe-subscription'
import { import {
assert, openapiAuthenticatedSecuritySchemas,
openapiErrorResponse404, openapiErrorResponse404,
openapiErrorResponse409, openapiErrorResponse409,
openapiErrorResponse410, openapiErrorResponse410,
openapiErrorResponses, openapiErrorResponses
parseZodSchema, } from '@/lib/openapi-utils'
sha256 import { assert, parseZodSchema, sha256 } from '@/lib/utils'
} from '@/lib/utils'
const route = createRoute({ const route = createRoute({
description: description:
@ -24,7 +23,7 @@ const route = createRoute({
operationId: 'createConsumer', operationId: 'createConsumer',
method: 'post', method: 'post',
path: 'consumers', path: 'consumers',
security: [{ bearerAuth: [] }], security: openapiAuthenticatedSecuritySchemas,
request: { request: {
body: { body: {
required: true, required: true,

Wyświetl plik

@ -36,6 +36,12 @@ export const apiV1 = new OpenAPIHono({
} }
}) })
apiV1.openAPIRegistry.registerComponent('securitySchemes', 'Bearer', {
type: 'http',
scheme: 'bearer',
bearerFormat: 'JWT'
})
// Public routes // Public routes
const pub = new OpenAPIHono() const pub = new OpenAPIHono()

Wyświetl plik

@ -6,11 +6,10 @@ import { aclTeamMember } from '@/lib/acl-team-member'
import { getProviderToken } from '@/lib/auth/get-provider-token' import { getProviderToken } from '@/lib/auth/get-provider-token'
import { ensureAuthUser } from '@/lib/ensure-auth-user' import { ensureAuthUser } from '@/lib/ensure-auth-user'
import { import {
assert, openapiAuthenticatedSecuritySchemas,
openapiErrorResponses, openapiErrorResponses
parseZodSchema, } from '@/lib/openapi-utils'
sha256 import { assert, parseZodSchema, sha256 } from '@/lib/utils'
} from '@/lib/utils'
const route = createRoute({ const route = createRoute({
description: 'Creates a new project.', description: 'Creates a new project.',
@ -18,7 +17,7 @@ const route = createRoute({
operationId: 'createProject', operationId: 'createProject',
method: 'post', method: 'post',
path: 'projects', path: 'projects',
security: [{ bearerAuth: [] }], security: openapiAuthenticatedSecuritySchemas,
request: { request: {
body: { body: {
required: true, required: true,

Wyświetl plik

@ -4,11 +4,11 @@ import type { AuthenticatedEnv } from '@/lib/types'
import { db, eq, schema } from '@/db' import { db, eq, schema } from '@/db'
import { acl } from '@/lib/acl' import { acl } from '@/lib/acl'
import { import {
assert, openapiAuthenticatedSecuritySchemas,
openapiErrorResponse404, openapiErrorResponse404,
openapiErrorResponses, openapiErrorResponses
parseZodSchema } from '@/lib/openapi-utils'
} from '@/lib/utils' import { assert, parseZodSchema } from '@/lib/utils'
import { populateProjectSchema, projectIdParamsSchema } from './schemas' import { populateProjectSchema, projectIdParamsSchema } from './schemas'
@ -18,7 +18,7 @@ const route = createRoute({
operationId: 'getProject', operationId: 'getProject',
method: 'get', method: 'get',
path: 'projects/{projectId}', path: 'projects/{projectId}',
security: [{ bearerAuth: [] }], security: openapiAuthenticatedSecuritySchemas,
request: { request: {
params: projectIdParamsSchema, params: projectIdParamsSchema,
query: populateProjectSchema query: populateProjectSchema

Wyświetl plik

@ -3,7 +3,11 @@ import { createRoute, type OpenAPIHono, z } from '@hono/zod-openapi'
import type { AuthenticatedEnv } from '@/lib/types' import type { AuthenticatedEnv } from '@/lib/types'
import { db, eq, schema } from '@/db' import { db, eq, schema } from '@/db'
import { ensureAuthUser } from '@/lib/ensure-auth-user' import { ensureAuthUser } from '@/lib/ensure-auth-user'
import { openapiErrorResponses, parseZodSchema } from '@/lib/utils' import {
openapiAuthenticatedSecuritySchemas,
openapiErrorResponses
} from '@/lib/openapi-utils'
import { parseZodSchema } from '@/lib/utils'
import { paginationAndPopulateProjectSchema } from './schemas' import { paginationAndPopulateProjectSchema } from './schemas'
@ -13,7 +17,7 @@ const route = createRoute({
operationId: 'listProjects', operationId: 'listProjects',
method: 'get', method: 'get',
path: 'projects', path: 'projects',
security: [{ bearerAuth: [] }], security: openapiAuthenticatedSecuritySchemas,
request: { request: {
query: paginationAndPopulateProjectSchema query: paginationAndPopulateProjectSchema
}, },

Wyświetl plik

@ -3,11 +3,11 @@ import { createRoute, type OpenAPIHono } from '@hono/zod-openapi'
import type { AuthenticatedEnv } from '@/lib/types' import type { AuthenticatedEnv } from '@/lib/types'
import { db, eq, schema } from '@/db' import { db, eq, schema } from '@/db'
import { import {
assert, openapiAuthenticatedSecuritySchemas,
openapiErrorResponse404, openapiErrorResponse404,
openapiErrorResponses, openapiErrorResponses
parseZodSchema } from '@/lib/openapi-utils'
} from '@/lib/utils' import { assert, parseZodSchema } from '@/lib/utils'
import { projectIdParamsSchema } from './schemas' import { projectIdParamsSchema } from './schemas'
@ -17,7 +17,7 @@ const route = createRoute({
operationId: 'updateProject', operationId: 'updateProject',
method: 'put', method: 'put',
path: 'projects/{projectId}', path: 'projects/{projectId}',
security: [{ bearerAuth: [] }], security: openapiAuthenticatedSecuritySchemas,
request: { request: {
params: projectIdParamsSchema, params: projectIdParamsSchema,
body: { body: {

Wyświetl plik

@ -4,7 +4,11 @@ import type { AuthenticatedEnv } from '@/lib/types'
import { db, schema } from '@/db' import { db, schema } from '@/db'
import { ensureAuthUser } from '@/lib/ensure-auth-user' import { ensureAuthUser } from '@/lib/ensure-auth-user'
import { ensureUniqueTeamSlug } from '@/lib/ensure-unique-team-slug' import { ensureUniqueTeamSlug } from '@/lib/ensure-unique-team-slug'
import { assert, openapiErrorResponses, parseZodSchema } from '@/lib/utils' import {
openapiAuthenticatedSecuritySchemas,
openapiErrorResponses
} from '@/lib/openapi-utils'
import { assert, parseZodSchema } from '@/lib/utils'
const route = createRoute({ const route = createRoute({
description: 'Creates a team.', description: 'Creates a team.',
@ -12,7 +16,7 @@ const route = createRoute({
operationId: 'createTeam', operationId: 'createTeam',
method: 'post', method: 'post',
path: 'teams', path: 'teams',
security: [{ bearerAuth: [] }], security: openapiAuthenticatedSecuritySchemas,
request: { request: {
body: { body: {
required: true, required: true,

Wyświetl plik

@ -4,11 +4,11 @@ import type { AuthenticatedEnv } from '@/lib/types'
import { db, eq, schema } from '@/db' import { db, eq, schema } from '@/db'
import { aclTeamAdmin } from '@/lib/acl-team-admin' import { aclTeamAdmin } from '@/lib/acl-team-admin'
import { import {
assert, openapiAuthenticatedSecuritySchemas,
openapiErrorResponse404, openapiErrorResponse404,
openapiErrorResponses, openapiErrorResponses
parseZodSchema } from '@/lib/openapi-utils'
} from '@/lib/utils' import { assert, parseZodSchema } from '@/lib/utils'
import { teamSlugParamsSchema } from './schemas' import { teamSlugParamsSchema } from './schemas'
@ -18,7 +18,7 @@ const route = createRoute({
operationId: 'deleteTeam', operationId: 'deleteTeam',
method: 'delete', method: 'delete',
path: 'teams/{team}', path: 'teams/{team}',
security: [{ bearerAuth: [] }], security: openapiAuthenticatedSecuritySchemas,
request: { request: {
params: teamSlugParamsSchema params: teamSlugParamsSchema
}, },

Wyświetl plik

@ -4,11 +4,11 @@ import type { AuthenticatedEnv } from '@/lib/types'
import { db, eq, schema } from '@/db' import { db, eq, schema } from '@/db'
import { aclTeamMember } from '@/lib/acl-team-member' import { aclTeamMember } from '@/lib/acl-team-member'
import { import {
assert, openapiAuthenticatedSecuritySchemas,
openapiErrorResponse404, openapiErrorResponse404,
openapiErrorResponses, openapiErrorResponses
parseZodSchema } from '@/lib/openapi-utils'
} from '@/lib/utils' import { assert, parseZodSchema } from '@/lib/utils'
import { teamSlugParamsSchema } from './schemas' import { teamSlugParamsSchema } from './schemas'
@ -18,7 +18,7 @@ const route = createRoute({
operationId: 'getTeam', operationId: 'getTeam',
method: 'get', method: 'get',
path: 'teams/{team}', path: 'teams/{team}',
security: [{ bearerAuth: [] }], security: openapiAuthenticatedSecuritySchemas,
request: { request: {
params: teamSlugParamsSchema params: teamSlugParamsSchema
}, },

Wyświetl plik

@ -2,7 +2,11 @@ import { createRoute, type OpenAPIHono, z } from '@hono/zod-openapi'
import type { AuthenticatedEnv } from '@/lib/types' import type { AuthenticatedEnv } from '@/lib/types'
import { db, eq, paginationSchema, schema } from '@/db' import { db, eq, paginationSchema, schema } from '@/db'
import { openapiErrorResponses, parseZodSchema } from '@/lib/utils' import {
openapiAuthenticatedSecuritySchemas,
openapiErrorResponses
} from '@/lib/openapi-utils'
import { parseZodSchema } from '@/lib/utils'
const route = createRoute({ const route = createRoute({
description: 'Lists all teams the authenticated user belongs to.', description: 'Lists all teams the authenticated user belongs to.',
@ -10,7 +14,7 @@ const route = createRoute({
operationId: 'listTeams', operationId: 'listTeams',
method: 'get', method: 'get',
path: 'teams', path: 'teams',
security: [{ bearerAuth: [] }], security: openapiAuthenticatedSecuritySchemas,
request: { request: {
query: paginationSchema query: paginationSchema
}, },

Wyświetl plik

@ -4,12 +4,12 @@ import type { AuthenticatedEnv } from '@/lib/types'
import { and, db, eq, schema } from '@/db' import { and, db, eq, schema } from '@/db'
import { aclTeamAdmin } from '@/lib/acl-team-admin' import { aclTeamAdmin } from '@/lib/acl-team-admin'
import { import {
assert, openapiAuthenticatedSecuritySchemas,
openapiErrorResponse404, openapiErrorResponse404,
openapiErrorResponse409, openapiErrorResponse409,
openapiErrorResponses, openapiErrorResponses
parseZodSchema } from '@/lib/openapi-utils'
} from '@/lib/utils' import { assert, parseZodSchema } from '@/lib/utils'
import { teamSlugParamsSchema } from '../schemas' import { teamSlugParamsSchema } from '../schemas'
@ -19,7 +19,7 @@ const route = createRoute({
operationId: 'createTeamMember', operationId: 'createTeamMember',
method: 'post', method: 'post',
path: 'teams/{team}/members', path: 'teams/{team}/members',
security: [{ bearerAuth: [] }], security: openapiAuthenticatedSecuritySchemas,
request: { request: {
params: teamSlugParamsSchema, params: teamSlugParamsSchema,
body: { body: {

Wyświetl plik

@ -5,11 +5,11 @@ import { and, db, eq, schema } from '@/db'
import { aclTeamAdmin } from '@/lib/acl-team-admin' import { aclTeamAdmin } from '@/lib/acl-team-admin'
import { aclTeamMember } from '@/lib/acl-team-member' import { aclTeamMember } from '@/lib/acl-team-member'
import { import {
assert, openapiAuthenticatedSecuritySchemas,
openapiErrorResponse404, openapiErrorResponse404,
openapiErrorResponses, openapiErrorResponses
parseZodSchema } from '@/lib/openapi-utils'
} from '@/lib/utils' import { assert, parseZodSchema } from '@/lib/utils'
import { teamSlugTeamMemberUserIdParamsSchema } from './schemas' import { teamSlugTeamMemberUserIdParamsSchema } from './schemas'
@ -19,7 +19,7 @@ const route = createRoute({
operationId: 'deleteTeamMember', operationId: 'deleteTeamMember',
method: 'delete', method: 'delete',
path: 'teams/{team}/members/{userId}', path: 'teams/{team}/members/{userId}',
security: [{ bearerAuth: [] }], security: openapiAuthenticatedSecuritySchemas,
request: { request: {
params: teamSlugTeamMemberUserIdParamsSchema params: teamSlugTeamMemberUserIdParamsSchema
}, },

Wyświetl plik

@ -5,11 +5,11 @@ import { and, db, eq, schema } from '@/db'
import { aclTeamAdmin } from '@/lib/acl-team-admin' import { aclTeamAdmin } from '@/lib/acl-team-admin'
import { aclTeamMember } from '@/lib/acl-team-member' import { aclTeamMember } from '@/lib/acl-team-member'
import { import {
assert, openapiAuthenticatedSecuritySchemas,
openapiErrorResponse404, openapiErrorResponse404,
openapiErrorResponses, openapiErrorResponses
parseZodSchema } from '@/lib/openapi-utils'
} from '@/lib/utils' import { assert, parseZodSchema } from '@/lib/utils'
import { teamSlugTeamMemberUserIdParamsSchema } from './schemas' import { teamSlugTeamMemberUserIdParamsSchema } from './schemas'
@ -19,7 +19,7 @@ const route = createRoute({
operationId: 'updateTeamMember', operationId: 'updateTeamMember',
method: 'put', method: 'put',
path: 'teams/{team}/members/{userId}', path: 'teams/{team}/members/{userId}',
security: [{ bearerAuth: [] }], security: openapiAuthenticatedSecuritySchemas,
request: { request: {
params: teamSlugTeamMemberUserIdParamsSchema, params: teamSlugTeamMemberUserIdParamsSchema,
body: { body: {

Wyświetl plik

@ -4,11 +4,11 @@ import type { AuthenticatedEnv } from '@/lib/types'
import { db, eq, schema } from '@/db' import { db, eq, schema } from '@/db'
import { aclTeamAdmin } from '@/lib/acl-team-admin' import { aclTeamAdmin } from '@/lib/acl-team-admin'
import { import {
assert, openapiAuthenticatedSecuritySchemas,
openapiErrorResponse404, openapiErrorResponse404,
openapiErrorResponses, openapiErrorResponses
parseZodSchema } from '@/lib/openapi-utils'
} from '@/lib/utils' import { assert, parseZodSchema } from '@/lib/utils'
import { teamSlugParamsSchema } from './schemas' import { teamSlugParamsSchema } from './schemas'
@ -18,7 +18,7 @@ const route = createRoute({
operationId: 'updateTeam', operationId: 'updateTeam',
method: 'put', method: 'put',
path: 'teams/{team}', path: 'teams/{team}',
security: [{ bearerAuth: [] }], security: openapiAuthenticatedSecuritySchemas,
request: { request: {
params: teamSlugParamsSchema, params: teamSlugParamsSchema,
body: { body: {

Wyświetl plik

@ -4,11 +4,11 @@ import type { AuthenticatedEnv } from '@/lib/types'
import { db, eq, schema } from '@/db' import { db, eq, schema } from '@/db'
import { acl } from '@/lib/acl' import { acl } from '@/lib/acl'
import { import {
assert, openapiAuthenticatedSecuritySchemas,
openapiErrorResponse404, openapiErrorResponse404,
openapiErrorResponses, openapiErrorResponses
parseZodSchema } from '@/lib/openapi-utils'
} from '@/lib/utils' import { assert, parseZodSchema } from '@/lib/utils'
import { userIdParamsSchema } from './schemas' import { userIdParamsSchema } from './schemas'
@ -18,7 +18,7 @@ const route = createRoute({
operationId: 'getUser', operationId: 'getUser',
method: 'get', method: 'get',
path: 'users/{userId}', path: 'users/{userId}',
security: [{ bearerAuth: [] }], security: openapiAuthenticatedSecuritySchemas,
request: { request: {
params: userIdParamsSchema params: userIdParamsSchema
}, },

Wyświetl plik

@ -4,11 +4,11 @@ import type { AuthenticatedEnv } from '@/lib/types'
import { db, eq, schema } from '@/db' import { db, eq, schema } from '@/db'
import { acl } from '@/lib/acl' import { acl } from '@/lib/acl'
import { import {
assert, openapiAuthenticatedSecuritySchemas,
openapiErrorResponse404, openapiErrorResponse404,
openapiErrorResponses, openapiErrorResponses
parseZodSchema } from '@/lib/openapi-utils'
} from '@/lib/utils' import { assert, parseZodSchema } from '@/lib/utils'
import { userIdParamsSchema } from './schemas' import { userIdParamsSchema } from './schemas'
@ -18,7 +18,7 @@ const route = createRoute({
operationId: 'updateUser', operationId: 'updateUser',
method: 'put', method: 'put',
path: 'users/{userId}', path: 'users/{userId}',
security: [{ bearerAuth: [] }], security: openapiAuthenticatedSecuritySchemas,
request: { request: {
params: userIdParamsSchema, params: userIdParamsSchema,
body: { body: {

Wyświetl plik

@ -0,0 +1,52 @@
import { z } from '@hono/zod-openapi'
const openapiErrorContent = {
'application/json': {
schema: z.object({
error: z.string()
})
}
} as const
export const openapiErrorResponses = {
400: {
description: 'Bad Request',
content: openapiErrorContent
},
401: {
description: 'Unauthorized',
content: openapiErrorContent
},
403: {
description: 'Forbidden',
content: openapiErrorContent
}
} as const
export const openapiErrorResponse404 = {
404: {
description: 'Not Found',
content: openapiErrorContent
}
} as const
export const openapiErrorResponse409 = {
409: {
description: 'Conflict',
content: openapiErrorContent
}
} as const
export const openapiErrorResponse410 = {
410: {
description: 'Gone',
content: openapiErrorContent
}
} as const
// No `as const` because zod openapi doesn't support readonly for `security`
export const openapiAuthenticatedSecuritySchemas = [
{
Bearer: []
}
]

Wyświetl plik

@ -2,7 +2,6 @@ import { createHash, randomUUID } from 'node:crypto'
import type { ContentfulStatusCode } from 'hono/utils/http-status' import type { ContentfulStatusCode } from 'hono/utils/http-status'
import type { ZodSchema } from 'zod' import type { ZodSchema } from 'zod'
import { z } from '@hono/zod-openapi'
import { HttpError, ZodValidationError } from './errors' import { HttpError, ZodValidationError } from './errors'
@ -50,47 +49,3 @@ export function parseZodSchema<T>(
}) })
} }
} }
const errorContent = {
'application/json': {
schema: z.object({
error: z.string()
})
}
} as const
export const openapiErrorResponses = {
400: {
description: 'Bad Request',
content: errorContent
},
401: {
description: 'Unauthorized',
content: errorContent
},
403: {
description: 'Forbidden',
content: errorContent
}
} as const
export const openapiErrorResponse404 = {
404: {
description: 'Not Found',
content: errorContent
}
} as const
export const openapiErrorResponse409 = {
409: {
description: 'Conflict',
content: errorContent
}
} as const
export const openapiErrorResponse410 = {
410: {
description: 'Gone',
content: errorContent
}
} as const