Skip to content
Merged
8 changes: 7 additions & 1 deletion docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,13 @@ the API's `ResumeSandbox` gRPC and retries — paused sandboxes wake transparent

A separate REST service (port 3010, spec `spec/openapi-dashboard.yml`) consumed by the web
dashboard, not the SDK: team management/provisioning, template tags, build listings, admin
bootstrap. Talks to Postgres and ClickHouse; never talks to orchestrators.
bootstrap. Its workspace-agnostic `/admin/v1` operations are defined in the same dashboard
OpenAPI contract and registered on the existing router. Their `AdminJWTAuth` OpenAPI security scheme
accepts only short-lived service JWTs verified against the workspace-api
`/.well-known/jwks.json` endpoint, with accepted signing methods derived from each JWK's required
`alg` metadata. Issuers and audiences are configured through the JSON `ADMIN_AUTH_PROVIDER_CONFIG` value —
the same config shape as `AUTH_PROVIDER_CONFIG`. Talks to Postgres and ClickHouse; never talks to
orchestrators.

### Docker reverse proxy (`packages/docker-reverse-proxy`)

Expand Down
8 changes: 4 additions & 4 deletions packages/api/internal/cfg/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"github.com/caarlos0/env/v11"
"github.com/golang-jwt/jwt/v5"

"github.com/e2b-dev/infra/packages/auth/pkg/auth"
sharedauth "github.com/e2b-dev/infra/packages/auth/pkg/auth"
)

const (
Expand Down Expand Up @@ -102,7 +102,7 @@ type Config struct {

VolumesToken VolumesTokenConfig

AuthProvider auth.ProviderConfig `env:"AUTH_PROVIDER_CONFIG"`
AuthProvider sharedauth.ProviderConfig `env:"AUTH_PROVIDER_CONFIG"`

DefaultPersistentVolumeType string `env:"DEFAULT_PERSISTENT_VOLUME_TYPE"`

Expand Down Expand Up @@ -198,8 +198,8 @@ var (
ErrUnknownKeyType = errors.New("unknown JWT signing key type")

parserFuncs = map[reflect.Type]env.ParserFunc{
reflect.TypeFor[auth.ProviderConfig](): func(v string) (any, error) {
return auth.ParseProviderConfig(v)
reflect.TypeFor[sharedauth.ProviderConfig](): func(v string) (any, error) {
return sharedauth.ParseProviderConfig(v)
},
reflect.TypeFor[JWTSigningKey](): func(v string) (any, error) {
keyPieces := strings.SplitN(v, ":", 2)
Expand Down
68 changes: 68 additions & 0 deletions packages/auth/internal/authcontext/context.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package authcontext

import (
"github.com/gin-gonic/gin"
"github.com/google/uuid"

"github.com/e2b-dev/infra/packages/auth/pkg/types"
)

const (
teamContextKey = "team"
userIDContextKey = "user_id"
)

func SetUserID(c *gin.Context, userID uuid.UUID) {
setInGinContext(c, userIDContextKey, userID)
}

func GetUserID(c *gin.Context) (uuid.UUID, bool) {
return getFromGinContextSafely[uuid.UUID](c, userIDContextKey)
}

func MustGetUserID(c *gin.Context) uuid.UUID {
userID, ok := GetUserID(c)
if !ok {
panic("user id not found in context")
}

return userID
}

func SetTeamInfo(c *gin.Context, t *types.Team) {
setInGinContext(c, teamContextKey, t)
}

func MustGetTeamInfo(c *gin.Context) *types.Team {
team, ok := GetTeamInfo(c)
if !ok {
panic("team not found in context")
}

return team
}

func MustGetTeamID(c *gin.Context) uuid.UUID {
return MustGetTeamInfo(c).Team.ID
}

func GetTeamInfo(c *gin.Context) (*types.Team, bool) {
return getFromGinContextSafely[*types.Team](c, teamContextKey)
}

func setInGinContext(c *gin.Context, key string, value any) {
c.Set(key, value)
}

func getFromGinContextSafely[T any](c *gin.Context, contextKey string) (T, bool) {
var t T

val, ok := c.Get(contextKey)
if !ok {
return t, false
}

t, ok = val.(T)

return t, ok
}
Loading
Loading