summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorØyvind Grønnesby <oyving@verizonmedia.com>2022-03-01 11:24:18 +0100
committerLeandro Alves <leandroalves@yahooinc.com>2022-03-14 11:01:55 +0100
commit6012cf065da30cf9baee97706d67a6ff6e77cb46 (patch)
treedc5ba6fc61e3a6acab5b61d6b22cbf225296e95a
parentfed4f6dddba35fe13b9d10dc79485fa7d4d97afb (diff)
Clean up the tenant info classes
There was some repetition in the TenantInfo classes. Created dedicated classes for TenantAddress and TenantContact. Used these throughout the TenantInfo tree. This commit also removes the 'invoiceEmail' field that was never used.
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/CloudTenant.java2
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantAddress.java97
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantContact.java68
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfo.java120
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfoAddress.java97
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfoBillingContact.java67
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializer.java53
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java80
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializerTest.java39
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java4
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/filter/SignatureFilterTest.java4
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/tenant-info-after-created.json1
12 files changed, 331 insertions, 301 deletions
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/CloudTenant.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/CloudTenant.java
index 9894de86116..9a4e04ebb3a 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/CloudTenant.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/CloudTenant.java
@@ -53,7 +53,7 @@ public class CloudTenant extends Tenant {
createdAt,
LastLoginInfo.EMPTY,
Optional.ofNullable(creator),
- ImmutableBiMap.of(), TenantInfo.EMPTY, List.of(), Optional.empty());
+ ImmutableBiMap.of(), TenantInfo.empty(), List.of(), Optional.empty());
}
/** The user that created the tenant */
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantAddress.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantAddress.java
new file mode 100644
index 00000000000..02a8629eff1
--- /dev/null
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantAddress.java
@@ -0,0 +1,97 @@
+package com.yahoo.vespa.hosted.controller.tenant;
+
+import java.util.Objects;
+
+/**
+ * A generic address container that tries to make as few assumptions about addresses as possible.
+ * Most addresses have some of these fields, but with different names (e.g. postal code vs zip code).
+ *
+ * When consuming data from this class, do not make any assumptions about which fields have content.
+ * An address might be still valid with surprisingly little information.
+ *
+ * All fields are non-null, but might be empty strings.
+ *
+ * @author ogronnesby
+ */
+public class TenantAddress {
+ private final String address;
+ private final String code;
+ private final String city;
+ private final String region;
+ private final String country;
+
+ TenantAddress(String address, String code, String city, String region, String country) {
+ this.address = Objects.requireNonNull(address, "'address' was null");
+ this.code = Objects.requireNonNull(code, "'code' was null");
+ this.city = Objects.requireNonNull(city, "'city' was null");
+ this.region = Objects.requireNonNull(region, "'region' was null");
+ this.country = Objects.requireNonNull(country, "'country' was null");
+ }
+
+ public static TenantAddress empty() {
+ return new TenantAddress("", "", "", "", "");
+ }
+
+ /** Multi-line fields that has the contents of the street address (or similar) */
+ public String address() { return address; }
+
+ /** The ZIP or postal code part of the address */
+ public String code() { return code; }
+
+ /** The city of the address */
+ public String city() { return city; }
+
+ /** The region part of the address - e.g. a state, county, or province */
+ public String region() { return region; }
+
+ /** The country part of the address. Its name, not a code */
+ public String country() { return country; }
+
+ public boolean isEmpty() {
+ return this.equals(empty());
+ }
+
+ public TenantAddress withAddress(String address) {
+ return new TenantAddress(address, code, city, region, country);
+ }
+
+ public TenantAddress withCode(String code) {
+ return new TenantAddress(address, code, city, region, country);
+ }
+
+ public TenantAddress withCity(String city) {
+ return new TenantAddress(address, code, city, region, country);
+ }
+
+ public TenantAddress withRegion(String region) {
+ return new TenantAddress(address, code, city, region, country);
+ }
+
+ public TenantAddress withCountry(String country) {
+ return new TenantAddress(address, code, city, region, country);
+ }
+
+ @Override
+ public String toString() {
+ return "TenantAddress{" +
+ "address='" + address + '\'' +
+ ", code='" + code + '\'' +
+ ", city='" + city + '\'' +
+ ", region='" + region + '\'' +
+ ", country='" + country + '\'' +
+ '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ TenantAddress that = (TenantAddress) o;
+ return Objects.equals(address, that.address) && Objects.equals(code, that.code) && Objects.equals(city, that.city) && Objects.equals(region, that.region) && Objects.equals(country, that.country);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(address, code, city, region, country);
+ }
+}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantContact.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantContact.java
new file mode 100644
index 00000000000..e99c126bef1
--- /dev/null
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantContact.java
@@ -0,0 +1,68 @@
+package com.yahoo.vespa.hosted.controller.tenant;
+
+import java.util.Objects;
+
+/**
+ * @author ogronnesby
+ */
+public class TenantContact {
+ private String name;
+ private String email;
+ private String phone;
+
+ private TenantContact(String name, String email, String phone) {
+ this.name = Objects.requireNonNull(name);
+ this.email = Objects.requireNonNull(email);
+ this.phone = Objects.requireNonNull(phone);
+ }
+
+ public static TenantContact from(String name, String email, String phone) {
+ return new TenantContact(name, email, phone);
+ }
+
+ public static TenantContact from(String name, String email) {
+ return TenantContact.from(name, email, "");
+ }
+
+ public static TenantContact empty() {
+ return new TenantContact("", "", "");
+ }
+
+ public String name() { return name; }
+ public String email() { return email; }
+ public String phone() { return phone; }
+
+ public TenantContact withName(String name) {
+ return new TenantContact(name, email, phone);
+ }
+
+ public TenantContact withEmail(String email) {
+ return new TenantContact(name, email, phone);
+ }
+
+ public TenantContact withPhone(String phone) {
+ return new TenantContact(name, email, phone);
+ }
+
+ @Override
+ public String toString() {
+ return "TenantContact{" +
+ "name='" + name + '\'' +
+ ", email='" + email + '\'' +
+ ", phone='" + phone + '\'' +
+ '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ TenantContact that = (TenantContact) o;
+ return Objects.equals(name, that.name) && Objects.equals(email, that.email) && Objects.equals(phone, that.phone);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, email, phone);
+ }
+}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfo.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfo.java
index 87d4f03b090..9a295c5d19a 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfo.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfo.java
@@ -13,51 +13,32 @@ import java.util.Objects;
* @author smorgrav
*/
public class TenantInfo {
- // Editable as 'Tenant Information - Company Name'
- // Viewable in the 'Account - Profile' section as 'Company Name'
- private final String name;
- // Editable as 'Tenant Information - Email'
- // Not displayed outside of 'Edit profile'
+ private final String name;
private final String email;
-
- // Editable as 'Tenant Information - Website'
- // Viewable in the 'Account - Profile' section at bottom of 'Contact Information'
private final String website;
- // Editable as 'Contact Information - Contact Name'
- // Viewable in the 'Account - Profile' section in 'Contact Information'
- private final String contactName;
-
- // Editable as 'Contact Information - Contact Email'
- // Viewable in the 'Account - Profile' section in 'Contact Information'
- private final String contactEmail;
-
- // Not editable in the account setting
- // Not viewable.
- // TODO: Remove
- private final String invoiceEmail;
-
- // See class for more info
- private final TenantInfoAddress address;
-
- // See class for more info
+ private final TenantContact contact;
+ private final TenantAddress address;
private final TenantInfoBillingContact billingContact;
TenantInfo(String name, String email, String website, String contactName, String contactEmail,
- String invoiceEmail, TenantInfoAddress address, TenantInfoBillingContact billingContact) {
+ TenantAddress address, TenantInfoBillingContact billingContact) {
+ this(name, email, website, TenantContact.from(contactName, contactEmail), address, billingContact);
+ }
+
+ TenantInfo(String name, String email, String website, TenantContact contact, TenantAddress address, TenantInfoBillingContact billing) {
this.name = Objects.requireNonNull(name);
this.email = Objects.requireNonNull(email);
this.website = Objects.requireNonNull(website);
- this.contactName = Objects.requireNonNull(contactName);
- this.contactEmail = Objects.requireNonNull(contactEmail);
- this.invoiceEmail = Objects.requireNonNull(invoiceEmail);
+ this.contact = Objects.requireNonNull(contact);
this.address = Objects.requireNonNull(address);
- this.billingContact = Objects.requireNonNull(billingContact);
+ this.billingContact = Objects.requireNonNull(billing);
}
- public static final TenantInfo EMPTY = new TenantInfo("","","", "", "", "",
- TenantInfoAddress.EMPTY, TenantInfoBillingContact.EMPTY);
+ public static TenantInfo empty() {
+ return new TenantInfo("", "", "", "", "", TenantAddress.empty(), TenantInfoBillingContact.empty());
+ }
public String name() {
return name;
@@ -71,60 +52,40 @@ public class TenantInfo {
return website;
}
- public String contactName() {
- return contactName;
- }
+ public TenantContact contact() { return contact; }
- public String contactEmail() {
- return contactEmail;
- }
-
- public String invoiceEmail() {
- return invoiceEmail;
- }
-
- public TenantInfoAddress address() {
- return address;
- }
+ public TenantAddress address() { return address; }
public TenantInfoBillingContact billingContact() {
return billingContact;
}
- public TenantInfo withName(String newName) {
- return new TenantInfo(newName, email, website, contactName, contactEmail, invoiceEmail, address, billingContact);
- }
-
- public TenantInfo withEmail(String newEmail) {
- return new TenantInfo(name, newEmail, website, contactName, contactEmail, invoiceEmail, address, billingContact);
- }
-
- public TenantInfo withWebsite(String newWebsite) {
- return new TenantInfo(name, email, newWebsite, contactName, contactEmail, invoiceEmail, address, billingContact);
+ public boolean isEmpty() {
+ return this.equals(empty());
}
- public TenantInfo withContactName(String newContactName) {
- return new TenantInfo(name, email, website, newContactName, contactEmail, invoiceEmail, address, billingContact);
+ public TenantInfo withName(String name) {
+ return new TenantInfo(name, email, website, contact, address, billingContact);
}
- public TenantInfo withContactEmail(String newContactEmail) {
- return new TenantInfo(name, email, website, contactName, newContactEmail, invoiceEmail, address, billingContact);
+ public TenantInfo withEmail(String email) {
+ return new TenantInfo(name, email, website, contact, address, billingContact);
}
- public TenantInfo withInvoiceEmail(String newInvoiceEmail) {
- return new TenantInfo(name, email, website, contactName, contactEmail, newInvoiceEmail, address, billingContact);
+ public TenantInfo withWebsite(String website) {
+ return new TenantInfo(name, email, website, contact, address, billingContact);
}
- public TenantInfo withAddress(TenantInfoAddress newAddress) {
- return new TenantInfo(name, email, website, contactName, contactEmail, invoiceEmail, newAddress, billingContact);
+ public TenantInfo withContact(TenantContact contact) {
+ return new TenantInfo(name, email, website, contact, address, billingContact);
}
- public TenantInfo withBillingContact(TenantInfoBillingContact newBillingContact) {
- return new TenantInfo(name, email, website, contactName, contactEmail, invoiceEmail, address, newBillingContact);
+ public TenantInfo withAddress(TenantAddress address) {
+ return new TenantInfo(name, email, website, contact, address, billingContact);
}
- public boolean isEmpty() {
- return this.equals(EMPTY);
+ public TenantInfo withBilling(TenantInfoBillingContact billingContact) {
+ return new TenantInfo(name, email, website, contact, address, billingContact);
}
@Override
@@ -132,18 +93,23 @@ public class TenantInfo {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TenantInfo that = (TenantInfo) o;
- return name.equals(that.name) &&
- email.equals(that.email) &&
- website.equals(that.website) &&
- contactName.equals(that.contactName) &&
- contactEmail.equals(that.contactEmail) &&
- invoiceEmail.equals(that.invoiceEmail) &&
- address.equals(that.address) &&
- billingContact.equals(that.billingContact);
+ return Objects.equals(name, that.name) && Objects.equals(email, that.email) && Objects.equals(website, that.website) && Objects.equals(contact, that.contact) && Objects.equals(address, that.address) && Objects.equals(billingContact, that.billingContact);
}
@Override
public int hashCode() {
- return Objects.hash(name, email, website, contactName, contactEmail, invoiceEmail, address, billingContact);
+ return Objects.hash(name, email, website, contact, address, billingContact);
+ }
+
+ @Override
+ public String toString() {
+ return "TenantInfo{" +
+ "name='" + name + '\'' +
+ ", email='" + email + '\'' +
+ ", website='" + website + '\'' +
+ ", contact=" + contact +
+ ", address=" + address +
+ ", billingContact=" + billingContact +
+ '}';
}
}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfoAddress.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfoAddress.java
deleted file mode 100644
index 740adde4519..00000000000
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfoAddress.java
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.hosted.controller.tenant;
-
-import java.util.Objects;
-
-/**
- * Address formats are quite diverse across the world both in therms of what fields are used, named and
- * the order of them.
- *
- * To be generic a little future proof the address fields here are a mix of free text (address lines) and fixed fields.
- * The address lines can be street address, P.O box, c/o name, apartment, suite, unit, building floor etc etc.
- *
- * All fields are mandatory but can be an empty string (ie. not null)
- *
- * @author smorgrav
- */
-public class TenantInfoAddress {
-
- // All fields are editable in 'Edit Profile - Company Address'.
- // The fields are not exposed outside the 'Edit Profile' form.
- private final String addressLines;
- private final String postalCodeOrZip;
- private final String city;
- private final String stateRegionProvince;
- private final String country;
-
- TenantInfoAddress(String addressLines, String postalCodeOrZip, String city, String country, String stateRegionProvince) {
- this.addressLines = Objects.requireNonNull(addressLines);;
- this.city = Objects.requireNonNull(city);
- this.postalCodeOrZip = Objects.requireNonNull(postalCodeOrZip);
- this.country = Objects.requireNonNull(country);
- this.stateRegionProvince = Objects.requireNonNull(stateRegionProvince);
- }
-
- public static final TenantInfoAddress EMPTY = new TenantInfoAddress("","","", "", "");
-
- public String addressLines() {
- return addressLines;
- }
-
- public String postalCodeOrZip() {
- return postalCodeOrZip;
- }
-
- public String city() {
- return city;
- }
-
- public String country() {
- return country;
- }
-
- public String stateRegionProvince() {
- return stateRegionProvince;
- }
-
- public TenantInfoAddress withAddressLines(String newAddressLines) {
- return new TenantInfoAddress(newAddressLines, postalCodeOrZip, city, country, stateRegionProvince);
- }
-
- public TenantInfoAddress withPostalCodeOrZip(String newPostalCodeOrZip) {
- return new TenantInfoAddress(addressLines, newPostalCodeOrZip, city, country, stateRegionProvince);
- }
-
- public TenantInfoAddress withCity(String newCity) {
- return new TenantInfoAddress(addressLines, postalCodeOrZip, newCity, country, stateRegionProvince);
- }
-
- public TenantInfoAddress withCountry(String newCountry) {
- return new TenantInfoAddress(addressLines, postalCodeOrZip, city, newCountry, stateRegionProvince);
- }
-
- public TenantInfoAddress withStateRegionProvince(String newStateRegionProvince) {
- return new TenantInfoAddress(addressLines, postalCodeOrZip, city, country, newStateRegionProvince);
- }
-
- public boolean isEmpty() {
- return this.equals(EMPTY);
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- TenantInfoAddress that = (TenantInfoAddress) o;
- return addressLines.equals(that.addressLines) &&
- postalCodeOrZip.equals(that.postalCodeOrZip) &&
- city.equals(that.city) &&
- stateRegionProvince.equals(that.stateRegionProvince) &&
- country.equals(that.country);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(addressLines, postalCodeOrZip, city, stateRegionProvince, country);
- }
-}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfoBillingContact.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfoBillingContact.java
index c875a19d57b..2c9a0196905 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfoBillingContact.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantInfoBillingContact.java
@@ -8,56 +8,40 @@ import java.util.Objects;
*/
public class TenantInfoBillingContact {
- // All fields are editable in 'Billing - Edit billing contact'
- // Only 'name' and 'email' are exposed outside the 'Edit billing contact' form.
- // All these fields are required by the billing process.
- private final String name;
- private final String email;
- private final String phone;
- private final TenantInfoAddress address;
+ private final TenantContact contact;
+ private final TenantAddress address;
- TenantInfoBillingContact(String name, String email, String phone, TenantInfoAddress address) {
- this.name = Objects.requireNonNull(name);
- this.email = Objects.requireNonNull(email);
- this.phone = Objects.requireNonNull(phone);
- this.address = Objects.requireNonNull(address);
+ TenantInfoBillingContact(String name, String email, String phone, TenantAddress address) {
+ this(TenantContact.from(name, email, phone), address);
}
- public static final TenantInfoBillingContact EMPTY =
- new TenantInfoBillingContact("","", "", TenantInfoAddress.EMPTY);
-
- public String name() {
- return name;
+ TenantInfoBillingContact(TenantContact contact, TenantAddress address) {
+ this.contact = Objects.requireNonNull(contact);
+ this.address = Objects.requireNonNull(address);
}
- public String email() { return email; }
-
- public String phone() {
- return phone;
+ public static TenantInfoBillingContact empty() {
+ return new TenantInfoBillingContact("", "", "", TenantAddress.empty());
}
- public TenantInfoAddress address() {
- return address;
+ public TenantContact contact() {
+ return contact;
}
- public TenantInfoBillingContact withName(String newName) {
- return new TenantInfoBillingContact(newName, email, phone, address);
- }
-
- public TenantInfoBillingContact withEmail(String newEmail) {
- return new TenantInfoBillingContact(name, newEmail, phone, address);
+ public TenantAddress address() {
+ return address;
}
- public TenantInfoBillingContact withPhone(String newPhone) {
- return new TenantInfoBillingContact(name, email, newPhone, address);
+ public TenantInfoBillingContact withContact(TenantContact updatedContact) {
+ return new TenantInfoBillingContact(updatedContact, this.address);
}
- public TenantInfoBillingContact withAddress(TenantInfoAddress newAddress) {
- return new TenantInfoBillingContact(name, email, phone, newAddress);
+ public TenantInfoBillingContact withAddress(TenantAddress updatedAddress) {
+ return new TenantInfoBillingContact(this.contact, updatedAddress);
}
public boolean isEmpty() {
- return this.equals(EMPTY);
+ return this.equals(empty());
}
@Override
@@ -65,14 +49,19 @@ public class TenantInfoBillingContact {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TenantInfoBillingContact that = (TenantInfoBillingContact) o;
- return name.equals(that.name) &&
- email.equals(that.email) &&
- phone.equals(that.phone) &&
- address.equals(that.address);
+ return Objects.equals(contact, that.contact) && Objects.equals(address, that.address);
}
@Override
public int hashCode() {
- return Objects.hash(name, email, phone, address);
+ return Objects.hash(contact, address);
+ }
+
+ @Override
+ public String toString() {
+ return "TenantInfoBillingContact{" +
+ "contact=" + contact +
+ ", address=" + address +
+ '}';
}
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializer.java
index 1b6a0a6a122..020e9137779 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializer.java
@@ -22,8 +22,9 @@ import com.yahoo.vespa.hosted.controller.tenant.CloudTenant;
import com.yahoo.vespa.hosted.controller.tenant.DeletedTenant;
import com.yahoo.vespa.hosted.controller.tenant.LastLoginInfo;
import com.yahoo.vespa.hosted.controller.tenant.Tenant;
+import com.yahoo.vespa.hosted.controller.tenant.TenantAddress;
+import com.yahoo.vespa.hosted.controller.tenant.TenantContact;
import com.yahoo.vespa.hosted.controller.tenant.TenantInfo;
-import com.yahoo.vespa.hosted.controller.tenant.TenantInfoAddress;
import com.yahoo.vespa.hosted.controller.tenant.TenantInfoBillingContact;
import java.net.URI;
@@ -193,33 +194,34 @@ public class TenantSerializer {
}
TenantInfo tenantInfoFromSlime(Inspector infoObject) {
- if (!infoObject.valid()) return TenantInfo.EMPTY;
+ if (!infoObject.valid()) return TenantInfo.empty();
- return TenantInfo.EMPTY
+ return TenantInfo.empty()
.withName(infoObject.field("name").asString())
.withEmail(infoObject.field("email").asString())
.withWebsite(infoObject.field("website").asString())
- .withContactName(infoObject.field("contactName").asString())
- .withContactEmail(infoObject.field("contactEmail").asString())
- .withInvoiceEmail(infoObject.field("invoiceEmail").asString())
+ .withContact(TenantContact.from(
+ infoObject.field("contactName").asString(),
+ infoObject.field("contactEmail").asString()))
.withAddress(tenantInfoAddressFromSlime(infoObject.field("address")))
- .withBillingContact(tenantInfoBillingContactFromSlime(infoObject.field("billingContact")));
+ .withBilling(tenantInfoBillingContactFromSlime(infoObject.field("billingContact")));
}
- private TenantInfoAddress tenantInfoAddressFromSlime(Inspector addressObject) {
- return TenantInfoAddress.EMPTY
- .withAddressLines(addressObject.field("addressLines").asString())
- .withPostalCodeOrZip(addressObject.field("postalCodeOrZip").asString())
+ private TenantAddress tenantInfoAddressFromSlime(Inspector addressObject) {
+ return TenantAddress.empty()
+ .withAddress(addressObject.field("addressLines").asString())
+ .withCode(addressObject.field("postalCodeOrZip").asString())
.withCity(addressObject.field("city").asString())
- .withStateRegionProvince(addressObject.field("stateRegionProvince").asString())
+ .withRegion(addressObject.field("stateRegionProvince").asString())
.withCountry(addressObject.field("country").asString());
}
private TenantInfoBillingContact tenantInfoBillingContactFromSlime(Inspector billingObject) {
- return TenantInfoBillingContact.EMPTY
- .withName(billingObject.field("name").asString())
- .withEmail(billingObject.field("email").asString())
- .withPhone(billingObject.field("phone").asString())
+ return TenantInfoBillingContact.empty()
+ .withContact(TenantContact.from(
+ billingObject.field("name").asString(),
+ billingObject.field("email").asString(),
+ billingObject.field("phone").asString()))
.withAddress(tenantInfoAddressFromSlime(billingObject.field("address")));
}
@@ -252,21 +254,20 @@ public class TenantSerializer {
infoCursor.setString("name", info.name());
infoCursor.setString("email", info.email());
infoCursor.setString("website", info.website());
- infoCursor.setString("invoiceEmail", info.invoiceEmail());
- infoCursor.setString("contactName", info.contactName());
- infoCursor.setString("contactEmail", info.contactEmail());
+ infoCursor.setString("contactName", info.contact().name());
+ infoCursor.setString("contactEmail", info.contact().email());
toSlime(info.address(), infoCursor);
toSlime(info.billingContact(), infoCursor);
}
- private void toSlime(TenantInfoAddress address, Cursor parentCursor) {
+ private void toSlime(TenantAddress address, Cursor parentCursor) {
if (address.isEmpty()) return;
Cursor addressCursor = parentCursor.setObject("address");
- addressCursor.setString("addressLines", address.addressLines());
- addressCursor.setString("postalCodeOrZip", address.postalCodeOrZip());
+ addressCursor.setString("addressLines", address.address());
+ addressCursor.setString("postalCodeOrZip", address.code());
addressCursor.setString("city", address.city());
- addressCursor.setString("stateRegionProvince", address.stateRegionProvince());
+ addressCursor.setString("stateRegionProvince", address.region());
addressCursor.setString("country", address.country());
}
@@ -274,9 +275,9 @@ public class TenantSerializer {
if (billingContact.isEmpty()) return;
Cursor addressCursor = parentCursor.setObject("billingContact");
- addressCursor.setString("name", billingContact.name());
- addressCursor.setString("email", billingContact.email());
- addressCursor.setString("phone", billingContact.phone());
+ addressCursor.setString("name", billingContact.contact().name());
+ addressCursor.setString("email", billingContact.contact().email());
+ addressCursor.setString("phone", billingContact.contact().phone());
toSlime(billingContact.address(), addressCursor);
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
index de8f1ec7ddc..954b5826317 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
@@ -111,8 +111,9 @@ import com.yahoo.vespa.hosted.controller.tenant.CloudTenant;
import com.yahoo.vespa.hosted.controller.tenant.DeletedTenant;
import com.yahoo.vespa.hosted.controller.tenant.LastLoginInfo;
import com.yahoo.vespa.hosted.controller.tenant.Tenant;
+import com.yahoo.vespa.hosted.controller.tenant.TenantAddress;
+import com.yahoo.vespa.hosted.controller.tenant.TenantContact;
import com.yahoo.vespa.hosted.controller.tenant.TenantInfo;
-import com.yahoo.vespa.hosted.controller.tenant.TenantInfoAddress;
import com.yahoo.vespa.hosted.controller.tenant.TenantInfoBillingContact;
import com.yahoo.vespa.hosted.controller.versions.VersionStatus;
import com.yahoo.vespa.hosted.controller.versions.VespaVersion;
@@ -503,9 +504,8 @@ public class ApplicationApiHandler extends AuditLoggingRequestHandler {
infoCursor.setString("name", info.name());
infoCursor.setString("email", info.email());
infoCursor.setString("website", info.website());
- infoCursor.setString("invoiceEmail", info.invoiceEmail());
- infoCursor.setString("contactName", info.contactName());
- infoCursor.setString("contactEmail", info.contactEmail());
+ infoCursor.setString("contactName", info.contact().name());
+ infoCursor.setString("contactEmail", info.contact().email());
toSlime(info.address(), infoCursor);
toSlime(info.billingContact(), infoCursor);
}
@@ -513,14 +513,14 @@ public class ApplicationApiHandler extends AuditLoggingRequestHandler {
return new SlimeJsonResponse(slime);
}
- private void toSlime(TenantInfoAddress address, Cursor parentCursor) {
+ private void toSlime(TenantAddress address, Cursor parentCursor) {
if (address.isEmpty()) return;
Cursor addressCursor = parentCursor.setObject("address");
- addressCursor.setString("addressLines", address.addressLines());
- addressCursor.setString("postalCodeOrZip", address.postalCodeOrZip());
+ addressCursor.setString("addressLines", address.address());
+ addressCursor.setString("postalCodeOrZip", address.code());
addressCursor.setString("city", address.city());
- addressCursor.setString("stateRegionProvince", address.stateRegionProvince());
+ addressCursor.setString("stateRegionProvince", address.region());
addressCursor.setString("country", address.country());
}
@@ -528,9 +528,9 @@ public class ApplicationApiHandler extends AuditLoggingRequestHandler {
if (billingContact.isEmpty()) return;
Cursor addressCursor = parentCursor.setObject("billingContact");
- addressCursor.setString("name", billingContact.name());
- addressCursor.setString("email", billingContact.email());
- addressCursor.setString("phone", billingContact.phone());
+ addressCursor.setString("name", billingContact.contact().name());
+ addressCursor.setString("email", billingContact.contact().email());
+ addressCursor.setString("phone", billingContact.contact().phone());
toSlime(billingContact.address(), addressCursor);
}
@@ -550,24 +550,27 @@ public class ApplicationApiHandler extends AuditLoggingRequestHandler {
// Merge info from request with the existing info
Inspector insp = toSlime(request.getData()).get();
- TenantInfo mergedInfo = TenantInfo.EMPTY
+
+ TenantContact mergedContact = TenantContact.empty()
+ .withName(getString(insp.field("contactName"), oldInfo.contact().name()))
+ .withEmail(getString(insp.field("contactEmail"), oldInfo.contact().email()));
+
+ TenantInfo mergedInfo = TenantInfo.empty()
.withName(getString(insp.field("name"), oldInfo.name()))
- .withEmail(getString(insp.field("email"), oldInfo.email()))
- .withWebsite(getString(insp.field("website"), oldInfo.website()))
- .withInvoiceEmail(getString(insp.field("invoiceEmail"), oldInfo.invoiceEmail()))
- .withContactName(getString(insp.field("contactName"), oldInfo.contactName()))
- .withContactEmail(getString(insp.field("contactEmail"), oldInfo.contactEmail()))
+ .withEmail(getString(insp.field("email"), oldInfo.email()))
+ .withWebsite(getString(insp.field("website"), oldInfo.website()))
+ .withContact(mergedContact)
.withAddress(updateTenantInfoAddress(insp.field("address"), oldInfo.address()))
- .withBillingContact(updateTenantInfoBillingContact(insp.field("billingContact"), oldInfo.billingContact()));
+ .withBilling(updateTenantInfoBillingContact(insp.field("billingContact"), oldInfo.billingContact()));
// Assert that we have a valid tenant info
- if (mergedInfo.contactName().isBlank()) {
+ if (mergedInfo.contact().name().isBlank()) {
throw new IllegalArgumentException("'contactName' cannot be empty");
}
- if (mergedInfo.contactEmail().isBlank()) {
+ if (mergedInfo.contact().email().isBlank()) {
throw new IllegalArgumentException("'contactEmail' cannot be empty");
}
- if (! mergedInfo.contactEmail().contains("@")) {
+ if (! mergedInfo.contact().email().contains("@")) {
// email address validation is notoriously hard - we should probably just try to send a
// verification email to this address. checking for @ is a simple best-effort.
throw new IllegalArgumentException("'contactEmail' needs to be an email address");
@@ -589,20 +592,20 @@ public class ApplicationApiHandler extends AuditLoggingRequestHandler {
return new MessageResponse("Tenant info updated");
}
- private TenantInfoAddress updateTenantInfoAddress(Inspector insp, TenantInfoAddress oldAddress) {
+ private TenantAddress updateTenantInfoAddress(Inspector insp, TenantAddress oldAddress) {
if (!insp.valid()) return oldAddress;
- TenantInfoAddress address = TenantInfoAddress.EMPTY
+ TenantAddress address = TenantAddress.empty()
.withCountry(getString(insp.field("country"), oldAddress.country()))
- .withStateRegionProvince(getString(insp.field("stateRegionProvince"), oldAddress.stateRegionProvince()))
+ .withRegion(getString(insp.field("stateRegionProvince"), oldAddress.region()))
.withCity(getString(insp.field("city"), oldAddress.city()))
- .withPostalCodeOrZip(getString(insp.field("postalCodeOrZip"), oldAddress.postalCodeOrZip()))
- .withAddressLines(getString(insp.field("addressLines"), oldAddress.addressLines()));
+ .withCode(getString(insp.field("postalCodeOrZip"), oldAddress.code()))
+ .withAddress(getString(insp.field("addressLines"), oldAddress.address()));
- List<String> fields = List.of(address.addressLines(),
- address.postalCodeOrZip(),
+ List<String> fields = List.of(address.address(),
+ address.code(),
address.country(),
address.city(),
- address.stateRegionProvince());
+ address.region());
if (fields.stream().allMatch(String::isBlank) || fields.stream().noneMatch(String::isBlank))
return address;
@@ -610,7 +613,7 @@ public class ApplicationApiHandler extends AuditLoggingRequestHandler {
throw new IllegalArgumentException("All address fields must be set");
}
- private TenantInfoBillingContact updateTenantInfoBillingContact(Inspector insp, TenantInfoBillingContact oldContact) {
+ private TenantContact updateTenantInfoContact(Inspector insp, TenantContact oldContact) {
if (!insp.valid()) return oldContact;
String email = getString(insp.field("email"), oldContact.email());
@@ -621,10 +624,17 @@ public class ApplicationApiHandler extends AuditLoggingRequestHandler {
throw new IllegalArgumentException("'email' needs to be an email address");
}
- return TenantInfoBillingContact.EMPTY
+ return TenantContact.empty()
.withName(getString(insp.field("name"), oldContact.name()))
- .withEmail(email)
- .withPhone(getString(insp.field("phone"), oldContact.phone()))
+ .withEmail(getString(insp.field("email"), oldContact.email()))
+ .withPhone(getString(insp.field("phone"), oldContact.phone()));
+ }
+
+ private TenantInfoBillingContact updateTenantInfoBillingContact(Inspector insp, TenantInfoBillingContact oldContact) {
+ if (!insp.valid()) return oldContact;
+
+ return TenantInfoBillingContact.empty()
+ .withContact(updateTenantInfoContact(insp, oldContact.contact()))
.withAddress(updateTenantInfoAddress(insp.field("address"), oldContact.address()));
}
@@ -647,6 +657,7 @@ public class ApplicationApiHandler extends AuditLoggingRequestHandler {
.forEach(notification -> toSlime(notificationsArray.addObject(), notification, includeTenantFieldInResponse, excludeMessages));
return new SlimeJsonResponse(slime);
}
+
private static <T> boolean propertyEquals(HttpRequest request, String property, Function<String, T> mapper, Optional<T> value) {
return Optional.ofNullable(request.getProperty(property))
.map(propertyValue -> value.isPresent() && mapper.apply(propertyValue).equals(value.get()))
@@ -1851,8 +1862,7 @@ public class ApplicationApiHandler extends AuditLoggingRequestHandler {
User user = getAttribute(request, User.ATTRIBUTE_NAME, User.class);
TenantInfo info = controller.tenants().require(tenant, CloudTenant.class)
.info()
- .withContactName(user.name())
- .withContactEmail(user.email());
+ .withContact(TenantContact.from(user.name(), user.email()));
// Store changes
controller.tenants().lockOrThrow(tenant, LockedTenant.Cloud.class, lockedTenant -> {
lockedTenant = lockedTenant.withInfo(info);
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 0b986667911..898ef957f32 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
@@ -16,8 +16,9 @@ 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.LastLoginInfo;
+import com.yahoo.vespa.hosted.controller.tenant.TenantAddress;
+import com.yahoo.vespa.hosted.controller.tenant.TenantContact;
import com.yahoo.vespa.hosted.controller.tenant.TenantInfo;
-import com.yahoo.vespa.hosted.controller.tenant.TenantInfoAddress;
import com.yahoo.vespa.hosted.controller.tenant.TenantInfoBillingContact;
import org.junit.Test;
@@ -97,7 +98,7 @@ public class TenantSerializerTest {
Optional.of(new SimplePrincipal("foobar-user")),
ImmutableBiMap.of(publicKey, new SimplePrincipal("joe"),
otherPublicKey, new SimplePrincipal("jane")),
- TenantInfo.EMPTY,
+ TenantInfo.empty(),
List.of(),
Optional.empty()
);
@@ -116,7 +117,7 @@ public class TenantSerializerTest {
Optional.of(new SimplePrincipal("foobar-user")),
ImmutableBiMap.of(publicKey, new SimplePrincipal("joe"),
otherPublicKey, new SimplePrincipal("jane")),
- TenantInfo.EMPTY.withName("Ofni Tnanet"),
+ TenantInfo.empty().withName("Ofni Tnanet"),
List.of(
new TenantSecretStore("ss1", "123", "role1"),
new TenantSecretStore("ss2", "124", "role2")
@@ -131,39 +132,35 @@ public class TenantSerializerTest {
@Test
public void cloud_tenant_with_tenant_info_partial() {
- TenantInfo partialInfo = TenantInfo.EMPTY
- .withAddress(TenantInfoAddress.EMPTY.withCity("Hønefoss"));
+ TenantInfo partialInfo = TenantInfo.empty()
+ .withAddress(TenantAddress.empty().withCity("Hønefoss"));
Slime slime = new Slime();
Cursor parentObject = slime.setObject();
serializer.toSlime(partialInfo, parentObject);
- assertEquals("{\"info\":{\"name\":\"\",\"email\":\"\",\"website\":\"\",\"invoiceEmail\":\"\",\"contactName\":\"\",\"contactEmail\":\"\",\"address\":{\"addressLines\":\"\",\"postalCodeOrZip\":\"\",\"city\":\"Hønefoss\",\"stateRegionProvince\":\"\",\"country\":\"\"}}}", slime.toString());
+ assertEquals("{\"info\":{\"name\":\"\",\"email\":\"\",\"website\":\"\",\"contactName\":\"\",\"contactEmail\":\"\",\"address\":{\"addressLines\":\"\",\"postalCodeOrZip\":\"\",\"city\":\"Hønefoss\",\"stateRegionProvince\":\"\",\"country\":\"\"}}}", slime.toString());
}
@Test
public void cloud_tenant_with_tenant_info_full() {
- TenantInfo fullInfo = TenantInfo.EMPTY
+ TenantInfo fullInfo = TenantInfo.empty()
.withName("My Company")
.withEmail("email@mycomp.any")
.withWebsite("http://mycomp.any")
- .withContactEmail("ceo@mycomp.any")
- .withContactName("My Name")
- .withInvoiceEmail("invoice@mycomp.any")
- .withAddress(TenantInfoAddress.EMPTY
+ .withContact(TenantContact.from("My Name", "ceo@mycomp.any"))
+ .withAddress(TenantAddress.empty()
.withCity("Hønefoss")
- .withAddressLines("Riperbakken 2")
+ .withAddress("Riperbakken 2")
.withCountry("Norway")
- .withPostalCodeOrZip("3510")
- .withStateRegionProvince("Viken"))
- .withBillingContact(TenantInfoBillingContact.EMPTY
- .withEmail("thomas@sodor.com")
- .withName("Thomas The Tank Engine")
- .withPhone("NA")
- .withAddress(TenantInfoAddress.EMPTY
+ .withCode("3510")
+ .withRegion("Viken"))
+ .withBilling(TenantInfoBillingContact.empty()
+ .withContact(TenantContact.from("Thomas The Tank Engine", "thomas@sodor.com", "NA"))
+ .withAddress(TenantAddress.empty()
.withCity("Suddery")
.withCountry("Sodor")
- .withAddressLines("Central Station")
- .withStateRegionProvince("Irish Sea")));
+ .withAddress("Central Station")
+ .withRegion("Irish Sea")));
Slime slime = new Slime();
Cursor parentCursor = slime.setObject();
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 fa1483fd90f..3c693bf4991 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
@@ -97,11 +97,11 @@ public class ApplicationApiCloudTest extends ControllerContainerCloudTest {
tester.assertResponse(postPartial, "{\"message\":\"Tenant info updated\"}", 200);
// Read back the updated info
- tester.assertResponse(infoRequest, "{\"name\":\"\",\"email\":\"\",\"website\":\"\",\"invoiceEmail\":\"\",\"contactName\":\"newName\",\"contactEmail\":\"foo@example.com\",\"billingContact\":{\"name\":\"billingName\",\"email\":\"\",\"phone\":\"\"}}", 200);
+ tester.assertResponse(infoRequest, "{\"name\":\"\",\"email\":\"\",\"website\":\"\",\"contactName\":\"newName\",\"contactEmail\":\"foo@example.com\",\"billingContact\":{\"name\":\"billingName\",\"email\":\"\",\"phone\":\"\"}}", 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 fullInfo = "{\"name\":\"name\",\"email\":\"foo@example\",\"website\":\"https://yahoo.com\",\"invoiceEmail\":\"invoiceEmail\",\"contactName\":\"contactName\",\"contactEmail\":\"contact@example.com\",\"address\":" + fullAddress + ",\"billingContact\":" + fullBillingContact + "}";
+ String fullInfo = "{\"name\":\"name\",\"email\":\"foo@example\",\"website\":\"https://yahoo.com\",\"contactName\":\"contactName\",\"contactEmail\":\"contact@example.com\",\"address\":" + fullAddress + ",\"billingContact\":" + fullBillingContact + "}";
// Now set all fields
var postFull =
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/filter/SignatureFilterTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/filter/SignatureFilterTest.java
index 7f588367819..15c7dbf73ab 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/filter/SignatureFilterTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/filter/SignatureFilterTest.java
@@ -74,7 +74,7 @@ public class SignatureFilterTest {
LastLoginInfo.EMPTY,
Optional.empty(),
ImmutableBiMap.of(),
- TenantInfo.EMPTY,
+ TenantInfo.empty(),
List.of(),
Optional.empty()));
tester.curator().writeApplication(new Application(appId, tester.clock().instant()));
@@ -120,7 +120,7 @@ public class SignatureFilterTest {
LastLoginInfo.EMPTY,
Optional.empty(),
ImmutableBiMap.of(publicKey, () -> "user"),
- TenantInfo.EMPTY,
+ TenantInfo.empty(),
List.of(),
Optional.empty()));
verifySecurityContext(requestOf(signer.signed(request.copy(), Method.POST, () -> new ByteArrayInputStream(hiBytes)), hiBytes),
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 942b5c1db45..938037d74df 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
@@ -2,7 +2,6 @@
"name": "",
"email": "",
"website":"",
- "invoiceEmail":"",
"contactName": "administrator",
"contactEmail": "administrator@tenant"
} \ No newline at end of file