summaryrefslogtreecommitdiffstats
path: root/controller-server/src/test/java/com
diff options
context:
space:
mode:
authorOla Aunrønning <olaa@yahooinc.com>2022-10-27 14:47:25 +0200
committerGitHub <noreply@github.com>2022-10-27 14:47:25 +0200
commit30a93b4910c1de1a10ebccfa545d03e1deac8056 (patch)
tree48f239e59fd895064f653165652b8d111140d991 /controller-server/src/test/java/com
parent0cb3aa286942e998a598c390332466a432b6e956 (diff)
parentc6903a0afe6244587ccf2ae345acaff3b55fb12b (diff)
Merge pull request #24555 from vespa-engine/olaa/email-verification
Add email verification
Diffstat (limited to 'controller-server/src/test/java/com')
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/MailVerifierTest.java102
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotificationsDbTest.java19
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotifierTest.java7
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/MailVerificationSerializerTest.java31
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializerTest.java11
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java30
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java18
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/tenant-info-after-created.json1
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": [ ]
}