fs

package
v0.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 26, 2026 License: Apache-2.0 Imports: 16 Imported by: 1

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type FSAPIKeyStore

type FSAPIKeyStore struct {
	StoragePath string
	// contains filtered or unexported fields
}

FSAPIKeyStore stores API keys as JSON files

func NewFSAPIKeyStore

func NewFSAPIKeyStore(storagePath string) *FSAPIKeyStore

NewFSAPIKeyStore creates a new file-based API key store

func (*FSAPIKeyStore) CreateAPIKey

func (s *FSAPIKeyStore) CreateAPIKey(userID, name string, scopes []string, expiresAt *time.Time) (fullKey string, apiKey *core.APIKey, err error)

CreateAPIKey creates a new API key and returns the full key (only shown once) The key format is: keyID + "_" + secret

func (*FSAPIKeyStore) GetAPIKeyByID

func (s *FSAPIKeyStore) GetAPIKeyByID(keyID string) (*core.APIKey, error)

GetAPIKeyByID retrieves an API key by its public ID

func (*FSAPIKeyStore) ListUserAPIKeys

func (s *FSAPIKeyStore) ListUserAPIKeys(userID string) ([]*core.APIKey, error)

ListUserAPIKeys returns all API keys for a user (without secrets)

func (*FSAPIKeyStore) RevokeAPIKey

func (s *FSAPIKeyStore) RevokeAPIKey(keyID string) error

RevokeAPIKey marks an API key as revoked

func (*FSAPIKeyStore) UpdateAPIKeyLastUsed

func (s *FSAPIKeyStore) UpdateAPIKeyLastUsed(keyID string) error

UpdateAPIKeyLastUsed updates the last used timestamp

func (*FSAPIKeyStore) ValidateAPIKey

func (s *FSAPIKeyStore) ValidateAPIKey(fullKey string) (*core.APIKey, error)

ValidateAPIKey validates a full API key and returns the key metadata if valid The fullKey format is: keyID + "_" + secret

type FSAppStore added in v0.0.81

type FSAppStore struct {
	StoragePath string
	// contains filtered or unexported fields
}

FSAppStore implements admin.AppRegistrationStore by persisting each registration as a JSON file under {basePath}/apps/{client_id}.json.

