From e9d92886a6ba80d6967f044bee78bcfbfe563fcd Mon Sep 17 00:00:00 2001 From: ac273043 Date: Tue, 15 Sep 2026 13:57:39 +0200 Subject: [PATCH 1/3] feat: new property to hash the passwords --- .../properties/PropertyPanelSection.java | 26 +++++++ .../display/builder/model/Messages.java | 2 + .../properties/CommonWidgetProperties.java | 16 ++++ .../properties/HashPasswordProperty.java | 73 +++++++++++++++++++ .../model/widgets/ActionButtonWidget.java | 17 ++++- .../model/widgets/BoolButtonWidget.java | 15 +++- .../builder/model/widgets/CheckBoxWidget.java | 11 +++ .../model/widgets/ChoiceButtonWidget.java | 16 +++- .../builder/model/widgets/ComboWidget.java | 10 +++ .../builder/model/widgets/RadioWidget.java | 10 +++ .../model/widgets/SlideButtonWidget.java | 19 +++-- .../display/builder/model/messages.properties | 2 + .../builder/model/messages_fr.properties | 2 + .../representation/javafx/PasswordDialog.java | 28 +++++-- 14 files changed, 228 insertions(+), 19 deletions(-) create mode 100644 app/display/model/src/main/java/org/csstudio/display/builder/model/properties/HashPasswordProperty.java diff --git a/app/display/editor/src/main/java/org/csstudio/display/builder/editor/properties/PropertyPanelSection.java b/app/display/editor/src/main/java/org/csstudio/display/builder/editor/properties/PropertyPanelSection.java index cd971b0583..0460cb3302 100644 --- a/app/display/editor/src/main/java/org/csstudio/display/builder/editor/properties/PropertyPanelSection.java +++ b/app/display/editor/src/main/java/org/csstudio/display/builder/editor/properties/PropertyPanelSection.java @@ -6,6 +6,7 @@ * http://www.eclipse.org/legal/epl-v10.html *******************************************************************************/ package org.csstudio.display.builder.editor.properties; +import org.csstudio.display.builder.model.properties.HashPasswordProperty; import javafx.event.ActionEvent; import javafx.event.EventHandler; @@ -545,6 +546,31 @@ public void bind() { field = points_field; } + else if (property instanceof HashPasswordProperty) { + final Button hashButton = new Button("Hash password"); + hashButton.setMnemonicParsing(false); + hashButton.setMaxWidth(Double.MAX_VALUE); + + hashButton.setOnAction(event -> { + final WidgetProperty passwordProperty = + (WidgetProperty) widget.getProperty("password"); + + if (passwordProperty == null) + return; + + final String password = passwordProperty.getValue(); + + if (password == null || password.isEmpty()) + return; + + undo.execute(new SetMacroizedWidgetPropertyAction( + (MacroizedWidgetProperty) passwordProperty, + HashPasswordProperty.crypt(password) + )); + }); + + field = hashButton; + } return field; } diff --git a/app/display/model/src/main/java/org/csstudio/display/builder/model/Messages.java b/app/display/model/src/main/java/org/csstudio/display/builder/model/Messages.java index ef89c2a3a6..ceddb44768 100644 --- a/app/display/model/src/main/java/org/csstudio/display/builder/model/Messages.java +++ b/app/display/model/src/main/java/org/csstudio/display/builder/model/Messages.java @@ -61,6 +61,7 @@ public class Messages GroupWidget_Description, GroupWidget_Name, HighlightActiveRegion, + InformativeTooltipHashPassword, InformativeTooltipActions, InformativeTooltipAlarmBorder, InformativeTooltipHeight, @@ -236,6 +237,7 @@ public class Messages WidgetProperties_GridStepX, WidgetProperties_GridStepY, WidgetProperties_GridVisible, + WidgetProperties_HashPassword, WidgetProperties_Height, WidgetProperties_HeightPVName, WidgetProperties_HighlightBar, diff --git a/app/display/model/src/main/java/org/csstudio/display/builder/model/properties/CommonWidgetProperties.java b/app/display/model/src/main/java/org/csstudio/display/builder/model/properties/CommonWidgetProperties.java index 236702a380..17b8f85825 100644 --- a/app/display/model/src/main/java/org/csstudio/display/builder/model/properties/CommonWidgetProperties.java +++ b/app/display/model/src/main/java/org/csstudio/display/builder/model/properties/CommonWidgetProperties.java @@ -771,6 +771,22 @@ public EnumWidgetProperty createProperty(final Widget widget, fin public static final WidgetPropertyDescriptor propPassword = newStringPropertyDescriptor(WidgetPropertyCategory.BEHAVIOR, "password", Messages.WidgetProperties_Password); + + public static final WidgetPropertyDescriptor propHashPassword = + new WidgetPropertyDescriptor<>(WidgetPropertyCategory.BEHAVIOR, "hash_password", Messages.WidgetProperties_HashPassword) + { + @Override + public WidgetProperty createProperty( + final Widget widget, + final String default_value) + { + return new HashPasswordProperty( + this, + widget, + default_value); + } + }; + /** * Runtime 'pv_value' property: Typically read from primary PV */ diff --git a/app/display/model/src/main/java/org/csstudio/display/builder/model/properties/HashPasswordProperty.java b/app/display/model/src/main/java/org/csstudio/display/builder/model/properties/HashPasswordProperty.java new file mode 100644 index 0000000000..c285434b2b --- /dev/null +++ b/app/display/model/src/main/java/org/csstudio/display/builder/model/properties/HashPasswordProperty.java @@ -0,0 +1,73 @@ +package org.csstudio.display.builder.model.properties; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; + +import org.csstudio.display.builder.model.Widget; +import org.csstudio.display.builder.model.WidgetProperty; +import org.csstudio.display.builder.model.WidgetPropertyDescriptor; +import org.csstudio.display.builder.model.persist.ModelReader; +import org.csstudio.display.builder.model.persist.ModelWriter; +import org.phoebus.framework.persistence.XMLUtil; +import org.w3c.dom.Element; + +import javax.xml.stream.XMLStreamWriter; + +@SuppressWarnings("nls") +public class HashPasswordProperty extends WidgetProperty +{ + public HashPasswordProperty( + final WidgetPropertyDescriptor descriptor, + final Widget widget, + final String default_value) + { + super(descriptor, widget, default_value); + } + + @Override + public void setValueFromObject(final Object value) + { + if (value == null) + setValue(""); + else + setValue(value.toString()); + } + + @Override + public void writeToXML(final ModelWriter model_writer, + final XMLStreamWriter writer) throws Exception + { + writer.writeCharacters(value); + } + + @Override + public void readFromXML(final ModelReader model_reader, + final Element property_xml) throws Exception + { + setValue(XMLUtil.getString(property_xml)); + } + + public static String crypt(final String password) + { + if (password == null || password.isEmpty()) + return password; + + try + { + final MessageDigest md = MessageDigest.getInstance("SHA-256"); + final byte[] hash = + md.digest(password.getBytes(StandardCharsets.UTF_8)); + + final StringBuilder hex = new StringBuilder(hash.length * 2); + + for (final byte b : hash) + hex.append(String.format("%02x", b)); + + return hex.toString(); + } + catch (Exception e) + { + throw new RuntimeException("Unable to hash password", e); + } + } +} diff --git a/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/ActionButtonWidget.java b/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/ActionButtonWidget.java index be5b2cad25..5553eda530 100644 --- a/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/ActionButtonWidget.java +++ b/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/ActionButtonWidget.java @@ -13,6 +13,7 @@ import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propEnabled; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propFont; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propForegroundColor; +import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propHashPassword; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propHorizontalAlignment; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propVerticalAlignment; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propPassword; @@ -25,6 +26,7 @@ import java.util.List; import org.csstudio.display.builder.model.MacroizedWidgetProperty; +import org.csstudio.display.builder.model.Messages; import org.csstudio.display.builder.model.Version; import org.csstudio.display.builder.model.Widget; import org.csstudio.display.builder.model.WidgetCategory; @@ -237,7 +239,7 @@ public WidgetConfigurator getConfigurator(final Version persisted_version) private volatile WidgetProperty confirm_dialog; private volatile WidgetProperty confirm_message; private volatile WidgetProperty password; - + private volatile WidgetProperty hash_password; /** Constructor */ public ActionButtonWidget() { @@ -271,6 +273,8 @@ protected void defineProperties(final List> properties) properties.add(confirm_dialog = propConfirmDialog.createProperty(this, false)); properties.add(confirm_message = propConfirmMessage.createProperty(this, "Are your sure you want to do this?")); properties.add(password = propPassword.createProperty(this, "")); + properties.add(hash_password = propHashPassword.createProperty(this, "")); + hash_password.setInformativeTooltip(Messages.InformativeTooltipHashPassword); } @Override @@ -310,13 +314,13 @@ public WidgetProperty propTransparent() { return transparent; } - + /** @return 'horizontal_alignment' property */ public WidgetProperty propHorizontalAlignment() { return horizontal_alignment; } - + /** @return 'vertical_alignment' property */ public WidgetProperty propVerticalAlignment() { @@ -353,9 +357,16 @@ public WidgetProperty propConfirmMessage() return confirm_message; } + /** @return 'hash_password' property */ + public WidgetProperty propHashPassword() + { + return hash_password; + } + /** @return 'password' property */ public WidgetProperty propPassword() { return password; } + } diff --git a/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/BoolButtonWidget.java b/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/BoolButtonWidget.java index 30b1b9222d..bf32f8bc48 100644 --- a/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/BoolButtonWidget.java +++ b/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/BoolButtonWidget.java @@ -16,6 +16,7 @@ import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propEnabled; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propFont; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propForegroundColor; +import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propHashPassword; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propHorizontalAlignment; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propVerticalAlignment; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propLabelsFromPV; @@ -182,6 +183,7 @@ public EnumWidgetProperty createProperty(final Widget widget, final Mode d private volatile WidgetProperty confirm_dialog; private volatile WidgetProperty confirm_message; private volatile WidgetProperty password; + private volatile WidgetProperty hash_password; /** Constructor */ public BoolButtonWidget() @@ -200,6 +202,7 @@ public WidgetConfigurator getConfigurator(Version persisted_version) protected void defineProperties(final List> properties) { super.defineProperties(properties); + properties.add(bit = propBit.createProperty(this, 0)); properties.add(off_label = propOffLabel.createProperty(this, "Off")); properties.add(off_color = propOffColor.createProperty(this, new WidgetColor(60, 100, 60))); @@ -219,6 +222,8 @@ protected void defineProperties(final List> properties) properties.add(confirm_dialog = propConfirmDialogOptions.createProperty(this, ConfirmDialog.NONE)); properties.add(confirm_message = propConfirmMessage.createProperty(this, "Are your sure you want to do this?")); properties.add(password = propPassword.createProperty(this, "")); + properties.add(hash_password = propHashPassword.createProperty(this, "")); + hash_password.setInformativeTooltip(Messages.InformativeTooltipHashPassword); } /** @return 'bit' property */ @@ -286,13 +291,13 @@ public WidgetProperty propForegroundColor() { return foreground; } - + /** @return 'horizontal_alignment' property */ public WidgetProperty propHorizontalAlignment() { return horizontal_alignment; } - + /** @return 'vertical_alignment' property */ public WidgetProperty propVerticalAlignment() { @@ -334,4 +339,10 @@ public WidgetProperty propPassword() { return password; } + + /** @return 'hash_password' property */ + public WidgetProperty propHashPassword() + { + return hash_password; + } } diff --git a/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/CheckBoxWidget.java b/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/CheckBoxWidget.java index 56a9635210..5cd780c821 100644 --- a/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/CheckBoxWidget.java +++ b/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/CheckBoxWidget.java @@ -15,6 +15,7 @@ import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propEnabled; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propFont; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propForegroundColor; +import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propHashPassword; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propPassword; import java.util.Arrays; @@ -73,6 +74,7 @@ public Widget createWidget() private volatile WidgetProperty confirm_dialog; private volatile WidgetProperty confirm_message; private volatile WidgetProperty password; + private volatile WidgetProperty hash_password; @Override protected void defineProperties(final List> properties) @@ -87,6 +89,8 @@ protected void defineProperties(final List> properties) properties.add(confirm_dialog = propConfirmDialogOptions.createProperty(this, ConfirmDialog.NONE)); properties.add(confirm_message = propConfirmMessage.createProperty(this, "Are your sure you want to do this?")); properties.add(password = propPassword.createProperty(this, "")); + properties.add(hash_password = propHashPassword.createProperty(this, "")); + hash_password.setInformativeTooltip(Messages.InformativeTooltipHashPassword); } /** Constructor */ @@ -148,4 +152,11 @@ public WidgetProperty propPassword() { return password; } + + /** @return 'hash_password' property */ + public WidgetProperty propHashPassword() + { + return hash_password; + } + } diff --git a/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/ChoiceButtonWidget.java b/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/ChoiceButtonWidget.java index 1ba8a08431..6be167bd3f 100644 --- a/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/ChoiceButtonWidget.java +++ b/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/ChoiceButtonWidget.java @@ -13,6 +13,7 @@ import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propEnabled; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propFont; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propForegroundColor; +import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propHashPassword; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propHorizontal; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propHorizontalAlignment; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propVerticalAlignment; @@ -77,7 +78,7 @@ public Widget createWidget() private volatile WidgetProperty confirm_dialog; private volatile WidgetProperty confirm_message; private volatile WidgetProperty password; - + private volatile WidgetProperty hash_password; /** Constructor */ public ChoiceButtonWidget() { @@ -110,6 +111,8 @@ protected void defineProperties(final List> properties) properties.add(confirm_dialog = propConfirmDialog.createProperty(this, false)); properties.add(confirm_message = propConfirmMessage.createProperty(this, "Are your sure you want to do this?")); properties.add(password = propPassword.createProperty(this, "")); + properties.add(hash_password = propHashPassword.createProperty(this, "")); + hash_password.setInformativeTooltip(Messages.InformativeTooltipHashPassword); } /** @return 'foreground_color' property */ @@ -147,13 +150,13 @@ public WidgetProperty< List> > propItems() { return items; } - + /** @return 'horizontal_alignment' property */ public WidgetProperty propHorizontalAlignment() { return horizontal_alignment; } - + /** @return 'vertical_alignment' property */ public WidgetProperty propVerticalAlignment() { @@ -189,4 +192,11 @@ public WidgetProperty propPassword() { return password; } + + /** @return 'hash_password' property */ + public WidgetProperty propHashPassword() + { + return hash_password; + } + } diff --git a/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/ComboWidget.java b/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/ComboWidget.java index e475602b42..6470d8ff49 100644 --- a/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/ComboWidget.java +++ b/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/ComboWidget.java @@ -14,6 +14,7 @@ import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propEnabled; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propFont; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propForegroundColor; +import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propHashPassword; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propItemsFromPV; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propPassword; @@ -132,6 +133,7 @@ public WidgetConfigurator getConfigurator(final Version persisted_version) private volatile WidgetProperty confirm_dialog; private volatile WidgetProperty confirm_message; private volatile WidgetProperty password; + private volatile WidgetProperty hash_password; /** Constructor */ public ComboWidget() @@ -153,6 +155,8 @@ protected void defineProperties(final List> properties) properties.add(confirm_dialog = propConfirmDialog.createProperty(this, false)); properties.add(confirm_message = propConfirmMessage.createProperty(this, "Are your sure you want to do this?")); properties.add(password = propPassword.createProperty(this, "")); + properties.add(hash_password = propHashPassword.createProperty(this, "")); + hash_password.setInformativeTooltip(Messages.InformativeTooltipHashPassword); } /** @return 'foreground_color' property */ @@ -234,4 +238,10 @@ public WidgetProperty propPassword() { return password; } + + /** @return 'hash_password' property */ + public WidgetProperty propHashPassword() + { + return hash_password; + } } diff --git a/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/RadioWidget.java b/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/RadioWidget.java index 13e2faaad3..69d8678d2e 100644 --- a/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/RadioWidget.java +++ b/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/RadioWidget.java @@ -12,6 +12,7 @@ import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propEnabled; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propFont; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propForegroundColor; +import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propHashPassword; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propHorizontal; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propItemsFromPV; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propPassword; @@ -65,6 +66,7 @@ public Widget createWidget() private volatile WidgetProperty confirm_dialog; private volatile WidgetProperty confirm_message; private volatile WidgetProperty password; + private volatile WidgetProperty hash_password; private static ArrayWidgetProperty.Descriptor> radioItemDescriptor = new ArrayWidgetProperty.Descriptor<>(WidgetPropertyCategory.BEHAVIOR, "items", "Items", @@ -95,6 +97,8 @@ protected void defineProperties(final List> properties) properties.add(confirm_dialog = propConfirmDialog.createProperty(this, false)); properties.add(confirm_message = propConfirmMessage.createProperty(this, "Are your sure you want to do this?")); properties.add(password = propPassword.createProperty(this, "")); + properties.add(hash_password = propHashPassword.createProperty(this, "")); + hash_password.setInformativeTooltip(Messages.InformativeTooltipHashPassword); } /** @return 'foreground_color' property */ @@ -151,6 +155,12 @@ public WidgetProperty propPassword() return password; } + /** @return 'hash_password' property */ + public WidgetProperty propHashPassword() + { + return hash_password; + } + // TODO: CR: Changing the name of a radio button item has no immediate effect, // only after a resize the name is changed. } diff --git a/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/SlideButtonWidget.java b/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/SlideButtonWidget.java index 95e5878fb0..2df62523e4 100644 --- a/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/SlideButtonWidget.java +++ b/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/SlideButtonWidget.java @@ -16,6 +16,7 @@ import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propEnabled; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propFont; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propForegroundColor; +import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propHashPassword; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propOffColor; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propOnColor; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propPassword; @@ -80,7 +81,7 @@ public Widget createWidget ( ) { private volatile WidgetProperty off_color; private volatile WidgetProperty on_color; private volatile WidgetProperty password; - + private volatile WidgetProperty hash_password; /** Constructor */ public SlideButtonWidget () { super(WIDGET_DESCRIPTOR.getType(), 100, 30); @@ -156,13 +157,18 @@ public WidgetProperty propOnColor ( ) { return on_color; } - /** - * @return 'password' property. - */ - public WidgetProperty propPassword ( ) { + /** @return 'password' property */ + public WidgetProperty propPassword() + { return password; } + /** @return 'hash_password' property */ + public WidgetProperty propHashPassword() + { + return hash_password; + } + @Override protected void defineProperties ( final List> properties ) { @@ -179,6 +185,7 @@ protected void defineProperties ( final List> properties ) { properties.add(confirm_dialog = propConfirmDialogOptions.createProperty(this, ConfirmDialog.NONE)); properties.add(confirm_message = propConfirmMessage.createProperty(this, "Are your sure you want to do this?")); properties.add(password = propPassword.createProperty(this, "")); - + properties.add(hash_password = propHashPassword.createProperty(this, "")); + hash_password.setInformativeTooltip(Messages.InformativeTooltipHashPassword); } } diff --git a/app/display/model/src/main/resources/org/csstudio/display/builder/model/messages.properties b/app/display/model/src/main/resources/org/csstudio/display/builder/model/messages.properties index 7955d4cd06..c2f634193a 100644 --- a/app/display/model/src/main/resources/org/csstudio/display/builder/model/messages.properties +++ b/app/display/model/src/main/resources/org/csstudio/display/builder/model/messages.properties @@ -43,6 +43,7 @@ FontStyle_UnderlineItalic=Underline & Italic GroupWidget_Description=Group of widgets GroupWidget_Name=Group HighlightActiveRegion=Highlight Active Region +InformativeTooltipHashPassword=Hash the provided password InformativeTooltipActions=Actions to execute when the widget is clicked on. InformativeTooltipAlarmBorder=Should an alarm border be shown around the widget when the displayed PV signals an alarm? InformativeTooltipHeight=The height of the widget in pixels. @@ -222,6 +223,7 @@ WidgetProperties_GridColor=Grid Color WidgetProperties_GridStepX=Horizontal Grid Step Size WidgetProperties_GridStepY=Vertical Grid Step Size WidgetProperties_GridVisible=Grid Visible +WidgetProperties_HashPassword=Hash Password WidgetProperties_Height=Height WidgetProperties_HeightPVName=Height PV WidgetProperties_HighlightBar=Highlight Bar diff --git a/app/display/model/src/main/resources/org/csstudio/display/builder/model/messages_fr.properties b/app/display/model/src/main/resources/org/csstudio/display/builder/model/messages_fr.properties index 63180b8aca..4777d2579f 100644 --- a/app/display/model/src/main/resources/org/csstudio/display/builder/model/messages_fr.properties +++ b/app/display/model/src/main/resources/org/csstudio/display/builder/model/messages_fr.properties @@ -45,6 +45,7 @@ GroupWidget_Name=Groupe HighlightActiveRegion=Mettre en surbrillance la r\u00E9gion active InformativeTooltipActions=Actions \u00E0 ex\u00E9cuter lors d\u2019un clic sur le widget. InformativeTooltipAlarmBorder=Faut-il afficher une bordure d\u2019alarme autour du widget lorsque la PV affich\u00E9e d\u00E9clenche une alarme ? +InformativeTooltipHashPassword=Hacher le mot de passe fourni InformativeTooltipHeight=Hauteur du widget en pixels. InformativeTooltipName=Nom du widget. InformativeTooltipPVName=Nom de la PV \u00E0 connecter et afficher dans le widget. @@ -222,6 +223,7 @@ WidgetProperties_GridColor=Couleur de la grille WidgetProperties_GridStepX=Pas de grille horizontal WidgetProperties_GridStepY=Pas de grille vertical WidgetProperties_GridVisible=Grille visible +WidgetProperties_HashPassword=Hacher le mot de passe WidgetProperties_Height=Hauteur WidgetProperties_HeightPVName=Hauteur PV WidgetProperties_HighlightBar=Mettre en surbrillance la barre diff --git a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/PasswordDialog.java b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/PasswordDialog.java index 7102d27ede..ed12b19131 100644 --- a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/PasswordDialog.java +++ b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/PasswordDialog.java @@ -19,6 +19,9 @@ import javafx.scene.layout.HBox; import javafx.scene.layout.Priority; +import java.security.MessageDigest; +import java.nio.charset.StandardCharsets; + /** Dialog that prompts for password * *

