Files
kubesphere/pkg/controller/user/user_webhook.go
2025-04-30 15:53:51 +08:00

96 lines
2.4 KiB
Go

/*
* Copyright 2024 the KubeSphere Authors.
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
package user
import (
"context"
"fmt"
"net/mail"
"k8s.io/apimachinery/pkg/runtime"
iamv1beta1 "kubesphere.io/api/iam/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
kscontroller "kubesphere.io/kubesphere/pkg/controller"
)
const webhookName = "user-webhook"
func (v *Webhook) Name() string {
return webhookName
}
var _ kscontroller.Controller = &Webhook{}
var _ admission.CustomValidator = &Webhook{}
type Webhook struct {
client.Client
}
func (v *Webhook) SetupWithManager(mgr *kscontroller.Manager) error {
v.Client = mgr.GetClient()
return builder.WebhookManagedBy(mgr).
For(&iamv1beta1.User{}).
WithValidator(v).
WithDefaulter(v).
Complete()
}
func (v *Webhook) Default(ctx context.Context, obj runtime.Object) error {
return nil
}
// validate admits a pod if a specific annotation exists.
func (v *Webhook) validate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
user, ok := obj.(*iamv1beta1.User)
if !ok {
return nil, fmt.Errorf("expected a User but got a %T", obj)
}
allUsers := iamv1beta1.UserList{}
if err := v.List(ctx, &allUsers, &client.ListOptions{}); err != nil {
return nil, err
}
if _, err := mail.ParseAddress(user.Spec.Email); user.Spec.Email != "" && err != nil {
return nil, fmt.Errorf("invalid email address:%s", user.Spec.Email)
}
alreadyExist := emailAlreadyExist(allUsers, user)
if alreadyExist {
return nil, fmt.Errorf("user email: %s already exists", user.Spec.Email)
}
return nil, nil
}
func (v *Webhook) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
return v.validate(ctx, obj)
}
func (v *Webhook) ValidateUpdate(ctx context.Context, _, newObj runtime.Object) (admission.Warnings, error) {
return v.validate(ctx, newObj)
}
func (v *Webhook) ValidateDelete(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
return v.validate(ctx, obj)
}
func emailAlreadyExist(users iamv1beta1.UserList, user *iamv1beta1.User) bool {
// empty email is allowed
if user.Spec.Email == "" {
return false
}
for _, exist := range users.Items {
if exist.Spec.Email == user.Spec.Email && exist.Name != user.Name {
return true
}
}
return false
}