Mirrors the FSKeyStore design: file-per-record (so concurrent ops don't serialize on a single mutex outside this process), atomic writes via temp-file + rename (so a crash mid-write leaves either the old file or the new file intact, never a half-written one), and safeName guarding path-traversal in client_ids.

In-process concurrency is mediated by sync.RWMutex. Multi-process deployments need a backend with real transaction semantics — see GORMAppStore (#167).

func NewFSAppStore added in v0.0.81

func NewFSAppStore(storagePath string) *FSAppStore

NewFSAppStore creates a filesystem-backed AppRegistrationStore. The {basePath}/apps/ directory is created lazily on first write.

func (*FSAppStore) DeleteApp added in v0.0.81

func (s *FSAppStore) DeleteApp(clientID string) error

DeleteApp removes the registration for clientID. Returns admin.ErrAppNotFound if no such registration exists, matching InMemoryAppStore semantics.

func (*FSAppStore) GetApp added in v0.0.81

func (s *FSAppStore) GetApp(clientID string) (*admin.AppRegistration, error)

GetApp returns the registration for clientID, or admin.ErrAppNotFound if no such file exists. A corrupt JSON file surfaces as a parse error rather than ErrAppNotFound — callers should distinguish "registration absent" from "registration unreadable" so an unexpected on-disk corruption isn't silently treated as a missing client.

func (*FSAppStore) ListApps added in v0.0.81

func (s *FSAppStore) ListApps() ([]*admin.AppRegistration, error)

ListApps returns every registration in the store. Files that fail to parse are skipped (with no error returned) so a single hand-corrupted file does not lock out admin tooling — partial recovery beats total failure here. Callers needing strict integrity should validate at the store level (e.g., periodic fsck) rather than relying on ListApps.

Returns an empty slice (not an error) when the apps dir does not yet exist, matching the InMemory backend's "fresh store has no apps" shape.

func (*FSAppStore) SaveApp added in v0.0.81

func (s *FSAppStore) SaveApp(app *admin.AppRegistration) error

SaveApp persists app to disk. Overwrites any existing registration with the same client_id. Empty client_id is rejected.

type FSChannelStore

type FSChannelStore struct {
	StoragePath string
}

FSChannelStore stores channels as JSON files

func NewFSChannelStore

func NewFSChannelStore(storagePath string) *FSChannelStore

func (*FSChannelStore) GetChannel

func (s *FSChannelStore) GetChannel(provider string, identityKey string, createIfMissing bool) (*accounts.Channel, bool, error)

func (*FSChannelStore) GetChannelsByIdentity

func (s *FSChannelStore) GetChannelsByIdentity(identityKey string) ([]*accounts.Channel, error)

func (*FSChannelStore) SaveChannel

func (s *FSChannelStore) SaveChannel(channel *accounts.Channel) error

type FSIdentityStore

type FSIdentityStore struct {
	StoragePath string
}

FSIdentityStore stores identities as JSON files

func NewFSIdentityStore

func NewFSIdentityStore(storagePath string) *FSIdentityStore

func (*FSIdentityStore) GetIdentity

func (s *FSIdentityStore) GetIdentity(identityType, identityValue string, createIfMissing bool) (*accounts.Identity, bool, error)

func (*FSIdentityStore) GetUserIdentities

func (s *FSIdentityStore) GetUserIdentities(userId string) ([]*accounts.Identity, error)

func (*FSIdentityStore) MarkIdentityVerified

func (s *FSIdentityStore) MarkIdentityVerified(identityType, identityValue string) error

func (*FSIdentityStore) SaveIdentity

func (s *FSIdentityStore) SaveIdentity(identity *accounts.Identity) error

func (*FSIdentityStore) SetUserForIdentity

func (s *FSIdentityStore) SetUserForIdentity(identityType, identityValue string, newUserId string) error

type FSKeyStore added in v0.0.32

type FSKeyStore struct {
	StoragePath string
	// contains filtered or unexported fields
}

FSKeyStore implements keys.KeyStorage using filesystem storage.

func NewFSKeyStore added in v0.0.32

func NewFSKeyStore(storagePath string) *FSKeyStore

NewFSKeyStore creates a new filesystem-backed KeyStore.

func (*FSKeyStore) DeleteKey added in v0.0.32

func (s *FSKeyStore) DeleteKey(clientID string) error

func (*FSKeyStore) GetCurrentKid added in v0.0.38

func (s *FSKeyStore) GetCurrentKid(clientID string) (string, error)

func (*FSKeyStore) GetExpectedAlg added in v0.0.32

func (s *FSKeyStore) GetExpectedAlg(clientID string) (string, error)

func (*FSKeyStore) GetKey added in v0.0.38

func (s *FSKeyStore) GetKey(clientID string) (*keys.KeyRecord, error)

func (*FSKeyStore) GetKeyByKid added in v0.0.38

func (s *FSKeyStore) GetKeyByKid(kid string) (*keys.KeyRecord, error)

func (*FSKeyStore) GetSigningKey added in v0.0.32

func (s *FSKeyStore) GetSigningKey(clientID string) (any, error)

func (*FSKeyStore) GetVerifyKey added in v0.0.32

func (s *FSKeyStore) GetVerifyKey(clientID string) (any, error)

func (*FSKeyStore) ListKeyIDs added in v0.0.38

func (s *FSKeyStore) ListKeyIDs() ([]string, error)

func (*FSKeyStore) ListKeys added in v0.0.32

func (s *FSKeyStore) ListKeys() ([]string, error)

func (*FSKeyStore) PutKey added in v0.0.38

func (s *FSKeyStore) PutKey(rec *keys.KeyRecord) error

func (*FSKeyStore) RegisterKey added in v0.0.32

func (s *FSKeyStore) RegisterKey(clientID string, key any, algorithm string) error

type FSKidStore added in v0.0.83

type FSKidStore struct {
	StoragePath string
	// contains filtered or unexported fields
}

FSKidStore implements keys.KidStorage using filesystem storage. One file per kid under {StoragePath}/kid_keys/, mirroring FSKeyStore's file-per-record layout.

func NewFSKidStore added in v0.0.83

func NewFSKidStore(storagePath string) *FSKidStore

NewFSKidStore creates a new filesystem-backed KidStorage.

func (*FSKidStore) Add added in v0.0.83

func (s *FSKidStore) Add(kid string, key any, algorithm string, clientID string, expiresAt time.Time) error

func (*FSKidStore) CleanExpired added in v0.0.83

func (s *FSKidStore) CleanExpired() error

func (*FSKidStore) GetKey added in v0.0.83

func (s *FSKidStore) GetKey(clientID string) (*keys.KeyRecord, error)

GetKey always returns ErrKeyNotFound — KidStorage is kid-indexed and has no clientID→key lookup. Matches the in-memory KidStore.

func (*FSKidStore) GetKeyByKid added in v0.0.83

func (s *FSKidStore) GetKeyByKid(kid string) (*keys.KeyRecord, error)

func (*FSKidStore) Remove added in v0.0.83

func (s *FSKidStore) Remove(kid string) error

Remove is idempotent — deleting an absent kid is not an error.

type FSRefreshTokenStore

type FSRefreshTokenStore struct {
	StoragePath string
	// contains filtered or unexported fields
}

FSRefreshTokenStore stores refresh tokens as JSON files

func NewFSRefreshTokenStore

func NewFSRefreshTokenStore(storagePath string) *FSRefreshTokenStore

NewFSRefreshTokenStore creates a new file-based refresh token store

func (*FSRefreshTokenStore) CleanupExpiredTokens

func (s *FSRefreshTokenStore) CleanupExpiredTokens() error

CleanupExpiredTokens removes expired tokens (for maintenance)

func (*FSRefreshTokenStore) CreateRefreshToken

func (s *FSRefreshTokenStore) CreateRefreshToken(userID, clientID string, deviceInfo map[string]any, scopes []string) (*core.RefreshToken, error)

CreateRefreshToken creates a new refresh token for a user

func (*FSRefreshTokenStore) GetRefreshToken

func (s *FSRefreshTokenStore) GetRefreshToken(token string) (*core.RefreshToken, error)

GetRefreshToken retrieves a refresh token by its value

func (*FSRefreshTokenStore) GetUserTokens

func (s *FSRefreshTokenStore) GetUserTokens(userID string) ([]*core.RefreshToken, error)

GetUserTokens lists all active (non-revoked, non-expired) refresh tokens for a user

func (*FSRefreshTokenStore) RevokeRefreshToken

func (s *FSRefreshTokenStore) RevokeRefreshToken(token string) error

RevokeRefreshToken marks a token as revoked

func (*FSRefreshTokenStore) RevokeTokenFamily

func (s *FSRefreshTokenStore) RevokeTokenFamily(family string) error

RevokeTokenFamily revokes all tokens in a family (theft detection)

func (*FSRefreshTokenStore) RevokeUserTokens

func (s *FSRefreshTokenStore) RevokeUserTokens(userID string) error

RevokeUserTokens revokes all refresh tokens for a user

func (*FSRefreshTokenStore) RotateRefreshToken

func (s *FSRefreshTokenStore) RotateRefreshToken(oldToken string) (*core.RefreshToken, error)

RotateRefreshToken invalidates old token and creates new one in same family Returns ErrTokenReused if the old token was already revoked (theft detection)

type FSTokenStore

type FSTokenStore struct {
	StoragePath string
}

FSTokenStore stores localauth verification and reset tokens as JSON files. Satisfies localauth.VerificationTokenStore.

func NewFSTokenStore

func NewFSTokenStore(storagePath string) *FSTokenStore

func (*FSTokenStore) CreateToken

func (s *FSTokenStore) CreateToken(userID, email string, tokenType localauth.VerificationType, expiryDuration time.Duration) (*localauth.VerificationToken, error)

func (*FSTokenStore) DeleteToken

func (s *FSTokenStore) DeleteToken(token string) error

func (*FSTokenStore) DeleteUserTokens

func (s *FSTokenStore) DeleteUserTokens(userID string, tokenType localauth.VerificationType) error

func (*FSTokenStore) GetToken

func (s *FSTokenStore) GetToken(token string) (*localauth.VerificationToken, error)

type FSUser

type FSUser struct {
	UserId      string         `json:"user_id"`
	IsActive    bool           `json:"is_active"`
	UserProfile map[string]any `json:"profile"`
	CreatedAt   time.Time      `json:"created_at"`
	UpdatedAt   time.Time      `json:"updated_at"`
}

FSUser implements the oneauth.User interface

func (*FSUser) Id

func (u *FSUser) Id() string

func (*FSUser) Profile

func (u *FSUser) Profile() map[string]any

type FSUserStore

type FSUserStore struct {
	StoragePath string
}

FSUserStore stores users as JSON files

func NewFSUserStore

func NewFSUserStore(storagePath string) *FSUserStore

func (*FSUserStore) CreateUser

func (s *FSUserStore) CreateUser(userId string, isActive bool, profile map[string]any) (accounts.User, error)

func (*FSUserStore) GetUserById

func (s *FSUserStore) GetUserById(userId string) (accounts.User, error)

func (*FSUserStore) SaveUser

func (s *FSUserStore) SaveUser(user accounts.User) error

type FSUsername added in v0.0.26

type FSUsername struct {
	NormalizedUsername string    `json:"normalized_username"` // Lowercase for lookups
	Username           string    `json:"username"`            // Original case-preserved
	UserID             string    `json:"user_id"`
	Version            int       `json:"version"` // For optimistic concurrency
	CreatedAt          time.Time `json:"created_at"`
	UpdatedAt          time.Time `json:"updated_at"`
}

FSUsername represents a username reservation stored as JSON

type FSUsernameStore added in v0.0.26

type FSUsernameStore struct {
	StoragePath string
}

FSUsernameStore implements oa.UsernameStore using filesystem storage.

Purpose

Provides username uniqueness enforcement and username-based login lookup using JSON files. Each username is stored as a separate file with the normalized (lowercase) username as the filename.

File Structure

{StoragePath}/
└── usernames/
    ├── johndoe.json     # {"username": "JohnDoe", "user_id": "abc123", ...}
    ├── janedoe.json     # {"username": "JaneDoe", "user_id": "xyz789", ...}
    └── ...

Concurrency Model

Uses optimistic locking with version numbers. The atomic file write (write to temp, rename) provides basic safety, but concurrent modifications to the same username should be serialized at the application level or will result in last-write-wins behavior.

Setup

usernameStore := fs.NewFSUsernameStore("/var/data/myapp")

localAuth := &oneauth.LocalAuth{
    UsernameStore: usernameStore,
    SignupPolicy: &oneauth.SignupPolicy{
        RequireUsername:       true,
        EnforceUsernameUnique: true,
    },
}

func NewFSUsernameStore added in v0.0.26

func NewFSUsernameStore(storagePath string) *FSUsernameStore

NewFSUsernameStore creates a new filesystem-backed UsernameStore

func (*FSUsernameStore) ChangeUsername added in v0.0.26

func (s *FSUsernameStore) ChangeUsername(oldUsername, newUsername, userID string) error

ChangeUsername atomically changes a username using optimistic concurrency. Returns error if new username is already taken.

Usage

Called from a "Change Username" profile page handler.

Concurrency Note

This is not fully atomic across files. In a race condition where another process takes the new username between our check and creation, we attempt to restore the old username. For production systems with high concurrency, consider using a database-backed store instead.

func (*FSUsernameStore) GetUserByUsername added in v0.0.26

func (s *FSUsernameStore) GetUserByUsername(username string) (string, error)

GetUserByUsername looks up a userID by username (case-insensitive).

Usage

Called by NewCredentialsValidatorWithUsername during login when user enters a username instead of email.

func (*FSUsernameStore) ReleaseUsername added in v0.0.26

func (s *FSUsernameStore) ReleaseUsername(username string) error

ReleaseUsername removes a username reservation.

When to Use

Call this when:

  • User deletes their account
  • Admin removes a username (e.g., for policy violations)

func (*FSUsernameStore) ReserveUsername added in v0.0.26

func (s *FSUsernameStore) ReserveUsername(username string, userID string) error

ReserveUsername reserves a username for a user. Returns error if username is already taken by a different user.

Concurrency

Uses file system as implicit lock. The atomic write (temp file + rename) ensures no partial writes, but concurrent reservations of the same username will result in one succeeding (the last to complete the rename).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL