Select Git revision
action_handler_test.go
auth.go 3.91 KiB
package perxis
import (
"context"
"runtime"
"strings"
"git.perx.ru/perxis/perxis-go/pkg/errors"
)
var (
ErrAccessDenied = errors.New("access denied")
)
type Principal interface {
GetID() string
}
// Authenticator интерфейс для аутентификации
type Authenticator interface {
// Authenticate аутентификация
Authenticate(ctx context.Context) (Principal, error)
}
type Authorization struct {
Authorizer Authorizer
}
// Authorizer интерфейс для авторизации
type Authorizer interface {
Authorize(principal Principal, action string, resource any) (*Authorization, error)
}
var (
authorizer Authorizer
authenticator Authenticator
)
func SetAuthorizer(a Authorizer) {
authorizer = a
}
func SetAuthenticator(a Authenticator) {
authenticator = a
}
func Authenticate(ctx context.Context) (Principal, error) {
if authenticator == nil {
return nil, nil
}
return authenticator.Authenticate(ctx)
}
func Authorize(principal Principal, action string, resource any) (*Authorization, error) {
if authorizer == nil {
return nil, nil
}
return authorizer.Authorize(principal, action, resource)
}
func AuthorizeContext(ctx context.Context, action string, resource any) (*Authorization, error) {
principal, err := Authenticate(ctx)
if err != nil {
return nil, err
}
return Authorize(principal, action, resource)
}
func IsAllowed(ctx context.Context, res any) (*Authorization, error) {
pc, _, _, _ := runtime.Caller(1)
parts := strings.Split(runtime.FuncForPC(pc).Name(), ".")
action := parts[len(parts)-1]
return AuthorizeContext(ctx, action, res)
}
//type AccessRequest struct {
// Resource any // Ресурс для которого запрашивается доступ
// Subject any // Субъект, который запрашивает доступ
// Action string // Действие, которое запрашивается
//}
//
//type AccessResponse struct {
// IsAllowed bool
// Filter func(action string, v any) any
// Err error
//}
//
//type Policy interface {
// IsAllowed(ctx context.Context, req *AccessRequest) (*AccessResponse, error)
//}
//
//func IsMethodAllowed(ctx context.Context, resource any) (*AccessResponse, error) {
// pc, _, _, _ := runtime.Caller(1)
// parts := strings.Split(runtime.FuncForPC(pc).Name(), ".")
// req := &AccessRequest{Action: parts[len(parts)-1], Resource: resource}
// return IsAllowed(ctx, req)
//}
//
//func IsAllowed(ctx context.Context, req *AccessRequest) (*AccessResponse, error) {
// if req != nil && req.Subject == nil {
// principal := GetPrincipal(ctx)
// if principal != nil {
// req.Subject = principal
// }
// }
//
// fmt.Printf("IsAllowed: %v\n", req)
// return DefaultPolicy.IsAllowed(ctx, req)
//}
//
//type Policies []Policy
//
//func (p Policies) IsAllowed(ctx context.Context, req *AccessRequest) (*AccessResponse, error) {
// for _, policy := range p {
// if resp, err := policy.IsAllowed(ctx, req); resp != nil || err != nil {
// return resp, err
// }
// }
// return nil, nil
//}
//
//type defaultPolicy struct {
// policies []Policy
//}
//
//func (d *defaultPolicy) IsAllowed(ctx context.Context, req *AccessRequest) (*AccessResponse, error) {
// if p, ok := req.Subject.(Policy); ok {
// if resp, err := p.IsAllowed(ctx, req); resp != nil || err != nil {
// return resp, err
// }
// }
//
// for _, policy := range d.policies {
// if resp, err := policy.IsAllowed(ctx, req); resp != nil || err != nil {
// return resp, err
// }
// }
//
// // Policy not found
// return nil, ErrAccessDenied
//}
//
//type AllowPolicy struct{}
//
//func (AllowPolicy) IsAllowed(ctx context.Context, req *AccessRequest) (*AccessResponse, error) {
// return &AccessResponse{IsAllowed: true, Filter: func(action string, v any) any { return v }}, nil
//}
//
//type DenyPolicy struct{}
//
//func (DenyPolicy) IsAllowed(ctx context.Context, req *AccessRequest) (*AccessResponse, error) {
// return nil, ErrAccessDenied
//}