diff options
author | Bjørn Christian Seime <bjorncs@vespa.ai> | 2023-11-02 14:56:16 +0100 |
---|---|---|
committer | Bjørn Christian Seime <bjorncs@vespa.ai> | 2023-11-02 14:56:16 +0100 |
commit | 0488bdf5c2b6712a08618c6a6e49d85997429c74 (patch) | |
tree | fec54ba58d3e61fae24e9c48fdbfa07e030b1e1a /controller-api/src/main | |
parent | e64583fa0b618da67189152c10310293221dd8bc (diff) |
Extend `/application/v4` with API for approving terms of service
Diffstat (limited to 'controller-api/src/main')
5 files changed, 63 insertions, 17 deletions
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/PathGroup.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/PathGroup.java index 54f53d64f76..9a3ea71660b 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/PathGroup.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/PathGroup.java @@ -253,7 +253,9 @@ enum PathGroup { emailVerification("/user/v1/email/verify"), /** Path used for dataplane token */ - dataplaneToken(Matcher.tenant,"/application/v4/tenant/{tenant}/token", "/application/v4/tenant/{tenant}/token/{ignored}"); + dataplaneToken(Matcher.tenant,"/application/v4/tenant/{tenant}/token", "/application/v4/tenant/{tenant}/token/{ignored}"), + + termsOfService(Matcher.tenant, "/application/v4/tenant/{tenant}/terms-of-service"); final List<String> pathSpecs; final List<Matcher> matchers; diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/Policy.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/Policy.java index d1a8b2ef0c3..44f6386e9bc 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/Policy.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/Policy.java @@ -191,6 +191,10 @@ enum Policy { dataplaneToken(Privilege.grant(Action.all()) .on(PathGroup.dataplaneToken) + .in(SystemName.PublicCd, SystemName.Public)), + + termsOfService(Privilege.grant(Action.create) + .on(PathGroup.termsOfService) .in(SystemName.PublicCd, SystemName.Public)); private final Set<Privilege> privileges; diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/RoleDefinition.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/RoleDefinition.java index 31c8560c908..0b5359ac826 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/RoleDefinition.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/RoleDefinition.java @@ -69,7 +69,8 @@ public enum RoleDefinition { Policy.applicationManager, Policy.keyRevokal, Policy.billingInformationRead, - Policy.accessRequests + Policy.accessRequests, + Policy.termsOfService ), /** Headless — the application specific role identified by deployment keys for production */ diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantBilling.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantBilling.java index 6e3b26661e5..1db84240fe2 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantBilling.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TenantBilling.java @@ -13,17 +13,21 @@ public class TenantBilling { private final TaxId taxId; private final PurchaseOrder purchaseOrder; private final Email invoiceEmail; + private final TermsOfServiceApproval tosApproval; - public TenantBilling(TenantContact contact, TenantAddress address, TaxId taxId, PurchaseOrder purchaseOrder, Email invoiceEmail) { + public TenantBilling(TenantContact contact, TenantAddress address, TaxId taxId, PurchaseOrder purchaseOrder, + Email invoiceEmail, TermsOfServiceApproval tosApproval) { this.contact = Objects.requireNonNull(contact); this.address = Objects.requireNonNull(address); this.taxId = Objects.requireNonNull(taxId); this.purchaseOrder = Objects.requireNonNull(purchaseOrder); this.invoiceEmail = Objects.requireNonNull(invoiceEmail); + this.tosApproval = Objects.requireNonNull(tosApproval); } public static TenantBilling empty() { - return new TenantBilling(TenantContact.empty(), TenantAddress.empty(), TaxId.empty(), PurchaseOrder.empty(), Email.empty()); + return new TenantBilling(TenantContact.empty(), TenantAddress.empty(), TaxId.empty(), PurchaseOrder.empty(), + Email.empty(), TermsOfServiceApproval.empty()); } public TenantContact contact() { @@ -46,24 +50,30 @@ public class TenantBilling { return invoiceEmail; } + public TermsOfServiceApproval getToSApproval() { return tosApproval; } + public TenantBilling withContact(TenantContact updatedContact) { - return new TenantBilling(updatedContact, this.address, this.taxId, this.purchaseOrder, this.invoiceEmail); + return new TenantBilling(updatedContact, this.address, this.taxId, this.purchaseOrder, this.invoiceEmail, tosApproval); } public TenantBilling withAddress(TenantAddress updatedAddress) { - return new TenantBilling(this.contact, updatedAddress, this.taxId, this.purchaseOrder, this.invoiceEmail); + return new TenantBilling(this.contact, updatedAddress, this.taxId, this.purchaseOrder, this.invoiceEmail, tosApproval); } public TenantBilling withTaxId(TaxId updatedTaxId) { - return new TenantBilling(this.contact, this.address, updatedTaxId, this.purchaseOrder, this.invoiceEmail); + return new TenantBilling(this.contact, this.address, updatedTaxId, this.purchaseOrder, this.invoiceEmail, tosApproval); } public TenantBilling withPurchaseOrder(PurchaseOrder updatedPurchaseOrder) { - return new TenantBilling(this.contact, this.address, this.taxId, updatedPurchaseOrder, this.invoiceEmail); + return new TenantBilling(this.contact, this.address, this.taxId, updatedPurchaseOrder, this.invoiceEmail, tosApproval); } public TenantBilling withInvoiceEmail(Email updatedInvoiceEmail) { - return new TenantBilling(this.contact, this.address, this.taxId, this.purchaseOrder, updatedInvoiceEmail); + return new TenantBilling(this.contact, this.address, this.taxId, this.purchaseOrder, updatedInvoiceEmail, tosApproval); + } + + public TenantBilling withToSApproval(TermsOfServiceApproval approval) { + return new TenantBilling(contact, address, taxId, purchaseOrder, invoiceEmail, approval); } public boolean isEmpty() { @@ -75,16 +85,14 @@ public class TenantBilling { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; TenantBilling that = (TenantBilling) o; - return Objects.equals(contact, that.contact) && - Objects.equals(address, that.address) && - Objects.equals(taxId, that.taxId) && - Objects.equals(purchaseOrder, that.purchaseOrder) && - Objects.equals(invoiceEmail, that.invoiceEmail); + return Objects.equals(contact, that.contact) && Objects.equals(address, that.address) + && Objects.equals(taxId, that.taxId) && Objects.equals(purchaseOrder, that.purchaseOrder) + && Objects.equals(invoiceEmail, that.invoiceEmail) && Objects.equals(tosApproval, that.tosApproval); } @Override public int hashCode() { - return Objects.hash(contact, address, taxId, purchaseOrder, invoiceEmail); + return Objects.hash(contact, address, taxId, purchaseOrder, invoiceEmail, tosApproval); } @Override @@ -92,9 +100,10 @@ public class TenantBilling { return "TenantBilling{" + "contact=" + contact + ", address=" + address + - ", taxId='" + taxId + '\'' + - ", purchaseOrder='" + purchaseOrder + '\'' + + ", taxId=" + taxId + + ", purchaseOrder=" + purchaseOrder + ", invoiceEmail=" + invoiceEmail + + ", tosApproval=" + tosApproval + '}'; } } diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TermsOfServiceApproval.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TermsOfServiceApproval.java new file mode 100644 index 00000000000..61fba17c473 --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/TermsOfServiceApproval.java @@ -0,0 +1,30 @@ +// 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 com.yahoo.vespa.hosted.controller.api.role.SimplePrincipal; + +import java.time.Instant; +import java.util.Optional; + +/** + * @author bjorncs + */ +public record TermsOfServiceApproval(Instant approvedAt, Optional<SimplePrincipal> approvedBy) { + + public TermsOfServiceApproval(Instant at, SimplePrincipal by) { this(at, Optional.of(by)); } + + public TermsOfServiceApproval(String at, String by) { + this(at.isBlank() ? Instant.EPOCH : Instant.parse(at), by.isBlank() ? Optional.empty() : Optional.of(new SimplePrincipal(by))); + } + + public TermsOfServiceApproval { + if (approvedBy.isEmpty() && !Instant.EPOCH.equals(approvedAt)) + throw new IllegalArgumentException("Missing approver"); + } + + public static TermsOfServiceApproval empty() { return new TermsOfServiceApproval(Instant.EPOCH, Optional.empty()); } + + public boolean hasApproved() { return approvedBy.isPresent(); } + public boolean isEmpty() { return approvedBy.isEmpty() && Instant.EPOCH.equals(approvedAt); } +} |