mirror of
https://github.com/saltbo/zpan.git
synced 2026-08-28 15:51:29 +08:00
2657f82ef1
* feat(auth): add contextual OAuth workspace grants * fix(auth): register RFC 9396 detail types * fix(openapi): restore delegated CLI auth profile * fix(store): recover paid capacity fulfillment * fix(auth): close OAuth contract gaps * fix(store): resume verified x402 settlements * chore(deps): update zpan cloud sdk to 2.5.2 * test(store): cover verified settlement recovery * fix(auth): localize standard consent scopes * fix(docker): include dependency patches before install * fix(store): harden x402 purchase responses * test(auth): cover OAuth authorization boundaries * docs: add PR 550 verification screenshots * chore: remove temporary verification screenshots * docs(openapi): document exhausted capacity response
47 lines
1.4 KiB
TypeScript
47 lines
1.4 KiB
TypeScript
import {
|
|
type OAuthGrant as OAuthGrantDTO,
|
|
type OAuthResourceScope,
|
|
oauthGrantDTO,
|
|
oauthResourceScopeSchema,
|
|
} from '@shared/schemas'
|
|
import type { Database } from '../platform/interface'
|
|
import type { Deps } from './deps'
|
|
import { notFound } from './ports'
|
|
|
|
export async function listOAuthGrants(
|
|
deps: Pick<Deps, 'oauth' | 'org'>,
|
|
db: Database,
|
|
input: { userId: string },
|
|
): Promise<{ items: OAuthGrantDTO[] }> {
|
|
const items = await deps.oauth.listGrants(db, input.userId)
|
|
const workspaceIds = [...new Set(items.flatMap((item) => item.workspaceIds))]
|
|
const orgNames = await deps.org.getOrgNames(workspaceIds)
|
|
return {
|
|
items: items.map((item) => {
|
|
const { workspaceIds: itemWorkspaceIds, ...grant } = item
|
|
return oauthGrantDTO({
|
|
...grant,
|
|
scopes: item.scopes.filter(isOAuthResourceScope),
|
|
workspaces: itemWorkspaceIds.map((id) => ({ id, name: orgNames.get(id) ?? null })),
|
|
})
|
|
}),
|
|
}
|
|
}
|
|
|
|
function isOAuthResourceScope(scope: string): scope is OAuthResourceScope {
|
|
return oauthResourceScopeSchema.safeParse(scope).success
|
|
}
|
|
|
|
export async function revokeOAuthGrant(
|
|
deps: Pick<Deps, 'oauth'>,
|
|
db: Database,
|
|
input: { userId: string; grantId: string; now?: Date },
|
|
): Promise<void> {
|
|
const revoked = await deps.oauth.revokeGrant(db, {
|
|
userId: input.userId,
|
|
grantId: input.grantId,
|
|
now: input.now ?? new Date(),
|
|
})
|
|
if (!revoked) throw notFound('OAuth grant not found')
|
|
}
|