security

package
v0.16.2 Latest Latest
Warning

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

Go to latest
Published: Dec 31, 2025 License: Apache-2.0 Imports: 19 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")

	ErrUserDetailsTypeMustBeStruct        = errors.New("user details type must be a struct")
	ErrExternalAppDetailsTypeMustBeStruct = errors.New("external app details type must be a struct")

	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 {
	Type        string `json:"type"`
	Principal   string `json:"principal"`
	Credentials any    `json:"credentials"`
}

type Authenticator

type Authenticator interface {
	Supports(authType 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)

LoadPermissions loads permissions for a single role, using cache when available.

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 added in v0.6.0

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 added in v0.6.0

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 a panic during initialization. Audience will be defaulted when empty.

func (*Jwt) Generate added in v0.6.0

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 added in v0.6.0

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 added in v0.6.0

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

func NewJwtClaimsAccessor added in v0.6.0

func NewJwtClaimsAccessor(claims jwt.MapClaims) *JwtClaimsAccessor

NewJwtClaimsAccessor creates a new Jwt claims accessor.

func (*JwtClaimsAccessor) Claim added in v0.6.0

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

Claim returns the claim.

func (*JwtClaimsAccessor) Details added in v0.6.0

func (a *JwtClaimsAccessor) Details() any

Details returns the details claim.

func (*JwtClaimsAccessor) Id added in v0.6.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 added in v0.6.0

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

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

func (*JwtClaimsAccessor) Subject added in v0.6.0

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 added in v0.6.0

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 added in v0.6.0

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

JwtClaimsBuilder helps build Jwt claims for different token types.

func NewJwtClaimsBuilder added in v0.6.0

func NewJwtClaimsBuilder() *JwtClaimsBuilder

NewJwtClaimsBuilder creates a new Jwt claims builder.

func (*JwtClaimsBuilder) Claim added in v0.6.0

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

Claim returns a custom claim.

func (*JwtClaimsBuilder) Details added in v0.6.0

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

Details returns the details claim.

func (*JwtClaimsBuilder) Id added in v0.6.0

func (b *JwtClaimsBuilder) Id() (string, bool)

Id returns the Jwt ID claim.

func (*JwtClaimsBuilder) Roles added in v0.6.0

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

Roles returns the roles claim.

func (*JwtClaimsBuilder) Subject added in v0.6.0

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

Subject returns the subject claim.

func (*JwtClaimsBuilder) Type added in v0.6.0

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

Type returns the token type claim.

func (*JwtClaimsBuilder) WithClaim added in v0.6.0

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

func (*JwtClaimsBuilder) WithDetails added in v0.6.0

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

func (*JwtClaimsBuilder) WithId added in v0.6.0

func (b *JwtClaimsBuilder) WithId(id string) *JwtClaimsBuilder

func (*JwtClaimsBuilder) WithRoles added in v0.6.0

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

func (*JwtClaimsBuilder) WithSubject added in v0.6.0

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

func (*JwtClaimsBuilder) WithType added in v0.6.0

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

type JwtConfig added in v0.6.0

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(
	authType string,
	userId, username string,
	loginIp, userAgent, traceId string,
	isOk bool, failReason string, errorCode int,
) *LoginEvent

NewLoginEvent creates a new login event with the given parameters.

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