security

package
v0.11.2 Latest Latest
Warning

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

Go to latest
Published: Nov 14, 2025 License: Apache-2.0 Imports: 25 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 HashPassword

func HashPassword(password string) (string, error)

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.

func VerifyPassword

func VerifyPassword(password, hashedPassword string) bool

Types

type AesPasswordDecryptor added in v0.6.0

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

func (*AesPasswordDecryptor) Decrypt added in v0.6.0

func (d *AesPasswordDecryptor) Decrypt(encryptedPassword string) (string, error)

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)
}

func NewAesPasswordDecryptor added in v0.6.0

func NewAesPasswordDecryptor(key, iv []byte) (PasswordDecryptor, error)

func NewAesPasswordDecryptorFromBase64 added in v0.6.0

func NewAesPasswordDecryptorFromBase64(keyBase64, ivBase64 string) (PasswordDecryptor, error)

func NewAesPasswordDecryptorFromHex added in v0.6.0

func NewAesPasswordDecryptorFromHex(keyHex, ivHex string) (PasswordDecryptor, error)

func NewRsaPasswordDecryptor added in v0.6.0

func NewRsaPasswordDecryptor(privateKey *rsa.PrivateKey) (PasswordDecryptor, error)

func NewRsaPasswordDecryptorFromBase64 added in v0.6.0

func NewRsaPasswordDecryptorFromBase64(privateKeyBase64 string) (PasswordDecryptor, error)

func NewRsaPasswordDecryptorFromHex added in v0.6.0

func NewRsaPasswordDecryptorFromHex(privateKeyHex string) (PasswordDecryptor, error)

func NewRsaPasswordDecryptorFromPEM added in v0.6.0

func NewRsaPasswordDecryptorFromPEM(pemKey []byte) (PasswordDecryptor, error)

func NewSm2PasswordDecryptor added in v0.6.0

func NewSm2PasswordDecryptor(privateKey *sm2.PrivateKey) (PasswordDecryptor, error)

func NewSm2PasswordDecryptorFromHex added in v0.6.0

func NewSm2PasswordDecryptorFromHex(privateKeyHex string) (PasswordDecryptor, error)

func NewSm2PasswordDecryptorFromPEM added in v0.6.0

func NewSm2PasswordDecryptorFromPEM(pemKey []byte) (PasswordDecryptor, error)

func NewSm4PasswordDecryptor added in v0.6.0

func NewSm4PasswordDecryptor(key, iv []byte, mode ...crypto.Sm4Mode) (PasswordDecryptor, error)

func NewSm4PasswordDecryptorFromBase64 added in v0.6.0

func NewSm4PasswordDecryptorFromBase64(keyBase64, ivBase64 string, mode ...crypto.Sm4Mode) (PasswordDecryptor, error)

func NewSm4PasswordDecryptorFromHex added in v0.6.0

func NewSm4PasswordDecryptorFromHex(keyHex, ivHex string, mode ...crypto.Sm4Mode) (PasswordDecryptor, error)

type PermissionChecker

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

type Principal

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

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        PrincipalType = "user"                   // PrincipalTypeUser is the type of the user.
	PrincipalTypeExternalApp PrincipalType = "external_app"           // PrincipalTypeExternalApp is the type of the external app.
	PrincipalTypeSystem      PrincipalType = constants.OperatorSystem // PrincipalTypeSystem is the type of the system.
)

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

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

func (*RsaPasswordDecryptor) Decrypt added in v0.6.0

func (d *RsaPasswordDecryptor) Decrypt(encryptedPassword string) (string, error)

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

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

func (*Sm2PasswordDecryptor) Decrypt added in v0.6.0

func (d *Sm2PasswordDecryptor) Decrypt(encryptedPassword string) (string, error)

type Sm4PasswordDecryptor added in v0.6.0

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

func (*Sm4PasswordDecryptor) Decrypt added in v0.6.0

func (d *Sm4PasswordDecryptor) Decrypt(encryptedPassword string) (string, error)

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"`
}

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"`

	Children []UserMenu `json:"children"`
}

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