11import { NodeHttpServer } from "@effect/platform-node"
2- import { Flag } from "@opencode-ai/core/flag/flag"
32import { describe , expect } from "bun:test"
4- import { Effect , Layer , Schema } from "effect"
3+ import { Effect , Layer , Option , Schema } from "effect"
54import { HttpClient , HttpClientRequest , HttpRouter } from "effect/unstable/http"
65import { HttpApi , HttpApiBuilder , HttpApiEndpoint , HttpApiGroup } from "effect/unstable/httpapi"
7- import { Authorization , authorizationLayer } from "../../src/server/routes/instance/httpapi/middleware/authorization"
6+ import {
7+ Authorization ,
8+ ServerAuthConfig ,
9+ authorizationLayer ,
10+ } from "../../src/server/routes/instance/httpapi/middleware/authorization"
811import { testEffect } from "../lib/effect"
912
1013const Api = HttpApi . make ( "test-authorization" ) . add (
@@ -24,48 +27,19 @@ const apiLayer = HttpRouter.serve(
2427 { disableListenLog : true , disableLogger : true } ,
2528) . pipe ( Layer . provideMerge ( NodeHttpServer . layerTest ) )
2629
27- const testStateLayer = Layer . effectDiscard (
28- Effect . gen ( function * ( ) {
29- const original = {
30- OPENCODE_SERVER_PASSWORD : Flag . OPENCODE_SERVER_PASSWORD ,
31- OPENCODE_SERVER_USERNAME : Flag . OPENCODE_SERVER_USERNAME ,
32- }
33- Flag . OPENCODE_SERVER_PASSWORD = undefined
34- Flag . OPENCODE_SERVER_USERNAME = undefined
35- yield * Effect . addFinalizer ( ( ) =>
36- Effect . sync ( ( ) => {
37- Flag . OPENCODE_SERVER_PASSWORD = original . OPENCODE_SERVER_PASSWORD
38- Flag . OPENCODE_SERVER_USERNAME = original . OPENCODE_SERVER_USERNAME
39- } ) ,
40- )
41- } ) ,
42- )
30+ const noAuthLayer = ServerAuthConfig . layer ( { password : Option . none ( ) , username : "opencode" } )
31+ const secretLayer = ServerAuthConfig . layer ( { password : Option . some ( "secret" ) , username : "opencode" } )
32+ const kitSecretLayer = ServerAuthConfig . layer ( { password : Option . some ( "secret" ) , username : "kit" } )
4333
44- const it = testEffect ( apiLayer . pipe ( Layer . provideMerge ( testStateLayer ) ) )
34+ const it = testEffect ( apiLayer . pipe ( Layer . provide ( noAuthLayer ) ) )
35+ const itSecret = testEffect ( apiLayer . pipe ( Layer . provide ( secretLayer ) ) )
36+ const itKitSecret = testEffect ( apiLayer . pipe ( Layer . provide ( kitSecretLayer ) ) )
4537
4638const basic = ( username : string , password : string ) =>
4739 `Basic ${ Buffer . from ( `${ username } :${ password } ` ) . toString ( "base64" ) } `
4840
4941const token = ( username : string , password : string ) => Buffer . from ( `${ username } :${ password } ` ) . toString ( "base64" )
5042
51- const useAuth = ( input : { password : string ; username ?: string } ) =>
52- Effect . acquireRelease (
53- Effect . sync ( ( ) => {
54- const original = {
55- OPENCODE_SERVER_PASSWORD : Flag . OPENCODE_SERVER_PASSWORD ,
56- OPENCODE_SERVER_USERNAME : Flag . OPENCODE_SERVER_USERNAME ,
57- }
58- Flag . OPENCODE_SERVER_PASSWORD = input . password
59- Flag . OPENCODE_SERVER_USERNAME = input . username
60- return original
61- } ) ,
62- ( original ) =>
63- Effect . sync ( ( ) => {
64- Flag . OPENCODE_SERVER_PASSWORD = original . OPENCODE_SERVER_PASSWORD
65- Flag . OPENCODE_SERVER_USERNAME = original . OPENCODE_SERVER_USERNAME
66- } ) ,
67- )
68-
6943const getProbe = ( headers ?: Record < string , string > ) =>
7044 HttpClientRequest . get ( "/probe" ) . pipe (
7145 headers ? HttpClientRequest . setHeaders ( headers ) : ( request ) => request ,
@@ -82,10 +56,8 @@ describe("HttpApi authorization middleware", () => {
8256 } ) ,
8357 )
8458
85- it . live ( "requires configured password for basic auth" , ( ) =>
59+ itSecret . live ( "requires configured password for basic auth" , ( ) =>
8660 Effect . gen ( function * ( ) {
87- yield * useAuth ( { password : "secret" } )
88-
8961 const [ missing , badPassword , good ] = yield * Effect . all (
9062 [
9163 getProbe ( ) ,
@@ -101,10 +73,8 @@ describe("HttpApi authorization middleware", () => {
10173 } ) ,
10274 )
10375
104- it . live ( "respects configured basic auth username" , ( ) =>
76+ itKitSecret . live ( "respects configured basic auth username" , ( ) =>
10577 Effect . gen ( function * ( ) {
106- yield * useAuth ( { username : "kit" , password : "secret" } )
107-
10878 const [ defaultUser , configuredUser ] = yield * Effect . all (
10979 [ getProbe ( { authorization : basic ( "opencode" , "secret" ) } ) , getProbe ( { authorization : basic ( "kit" , "secret" ) } ) ] ,
11080 { concurrency : "unbounded" } ,
@@ -115,20 +85,16 @@ describe("HttpApi authorization middleware", () => {
11585 } ) ,
11686 )
11787
118- it . live ( "accepts auth token query credentials" , ( ) =>
88+ itSecret . live ( "accepts auth token query credentials" , ( ) =>
11989 Effect . gen ( function * ( ) {
120- yield * useAuth ( { password : "secret" } )
121-
12290 const response = yield * HttpClient . get ( `/probe?auth_token=${ encodeURIComponent ( token ( "opencode" , "secret" ) ) } ` )
12391
12492 expect ( response . status ) . toBe ( 200 )
12593 } ) ,
12694 )
12795
128- it . live ( "rejects malformed auth token query credentials" , ( ) =>
96+ itSecret . live ( "rejects malformed auth token query credentials" , ( ) =>
12997 Effect . gen ( function * ( ) {
130- yield * useAuth ( { password : "secret" } )
131-
13298 const response = yield * HttpClient . get ( "/probe?auth_token=not-base64" )
13399
134100 expect ( response . status ) . toBe ( 401 )
0 commit comments