refactor(api): scope oauth operations by integration
This commit is contained in:
parent
fd19fa89c4
commit
a772767e9b
19 changed files with 404 additions and 303 deletions
|
|
@ -181,14 +181,14 @@ describe("Integration", () => {
|
|||
}),
|
||||
)
|
||||
|
||||
const attempt = yield* integrations.connection.oauth({
|
||||
const attempt = yield* integrations.oauth.connect({
|
||||
integrationID,
|
||||
methodID,
|
||||
inputs: {},
|
||||
label: "Personal",
|
||||
})
|
||||
expect(attempt.mode).toBe("code")
|
||||
yield* integrations.attempt.complete({ attemptID: attempt.attemptID, code: "1234" })
|
||||
yield* integrations.oauth.complete({ integrationID, attemptID: attempt.attemptID, code: "1234" })
|
||||
|
||||
expect((yield* credentials.list(integrationID))[0]).toEqual(
|
||||
expect.objectContaining({
|
||||
|
|
@ -230,12 +230,17 @@ describe("Integration", () => {
|
|||
}),
|
||||
)
|
||||
|
||||
const attempt = yield* integrations.connection.oauth({ integrationID, methodID, inputs: {} })
|
||||
expect(yield* integrations.attempt.complete({ attemptID: attempt.attemptID }).pipe(Effect.flip)).toBeInstanceOf(
|
||||
Integration.CodeRequiredError,
|
||||
)
|
||||
const attempt = yield* integrations.oauth.connect({ integrationID, methodID, inputs: {} })
|
||||
expect(
|
||||
yield* integrations.oauth.complete({ integrationID, attemptID: attempt.attemptID }).pipe(Effect.flip),
|
||||
).toBeInstanceOf(Integration.CodeRequiredError)
|
||||
expect(closed).toBe(false)
|
||||
yield* integrations.attempt.cancel(attempt.attemptID)
|
||||
yield* integrations.oauth.cancel({
|
||||
integrationID: Integration.ID.make("other"),
|
||||
attemptID: attempt.attemptID,
|
||||
})
|
||||
expect(closed).toBe(false)
|
||||
yield* integrations.oauth.cancel({ integrationID, attemptID: attempt.attemptID })
|
||||
expect(closed).toBe(true)
|
||||
expect(yield* credentials.list(integrationID)).toEqual([])
|
||||
}),
|
||||
|
|
@ -263,9 +268,9 @@ describe("Integration", () => {
|
|||
}),
|
||||
)
|
||||
|
||||
const attempt = yield* integrations.connection.oauth({ integrationID, methodID, inputs: {} })
|
||||
const attempt = yield* integrations.oauth.connect({ integrationID, methodID, inputs: {} })
|
||||
yield* Effect.yieldNow
|
||||
expect(yield* integrations.attempt.status(attempt.attemptID)).toEqual({
|
||||
expect(yield* integrations.oauth.status({ integrationID, attemptID: attempt.attemptID })).toEqual({
|
||||
status: "complete",
|
||||
time: attempt.time,
|
||||
})
|
||||
|
|
@ -301,12 +306,12 @@ describe("Integration", () => {
|
|||
}),
|
||||
)
|
||||
|
||||
const attempt = yield* integrations.connection.oauth({ integrationID, methodID, inputs: {} })
|
||||
const exit = yield* integrations.attempt
|
||||
.complete({ attemptID: attempt.attemptID, code: "1234" })
|
||||
const attempt = yield* integrations.oauth.connect({ integrationID, methodID, inputs: {} })
|
||||
const exit = yield* integrations.oauth
|
||||
.complete({ integrationID, attemptID: attempt.attemptID, code: "1234" })
|
||||
.pipe(Effect.exit)
|
||||
expect(Exit.isFailure(exit) && Cause.hasDies(exit.cause)).toBe(true)
|
||||
expect(yield* integrations.attempt.status(attempt.attemptID)).toEqual({
|
||||
expect(yield* integrations.oauth.status({ integrationID, attemptID: attempt.attemptID })).toEqual({
|
||||
status: "failed",
|
||||
message: "credential persistence failed",
|
||||
time: attempt.time,
|
||||
|
|
@ -337,11 +342,11 @@ describe("Integration", () => {
|
|||
}),
|
||||
)
|
||||
|
||||
const attempt = yield* integrations.connection.oauth({ integrationID, methodID, inputs: {} })
|
||||
const attempt = yield* integrations.oauth.connect({ integrationID, methodID, inputs: {} })
|
||||
expect(attempt.time.expires - attempt.time.created).toBe(Duration.toMillis(Duration.minutes(10)))
|
||||
yield* TestClock.adjust(Duration.minutes(10))
|
||||
yield* Effect.yieldNow
|
||||
expect(yield* integrations.attempt.status(attempt.attemptID)).toEqual({
|
||||
expect(yield* integrations.oauth.status({ integrationID, attemptID: attempt.attemptID })).toEqual({
|
||||
status: "expired",
|
||||
time: attempt.time,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -187,11 +187,11 @@ function resourceMcpLayer(url: string, onFormCreated?: (form: Form.Info) => Effe
|
|||
active: unusedIntegration,
|
||||
resolve: unusedIntegration,
|
||||
key: unusedIntegration,
|
||||
oauth: unusedIntegration,
|
||||
update: unusedIntegration,
|
||||
remove: unusedIntegration,
|
||||
},
|
||||
attempt: {
|
||||
oauth: {
|
||||
connect: unusedIntegration,
|
||||
status: unusedIntegration,
|
||||
complete: unusedIntegration,
|
||||
cancel: unusedIntegration,
|
||||
|
|
|
|||
|
|
@ -48,12 +48,12 @@ export function host(overrides: Overrides = {}): PluginContext {
|
|||
get: () => Effect.die("unused integration.get"),
|
||||
connect: {
|
||||
key: () => Effect.die("unused integration.connect.key"),
|
||||
oauth: () => Effect.die("unused integration.connect.oauth"),
|
||||
},
|
||||
attempt: {
|
||||
status: () => Effect.die("unused integration.attempt.status"),
|
||||
complete: () => Effect.die("unused integration.attempt.complete"),
|
||||
cancel: () => Effect.die("unused integration.attempt.cancel"),
|
||||
oauth: {
|
||||
connect: () => Effect.die("unused integration.oauth.connect"),
|
||||
status: () => Effect.die("unused integration.oauth.status"),
|
||||
complete: () => Effect.die("unused integration.oauth.complete"),
|
||||
cancel: () => Effect.die("unused integration.oauth.cancel"),
|
||||
},
|
||||
transform: () => Effect.die("unused integration.transform"),
|
||||
reload: () => Effect.die("unused integration.reload"),
|
||||
|
|
@ -193,12 +193,12 @@ export function integrationHost(integration: Integration.Interface): PluginConte
|
|||
get: () => Effect.die("unused integration.get"),
|
||||
connect: {
|
||||
key: () => Effect.die("unused integration.connect.key"),
|
||||
oauth: () => Effect.die("unused integration.connect.oauth"),
|
||||
},
|
||||
attempt: {
|
||||
status: () => Effect.die("unused integration.attempt.status"),
|
||||
complete: () => Effect.die("unused integration.attempt.complete"),
|
||||
cancel: () => Effect.die("unused integration.attempt.cancel"),
|
||||
oauth: {
|
||||
connect: () => Effect.die("unused integration.oauth.connect"),
|
||||
status: () => Effect.die("unused integration.oauth.status"),
|
||||
complete: () => Effect.die("unused integration.oauth.complete"),
|
||||
cancel: () => Effect.die("unused integration.oauth.cancel"),
|
||||
},
|
||||
reload: integration.reload,
|
||||
connection: {
|
||||
|
|
|
|||
|
|
@ -124,13 +124,17 @@ describe("OpencodePlugin", () => {
|
|||
Effect.gen(function* () {
|
||||
yield* addPlugin()
|
||||
const integrations = yield* Integration.Service
|
||||
const attempt = yield* integrations.connection.oauth({
|
||||
integrationID: Integration.ID.make("opencode"),
|
||||
const integrationID = Integration.ID.make("opencode")
|
||||
const attempt = yield* integrations.oauth.connect({
|
||||
integrationID,
|
||||
methodID: Integration.MethodID.make("device"),
|
||||
inputs: { server: `${server.url.origin}/console///?ignored=true#ignored` },
|
||||
})
|
||||
expect(attempt.url).toBe(`${server.url.origin}/verify`)
|
||||
yield* eventually(integrations.attempt.status(attempt.attemptID), (status) => status.status === "complete")
|
||||
yield* eventually(
|
||||
integrations.oauth.status({ integrationID, attemptID: attempt.attemptID }),
|
||||
(status) => status.status === "complete",
|
||||
)
|
||||
|
||||
expect(requests).toContain("POST /console/auth/device/code")
|
||||
expect(requests).toContain("POST /console/auth/device/token")
|
||||
|
|
@ -147,8 +151,8 @@ describe("OpencodePlugin", () => {
|
|||
it.effect("rejects non-HTTP OpenCode servers", () =>
|
||||
Effect.gen(function* () {
|
||||
yield* addPlugin()
|
||||
const error = yield* (yield* Integration.Service).connection
|
||||
.oauth({
|
||||
const error = yield* (yield* Integration.Service).oauth
|
||||
.connect({
|
||||
integrationID: Integration.ID.make("opencode"),
|
||||
methodID: Integration.MethodID.make("device"),
|
||||
inputs: { server: "ftp://console.example.com" },
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue