security

package
v0.18.0 Latest Latest
Warning

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

Go to latest
Published: Jan 27, 2026 License: Apache-2.0 Imports: 20 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// PrioritySelf indicates access only to data created by the user themselves.
	// This is the most restrictive data scope.
	PrioritySelf = 10

	// PriorityDepartment indicates access to data within the user's department.
	PriorityDepartment = 20

	// PriorityDepartmentAndSub indicates access to data within the user's department and all sub-departments.
	PriorityDepartmentAndSub = 30

	// PriorityOrganization indicates access to data within the user's organization.
	PriorityOrganization = 40

	// PriorityOrganizationAndSub indicates access to data within the user's organization and all sub-organizations.
	PriorityOrganizationAndSub = 50

	// PriorityCustom indicates access to data within the user's custom data scope.
	PriorityCustom = 60

	// PriorityAll indicates unrestricted access to all data.
	// This is the broadest data scope, typically used for system administrators.
	PriorityAll = 10000
)

Variables

View Source
var (
	ErrInvalidAESKeyLength   = errors.New("invalid AES key length")
	ErrCannotDeriveIV        = errors.New("cannot derive IV")
	ErrInvalidIVLength       = errors.New("invalid IV length")
	ErrCreateAESCipherFailed = errors.New("failed to create AES cipher")

	ErrPrivateKeyNil                   = errors.New("private key cannot be nil")
	ErrCreateRSACipherFailed           = errors.New("failed to create RSA cipher")
	ErrCreateRSACipherFromPEMFailed    = errors.New("failed to create RSA cipher from PEM")
	ErrCreateRSACipherFromHexFailed    = errors.New("failed to create RSA cipher from hex")
	ErrCreateRSACipherFromBase64Failed = errors.New("failed to create RSA cipher from base64")

	ErrCreateSM2CipherFailed        = errors.New("failed to create SM2 cipher")
	ErrCreateSM2CipherFromPEMFailed = errors.New("failed to create SM2 cipher from PEM")
	ErrCreateSM2CipherFromHexFailed = errors.New("failed to create SM2 cipher from hex")

	ErrInvalidSM4KeyLength             = errors.New("invalid SM4 key length")
	ErrCreateSM4CipherFailed           = errors.New("failed to create SM4 cipher")
	ErrCreateSM4CipherFromHexFailed    = errors.New("failed to create SM4 cipher from hex")
	ErrCreateSM4CipherFromBase64Failed = errors.New("failed to create SM4 cipher from base64")

	ErrDecodeJWTSecretFailed = errors.New("failed to decode jwt secret")

	ErrUserDetailsNotStruct        = errors.New("user details type must be a struct or struct pointer")
	ErrExternalAppDetailsNotStruct = errors.New("external app details type must be a struct or struct pointer")

	ErrQueryNotQueryBuilder = errors.New("query does not implement QueryBuilder interface")
	ErrQueryModelNotSet     = errors.New("query must call Model() before applying data permission")
)
View Source
var (
	PrincipalSystem = &Principal{
		Type: PrincipalTypeSystem,
		ID:   constants.OperatorSystem,
		Name: "系统",
	}
	PrincipalAnonymous = NewUser(constants.OperatorAnonymous, "匿名")
)

Functions

func PublishRolePermissionsChangedEvent

func PublishRolePermissionsChangedEvent(publisher event.Publisher, roles ...string)

PublishRolePermissionsChangedEvent publishes a role permissions changed event via the provided publisher. If no roles are specified, subscribers should interpret the event as affecting all roles.

func SetExternalAppDetailsType

func SetExternalAppDetailsType[T any]()

func SetUserDetailsType

func SetUserDetailsType[T any]()

func SubscribeLoginEvent added in v0.9.0

func SubscribeLoginEvent(subscriber event.Subscriber, handler func(context.Context, *LoginEvent)) event.UnsubscribeFunc

SubscribeLoginEvent subscribes to login events. Returns an unsubscribe function that can be called to remove the subscription.

Types

type AllDataScope

type AllDataScope struct{}

AllDataScope grants access to all data without any restrictions. This is typically used for system administrators or users with full data access.

func (*AllDataScope) Apply

func (*AllDataScope) Key

func (*AllDataScope) Key() string

func (*AllDataScope) Priority

func (*AllDataScope) Priority() int

func (*AllDataScope) Supports

func (*AllDataScope) Supports(*Principal, *orm.Table) bool

type AuthManager

type AuthManager interface {
	Authenticate(ctx context.Context, authentication Authentication) (*Principal, error)
}

type AuthTokens

type AuthTokens struct {
	AccessToken  string `json:"accessToken"`
	RefreshToken string `json:"refreshToken"`
}

type Authentication

type Authentication struct {
	Kind        string `json:"kind"`
	Principal   string `json:"principal"`
	Credentials any    `json:"credentials"`
}

type Authenticator

type Authenticator interface {
	Supports(kind string) bool
	Authenticate(ctx context.Context, authentication Authentication) (*Principal, error)
}

type CachedRolePermissionsLoader

type CachedRolePermissionsLoader struct {
	// contains filtered or unexported fields
}

CachedRolePermissionsLoader is a decorator that adds caching to a RolePermissionsLoader. It uses the cache system and event bus for automatic cache invalidation.

func (*CachedRolePermissionsLoader) LoadPermissions

func (c *CachedRolePermissionsLoader) LoadPermissions(ctx context.Context, role string) (map[string]DataScope, error)

type DataPermissionApplier

type DataPermissionApplier interface {
	Apply(query orm.SelectQuery) error
}

func NewRequestScopedDataPermApplier

func NewRequestScopedDataPermApplier(
	principal *Principal,
	dataScope DataScope,
	logger log.Logger,
) DataPermissionApplier

NewRequestScopedDataPermApplier creates a new request-scoped data permission applier. This function is typically called by the data permission middleware for each request.

type DataPermissionResolver

type DataPermissionResolver interface {
	ResolveDataScope(ctx context.Context, principal *Principal, permToken string) (DataScope, error)
}

type DataScope

type DataScope interface {
	Key() string
	Priority() int
	Supports(principal *Principal, table *orm.Table) bool
	Apply(principal *Principal, query orm.SelectQuery) error
}

func NewAllDataScope

func NewAllDataScope() DataScope

NewAllDataScope creates a new AllDataScope instance.

func NewSelfDataScope

func NewSelfDataScope(createdByColumn string) DataScope

NewSelfDataScope creates a new SelfDataScope instance. The createdByColumn parameter specifies the database column name for the creator. If empty, it defaults to "created_by".

type ExternalAppConfig

type ExternalAppConfig struct {
	Enabled     bool   `json:"enabled"`
	IPWhitelist string `json:"ipWhitelist"`
}

type ExternalAppLoader

type ExternalAppLoader interface {
	LoadByID(ctx context.Context, id string) (*Principal, string, error)
}

type Gender added in v0.6.0

type Gender string
const (
	GenderMale    Gender = "male"
	GenderFemale  Gender = "female"
	GenderUnknown Gender = "unknown"
)

type JWT

type JWT struct {
	// contains filtered or unexported fields
}

JWT provides low-level JWT token operations. It handles token generation, parsing, and validation without business logic.

func NewJWT

func NewJWT(config *JWTConfig) (*JWT, error)

NewJWT creates a new JWT instance with the given configuration. Secret expects a hex-encoded string; invalid hex will cause an error. Audience will be defaulted when empty.

func (*JWT) Generate

func (j *JWT) Generate(claimsBuilder *JWTClaimsBuilder, expires, notBefore time.Duration) (string, error)

Generate creates a JWT token with the given claims and expires. The expiration is computed as now + expires; iat and nbf are set to now.

func (*JWT) Parse

func (j *JWT) Parse(tokenString string) (*JWTClaimsAccessor, error)

Parse parses and validates a JWT token. It returns a read-only claims accessor which performs safe conversions and never panics.

type JWTClaimsAccessor

type JWTClaimsAccessor struct {
	// contains filtered or unexported fields
}

func NewJWTClaimsAccessor

func NewJWTClaimsAccessor(claims jwt.MapClaims) *JWTClaimsAccessor

NewJWTClaimsAccessor creates a new JWT claims accessor.

func (*JWTClaimsAccessor) Claim

func (a *JWTClaimsAccessor) Claim(key string) any

Claim returns the claim.

func (*JWTClaimsAccessor) Details

func (a *JWTClaimsAccessor) Details() any

Details returns the details claim.

func (*JWTClaimsAccessor) ID added in v0.18.0

func (a *JWTClaimsAccessor) ID() string

ID returns the JWT ID claim. Returns empty string if the claim is missing or not a string.

func (*JWTClaimsAccessor) Roles

func (a *JWTClaimsAccessor) Roles() []string

Roles returns the roles claim. Supports both []string and []any payloads; returns empty slice if absent.

func (*JWTClaimsAccessor) Subject

func (a *JWTClaimsAccessor) Subject() string

