diff --git a/pkg/controller/signup_test.go b/pkg/controller/signup_test.go index f1449d62..8fdbfc3e 100644 --- a/pkg/controller/signup_test.go +++ b/pkg/controller/signup_test.go @@ -602,24 +602,73 @@ func initPhoneVerification(t *testing.T, handler gin.HandlerFunc, params gin.Par func (s *TestSignupSuite) TestVerifyActivationCodeHandler() { s.Run("verification successful", func() { - // given - userSignup := testusersignup.NewUserSignup(testusersignup.VerificationRequiredAgo(time.Second)) // just signed up - event := testsocialevent.NewSocialEvent(commontest.HostOperatorNs, "event") - fakeClient, application := testutil.PrepareInClusterApp(s.T(), userSignup, event) - ctrl := controller.NewSignup(application) - handler := gin.HandlerFunc(ctrl.VerifyActivationCodeHandler) - // when - rr := initActivationCodeVerification(s.T(), handler, userSignup.Name, event.Name) + s.Run("usersignup already exists", func() { + // given + userSignup := testusersignup.NewUserSignup(testusersignup.VerificationRequiredAgo(time.Second)) // just signed up + event := testsocialevent.NewSocialEvent(commontest.HostOperatorNs, "event") + fakeClient, application := testutil.PrepareInClusterApp(s.T(), userSignup, event) + ctrl := controller.NewSignup(application) + handler := gin.HandlerFunc(ctrl.VerifyActivationCodeHandler) - // then - require.Equal(s.T(), http.StatusOK, rr.Code) - updatedUserSignup := &crtapi.UserSignup{} - err := fakeClient.Get(gocontext.TODO(), client.ObjectKeyFromObject(userSignup), updatedUserSignup) - require.NoError(s.T(), err) - require.False(s.T(), states.VerificationRequired(updatedUserSignup)) - require.Empty(s.T(), updatedUserSignup.Annotations[crtapi.UserVerificationAttemptsAnnotationKey]) - require.Equal(s.T(), event.Name, updatedUserSignup.Labels[crtapi.SocialEventUserSignupLabelKey]) + // when + rr := initActivationCodeVerification(s.T(), handler, userSignup.Name, event.Name) + + // then + require.Equal(s.T(), http.StatusOK, rr.Code) + updatedUserSignup := &crtapi.UserSignup{} + err := fakeClient.Get(gocontext.TODO(), client.ObjectKeyFromObject(userSignup), updatedUserSignup) + require.NoError(s.T(), err) + require.False(s.T(), states.VerificationRequired(updatedUserSignup)) + require.Empty(s.T(), updatedUserSignup.Annotations[crtapi.UserVerificationAttemptsAnnotationKey]) + require.Equal(s.T(), event.Name, updatedUserSignup.Labels[crtapi.SocialEventUserSignupLabelKey]) + }) + + s.Run("usersignup already exists but it's deactivated", func() { + // given + // the user is deactivated + deactivatedUS := testusersignup.NewUserSignup(testusersignup.VerificationRequiredAgo(time.Second)) // just signed up + states.SetDeactivated(deactivatedUS, true) + deactivatedUS.Status.Conditions = fake.Deactivated() + event := testsocialevent.NewSocialEvent(commontest.HostOperatorNs, "event") + fakeClient, application := testutil.PrepareInClusterApp(s.T(), deactivatedUS, event) + ctrl := controller.NewSignup(application) + handler := gin.HandlerFunc(ctrl.VerifyActivationCodeHandler) + + // when + rr := initActivationCodeVerification(s.T(), handler, deactivatedUS.Name, event.Name) + + // then + require.Equal(s.T(), http.StatusOK, rr.Code) + updatedUserSignup := &crtapi.UserSignup{} + err := fakeClient.Get(gocontext.TODO(), client.ObjectKeyFromObject(deactivatedUS), updatedUserSignup) + require.NoError(s.T(), err) + require.False(s.T(), states.VerificationRequired(updatedUserSignup)) + require.Empty(s.T(), updatedUserSignup.Annotations[crtapi.UserVerificationAttemptsAnnotationKey]) + require.Equal(s.T(), event.Name, updatedUserSignup.Labels[crtapi.SocialEventUserSignupLabelKey]) + require.False(s.T(), states.VerificationRequired(updatedUserSignup)) // user is activated + require.False(s.T(), states.Deactivated(updatedUserSignup)) // user is activated + }) + + s.Run("usersignup doesn't exist it should be created", func() { + // given + event := testsocialevent.NewSocialEvent(commontest.HostOperatorNs, "event") + fakeClient, application := testutil.PrepareInClusterApp(s.T(), event) + ctrl := controller.NewSignup(application) + handler := gin.HandlerFunc(ctrl.VerifyActivationCodeHandler) + + // when + rr := initActivationCodeVerification(s.T(), handler, "Jane", event.Name) + + // then + require.Equal(s.T(), http.StatusOK, rr.Code) + createdUserSignup := &crtapi.UserSignup{} + err := fakeClient.Get(gocontext.TODO(), client.ObjectKey{Namespace: commontest.HostOperatorNs, Name: usersignup.EncodeUserIdentifier("Jane")}, createdUserSignup) + require.NoError(s.T(), err) + require.False(s.T(), states.VerificationRequired(createdUserSignup)) + require.Empty(s.T(), createdUserSignup.Annotations[crtapi.UserVerificationAttemptsAnnotationKey]) + require.Equal(s.T(), event.Name, createdUserSignup.Labels[crtapi.SocialEventUserSignupLabelKey]) + }) }) s.Run("verification failed", func() { diff --git a/pkg/signup/service/signup_service_test.go b/pkg/signup/service/signup_service_test.go index 6a91335c..5fdb41ca 100644 --- a/pkg/signup/service/signup_service_test.go +++ b/pkg/signup/service/signup_service_test.go @@ -127,7 +127,7 @@ func (s *TestSignupServiceSuite) TestSignup() { deactivatedUS.Annotations[toolchainv1alpha1.UserSignupActivationCounterAnnotationKey] = "2" // assume the user was activated 2 times already deactivatedUS.Annotations[toolchainv1alpha1.UserSignupLastTargetClusterAnnotationKey] = "member-3" // assume the user was targeted to member-3 states.SetDeactivated(deactivatedUS, true) - deactivatedUS.Status.Conditions = deactivated() + deactivatedUS.Status.Conditions = fake.Deactivated() fakeClient, application := testutil.PrepareInClusterApp(s.T(), deactivatedUS) // when @@ -144,7 +144,7 @@ func (s *TestSignupServiceSuite) TestSignup() { // given deactivatedUS := existing.DeepCopy() states.SetDeactivated(deactivatedUS, true) - deactivatedUS.Status.Conditions = deactivated() + deactivatedUS.Status.Conditions = fake.Deactivated() // also, alter the activation counter annotation delete(deactivatedUS.Annotations, toolchainv1alpha1.UserSignupActivationCounterAnnotationKey) delete(deactivatedUS.Annotations, toolchainv1alpha1.UserSignupLastTargetClusterAnnotationKey) @@ -164,7 +164,7 @@ func (s *TestSignupServiceSuite) TestSignup() { // given deactivatedUS := existing.DeepCopy() states.SetDeactivated(deactivatedUS, true) - deactivatedUS.Status.Conditions = deactivated() + deactivatedUS.Status.Conditions = fake.Deactivated() fakeClient, application := testutil.PrepareInClusterApp(s.T(), deactivatedUS) fakeClient.MockUpdate = func(ctx gocontext.Context, obj client.Object, opts ...client.UpdateOption) error { if _, ok := obj.(*toolchainv1alpha1.UserSignup); ok && obj.GetName() == signupcommon.EncodeUserIdentifier("jsmith@kubesaw") { @@ -698,7 +698,7 @@ func (s *TestSignupServiceSuite) TestGetSignupDeactivated() { s.ServiceConfiguration(true, "", 5) username, us := s.newUserSignupComplete() - us.Status.Conditions = deactivated() + us.Status.Conditions = fake.Deactivated() _, application := testutil.PrepareInClusterApp(s.T(), us) @@ -1346,21 +1346,6 @@ func (s *TestSignupServiceSuite) newSpaceBinding(murName, spaceName string) *too return fake.NewSpaceBinding(name.String(), murName, spaceName, "admin") } -func deactivated() []toolchainv1alpha1.Condition { - return []toolchainv1alpha1.Condition{ - { - Type: toolchainv1alpha1.UserSignupComplete, - Status: apiv1.ConditionTrue, - Reason: toolchainv1alpha1.UserSignupUserDeactivatedReason, - }, - { - Type: toolchainv1alpha1.UserSignupApproved, - Status: apiv1.ConditionFalse, - Reason: toolchainv1alpha1.UserSignupUserDeactivatedReason, - }, - } -} - type FakeCaptchaChecker struct { score float32 result error diff --git a/pkg/verification/service/verification_service.go b/pkg/verification/service/verification_service.go index 8a4a383b..9d9be339 100644 --- a/pkg/verification/service/verification_service.go +++ b/pkg/verification/service/verification_service.go @@ -12,8 +12,10 @@ import ( "github.com/codeready-toolchain/registration-service/pkg/namespaced" signuppkg "github.com/codeready-toolchain/registration-service/pkg/signup" + signupsvc "github.com/codeready-toolchain/registration-service/pkg/signup/service" "github.com/codeready-toolchain/registration-service/pkg/verification/sender" signupcommon "github.com/codeready-toolchain/toolchain-common/pkg/usersignup" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" toolchainv1alpha1 "github.com/codeready-toolchain/api/api/v1alpha1" @@ -26,7 +28,6 @@ import ( "github.com/gin-gonic/gin" apierrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) const ( @@ -41,6 +42,7 @@ type ServiceImpl struct { // nolint:revive namespaced.Client HTTPClient *http.Client NotificationService sender.NotificationSender + SignupService service.SignupService } type VerificationServiceOption func(svc *ServiceImpl) @@ -54,6 +56,7 @@ func NewVerificationService(client namespaced.Client) service.VerificationServic return &ServiceImpl{ Client: client, NotificationService: sender.CreateNotificationSender(httpClient), + SignupService: signupsvc.NewSignupService(client), } } @@ -387,9 +390,16 @@ func (s *ServiceImpl) VerifyActivationCode(ctx *gin.Context, username, code stri signup := &toolchainv1alpha1.UserSignup{} if err := s.Get(gocontext.TODO(), s.NamespacedName(signupcommon.EncodeUserIdentifier(username)), signup); err != nil { if apierrors.IsNotFound(err) { - return crterrors.NewNotFoundError(err, "user not found") + // signup user + signup, err = s.SignupService.Signup(ctx) + if err != nil { + log.Error(ctx, err, "error creating UserSignup resource") + return crterrors.NewInternalError(err, "error creating UserSignup resource") + } + log.Infof(ctx, "UserSignup created: %s", signup.Name) + } else { + return crterrors.NewInternalError(err, fmt.Sprintf("error retrieving usersignup with username '%s'", username)) } - return crterrors.NewInternalError(err, fmt.Sprintf("error retrieving usersignup with username '%s'", username)) } annotationValues := map[string]string{} annotationsToDelete := []string{} @@ -404,6 +414,7 @@ func (s *ServiceImpl) VerifyActivationCode(ctx *gin.Context, username, code stri } if unsetVerificationRequired { states.SetVerificationRequired(signup, false) + states.SetDeactivated(signup, false) } if signup.Annotations == nil { signup.Annotations = map[string]string{} diff --git a/test/fake/conditions.go b/test/fake/conditions.go new file mode 100644 index 00000000..222cf20f --- /dev/null +++ b/test/fake/conditions.go @@ -0,0 +1,21 @@ +package fake + +import ( + toolchainv1alpha1 "github.com/codeready-toolchain/api/api/v1alpha1" + apiv1 "k8s.io/api/core/v1" +) + +func Deactivated() []toolchainv1alpha1.Condition { + return []toolchainv1alpha1.Condition{ + { + Type: toolchainv1alpha1.UserSignupComplete, + Status: apiv1.ConditionTrue, + Reason: toolchainv1alpha1.UserSignupUserDeactivatedReason, + }, + { + Type: toolchainv1alpha1.UserSignupApproved, + Status: apiv1.ConditionFalse, + Reason: toolchainv1alpha1.UserSignupUserDeactivatedReason, + }, + } +}