package system import ( "context" "errors" "io" "time" ) // Cache is the shared cache seam. The data implementation uses Redis when it // is reachable and falls back to process memory for local development. type Cache interface { Get(context.Context, string) (string, bool, error) Set(context.Context, string, string, time.Duration) error Delete(context.Context, string) error Increment(context.Context, string, time.Duration) (int64, error) } type StoredFile struct { Name string Path string URL string Size int64 LastModified time.Time ContentType string } // FileStorage owns the persistence boundary for uploaded files. type FileStorage interface { Put(context.Context, string, io.Reader) (*StoredFile, error) Open(context.Context, string) (io.ReadCloser, error) Delete(context.Context, string) error Compose(context.Context, []string, string) (*StoredFile, string, error) DeletePrefix(context.Context, string) error List(context.Context, string, string, int) ([]*StoredFile, string, bool, error) } type JWTSettings struct { SigningKey string Issuer string Expires time.Duration Buffer time.Duration } type CaptchaSettings struct { KeyLong int ImageWidth int ImageHeight int StoreExpiration time.Duration } type MediaSettings struct { SessionTTL int MaxFileSize int64 ChunkDir string } const DefaultMaxMediaFileSize int64 = 100 << 20 func (s MediaSettings) EffectiveMaxFileSize() int64 { if s.MaxFileSize > 0 { return s.MaxFileSize } return DefaultMaxMediaFileSize } // RuntimeSettings exposes only the active values needed by the application. // The data implementation resolves every call from config.Store so hot reloads // take effect without rebuilding services. type RuntimeSettings interface { RouterPrefix() string JWTSettings() JWTSettings CaptchaSettings() CaptchaSettings MediaSettings() MediaSettings UseMultipoint() bool } type IssuedToken struct { Value string ExpiresAt time.Time TTL time.Duration } type AuthClaims struct { UUID string ID uint Username string NickName string AuthorityID uint UserType string BufferTime time.Duration MustChangePwd bool PasswordVersion int64 Issuer string Audience []string IssuedAt time.Time NotBefore time.Time ExpiresAt time.Time } var ( ErrTokenExpired = errors.New("token expired") ErrTokenMalformed = errors.New("token malformed") ErrTokenSignatureInvalid = errors.New("token signature invalid") ErrTokenNotValidYet = errors.New("token not valid yet") ErrTokenInvalid = errors.New("token invalid") ErrTokenDisabled = errors.New("token disabled") ) type TokenIssuer interface { IssueToken(*User, uint, bool, time.Duration) (*IssuedToken, error) ReissueToken(*AuthClaims, uint) (*IssuedToken, error) ParseToken(string) (*AuthClaims, error) }