Subject returns the subject claim. Returns empty string if the claim is missing or not a string.

func (*JWTClaimsAccessor) Type

func (a *JWTClaimsAccessor) Type() string

Type returns the token type claim. Returns empty string if the claim is missing or not a string.

type JWTClaimsBuilder

type JWTClaimsBuilder struct {
	// contains filtered or unexported fields
}

JWTClaimsBuilder helps build JWT claims for different token types.

func NewJWTClaimsBuilder

func NewJWTClaimsBuilder() *JWTClaimsBuilder

NewJWTClaimsBuilder creates a new JWT claims builder.

func (*JWTClaimsBuilder) Claim

func (b *JWTClaimsBuilder) Claim(key string) (any, bool)

Claim returns a custom claim.

func (*JWTClaimsBuilder) Details

func (b *JWTClaimsBuilder) Details() (any, bool)

Details returns the details claim.

func (*JWTClaimsBuilder) ID added in v0.18.0

func (b *JWTClaimsBuilder) ID() (string, bool)

ID returns the JWT ID claim.

func (*JWTClaimsBuilder) Roles

func (b *JWTClaimsBuilder) Roles() ([]string, bool)

Roles returns the roles claim.

func (*JWTClaimsBuilder) Subject

func (b *JWTClaimsBuilder) Subject() (string, bool)

Subject returns the subject claim.

func (*JWTClaimsBuilder) Type

func (b *JWTClaimsBuilder) Type() (string, bool)

Type returns the token type claim.

func (*JWTClaimsBuilder) WithClaim

func (b *JWTClaimsBuilder) WithClaim(key string, value any) *JWTClaimsBuilder

func (*JWTClaimsBuilder) WithDetails

func (b *JWTClaimsBuilder) WithDetails(details any) *JWTClaimsBuilder

func (*JWTClaimsBuilder) WithID added in v0.18.0

func (b *JWTClaimsBuilder) WithID(id string) *JWTClaimsBuilder

func (*JWTClaimsBuilder) WithRoles

func (b *JWTClaimsBuilder) WithRoles(roles []string) *JWTClaimsBuilder

func (*JWTClaimsBuilder) WithSubject

func (b *JWTClaimsBuilder) WithSubject(subject string) *JWTClaimsBuilder

func (*JWTClaimsBuilder) WithType

func (b *JWTClaimsBuilder) WithType(typ string) *JWTClaimsBuilder

type JWTConfig

type JWTConfig struct {
	Secret   string `config:"secret"`   // Secret key for JWT signing
	Audience string `config:"audience"` // JWT audience
}

JWTConfig is the configuration for the JWT token.

type LoginEvent added in v0.9.0

type LoginEvent struct {
	event.BaseEvent

	AuthType   string `json:"authType"`
	UserID     string `json:"userId"` // Populated on success
	Username   string `json:"username"`
	LoginIP    string `json:"loginIp"`
	UserAgent  string `json:"userAgent"`
	TraceID    string `json:"traceId"`
	IsOk       bool   `json:"isOk"`
	FailReason string `json:"failReason"` // Populated on failure
	ErrorCode  int    `json:"errorCode"`
}

LoginEvent represents a user login event.

func NewLoginEvent added in v0.9.0

func NewLoginEvent(params LoginEventParams) *LoginEvent

NewLoginEvent creates a new login event with the given parameters.

type LoginEventParams added in v0.18.0

type LoginEventParams struct {
	AuthType   string
	UserID     string
	Username   string
	LoginIP    string
	UserAgent  string
	TraceID    string
	IsOk       bool
	FailReason string
	ErrorCode  int
}

LoginEventParams contains parameters for creating a LoginEvent.

type PasswordDecryptor

type PasswordDecryptor interface {
	Decrypt(encryptedPassword string) (string, error)
}

type PermissionChecker

type PermissionChecker interface {
	HasPermission(ctx context.Context, principal *Principal, permToken string) (bool, error)
}

type Principal

type Principal struct {
	// Type is the type of the principal.
	Type PrincipalType `json:"type"`
	// ID is the id of the user.
	ID string `json:"id"`
	// Name is the name of the user.
	Name string `json:"name"`
	// Roles is the roles of the user.
	Roles []string `json:"roles"`
	// Details is the details of the user.
	Details any `json:"details"`
}

Principal is the principal of the user.

func NewExternalApp

func NewExternalApp(id, name string, roles ...string) *Principal

NewExternalApp is the function to create a new external app principal.

func NewUser

func NewUser(id, name string, roles ...string) *Principal

