diff options
Diffstat (limited to 'controller-server/src/test/java/com')
8 files changed, 193 insertions, 26 deletions
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/MailVerifierTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/MailVerifierTest.java new file mode 100644 index 00000000000..873ab435444 --- /dev/null +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/MailVerifierTest.java @@ -0,0 +1,102 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller; + +import com.yahoo.config.provision.SystemName; +import com.yahoo.config.provision.TenantName; +import com.yahoo.vespa.hosted.controller.api.integration.stubs.MockMailer; +import com.yahoo.vespa.hosted.controller.tenant.CloudTenant; +import com.yahoo.vespa.hosted.controller.tenant.Email; +import com.yahoo.vespa.hosted.controller.tenant.PendingMailVerification; +import com.yahoo.vespa.hosted.controller.tenant.Tenant; +import com.yahoo.vespa.hosted.controller.tenant.TenantContacts; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.time.Duration; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + + +/** + * @author olaa + */ +class MailVerifierTest { + + private final ControllerTester tester = new ControllerTester(SystemName.Public); + private final MockMailer mailer = tester.serviceRegistry().mailer(); + private final MailVerifier mailVerifier = new MailVerifier(tester.controller().tenants(), mailer, tester.curator(), tester.clock()); + + private static final TenantName tenantName = TenantName.from("scoober"); + private static final String mail = "unverified@bar.com"; + private static final List<TenantContacts.Audience> audiences = List.of(TenantContacts.Audience.NOTIFICATIONS, TenantContacts.Audience.TENANT); + + @BeforeEach + public void setup() { + tester.createTenant(tenantName.value(), Tenant.Type.cloud); + + tester.controller().tenants().lockOrThrow(tenantName, LockedTenant.Cloud.class, lockedTenant -> { + var contacts = List.of( + new TenantContacts.EmailContact(audiences, new Email("verified@bar.com", true)), + new TenantContacts.EmailContact(audiences, new Email(mail, false)), + new TenantContacts.EmailContact(audiences, new Email("another-unverified@bar.com", false)) + ); + lockedTenant = lockedTenant.withInfo(lockedTenant.get().info().withContacts(new TenantContacts(contacts))); + tester.controller().tenants().store(lockedTenant); + }); + } + + @Test + public void test_new_mail_verification() { + mailVerifier.sendMailVerification(tenantName, mail, PendingMailVerification.MailType.NOTIFICATIONS); + + // Verify mail is sent + var expectedMail = "message"; + assertEquals(1, mailer.inbox(mail).size()); + assertEquals(expectedMail, mailer.inbox(mail).get(0).message()); + + // Verify ZK data is updated + var writtenMailVerification = tester.curator().listPendingMailVerifications().get(0); + assertEquals(PendingMailVerification.MailType.NOTIFICATIONS, writtenMailVerification.getMailType()); + assertEquals(tenantName, writtenMailVerification.getTenantName()); + assertEquals(tester.clock().instant().plus(Duration.ofDays(7)), writtenMailVerification.getVerificationDeadline()); + assertEquals(mail, writtenMailVerification.getMailAddress()); + + // Mail verification is no-op if deadline has passed + tester.clock().advance(Duration.ofDays(14)); + assertFalse(mailVerifier.verifyMail(writtenMailVerification.getVerificationCode())); + assertFalse(tester.curator().listPendingMailVerifications().isEmpty()); + + // Mail is verified + tester.clock().retreat(Duration.ofDays(14)); + mailVerifier.verifyMail(writtenMailVerification.getVerificationCode()); + assertTrue(tester.curator().listPendingMailVerifications().isEmpty()); + var tenant = tester.controller().tenants().require(tenantName, CloudTenant.class); + var expectedContacts = List.of( + new TenantContacts.EmailContact(audiences, new Email("verified@bar.com", true)), + new TenantContacts.EmailContact(audiences, new Email(mail, true)), + new TenantContacts.EmailContact(audiences, new Email("another-unverified@bar.com", false)) + ); + assertEquals(expectedContacts, tenant.info().contacts().all()); + } + + @Test + public void resending_verification_deletes_old_one() { + var pendingMailVerification = mailVerifier.sendMailVerification(tenantName, mail, PendingMailVerification.MailType.NOTIFICATIONS); + var tenant = tester.controller().tenants().require(tenantName, CloudTenant.class); + + // Unknown mail is no-op + var resentVerification = mailVerifier.resendMailVerification(tenantName, "unknown-mail", PendingMailVerification.MailType.NOTIFICATIONS); + assertTrue(resentVerification.isEmpty()); + assertTrue(tester.curator().getPendingMailVerification(pendingMailVerification.getVerificationCode()).isPresent()); + + // Verification mail is re-sent, old data is replaced + resentVerification = mailVerifier.resendMailVerification(tenantName, mail, PendingMailVerification.MailType.NOTIFICATIONS); + assertTrue(resentVerification.isPresent()); + assertTrue(tester.curator().getPendingMailVerification(pendingMailVerification.getVerificationCode()).isEmpty()); + assertTrue(tester.curator().getPendingMailVerification(resentVerification.get().getVerificationCode()).isPresent()); + } + +}
\ No newline at end of file diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotificationsDbTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotificationsDbTest.java index 4c1344650f8..852d4847b7e 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotificationsDbTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotificationsDbTest.java @@ -22,6 +22,7 @@ import com.yahoo.vespa.hosted.controller.integration.ZoneRegistryMock; import com.yahoo.vespa.hosted.controller.persistence.MockCuratorDb; import com.yahoo.vespa.hosted.controller.tenant.ArchiveAccess; import com.yahoo.vespa.hosted.controller.tenant.CloudTenant; +import com.yahoo.vespa.hosted.controller.tenant.Email; import com.yahoo.vespa.hosted.controller.tenant.LastLoginInfo; import com.yahoo.vespa.hosted.controller.tenant.TenantContacts; import com.yahoo.vespa.hosted.controller.tenant.TenantInfo; @@ -49,7 +50,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; public class NotificationsDbTest { private static final TenantName tenant = TenantName.from("tenant1"); - private static final String email = "user1@example.com"; + private static final Email email = new Email("user1@example.com", true); private static final CloudTenant cloudTenant = new CloudTenant(tenant, Instant.now(), LastLoginInfo.EMPTY, @@ -111,19 +112,19 @@ public class NotificationsDbTest { ; var a = notifications.get(0); notificationsDb.setNotification(a.source(), a.type(), a.level(), a.messages()); - assertEquals(0, mailer.inbox(email).size()); + assertEquals(0, mailer.inbox(email.getEmailAddress()).size()); // Replace the 3rd notification. but don't change source or type notificationsDb.setNotification(notification1.source(), notification1.type(), notification1.level(), notification1.messages()); - assertEquals(0, mailer.inbox(email).size()); + assertEquals(0, mailer.inbox(email.getEmailAddress()).size()); // Notification for a new app, add without replacement notificationsDb.setNotification(notification2.source(), notification2.type(), notification2.level(), notification2.messages()); - assertEquals(1, mailer.inbox(email).size()); + assertEquals(1, mailer.inbox(email.getEmailAddress()).size()); // Notification for new type on existing app notificationsDb.setNotification(notification3.source(), notification3.type(), notification3.level(), notification3.messages()); - assertEquals(2, mailer.inbox(email).size()); + assertEquals(2, mailer.inbox(email.getEmailAddress()).size()); } @Test @@ -157,19 +158,19 @@ public class NotificationsDbTest { // No metrics, no new notification notificationsDb.setDeploymentMetricsNotifications(deploymentId, List.of()); - assertEquals(0, mailer.inbox(email).size()); + assertEquals(0, mailer.inbox(email.getEmailAddress()).size()); // Metrics that contain none of the feed block metrics does not create new notification notificationsDb.setDeploymentMetricsNotifications(deploymentId, List.of(clusterMetrics("cluster1", null, null, null, null, Map.of()))); - assertEquals(0, mailer.inbox(email).size()); + assertEquals(0, mailer.inbox(email.getEmailAddress()).size()); // One resource is at warning notificationsDb.setDeploymentMetricsNotifications(deploymentId, List.of(clusterMetrics("cluster1", 0.88, 0.9, 0.3, 0.5, Map.of()))); - assertEquals(1, mailer.inbox(email).size()); + assertEquals(1, mailer.inbox(email.getEmailAddress()).size()); // One resource over the limit notificationsDb.setDeploymentMetricsNotifications(deploymentId, List.of(clusterMetrics("cluster1", 0.95, 0.9, 0.3, 0.5, Map.of()))); - assertEquals(2, mailer.inbox(email).size()); + assertEquals(2, mailer.inbox(email.getEmailAddress()).size()); } @Test diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotifierTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotifierTest.java index 7c07192d633..c0501206494 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotifierTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotifierTest.java @@ -13,6 +13,7 @@ import com.yahoo.vespa.hosted.controller.integration.ZoneRegistryMock; import com.yahoo.vespa.hosted.controller.persistence.MockCuratorDb; import com.yahoo.vespa.hosted.controller.tenant.ArchiveAccess; import com.yahoo.vespa.hosted.controller.tenant.CloudTenant; +import com.yahoo.vespa.hosted.controller.tenant.Email; import com.yahoo.vespa.hosted.controller.tenant.LastLoginInfo; import com.yahoo.vespa.hosted.controller.tenant.TenantContacts; import com.yahoo.vespa.hosted.controller.tenant.TenantInfo; @@ -28,7 +29,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; public class NotifierTest { private static final TenantName tenant = TenantName.from("tenant1"); - private static final String email = "user1@example.com"; + private static final Email email = new Email("user1@example.com", true); private static final CloudTenant cloudTenant = new CloudTenant(tenant, Instant.now(), @@ -63,8 +64,8 @@ public class NotifierTest { List.of("test package has production tests, but no production tests are declared in deployment.xml", "see https://docs.vespa.ai/en/testing.html for details on how to write system tests for Vespa")); notifier.dispatch(notification); - assertEquals(1, mailer.inbox(email).size()); - var mail = mailer.inbox(email).get(0); + assertEquals(1, mailer.inbox(email.getEmailAddress()).size()); + var mail = mailer.inbox(email.getEmailAddress()).get(0); assertEquals("[WARNING] Test package Vespa Notification for tenant1.default.default", mail.subject()); assertEquals(""" diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/MailVerificationSerializerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/MailVerificationSerializerTest.java new file mode 100644 index 00000000000..69c6e13ba62 --- /dev/null +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/MailVerificationSerializerTest.java @@ -0,0 +1,31 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller.persistence; + +import com.yahoo.config.provision.TenantName; +import com.yahoo.vespa.hosted.controller.tenant.PendingMailVerification; +import org.junit.jupiter.api.Test; + +import java.time.Instant; +import java.time.temporal.ChronoUnit; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author olaa + */ +public class MailVerificationSerializerTest { + + @Test + public void test_serialization() { + var original = new PendingMailVerification(TenantName.from("test-tenant"), + "email@mycomp.any", + "xyz-123", + Instant.now().truncatedTo(ChronoUnit.MILLIS), + PendingMailVerification.MailType.TENANT_CONTACT + ); + + var serialized = MailVerificationSerializer.toSlime(original); + var deserialized = MailVerificationSerializer.fromSlime(serialized); + assertEquals(original, deserialized); + } +}
\ No newline at end of file diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializerTest.java index 636620acf07..5144c5cb7b4 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializerTest.java @@ -17,6 +17,7 @@ import com.yahoo.vespa.hosted.controller.tenant.ArchiveAccess; import com.yahoo.vespa.hosted.controller.tenant.AthenzTenant; import com.yahoo.vespa.hosted.controller.tenant.CloudTenant; import com.yahoo.vespa.hosted.controller.tenant.DeletedTenant; +import com.yahoo.vespa.hosted.controller.tenant.Email; import com.yahoo.vespa.hosted.controller.tenant.LastLoginInfo; import com.yahoo.vespa.hosted.controller.tenant.TenantAddress; import com.yahoo.vespa.hosted.controller.tenant.TenantBilling; @@ -190,7 +191,7 @@ public class TenantSerializerTest { Slime slime = new Slime(); Cursor parentObject = slime.setObject(); serializer.toSlime(partialInfo, parentObject); - assertEquals("{\"info\":{\"name\":\"\",\"email\":\"\",\"website\":\"\",\"contactName\":\"\",\"contactEmail\":\"\",\"address\":{\"addressLines\":\"\",\"postalCodeOrZip\":\"\",\"city\":\"Hønefoss\",\"stateRegionProvince\":\"\",\"country\":\"\"}}}", slime.toString()); + assertEquals("{\"info\":{\"name\":\"\",\"email\":\"\",\"website\":\"\",\"contactName\":\"\",\"contactEmail\":\"\",\"contactEmailVerified\":true,\"address\":{\"addressLines\":\"\",\"postalCodeOrZip\":\"\",\"city\":\"Hønefoss\",\"stateRegionProvince\":\"\",\"country\":\"\"}}}", slime.toString()); } @Test @@ -199,7 +200,7 @@ public class TenantSerializerTest { .withName("My Company") .withEmail("email@mycomp.any") .withWebsite("http://mycomp.any") - .withContact(TenantContact.from("My Name", "ceo@mycomp.any")) + .withContact(TenantContact.from("My Name", new Email("ceo@mycomp.any", true))) .withAddress(TenantAddress.empty() .withCity("Hønefoss") .withAddress("Riperbakken 2") @@ -207,7 +208,7 @@ public class TenantSerializerTest { .withCode("3510") .withRegion("Viken")) .withBilling(TenantBilling.empty() - .withContact(TenantContact.from("Thomas The Tank Engine", "thomas@sodor.com", "NA")) + .withContact(TenantContact.from("Thomas The Tank Engine", new Email("ceo@mycomp.any", true), "NA")) .withAddress(TenantAddress.empty() .withCity("Suddery") .withCountry("Sodor") @@ -226,8 +227,8 @@ public class TenantSerializerTest { void cloud_tenant_with_tenant_info_contacts() { TenantInfo tenantInfo = TenantInfo.empty() .withContacts(new TenantContacts(List.of( - new TenantContacts.EmailContact(List.of(TenantContacts.Audience.TENANT), "email1@email.com"), - new TenantContacts.EmailContact(List.of(TenantContacts.Audience.TENANT, TenantContacts.Audience.NOTIFICATIONS), "email2@email.com")))); + new TenantContacts.EmailContact(List.of(TenantContacts.Audience.TENANT), new Email("email1@email.com", true)), + new TenantContacts.EmailContact(List.of(TenantContacts.Audience.TENANT, TenantContacts.Audience.NOTIFICATIONS), new Email("email2@email.com", true))))); Slime slime = new Slime(); Cursor parentCursor = slime.setObject(); serializer.toSlime(tenantInfo, parentCursor); diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java index ab671be23eb..4a816ebeee9 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java @@ -90,7 +90,7 @@ public class ApplicationApiCloudTest extends ControllerContainerCloudTest { .roles(Set.of(Role.administrator(tenantName))); tester.assertResponse(updateRequest, "{\"message\":\"Tenant info updated\"}", 200); - tester.assertResponse(request, "{\"contact\":{\"name\":\"Some Name\",\"email\":\"foo@example.com\"},\"tenant\":{\"company\":\"\",\"website\":\"https://example.com/\"}}", 200); + tester.assertResponse(request, "{\"contact\":{\"name\":\"Some Name\",\"email\":\"foo@example.com\",\"emailVerified\":false},\"tenant\":{\"company\":\"\",\"website\":\"https://example.com/\"}}", 200); } @Test @@ -117,7 +117,7 @@ public class ApplicationApiCloudTest extends ControllerContainerCloudTest { tester.assertResponse(request, "{\"contacts\":[]}", 200); - var fullContacts = "{\"contacts\":[{\"audiences\":[\"tenant\"],\"email\":\"contact1@example.com\"},{\"audiences\":[\"notifications\"],\"email\":\"contact2@example.com\"},{\"audiences\":[\"tenant\",\"notifications\"],\"email\":\"contact3@example.com\"}]}"; + var fullContacts = "{\"contacts\":[{\"audiences\":[\"tenant\"],\"email\":\"contact1@example.com\",\"emailVerified\":false},{\"audiences\":[\"notifications\"],\"email\":\"contact2@example.com\",\"emailVerified\":false},{\"audiences\":[\"tenant\",\"notifications\"],\"email\":\"contact3@example.com\",\"emailVerified\":false}]}"; var updateRequest = request("/application/v4/tenant/scoober/info/contacts", PUT) .data(fullContacts) .roles(Set.of(Role.administrator(tenantName))); @@ -147,12 +147,12 @@ public class ApplicationApiCloudTest extends ControllerContainerCloudTest { tester.assertResponse(postPartialContacts, "{\"message\":\"Tenant info updated\"}", 200); // Read back the updated info - tester.assertResponse(infoRequest, "{\"name\":\"\",\"email\":\"\",\"website\":\"\",\"contactName\":\"newName\",\"contactEmail\":\"foo@example.com\",\"billingContact\":{\"name\":\"billingName\",\"email\":\"\",\"phone\":\"\"},\"contacts\":[{\"audiences\":[\"tenant\"],\"email\":\"contact1@example.com\"}]}", 200); + tester.assertResponse(infoRequest, "{\"name\":\"\",\"email\":\"\",\"website\":\"\",\"contactName\":\"newName\",\"contactEmail\":\"foo@example.com\",\"contactEmailVerified\":false,\"billingContact\":{\"name\":\"billingName\",\"email\":\"\",\"phone\":\"\"},\"contacts\":[{\"audiences\":[\"tenant\"],\"email\":\"contact1@example.com\",\"emailVerified\":false}]}", 200); String fullAddress = "{\"addressLines\":\"addressLines\",\"postalCodeOrZip\":\"postalCodeOrZip\",\"city\":\"city\",\"stateRegionProvince\":\"stateRegionProvince\",\"country\":\"country\"}"; String fullBillingContact = "{\"name\":\"name\",\"email\":\"foo@example\",\"phone\":\"phone\",\"address\":" + fullAddress + "}"; - String fullContacts = "[{\"audiences\":[\"tenant\"],\"email\":\"contact1@example.com\"},{\"audiences\":[\"notifications\"],\"email\":\"contact2@example.com\"},{\"audiences\":[\"tenant\",\"notifications\"],\"email\":\"contact3@example.com\"}]"; - String fullInfo = "{\"name\":\"name\",\"email\":\"foo@example\",\"website\":\"https://yahoo.com\",\"contactName\":\"contactName\",\"contactEmail\":\"contact@example.com\",\"address\":" + fullAddress + ",\"billingContact\":" + fullBillingContact + ",\"contacts\":" + fullContacts + "}"; + String fullContacts = "[{\"audiences\":[\"tenant\"],\"email\":\"contact1@example.com\",\"emailVerified\":false},{\"audiences\":[\"notifications\"],\"email\":\"contact2@example.com\",\"emailVerified\":false},{\"audiences\":[\"tenant\",\"notifications\"],\"email\":\"contact3@example.com\",\"emailVerified\":false}]"; + String fullInfo = "{\"name\":\"name\",\"email\":\"foo@example\",\"website\":\"https://yahoo.com\",\"contactName\":\"contactName\",\"contactEmail\":\"contact@example.com\",\"contactEmailVerified\":false,\"address\":" + fullAddress + ",\"billingContact\":" + fullBillingContact + ",\"contacts\":" + fullContacts + "}"; // Now set all fields var postFull = @@ -163,6 +163,20 @@ public class ApplicationApiCloudTest extends ControllerContainerCloudTest { // Now compare the updated info with the full info we sent tester.assertResponse(infoRequest, fullInfo, 200); + + var invalidBody = "{\"mail\":\"contact1@example.com\", \"mailType\":\"blurb\"}"; + var resendMailRequest = + request("/application/v4/tenant/scoober/info/resend-mail-verification", PUT) + .data(invalidBody) + .roles(Set.of(Role.administrator(tenantName))); + tester.assertResponse(resendMailRequest, "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Unknown mail type blurb\"}", 400); + + var resendMailBody = "{\"mail\":\"contact1@example.com\", \"mailType\":\"notifications\"}"; + resendMailRequest = + request("/application/v4/tenant/scoober/info/resend-mail-verification", PUT) + .data(resendMailBody) + .roles(Set.of(Role.administrator(tenantName))); + tester.assertResponse(resendMailRequest, "{\"message\":\"Re-sent verification mail to contact1@example.com\"}", 200); } @Test @@ -185,13 +199,13 @@ public class ApplicationApiCloudTest extends ControllerContainerCloudTest { var missingEmailResponse = request("/application/v4/tenant/scoober/info", PUT) .data(partialInfoMissingEmail) .roles(Set.of(Role.administrator(tenantName))); - tester.assertResponse(missingEmailResponse, "{\"error-code\":\"BAD_REQUEST\",\"message\":\"'contactEmail' cannot be empty\"}", 400); + tester.assertResponse(missingEmailResponse, "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Invalid email address\"}", 400); var partialInfoBadEmail = "{\"contactName\": \"Scoober Rentals Inc.\", \"contactEmail\": \"somethingweird\"}"; var badEmailResponse = request("/application/v4/tenant/scoober/info", PUT) .data(partialInfoBadEmail) .roles(Set.of(Role.administrator(tenantName))); - tester.assertResponse(badEmailResponse, "{\"error-code\":\"BAD_REQUEST\",\"message\":\"'contactEmail' needs to be an email address\"}", 400); + tester.assertResponse(badEmailResponse, "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Invalid email address\"}", 400); var invalidWebsite = "{\"contactName\": \"Scoober Rentals Inc.\", \"contactEmail\": \"email@scoober.com\", \"website\": \"scoober\" }"; var badWebsiteResponse = request("/application/v4/tenant/scoober/info", PUT) @@ -231,7 +245,7 @@ public class ApplicationApiCloudTest extends ControllerContainerCloudTest { var contactsWithInvalidEmailResponse = request("/application/v4/tenant/scoober/info", PUT) .data(contactsWithInvalidEmail) .roles(Set.of(Role.administrator(tenantName))); - tester.assertResponse(contactsWithInvalidEmailResponse, "{\"error-code\":\"BAD_REQUEST\",\"message\":\"'email' needs to be an email address\"}", 400); + tester.assertResponse(contactsWithInvalidEmailResponse, "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Invalid email address\"}", 400); // duplicate contact is not allowed var contactsWithDuplicateEmail = "{\"contacts\": [{\"audiences\": [\"tenant\"],\"email\": \"contact1@email.com\"}, {\"audiences\": [\"tenant\"],\"email\": \"contact1@email.com\"}]}"; diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java index b573940d150..075e001655f 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java @@ -10,11 +10,11 @@ import com.yahoo.vespa.flags.PermanentFlags; import com.yahoo.vespa.hosted.controller.ControllerTester; import com.yahoo.vespa.hosted.controller.api.integration.billing.PlanId; import com.yahoo.jdisc.http.filter.security.misc.User; -import com.yahoo.vespa.hosted.controller.api.integration.stubs.MockUserManagement; import com.yahoo.vespa.hosted.controller.api.integration.user.UserId; import com.yahoo.vespa.hosted.controller.api.role.Role; import com.yahoo.vespa.hosted.controller.restapi.ContainerTester; import com.yahoo.vespa.hosted.controller.restapi.ControllerContainerCloudTest; +import com.yahoo.vespa.hosted.controller.tenant.PendingMailVerification; import com.yahoo.vespa.hosted.controller.tenant.Tenant; import org.junit.jupiter.api.Test; @@ -321,4 +321,20 @@ public class UserApiTest extends ControllerContainerCloudTest { } } + + @Test + public void verifyMail() { + var tester = new ContainerTester(container, responseFiles); + var controller = new ControllerTester(tester); + controller.createTenant("tenant1", Tenant.Type.cloud); + var pendingMailVerification = tester.controller().mailVerifier().sendMailVerification(TenantName.from("tenant1"), "foo@bar.com", PendingMailVerification.MailType.NOTIFICATIONS); + + tester.assertResponse(request("/user/v1/email/verify", POST) + .data("{\"verificationCode\":\"blurb\"}"), + "{\"error-code\":\"NOT_FOUND\",\"message\":\"No pending email verification with code blurb found\"}", 404); + + tester.assertResponse(request("/user/v1/email/verify", POST) + .data("{\"verificationCode\":\"" + pendingMailVerification.getVerificationCode() + "\"}"), + "{\"message\":\"Email with verification code " + pendingMailVerification.getVerificationCode() + " has been verified\"}", 200); + } } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/tenant-info-after-created.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/tenant-info-after-created.json index 2a33f35545c..6702eff8dde 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/tenant-info-after-created.json +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/tenant-info-after-created.json @@ -4,5 +4,6 @@ "website": "", "contactName": "administrator", "contactEmail": "administrator@tenant", + "contactEmailVerified": true, "contacts": [ ] } |