Skip to main content
Glama

Storyden

by Southclaws
Mozilla Public License 2.0
229
context.go6.03 kB
package session import ( "context" "errors" "github.com/Southclaws/fault" "github.com/Southclaws/fault/fctx" "github.com/Southclaws/fault/fmsg" "github.com/Southclaws/fault/ftag" "github.com/Southclaws/opt" "github.com/Southclaws/storyden/app/resources/account" "github.com/Southclaws/storyden/app/resources/account/role" "github.com/Southclaws/storyden/app/resources/rbac" ) var ( ErrNoAccountInContext = errors.New("no account in context") ErrMalformedContextValue = errors.New("malformed context value: internal bug") ) var contextKey = struct{}{} type sessionContext struct { account opt.Optional[account.Account] roles role.Roles // NOTE: These are the security schemes defined in the OpenAPI spec under // `securitySchemes` - they aren't generated by the codegen so be careful. securityScheme string // sessionToken stores the session token for later revocation during logout. // This is only populated for browser sessions, not access keys. sessionToken opt.Optional[string] } func WithAccount(ctx context.Context, u account.Account, roles role.Roles) context.Context { return context.WithValue(ctx, contextKey, sessionContext{ account: opt.New(u), roles: roles, securityScheme: "browser", sessionToken: opt.NewEmpty[string](), }) } func WithAccountAndToken(ctx context.Context, u account.Account, roles role.Roles, token string) context.Context { return context.WithValue(ctx, contextKey, sessionContext{ account: opt.New(u), roles: roles, securityScheme: "browser", sessionToken: opt.New(token), }) } func WithAccessKey(ctx context.Context, u account.Account, roles role.Roles) context.Context { return context.WithValue(ctx, contextKey, sessionContext{ account: opt.New(u), roles: roles, securityScheme: "access_key", sessionToken: opt.NewEmpty[string](), }) } func WithGuest(ctx context.Context, roles role.Roles) context.Context { return context.WithValue(ctx, contextKey, sessionContext{ account: opt.NewEmpty[account.Account](), roles: roles, securityScheme: "browser", sessionToken: opt.NewEmpty[string](), }) } func WithInternal(ctx context.Context) context.Context { return context.WithValue(ctx, contextKey, sessionContext{ account: opt.NewEmpty[account.Account](), roles: role.Roles{}, securityScheme: "", sessionToken: opt.NewEmpty[string](), }) } func Authorise(ctx context.Context, fn func() error, perms ...rbac.Permission) error { value := ctx.Value(contextKey) if value == nil { panic("request context does not contain a session context value, this is an internal bug") } sc, ok := value.(sessionContext) if !ok { return fault.Wrap(ErrMalformedContextValue, fctx.With(ctx), ftag.With(ftag.Unauthenticated)) } return sc.roles.Permissions().Authorise(ctx, fn, perms...) } func GetRoles(ctx context.Context) role.Roles { value := ctx.Value(contextKey) if value == nil { panic("request context does not contain a session context value, this is an internal bug") } sc, ok := value.(sessionContext) if !ok { panic(ErrMalformedContextValue) } return sc.roles } // GetAccountID pulls out an account ID associated with the call. func GetAccountID(ctx context.Context) (account.AccountID, error) { value := ctx.Value(contextKey) if value == nil { panic("request context does not contain a session context value, this is an internal bug") } sc, ok := value.(sessionContext) if !ok { return account.AccountID{}, fault.Wrap(ErrMalformedContextValue, fctx.With(ctx), ftag.With(ftag.Unauthenticated)) } acc, ok := sc.account.Get() if !ok { return account.AccountID{}, fault.Wrap(ErrNoAccountInContext, fctx.With(ctx), ftag.With(ftag.Unauthenticated), fmsg.With("GetAccountID"), ) } return acc.ID, nil } // GetAccount pulls out an account associated with the call. func GetAccount(ctx context.Context) (account.Account, error) { value := ctx.Value(contextKey) if value == nil { panic("request context does not contain a session context value, this is an internal bug") } sc, ok := value.(sessionContext) if !ok { return account.Account{}, fault.Wrap(ErrMalformedContextValue, fctx.With(ctx), ftag.With(ftag.Unauthenticated)) } acc, ok := sc.account.Get() if !ok { return account.Account{}, fault.Wrap(ErrNoAccountInContext, fctx.With(ctx), ftag.With(ftag.Unauthenticated), fmsg.With("GetAccount"), ) } return acc, nil } func GetSecurityScheme(ctx context.Context) (string, error) { value := ctx.Value(contextKey) if value == nil { panic("request context does not contain a session context value, this is an internal bug") } sc, ok := value.(sessionContext) if !ok { return "", fault.Wrap(ErrMalformedContextValue, fctx.With(ctx), ftag.With(ftag.Unauthenticated)) } return sc.securityScheme, nil } func GetOptAccountID(ctx context.Context) opt.Optional[account.AccountID] { value := ctx.Value(contextKey) if value == nil { return opt.NewEmpty[account.AccountID]() } sc, ok := value.(sessionContext) if !ok { return opt.NewEmpty[account.AccountID]() } acc, ok := sc.account.Get() if !ok { return opt.NewEmpty[account.AccountID]() } return opt.New(acc.ID) } func GetOptAccount(ctx context.Context) opt.Optional[account.Account] { value := ctx.Value(contextKey) if value == nil { return opt.NewEmpty[account.Account]() } sc, ok := value.(sessionContext) if !ok { return opt.NewEmpty[account.Account]() } acc, ok := sc.account.Get() if !ok { return opt.NewEmpty[account.Account]() } return opt.New(acc) } // GetSessionToken retrieves the session token from the context if present. // This is only available for browser sessions, not access keys. func GetSessionToken(ctx context.Context) opt.Optional[string] { value := ctx.Value(contextKey) if value == nil { return opt.NewEmpty[string]() } sc, ok := value.(sessionContext) if !ok { return opt.NewEmpty[string]() } return sc.sessionToken }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Southclaws/storyden'

If you have feedback or need assistance with the MCP directory API, please join our Discord server