diff --git a/code/contacts/org.eclipse.scout.contacts.client/src/main/java/org/eclipse/scout/contacts/client/ConfigProperties.java b/code/contacts/org.eclipse.scout.contacts.client/src/main/java/org/eclipse/scout/contacts/client/ContactsClientConfigProperties.java similarity index 57% rename from code/contacts/org.eclipse.scout.contacts.client/src/main/java/org/eclipse/scout/contacts/client/ConfigProperties.java rename to code/contacts/org.eclipse.scout.contacts.client/src/main/java/org/eclipse/scout/contacts/client/ContactsClientConfigProperties.java index a5e4fa14881..37d9b6b426d 100644 --- a/code/contacts/org.eclipse.scout.contacts.client/src/main/java/org/eclipse/scout/contacts/client/ConfigProperties.java +++ b/code/contacts/org.eclipse.scout.contacts.client/src/main/java/org/eclipse/scout/contacts/client/ContactsClientConfigProperties.java @@ -9,12 +9,11 @@ */ package org.eclipse.scout.contacts.client; -import org.eclipse.scout.rt.platform.config.AbstractBooleanConfigProperty; import org.eclipse.scout.rt.platform.config.AbstractStringConfigProperty; -public final class ConfigProperties { +public final class ContactsClientConfigProperties { - private ConfigProperties() { + private ContactsClientConfigProperties() { } public static class UserDomainProperty extends AbstractStringConfigProperty { @@ -29,22 +28,4 @@ public String description() { return "If a domain is set, the user image is loaded from gravatar by using the following email: userId@userDomain (see UserForm.java)"; } } - - public static class ReadOnlyProperty extends AbstractBooleanConfigProperty { - - @Override - public String getKey() { - return "contacts.readOnly"; - } - - @Override - public String description() { - return "Global flag to activate a read-only mode when contacts application is deployed as public available demo application"; - } - - @Override - public Boolean getDefaultValue() { - return false; - } - } } diff --git a/code/contacts/org.eclipse.scout.contacts.client/src/main/java/org/eclipse/scout/contacts/client/UserForm.java b/code/contacts/org.eclipse.scout.contacts.client/src/main/java/org/eclipse/scout/contacts/client/UserForm.java index 6e7d25f2fb8..1d59dcda0a0 100644 --- a/code/contacts/org.eclipse.scout.contacts.client/src/main/java/org/eclipse/scout/contacts/client/UserForm.java +++ b/code/contacts/org.eclipse.scout.contacts.client/src/main/java/org/eclipse/scout/contacts/client/UserForm.java @@ -15,9 +15,9 @@ import java.security.NoSuchAlgorithmException; import java.util.List; -import org.eclipse.scout.contacts.client.ConfigProperties.ReadOnlyProperty; -import org.eclipse.scout.contacts.client.ConfigProperties.UserDomainProperty; +import org.eclipse.scout.contacts.client.ContactsClientConfigProperties.UserDomainProperty; import org.eclipse.scout.contacts.client.UserForm.MainBox.GroupBox.HtmlField; +import org.eclipse.scout.contacts.shared.ContactsSharedConfigProperties.ReadOnlyProperty; import org.eclipse.scout.contacts.shared.common.IResetDataStoreService; import org.eclipse.scout.rt.client.session.ClientSessionProvider; import org.eclipse.scout.rt.client.ui.form.AbstractForm; diff --git a/code/contacts/org.eclipse.scout.contacts.client/src/main/java/org/eclipse/scout/contacts/client/common/ContactsHelper.java b/code/contacts/org.eclipse.scout.contacts.client/src/main/java/org/eclipse/scout/contacts/client/common/ContactsHelper.java index 5c32b289976..c7261ab9955 100644 --- a/code/contacts/org.eclipse.scout.contacts.client/src/main/java/org/eclipse/scout/contacts/client/common/ContactsHelper.java +++ b/code/contacts/org.eclipse.scout.contacts.client/src/main/java/org/eclipse/scout/contacts/client/common/ContactsHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2023 BSI Business Systems Integration AG + * Copyright (c) 2010, 2026 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -9,11 +9,9 @@ */ package org.eclipse.scout.contacts.client.common; -import org.eclipse.scout.contacts.client.ConfigProperties.ReadOnlyProperty; +import org.eclipse.scout.contacts.shared.ContactsSharedConfigProperties.ReadOnlyProperty; import org.eclipse.scout.rt.client.ui.action.menu.AbstractMenu; import org.eclipse.scout.rt.client.ui.action.menu.IMenu; -import org.eclipse.scout.rt.client.ui.form.fields.button.AbstractOkButton; -import org.eclipse.scout.rt.client.ui.form.fields.button.IButton; import org.eclipse.scout.rt.platform.ApplicationScoped; import org.eclipse.scout.rt.platform.Order; import org.eclipse.scout.rt.platform.classid.ClassId; @@ -24,13 +22,6 @@ @ApplicationScoped public class ContactsHelper { - public void handleReadOnly(AbstractOkButton okButton) { - if (CONFIG.getPropertyValue(ReadOnlyProperty.class)) { - okButton.setLabel(TEXTS.get("CloseButton")); - okButton.setSystemType(IButton.SYSTEM_TYPE_CLOSE); - } - } - public void injectReadOnlyMenu(OrderedCollection menus) { if (CONFIG.getPropertyValue(ReadOnlyProperty.class)) { menus.addLast(new ReadOnlyMenu()); diff --git a/code/contacts/org.eclipse.scout.contacts.client/src/main/java/org/eclipse/scout/contacts/client/organization/OrganizationForm.java b/code/contacts/org.eclipse.scout.contacts.client/src/main/java/org/eclipse/scout/contacts/client/organization/OrganizationForm.java index a1a2cc7bffc..58675dd2c02 100644 --- a/code/contacts/org.eclipse.scout.contacts.client/src/main/java/org/eclipse/scout/contacts/client/organization/OrganizationForm.java +++ b/code/contacts/org.eclipse.scout.contacts.client/src/main/java/org/eclipse/scout/contacts/client/organization/OrganizationForm.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2023 BSI Business Systems Integration AG + * Copyright (c) 2010, 2026 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -32,7 +32,6 @@ import org.eclipse.scout.contacts.client.organization.OrganizationForm.MainBox.OkButton; import org.eclipse.scout.contacts.shared.organization.IOrganizationService; import org.eclipse.scout.contacts.shared.organization.OrganizationFormData; -import org.eclipse.scout.contacts.shared.organization.UpdateOrganizationPermission; import org.eclipse.scout.rt.client.dto.FormData; import org.eclipse.scout.rt.client.dto.FormData.SdkCommand; import org.eclipse.scout.rt.client.ui.action.menu.IMenu; @@ -154,11 +153,6 @@ public PhoneField getPhoneField() { return getFieldByClass(PhoneField.class); } - @Override - protected void execInitForm() { - BEANS.get(ContactsHelper.class).handleReadOnly(getOkButton()); - } - // tag::layout[] // tag::refactor[] @Order(10) @@ -341,7 +335,6 @@ protected void execLoad() { exportFormData(formData); formData = BEANS.get(IOrganizationService.class).load(formData); importFormData(formData); - setEnabledPermission(new UpdateOrganizationPermission()); getForm().setSubTitle(calculateSubTitle()); } diff --git a/code/contacts/org.eclipse.scout.contacts.client/src/main/java/org/eclipse/scout/contacts/client/person/PersonForm.java b/code/contacts/org.eclipse.scout.contacts.client/src/main/java/org/eclipse/scout/contacts/client/person/PersonForm.java index 9593771d0be..f5cc87547bd 100644 --- a/code/contacts/org.eclipse.scout.contacts.client/src/main/java/org/eclipse/scout/contacts/client/person/PersonForm.java +++ b/code/contacts/org.eclipse.scout.contacts.client/src/main/java/org/eclipse/scout/contacts/client/person/PersonForm.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2023 BSI Business Systems Integration AG + * Copyright (c) 2010, 2026 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -643,7 +643,7 @@ public class EmailField extends AbstractStringField { // http://www.mkyong.com/regular-expressions/how-to-validate-email-address-with-regular-expression/ // tag::email[] private static final String EMAIL_PATTERN = // <1> - "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@" + + "^[_A-Za-z0-9-+]+(\\.[_A-Za-z0-9-]+)*@" + "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$"; @Override @@ -816,7 +816,7 @@ protected void execStore() { } // end::handler[] - //This modify handler is used in the application: + //This modify-handler is used in the application: public class ModifyDirtyHandler extends AbstractDirtyFormHandler { @Override @@ -867,11 +867,6 @@ protected void execDirtyStatusChanged(boolean dirty) { } } - @Override - protected void execInitForm() { - BEANS.get(ContactsHelper.class).handleReadOnly(getOkButton()); - } - // tag::validate[] @Override // <1> diff --git a/code/contacts/org.eclipse.scout.contacts.events.client/src/main/java/org/eclipse/scout/contacts/events/client/event/EventForm.java b/code/contacts/org.eclipse.scout.contacts.events.client/src/main/java/org/eclipse/scout/contacts/events/client/event/EventForm.java index 57d7d541793..89c7759254e 100644 --- a/code/contacts/org.eclipse.scout.contacts.events.client/src/main/java/org/eclipse/scout/contacts/events/client/event/EventForm.java +++ b/code/contacts/org.eclipse.scout.contacts.events.client/src/main/java/org/eclipse/scout/contacts/events/client/event/EventForm.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2023 BSI Business Systems Integration AG + * Copyright (c) 2010, 2026 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -38,7 +38,6 @@ import org.eclipse.scout.contacts.events.client.person.PersonChooserForm; import org.eclipse.scout.contacts.events.shared.event.EventFormData; import org.eclipse.scout.contacts.events.shared.event.IEventService; -import org.eclipse.scout.contacts.events.shared.event.UpdateEventPermission; import org.eclipse.scout.contacts.shared.organization.OrganizationLookupCall; import org.eclipse.scout.contacts.shared.person.IPersonService; import org.eclipse.scout.contacts.shared.person.PersonFormData; @@ -182,11 +181,6 @@ public Object computeExclusiveKey() { return getEventId(); } - @Override - protected void execInitForm() { - BEANS.get(ContactsHelper.class).handleReadOnly(getOkButton()); - } - @Order(1) @ClassId("3d45e0e1-e128-4aad-9cef-6dbd78aaeb7d") public class MainBox extends AbstractGroupBox { @@ -333,11 +327,6 @@ protected String getConfiguredLabel() { @ClassId("627f6a0e-349f-4846-8449-1ec41156657d") public class ParticipantTableFieldField extends AbstractTableField { - @Override - protected int getConfiguredGridH() { - return 3; - } - @Override protected boolean getConfiguredLabelVisible() { return false; @@ -555,7 +544,6 @@ protected void execLoad() { exportFormData(formData); formData = BEANS.get(IEventService.class).load(formData); importFormData(formData); - setEnabledPermission(new UpdateEventPermission()); getForm().setSubTitle(getTitleField().getValue()); } diff --git a/code/contacts/org.eclipse.scout.contacts.events.shared/src/main/java/org/eclipse/scout/contacts/events/shared/event/EventFormData.java b/code/contacts/org.eclipse.scout.contacts.events.shared/src/main/java/org/eclipse/scout/contacts/events/shared/event/EventFormData.java index c3e96f7548a..d97e62b9462 100644 --- a/code/contacts/org.eclipse.scout.contacts.events.shared/src/main/java/org/eclipse/scout/contacts/events/shared/event/EventFormData.java +++ b/code/contacts/org.eclipse.scout.contacts.events.shared/src/main/java/org/eclipse/scout/contacts/events/shared/event/EventFormData.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2025 BSI Business Systems Integration AG + * Copyright (c) 2010, 2026 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 diff --git a/code/contacts/org.eclipse.scout.contacts.server.app.image/src/main/resources/config.properties b/code/contacts/org.eclipse.scout.contacts.server.app.image/src/main/resources/config.properties index 2506674856f..de34d3bc75e 100644 --- a/code/contacts/org.eclipse.scout.contacts.server.app.image/src/main/resources/config.properties +++ b/code/contacts/org.eclipse.scout.contacts.server.app.image/src/main/resources/config.properties @@ -17,3 +17,4 @@ scout.auth.publicKey=MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEi6zfTmwzAY7hiEoRyJgGdgz ### Application specific contacts.superuser=system +contacts.readOnly=true diff --git a/code/contacts/org.eclipse.scout.contacts.server/src/main/java/org/eclipse/scout/contacts/server/security/ContactsServerAccessControlService.java b/code/contacts/org.eclipse.scout.contacts.server/src/main/java/org/eclipse/scout/contacts/server/security/ContactsServerAccessControlService.java new file mode 100644 index 00000000000..0be5c55e03f --- /dev/null +++ b/code/contacts/org.eclipse.scout.contacts.server/src/main/java/org/eclipse/scout/contacts/server/security/ContactsServerAccessControlService.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2010, 2026 BSI Business Systems Integration AG + * + * 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 + */ +package org.eclipse.scout.contacts.server.security; + +import java.util.function.Supplier; +import java.util.stream.Stream; + +import org.eclipse.scout.contacts.shared.ContactsSharedConfigProperties.ReadOnlyProperty; +import org.eclipse.scout.rt.platform.BEANS; +import org.eclipse.scout.rt.platform.Replace; +import org.eclipse.scout.rt.platform.config.CONFIG; +import org.eclipse.scout.rt.platform.internal.BeanInstanceUtil; +import org.eclipse.scout.rt.platform.inventory.ClassInventory; +import org.eclipse.scout.rt.platform.inventory.IClassInfo; +import org.eclipse.scout.rt.security.DefaultPermissionCollection; +import org.eclipse.scout.rt.security.IPermission; +import org.eclipse.scout.rt.security.IPermissionCollection; +import org.eclipse.scout.rt.security.PermissionLevel; +import org.eclipse.scout.rt.shared.security.CopyToClipboardPermission; +import org.eclipse.scout.rt.shared.security.RemoteServiceAccessPermission; + +/** + * The Contacts application logic is extracted to this extra class to not pollute the super class used in the One-Day-Tutorial. + * The extra readOnly Contacts logic is implemented here, extending the default behavior of the super class. + */ +@Replace +public class ContactsServerAccessControlService extends ServerAccessControlService { + @Override + protected IPermissionCollection execLoadPermissions(String userId) { + if (CONFIG.getPropertyValue(ReadOnlyProperty.class)) { + DefaultPermissionCollection permissions = BEANS.get(DefaultPermissionCollection.class); + getReadPermissions().forEach(permissions::add); + permissions.add(new RemoteServiceAccessPermission("*.shared.*", "*"), PermissionLevel.ALL); + permissions.add(new CopyToClipboardPermission(), PermissionLevel.ALL); + return permissions; + } + return super.execLoadPermissions(userId); + } + + protected Stream getReadPermissions() { + return getReadPermissionClasses() + .map(BeanInstanceUtil::beanInstanceCreator) + .map(Supplier::get); + } + + @SuppressWarnings("unchecked") + protected Stream> getReadPermissionClasses() { + return ClassInventory.get().getAllKnownSubClasses(IPermission.class).stream() + .filter(IClassInfo::isInstanciable) + .filter(IClassInfo::hasNoArgsConstructor) + .filter(classInfo -> classInfo.name().contains("Read")) + .map(classInfo -> (Class) classInfo.resolveClass()); + } +} diff --git a/code/contacts/org.eclipse.scout.contacts.shared/src/generated/java/org/eclipse/scout/contacts/shared/organization/OrganizationFormData.java b/code/contacts/org.eclipse.scout.contacts.shared/src/generated/java/org/eclipse/scout/contacts/shared/organization/OrganizationFormData.java index aee82a87b27..2b071729efc 100644 --- a/code/contacts/org.eclipse.scout.contacts.shared/src/generated/java/org/eclipse/scout/contacts/shared/organization/OrganizationFormData.java +++ b/code/contacts/org.eclipse.scout.contacts.shared/src/generated/java/org/eclipse/scout/contacts/shared/organization/OrganizationFormData.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2025 BSI Business Systems Integration AG + * Copyright (c) 2010, 2026 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 diff --git a/code/contacts/org.eclipse.scout.contacts.shared/src/generated/java/org/eclipse/scout/contacts/shared/person/PersonFormData.java b/code/contacts/org.eclipse.scout.contacts.shared/src/generated/java/org/eclipse/scout/contacts/shared/person/PersonFormData.java index b1ee3c691e8..e13cfdb91b6 100644 --- a/code/contacts/org.eclipse.scout.contacts.shared/src/generated/java/org/eclipse/scout/contacts/shared/person/PersonFormData.java +++ b/code/contacts/org.eclipse.scout.contacts.shared/src/generated/java/org/eclipse/scout/contacts/shared/person/PersonFormData.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2025 BSI Business Systems Integration AG + * Copyright (c) 2010, 2026 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 diff --git a/code/contacts/org.eclipse.scout.contacts.shared/src/main/java/org/eclipse/scout/contacts/shared/ContactsSharedConfigProperties.java b/code/contacts/org.eclipse.scout.contacts.shared/src/main/java/org/eclipse/scout/contacts/shared/ContactsSharedConfigProperties.java new file mode 100644 index 00000000000..27301132aa8 --- /dev/null +++ b/code/contacts/org.eclipse.scout.contacts.shared/src/main/java/org/eclipse/scout/contacts/shared/ContactsSharedConfigProperties.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2010, 2026 BSI Business Systems Integration AG + * + * 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 + */ +package org.eclipse.scout.contacts.shared; + +import org.eclipse.scout.rt.platform.config.AbstractBooleanConfigProperty; + +public final class ContactsSharedConfigProperties { + + private ContactsSharedConfigProperties() { + } + + public static class ReadOnlyProperty extends AbstractBooleanConfigProperty { + + @Override + public String getKey() { + return "contacts.readOnly"; + } + + @Override + public String description() { + return "Flag to activate a read-only mode when contacts application is deployed as public available demo application"; + } + + @Override + public Boolean getDefaultValue() { + return false; + } + } +}