NewUser is the function to create a new user principal.

func (*Principal) AttemptUnmarshalDetails

func (p *Principal) AttemptUnmarshalDetails(details any)

AttemptUnmarshalDetails attempts to unmarshal the details into the principal.

func (*Principal) UnmarshalJSON

func (p *Principal) UnmarshalJSON(data []byte) error

UnmarshalJSON implements custom JSON unmarshaling for Principal. This allows the Details field to be properly deserialized based on the Type field.

func (*Principal) WithRoles

func (p *Principal) WithRoles(roles ...string) *Principal

WithRoles adds roles to the principal.

type PrincipalType

type PrincipalType string

PrincipalType is the type of the principal.

const (
	// PrincipalTypeUser is the type of the user.
	PrincipalTypeUser PrincipalType = "user"
	// PrincipalTypeExternalApp is the type of the external app.
	PrincipalTypeExternalApp PrincipalType = "external_app"
	// PrincipalTypeSystem is the type of the system.
	PrincipalTypeSystem PrincipalType = constants.OperatorSystem
)

type RequestScopedDataPermApplier

type RequestScopedDataPermApplier struct {
	// contains filtered or unexported fields
}

RequestScopedDataPermApplier is the default implementation of DataPermissionApplier. It applies data permission filtering using a single DataScope instance.

IMPORTANT: This struct is request-scoped and should NOT be stored beyond request lifecycle.

func (*RequestScopedDataPermApplier) Apply

Apply implements security.DataPermissionApplier.Apply.

type RolePermissionsChangedEvent

type RolePermissionsChangedEvent struct {
	event.BaseEvent

	Roles []string `json:"roles"` // Affected role names (empty means all roles)
}

RolePermissionsChangedEvent is published when role permissions are modified.

type RolePermissionsLoader

type RolePermissionsLoader interface {
	LoadPermissions(ctx context.Context, role string) (map[string]DataScope, error)
}

func NewCachedRolePermissionsLoader

func NewCachedRolePermissionsLoader(
	loader RolePermissionsLoader,
	eventBus event.Subscriber,
) RolePermissionsLoader

NewCachedRolePermissionsLoader creates a new cached role permissions loader. It automatically subscribes to role permissions change events to invalidate cache.

type SelfDataScope

type SelfDataScope struct {
	// contains filtered or unexported fields
}

SelfDataScope restricts access to data created by the user themselves. This is commonly used for personal data access where users can only see their own records.

func (*SelfDataScope) Apply

func (s *SelfDataScope) Apply(principal *Principal, query orm.SelectQuery) error

func (*SelfDataScope) Key

func (*SelfDataScope) Key() string

func (*SelfDataScope) Priority

func (*SelfDataScope) Priority() int

func (*SelfDataScope) Supports

func (s *SelfDataScope) Supports(_ *Principal, table *orm.Table) bool

type TokenGenerator

type TokenGenerator interface {
	Generate(principal *Principal) (*AuthTokens, error)
}

type UserInfo added in v0.6.0

type UserInfo struct {
	ID         string      `json:"id"`
	Name       string      `json:"name"`
	Gender     Gender      `json:"gender"`
	Avatar     null.String `json:"avatar"`
	PermTokens []string    `json:"permTokens"`
	Menus      []UserMenu  `json:"menus"`
	Details    any         `json:"details,omitempty"`
}

type UserInfoLoader added in v0.6.0

type UserInfoLoader interface {
	LoadUserInfo(ctx context.Context, principal *Principal, params map[string]any) (*UserInfo, error)
}

type UserLoader

type UserLoader interface {
	LoadByUsername(ctx context.Context, username string) (*Principal, string, error)
	LoadByID(ctx context.Context, id string) (*Principal, error)
}

type UserMenu added in v0.6.0

type UserMenu struct {
	Type     UserMenuType   `json:"type"`
	Path     string         `json:"path"`
	Name     string         `json:"name"`
	Icon     null.String    `json:"icon"`
	Meta     map[string]any `json:"metadata,omitempty"`
	Children []UserMenu     `json:"children,omitempty"`
}

type UserMenuType added in v0.6.0

type UserMenuType string
const (
	UserMenuTypeDirectory UserMenuType = "directory"
	UserMenuTypeMenu      UserMenuType = "menu"
	UserMenuTypeView      UserMenuType = "view"
	UserMenuTypeDashboard UserMenuType = "dashboard"
	UserMenuTypeReport    UserMenuType = "report"
)

Jump to

Keyboard shortcuts

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