File size: 1,851 Bytes
89a2873 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | export * as ServerAuth from "./auth"
import { Config as EffectConfig, Context, Effect, Layer, Option, Redacted } from "effect"
export type Credentials = {
password?: string
username?: string
}
export type DecodedCredentials = {
readonly username: string
readonly password: Redacted.Redacted
}
export type Info = {
readonly password: Option.Option<string>
readonly username: string
}
export class Config extends Context.Service<Config, Info>()("@opencode/ServerAuthConfig") {
static configLayer(input: Info) {
return Layer.succeed(this, this.of(input))
}
static get layer() {
return Layer.effect(
this,
Effect.gen(function* () {
return Config.of(
yield* EffectConfig.all({
password: EffectConfig.string("OPENCODE_SERVER_PASSWORD").pipe(EffectConfig.option),
username: EffectConfig.string("OPENCODE_SERVER_USERNAME").pipe(EffectConfig.withDefault("opencode")),
}),
)
}),
)
}
}
export function required(config: Info) {
return Option.isSome(config.password) && config.password.value !== ""
}
export function authorized(credentials: DecodedCredentials, config: Info) {
return (
Option.isSome(config.password) &&
credentials.username === config.username &&
Redacted.value(credentials.password) === config.password.value
)
}
export function header(credentials?: Credentials) {
const password = credentials?.password ?? process.env.OPENCODE_SERVER_PASSWORD
if (!password) return undefined
return `Basic ${Buffer.from(`${credentials?.username ?? process.env.OPENCODE_SERVER_USERNAME ?? "opencode"}:${password}`).toString("base64")}`
}
export function headers(credentials?: Credentials) {
const authorization = header(credentials)
if (!authorization) return undefined
return { Authorization: authorization }
}
|