From c27ef4408ed8fdc752943b5c7d2e802d2e05cf38 Mon Sep 17 00:00:00 2001 From: Elena Parovyshnaia Date: Sat, 17 Apr 2021 13:55:05 +0300 Subject: [PATCH 1/2] Bug 572833 protect the product with common-use license Protect personal license issuing with `.full` feature Signed-off-by: eparovyshnaya --- .../licenses/core/IssuePersonalLicense.java | 3 + .../issue/ClosedValidityPeriodReduction.java | 51 ++++++++++++++ .../PersonalLicenseIssuingProtection.java | 70 +++++++++++++++++++ .../licenses/core/issue/Reduction.java | 19 +++++ 4 files changed, 143 insertions(+) create mode 100644 bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/issue/ClosedValidityPeriodReduction.java create mode 100644 bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/issue/PersonalLicenseIssuingProtection.java create mode 100644 bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/issue/Reduction.java diff --git a/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/IssuePersonalLicense.java b/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/IssuePersonalLicense.java index 2deee9334..4e4aa5ac1 100644 --- a/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/IssuePersonalLicense.java +++ b/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/IssuePersonalLicense.java @@ -35,6 +35,7 @@ import org.eclipse.passage.loc.internal.api.OperatorProductService; import org.eclipse.passage.loc.internal.licenses.LicenseRegistry; import org.eclipse.passage.loc.internal.licenses.core.i18n.LicensesCoreMessages; +import org.eclipse.passage.loc.internal.licenses.core.issue.PersonalLicenseIssuingProtection; import org.eclipse.passage.loc.internal.licenses.trouble.code.LicenseIssuingFailed; import org.eclipse.passage.loc.internal.licenses.trouble.code.LicenseValidationFailed; import org.eclipse.passage.loc.internal.products.ProductRegistry; @@ -70,6 +71,7 @@ ServiceInvocationResult issue(Supplier template) { } LicensedProduct product = new BaseLicensedProduct(license.getProductIdentifier(), license.getProductVersion()); Path path = new UserHomeProductResidence(product).get(); + Path decrypted; try { decrypted = new PersistedDecoded(path, license)// @@ -97,6 +99,7 @@ private LicensePack adjsut(LicensePack license) { license.setIdentifier(UUID.randomUUID().toString()); license.setIssueDate(issueDate); new AssignGrantIdentifiers().accept(license); + new PersonalLicenseIssuingProtection().accept(license); return license; } diff --git a/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/issue/ClosedValidityPeriodReduction.java b/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/issue/ClosedValidityPeriodReduction.java new file mode 100644 index 000000000..05d0e57f4 --- /dev/null +++ b/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/issue/ClosedValidityPeriodReduction.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2021 ArSysOp + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0/. + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * ArSysOp - initial API and implementation + *******************************************************************************/ +package org.eclipse.passage.loc.internal.licenses.core.issue; + +import java.time.ZonedDateTime; +import java.time.temporal.ChronoUnit; +import java.util.Optional; +import java.util.function.BiConsumer; +import java.util.function.Function; + +import org.eclipse.passage.lic.internal.api.conditions.ValidityPeriodClosed; +import org.eclipse.passage.lic.internal.base.conditions.BaseValidityPeriodClosed; + +final class ClosedValidityPeriodReduction implements Reduction { + + private final Function> get; + private final BiConsumer set; + private final int length = 1; + + ClosedValidityPeriodReduction(Function> get, BiConsumer set) { + this.get = get; + this.set = set; + } + + @Override + public void accept(L license) { + Optional valid = get.apply(license); + if (!valid.isPresent()) { + return; + } + ZonedDateTime allowed = allowed(valid.get().from()); + if (allowed.isBefore(valid.get().to())) { + set.accept(license, new BaseValidityPeriodClosed(valid.get().from(), allowed)); + } + } + + private ZonedDateTime allowed(ZonedDateTime from) { + return from.plus(length, ChronoUnit.MONTHS); + } + +} diff --git a/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/issue/PersonalLicenseIssuingProtection.java b/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/issue/PersonalLicenseIssuingProtection.java new file mode 100644 index 000000000..d3efe4d5b --- /dev/null +++ b/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/issue/PersonalLicenseIssuingProtection.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (c) 2021 ArSysOp + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0/. + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * ArSysOp - initial API and implementation + *******************************************************************************/ +package org.eclipse.passage.loc.internal.licenses.core.issue; + +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Optional; +import java.util.function.Consumer; + +import org.eclipse.passage.lic.internal.api.conditions.ValidityPeriodClosed; +import org.eclipse.passage.lic.internal.base.conditions.BaseValidityPeriodClosed; +import org.eclipse.passage.lic.internal.equinox.EquinoxPassage; +import org.eclipse.passage.lic.licenses.model.api.LicenseGrant; +import org.eclipse.passage.lic.licenses.model.api.LicensePack; + +@SuppressWarnings("restriction") +public final class PersonalLicenseIssuingProtection implements Consumer { + + private final String feature = "org.eclipse.passage.loc.operator.issue.personal.full"; //$NON-NLS-1$ + private final List> reductions; + + public PersonalLicenseIssuingProtection() { + this.reductions = Arrays.asList(// + new ClosedValidityPeriodReduction(this::validGet, this::validSet)// + ); + } + + @Override + public void accept(LicensePack license) { + if (new EquinoxPassage().canUse(feature)) { + return; + } + diminish(license); + } + + private void diminish(LicensePack license) { + license.getLicenseGrants().forEach(this::diminishGrant); + } + + private void diminishGrant(LicenseGrant grant) { + reductions.forEach(r -> r.accept(grant)); + } + + private Optional validGet(LicenseGrant grant) { + return Optional.of(new BaseValidityPeriodClosed(date(grant.getValidFrom()), date(grant.getValidUntil()))); + } + + private void validSet(LicenseGrant grant, ValidityPeriodClosed period) { + grant.setValidFrom(Date.from(period.from().toInstant())); + grant.setValidUntil(Date.from(period.to().toInstant())); + } + + private ZonedDateTime date(Date date) { + return ZonedDateTime.from(date.toInstant().atZone(ZoneId.systemDefault())); + } + +} diff --git a/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/issue/Reduction.java b/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/issue/Reduction.java new file mode 100644 index 000000000..69452746f --- /dev/null +++ b/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/issue/Reduction.java @@ -0,0 +1,19 @@ +/******************************************************************************* + * Copyright (c) 2021 ArSysOp + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0/. + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * ArSysOp - initial API and implementation + *******************************************************************************/ +package org.eclipse.passage.loc.internal.licenses.core.issue; + +import java.util.function.Consumer; + +interface Reduction extends Consumer { + +} From 3cdb5072ba7b59dd98e48dde48972a0970d19a80 Mon Sep 17 00:00:00 2001 From: Elena Parovyshnaia Date: Sat, 17 Apr 2021 14:55:35 +0300 Subject: [PATCH 2/2] Bug 572833 protect the product with common-use license Protect floating license issuing with `.full` feature Signed-off-by: eparovyshnaya --- .../licenses/core/IssueFloatingLicense.java | 19 ++- .../issue/FeatureGrantCapacityReduction.java | 27 ++++ .../FloatingLicenseIssuingProtection.java | 116 ++++++++++++++++++ .../core/issue/UserGrantsAmountReduction.java | 34 +++++ 4 files changed, 194 insertions(+), 2 deletions(-) create mode 100644 bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/issue/FeatureGrantCapacityReduction.java create mode 100644 bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/issue/FloatingLicenseIssuingProtection.java create mode 100644 bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/issue/UserGrantsAmountReduction.java diff --git a/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/IssueFloatingLicense.java b/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/IssueFloatingLicense.java index 39a1a3d43..f172266a5 100644 --- a/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/IssueFloatingLicense.java +++ b/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/IssueFloatingLicense.java @@ -21,6 +21,7 @@ import java.util.List; import java.util.Optional; import java.util.function.BinaryOperator; +import java.util.stream.Collectors; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.util.EcoreUtil; @@ -39,10 +40,12 @@ import org.eclipse.passage.lic.licenses.model.api.FloatingLicensePack; import org.eclipse.passage.lic.licenses.model.api.LicenseRequisites; import org.eclipse.passage.lic.licenses.model.api.ProductRef; +import org.eclipse.passage.lic.licenses.model.api.UserGrant; import org.eclipse.passage.loc.internal.api.IssuedFloatingLicense; import org.eclipse.passage.loc.internal.api.OperatorProductService; import org.eclipse.passage.loc.internal.licenses.LicenseRegistry; import org.eclipse.passage.loc.internal.licenses.core.i18n.LicensesCoreMessages; +import org.eclipse.passage.loc.internal.licenses.core.issue.FloatingLicenseIssuingProtection; import org.eclipse.passage.loc.internal.licenses.trouble.code.LicenseIssuingFailed; import org.eclipse.passage.loc.internal.licenses.trouble.code.LicenseValidationFailed; import org.eclipse.passage.loc.internal.products.ProductRegistry; @@ -62,13 +65,25 @@ final class IssueFloatingLicense { ServiceInvocationResult issue(FloatingLicensePack pack, Collection configs) { + FloatingLicensePack license = shielded(EcoreUtil.copy(pack), configs); try { - new UpdateLicensePlan(licenses).withFloating(EcoreUtil.copy(pack)); + new UpdateLicensePlan(licenses).withFloating(license); } catch (IOException e) { return new BaseServiceInvocationResult<>(new Trouble(new LicenseIssuingFailed(), LicensesCoreMessages.LicenseOperatorServiceImpl_error_io, e)); } - return persistLicenseFiles(EcoreUtil.copy(pack), configs); + return persistLicenseFiles(EcoreUtil.copy(license), configs); + } + + private FloatingLicensePack shielded(FloatingLicensePack pack, Collection configs) { + new FloatingLicenseIssuingProtection().accept(pack); + Collection users = pack.getUsers().stream()// + .map(UserGrant::getUser)// + .collect(Collectors.toSet()); + Collection redundant = configs.stream()// + .filter(c -> !users.contains(c.getUser())).collect(Collectors.toSet()); + configs.removeAll(redundant); + return pack; } private ServiceInvocationResult persistLicenseFiles(FloatingLicensePack pack, diff --git a/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/issue/FeatureGrantCapacityReduction.java b/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/issue/FeatureGrantCapacityReduction.java new file mode 100644 index 000000000..09524c70f --- /dev/null +++ b/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/issue/FeatureGrantCapacityReduction.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2021 ArSysOp + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0/. + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * ArSysOp - initial API and implementation + *******************************************************************************/ +package org.eclipse.passage.loc.internal.licenses.core.issue; + +import org.eclipse.passage.lic.licenses.model.api.FeatureGrant; + +@SuppressWarnings("restriction") +final class FeatureGrantCapacityReduction implements Reduction { + + private final int capacity = 3; + + @Override + public void accept(FeatureGrant grant) { + grant.setCapacity(Math.min(capacity, grant.getCapacity())); + } + +} diff --git a/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/issue/FloatingLicenseIssuingProtection.java b/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/issue/FloatingLicenseIssuingProtection.java new file mode 100644 index 000000000..492ddc474 --- /dev/null +++ b/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/issue/FloatingLicenseIssuingProtection.java @@ -0,0 +1,116 @@ +/******************************************************************************* + * Copyright (c) 2021 ArSysOp + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0/. + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * ArSysOp - initial API and implementation + *******************************************************************************/ +package org.eclipse.passage.loc.internal.licenses.core.issue; + +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Optional; +import java.util.function.Consumer; + +import org.eclipse.passage.lic.internal.base.conditions.BaseValidityPeriodClosed; +import org.eclipse.passage.lic.internal.equinox.EquinoxPassage; +import org.eclipse.passage.lic.licenses.model.api.FeatureGrant; +import org.eclipse.passage.lic.licenses.model.api.FloatingLicensePack; +import org.eclipse.passage.lic.licenses.model.api.ValidityPeriod; +import org.eclipse.passage.lic.licenses.model.api.ValidityPeriodClosed; +import org.eclipse.passage.lic.licenses.model.meta.LicensesFactory; + +@SuppressWarnings("restriction") +public final class FloatingLicenseIssuingProtection implements Consumer { + + private final String feature = "org.eclipse.passage.loc.operator.issue.floating.full"; //$NON-NLS-1$ + private final List> featureReductions; + private final List> licReductions; + + public FloatingLicenseIssuingProtection() { + this.featureReductions = Arrays.asList(// + new ClosedValidityPeriodReduction(this::validGet, this::validSet), // + new FeatureGrantCapacityReduction()// + ); + this.licReductions = Arrays.asList(// + new ClosedValidityPeriodReduction(this::validGet, this::validSet), // + new UserGrantsAmountReduction()// + ); + } + + @Override + public void accept(FloatingLicensePack license) { + if (new EquinoxPassage().canUse(feature)) { + return; + } + // TODO: log diminishing + diminish(license); + } + + private void diminish(FloatingLicensePack license) { + diminishFeatureGrants(license); + diminishLicense(license); + } + + private void diminishFeatureGrants(FloatingLicensePack license) { + license.getFeatures().forEach(this::diminishGrant); + } + + private void diminishLicense(FloatingLicensePack lic) { + licReductions.forEach(r -> r.accept(lic)); + } + + private void diminishGrant(FeatureGrant grant) { + featureReductions.forEach(r -> r.accept(grant)); + } + + private Optional validGet( + FloatingLicensePack lic) { + return validGet(lic.getLicense().getValid()); + } + + private Optional validGet( + FeatureGrant grant) { + return validGet(grant.getValid()); + } + + private Optional validGet( + ValidityPeriod period) { + if (!(period instanceof ValidityPeriodClosed)) { + return Optional.empty(); // nothing we can reduce for now + } + ValidityPeriodClosed closed = (ValidityPeriodClosed) period; + return Optional.of(new BaseValidityPeriodClosed(date(closed.getFrom()), date(closed.getUntil()))); + } + + private void validSet(FloatingLicensePack lic, + org.eclipse.passage.lic.internal.api.conditions.ValidityPeriodClosed period) { + lic.getLicense().setValid(convert(period)); + } + + private void validSet(FeatureGrant grant, + org.eclipse.passage.lic.internal.api.conditions.ValidityPeriodClosed period) { + grant.setValid(convert(period)); + } + + private ValidityPeriodClosed convert(org.eclipse.passage.lic.internal.api.conditions.ValidityPeriodClosed period) { + org.eclipse.passage.lic.licenses.model.api.ValidityPeriodClosed valid = LicensesFactory.eINSTANCE + .createValidityPeriodClosed(); + valid.setFrom(Date.from(period.from().toInstant())); + valid.setUntil(Date.from(period.to().toInstant())); + return valid; + } + + private ZonedDateTime date(Date date) { + return ZonedDateTime.from(date.toInstant().atZone(ZoneId.systemDefault())); + } + +} diff --git a/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/issue/UserGrantsAmountReduction.java b/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/issue/UserGrantsAmountReduction.java new file mode 100644 index 000000000..a160106ac --- /dev/null +++ b/bundles/org.eclipse.passage.loc.licenses.core/src/org/eclipse/passage/loc/internal/licenses/core/issue/UserGrantsAmountReduction.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2021 ArSysOp + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0/. + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * ArSysOp - initial API and implementation + *******************************************************************************/ +package org.eclipse.passage.loc.internal.licenses.core.issue; + +import org.eclipse.emf.common.util.EList; +import org.eclipse.passage.lic.licenses.model.api.FloatingLicensePack; +import org.eclipse.passage.lic.licenses.model.api.UserGrant; + +@SuppressWarnings("restriction") +final class UserGrantsAmountReduction implements Reduction { + + private final int amount = 1; + + @Override + public void accept(FloatingLicensePack license) { + EList users = license.getUsers(); + if (users.size() > amount) { + for (int i = users.size() - 1; i >= amount; i--) { + users.remove(i); + } + } + } + +}