auth.ts 1.8 KB

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