When a 'correct' password is provided, @@ -70,8 +73,12 @@ public PasswordDialog(final String title, final String correct_password) final Button okButton = (Button) pane.lookupButton(ButtonType.OK); okButton.addEventFilter(ActionEvent.ACTION, event -> { - if (! checkPassword()) - event.consume(); + try { + if (! checkPassword()) + event.consume(); + } catch (Exception e) { + throw new RuntimeException(e); + } }); } @@ -84,9 +91,20 @@ public PasswordDialog(final String title, final String correct_password) } private boolean checkPassword() - { + throws Exception { final String password = pass_entry.getText(); - if (correct_password.equals(password)) + boolean check; + boolean check_crypt; + MessageDigest md = MessageDigest.getInstance("SHA-256"); + byte[] hash = md.digest(password.getBytes(StandardCharsets.UTF_8)); + + StringBuilder hex = new StringBuilder(hash.length * 2); + for (byte b : hash) { + hex.append(String.format("%02x", b)); + } + check_crypt = correct_password.equals(hex.toString()); + check = correct_password.equals(password); + if (check || check_crypt) return true; setHeaderText(Messages.Password_Error); Platform.runLater(() -> @@ -96,4 +114,4 @@ private boolean checkPassword() }); return false; } -} \ No newline at end of file +} From 173948c762ed9d526004c48d77620552be8c01da Mon Sep 17 00:00:00 2001 From: ac273043 Date: Fri, 30 Oct 2026 10:41:25 +0100 Subject: [PATCH 2/3] make hashPasswordProperty unavailable from rules & script --- .../org/csstudio/display/builder/model/rules/RuleInfo.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/display/model/src/main/java/org/csstudio/display/builder/model/rules/RuleInfo.java b/app/display/model/src/main/java/org/csstudio/display/builder/model/rules/RuleInfo.java index a1a3658564..c567475dd5 100644 --- a/app/display/model/src/main/java/org/csstudio/display/builder/model/rules/RuleInfo.java +++ b/app/display/model/src/main/java/org/csstudio/display/builder/model/rules/RuleInfo.java @@ -13,6 +13,7 @@ import org.csstudio.display.builder.model.properties.MacrosWidgetProperty; import org.csstudio.display.builder.model.properties.ActionsWidgetProperty; import org.csstudio.display.builder.model.properties.RulesWidgetProperty; +import org.csstudio.display.builder.model.properties.HashPasswordProperty; import org.csstudio.display.builder.model.properties.ScriptPV; import org.csstudio.display.builder.model.properties.ScriptsWidgetProperty; @@ -213,7 +214,8 @@ static public List getTargettableProperties(final Widget attached_widg if ((prop instanceof MacrosWidgetProperty) || (prop instanceof ActionsWidgetProperty) || (prop instanceof ScriptsWidgetProperty) || - (prop instanceof RulesWidgetProperty)) + (prop instanceof RulesWidgetProperty) || + (prop instanceof HashPasswordProperty)) continue; for (String name : Widget.expandPropertyNames(prop)) From 11399e169100ddf1d637d8d6ff4a437cd06e2724 Mon Sep 17 00:00:00 2001 From: ac273043 Date: Fri, 30 Oct 2026 11:38:16 +0100 Subject: [PATCH 3/3] update message on hash button: "Compute hash" --- .../main/java/org/csstudio/display/builder/editor/Messages.java | 1 + .../display/builder/editor/properties/PropertyPanelSection.java | 2 +- .../org/csstudio/display/builder/editor/messages.properties | 1 + .../org/csstudio/display/builder/editor/messages_fr.properties | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/display/editor/src/main/java/org/csstudio/display/builder/editor/Messages.java b/app/display/editor/src/main/java/org/csstudio/display/builder/editor/Messages.java index 6d50e93ee3..0deb45bf53 100644 --- a/app/display/editor/src/main/java/org/csstudio/display/builder/editor/Messages.java +++ b/app/display/editor/src/main/java/org/csstudio/display/builder/editor/Messages.java @@ -54,6 +54,7 @@ public class Messages FindWidget, Grid, InstallExampleDisplays, + HashPassword_button, LoadDisplay, LoadDisplay_TT, MacroEditButton, diff --git a/app/display/editor/src/main/java/org/csstudio/display/builder/editor/properties/PropertyPanelSection.java b/app/display/editor/src/main/java/org/csstudio/display/builder/editor/properties/PropertyPanelSection.java index 0460cb3302..46d407877f 100644 --- a/app/display/editor/src/main/java/org/csstudio/display/builder/editor/properties/PropertyPanelSection.java +++ b/app/display/editor/src/main/java/org/csstudio/display/builder/editor/properties/PropertyPanelSection.java @@ -547,7 +547,7 @@ public void bind() { field = points_field; } else if (property instanceof HashPasswordProperty) { - final Button hashButton = new Button("Hash password"); + final Button hashButton = new Button(Messages.HashPassword_button); hashButton.setMnemonicParsing(false); hashButton.setMaxWidth(Double.MAX_VALUE); diff --git a/app/display/editor/src/main/resources/org/csstudio/display/builder/editor/messages.properties b/app/display/editor/src/main/resources/org/csstudio/display/builder/editor/messages.properties index 67340ad904..057a1ded49 100644 --- a/app/display/editor/src/main/resources/org/csstudio/display/builder/editor/messages.properties +++ b/app/display/editor/src/main/resources/org/csstudio/display/builder/editor/messages.properties @@ -36,6 +36,7 @@ FilePath=File Path FindWidget=Find Widget... Grid=Align widgets to Grid InstallExampleDisplays=Install Example Displays +HashPassword_button=Compute hash LoadDisplay=Load display LoadDisplay_TT=Load display MacroEditButton=Edit Macros diff --git a/app/display/editor/src/main/resources/org/csstudio/display/builder/editor/messages_fr.properties b/app/display/editor/src/main/resources/org/csstudio/display/builder/editor/messages_fr.properties index b60feb9adc..0ea3cb1b16 100644 --- a/app/display/editor/src/main/resources/org/csstudio/display/builder/editor/messages_fr.properties +++ b/app/display/editor/src/main/resources/org/csstudio/display/builder/editor/messages_fr.properties @@ -36,6 +36,7 @@ FilePath=Chemin du fichier FindWidget=Trouver un widget... Grid=Aligner les widgets sur la grille InstallExampleDisplays=Installer exemples d'affichages +HashPassword_button=Calculer hash LoadDisplay=Charger l'affichage LoadDisplay_TT=Charger l'affichage MacroEditButton=Modifier les macros