1919package org .phoebus .applications .credentialsmanagement ;
2020
2121import javafx .application .Platform ;
22+ import javafx .beans .binding .Bindings ;
2223import javafx .beans .property .SimpleBooleanProperty ;
24+ import javafx .beans .property .SimpleStringProperty ;
25+ import javafx .beans .property .StringProperty ;
2326import javafx .collections .FXCollections ;
2427import javafx .collections .ObservableList ;
2528import javafx .event .ActionEvent ;
@@ -62,7 +65,7 @@ public class CredentialsManagementController {
6265 private TableView <ServiceItem > tableView ;
6366 @ SuppressWarnings ("unused" )
6467 @ FXML
65- private TableColumn <ServiceItem , Void > actionButtonColumn ;
68+ private TableColumn <ServiceItem , ServiceItem > actionButtonColumn ;
6669 @ SuppressWarnings ("unused" )
6770 @ FXML
6871 private TableColumn <ServiceItem , String > usernameColumn ;
@@ -71,7 +74,16 @@ public class CredentialsManagementController {
7174 private TableColumn <ServiceItem , String > passwordColumn ;
7275 @ SuppressWarnings ("unused" )
7376 @ FXML
74- private Button clearAllCredentialsButton ;
77+ private Button loginToAllButton ;
78+ @ SuppressWarnings ("unused" )
79+ @ FXML
80+ private Button logoutFromAllButton ;
81+ @ SuppressWarnings ("unused" )
82+ @ FXML
83+ private TextField loginToAllUsernameTextField ;
84+ @ SuppressWarnings ("unused" )
85+ @ FXML
86+ private PasswordField loginToAllPasswordTextField ;
7587 @ SuppressWarnings ("unused" )
7688 @ FXML
7789 private TableColumn <ServiceItem , String > scopeColumn ;
@@ -82,6 +94,8 @@ public class CredentialsManagementController {
8294 private final SecureStore secureStore ;
8395 private static final Logger LOGGER = Logger .getLogger (CredentialsManagementController .class .getName ());
8496 private final List <ServiceAuthenticationProvider > authenticationProviders ;
97+ private final StringProperty loginToAllUsernameProperty = new SimpleStringProperty ();
98+ private final StringProperty loginToAllPasswordProperty = new SimpleStringProperty ();
8599
86100 private Stage stage ;
87101
@@ -95,33 +109,34 @@ public CredentialsManagementController(List<ServiceAuthenticationProvider> authe
95109 public void initialize () {
96110
97111 tableView .getStylesheets ().add (getClass ().getResource ("/css/credentials-management-style.css" ).toExternalForm ());
98- clearAllCredentialsButton .disableProperty ().bind (listEmpty );
99- Callback <TableColumn <ServiceItem , Void >, TableCell <ServiceItem , Void >> actionColumnCellFactory = new Callback <>() {
112+
113+ logoutFromAllButton .disableProperty ().bind (listEmpty );
114+ Callback <TableColumn <ServiceItem , ServiceItem >, TableCell <ServiceItem , ServiceItem >> actionColumnCellFactory = new Callback <>() {
100115 @ Override
101- public TableCell <ServiceItem , Void > call (final TableColumn <ServiceItem , Void > param ) {
102- final TableCell <ServiceItem , Void > cell = new TableCell <>() {
116+ public TableCell <ServiceItem , ServiceItem > call (final TableColumn <ServiceItem , ServiceItem > param ) {
117+ final TableCell <ServiceItem , ServiceItem > cell = new TableCell <>() {
103118
104119 private final Button btn = new Button (Messages .LogoutButtonText );
120+
105121 {
106122 btn .getStyleClass ().add ("button-style" );
107123 btn .setOnAction ((ActionEvent event ) -> {
108124 ServiceItem serviceItem = getTableView ().getItems ().get (getIndex ());
109- if (serviceItem .isLoginAction ()) {
125+ if (serviceItem .loginAction ) {
110126 login (serviceItem );
111- }
112- else {
127+ } else {
113128 logOut (serviceItem .getAuthenticationScope ());
114129 }
115130 });
116131 }
117132
118133 @ Override
119- public void updateItem (Void o , boolean empty ) {
134+ public void updateItem (ServiceItem o , boolean empty ) {
120135 super .updateItem (o , empty );
121136 if (empty ) {
122137 setGraphic (null );
123138 } else {
124- if (getTableRow () != null && getTableRow ().getItem () != null ){
139+ if (getTableRow () != null && getTableRow ().getItem () != null ) {
125140 btn .setText (getTableRow ().getItem ().loginAction ?
126141 Messages .LoginButtonText : Messages .LogoutButtonText );
127142 }
@@ -136,14 +151,37 @@ public void updateItem(Void o, boolean empty) {
136151 usernameColumn .setCellFactory (c -> new UsernameTableCell ());
137152 passwordColumn .setCellFactory (c -> new PasswordTableCell ());
138153
139- scopeColumn .setStyle ( "-fx-alignment: CENTER-LEFT;" );
154+ loginToAllUsernameTextField .textProperty ().bindBidirectional (loginToAllUsernameProperty );
155+ loginToAllPasswordTextField .textProperty ().bindBidirectional (loginToAllPasswordProperty );
156+
157+ loginToAllButton .disableProperty ().bind (Bindings .createBooleanBinding (() -> loginToAllUsernameProperty .get () == null ||
158+ loginToAllUsernameProperty .get ().isEmpty () ||
159+ loginToAllPasswordProperty .get () == null ||
160+ loginToAllPasswordProperty .get ().isEmpty (),
161+ loginToAllUsernameProperty , loginToAllPasswordProperty ));
140162
141163 updateTable ();
164+
165+ // Don't want focus on the username field for "login to all" as that obscures the prompt.
166+ // Let table request focus.
167+ Platform .runLater (() -> tableView .requestFocus ());
168+ }
169+
170+ @ SuppressWarnings ("unused" )
171+ @ FXML
172+ public void logoutFromAll () {
173+ try {
174+ secureStore .deleteAllScopedAuthenticationTokens ();
175+ updateTable ();
176+ } catch (Exception e ) {
177+ LOGGER .log (Level .WARNING , "Failed to delete all authentication tokens from key store" , e );
178+ ExceptionDetailsErrorDialog .openError (parent , Messages .ErrorDialogTitle , Messages .ErrorDialogBody , e );
179+ }
142180 }
143181
144182 @ SuppressWarnings ("unused" )
145183 @ FXML
146- public void logOutFromAll () {
184+ public void loginToAll () {
147185 try {
148186 secureStore .deleteAllScopedAuthenticationTokens ();
149187 updateTable ();
@@ -156,9 +194,10 @@ public void logOutFromAll() {
156194 /**
157195 * Attempts to sign in user based on provided credentials. If sign-in succeeds, this method will close the
158196 * associated UI.
197+ *
159198 * @param serviceItem The {@link ServiceItem} defining the scope, and implicitly the authentication service.
160199 */
161- private void login (ServiceItem serviceItem ){
200+ private void login (ServiceItem serviceItem ) {
162201 try {
163202 serviceItem .getServiceAuthenticationProvider ().authenticate (serviceItem .getUsername (), serviceItem .getPassword ());
164203 try {
@@ -191,19 +230,20 @@ private void updateTable() {
191230 // Match saved tokens with an authentication provider, where applicable
192231 List <ServiceItem > serviceItems = savedTokens .stream ().map (token -> {
193232 ServiceAuthenticationProvider provider =
194- authenticationProviders .stream ().filter (p -> p .getAuthenticationScope ().getScope ().equals (token .getAuthenticationScope ().getScope ())).findFirst ().orElse (null );
233+ authenticationProviders .stream ().filter (p -> p .getAuthenticationScope ().getScope ().equals (token .getAuthenticationScope ().getScope ())).findFirst ().orElse (null );
195234 return new ServiceItem (provider , token .getUsername (), token .getPassword ());
196235 }).collect (Collectors .toList ());
197236 // Also need to add ServiceItems for providers not matched with a saved token, i.e. for logged-out services
198237 authenticationProviders .forEach (p -> {
199238 Optional <ServiceItem > serviceItem =
200239 serviceItems .stream ().filter (si ->
201240 p .getAuthenticationScope ().getScope ().equals (si .getAuthenticationScope ().getScope ())).findFirst ();
202- if (serviceItem .isEmpty ()){
241+ if (serviceItem .isEmpty ()) {
203242 serviceItems .add (new ServiceItem (p ));
204243 }
205244 });
206245 serviceItems .sort (Comparator .comparing (i -> i .getAuthenticationScope ().getDisplayName ()));
246+
207247 Platform .runLater (() -> {
208248 this .serviceItems .setAll (serviceItems );
209249 listEmpty .set (savedTokens .isEmpty ());
@@ -219,7 +259,7 @@ public static class ServiceItem {
219259 private final ServiceAuthenticationProvider serviceAuthenticationProvider ;
220260 private String username ;
221261 private String password ;
222- private boolean loginAction = false ;
262+ private boolean loginAction ;
223263
224264 public ServiceItem (ServiceAuthenticationProvider serviceAuthenticationProvider , String username , String password ) {
225265 this .serviceAuthenticationProvider = serviceAuthenticationProvider ;
@@ -229,14 +269,14 @@ public ServiceItem(ServiceAuthenticationProvider serviceAuthenticationProvider,
229269
230270 public ServiceItem (ServiceAuthenticationProvider serviceAuthenticationProvider ) {
231271 this .serviceAuthenticationProvider = serviceAuthenticationProvider ;
232- loginAction = true ;
272+ this . loginAction = true ;
233273 }
234274
235275 public String getUsername () {
236276 return username ;
237277 }
238278
239- public void setUsername (String username ){
279+ public void setUsername (String username ) {
240280 this .username = username ;
241281 }
242282
@@ -249,53 +289,54 @@ public AuthenticationScope getAuthenticationScope() {
249289 * @return String representation of the authentication scope.
250290 */
251291 @ SuppressWarnings ("unused" )
252- public String getScope (){
292+ public String getScope () {
253293 return serviceAuthenticationProvider != null ?
254294 serviceAuthenticationProvider .getAuthenticationScope ().getScope () : "" ;
255295 }
256296
257297 @ SuppressWarnings ("unused" )
258- public String getDisplayName (){
298+ public String getDisplayName () {
259299 return serviceAuthenticationProvider != null ?
260300 serviceAuthenticationProvider .getAuthenticationScope ().getDisplayName () : "" ;
261301 }
262302
263- public String getPassword (){
303+ public String getPassword () {
264304 return password ;
265305 }
266306
267- public void setPassword (String password ){
307+ public void setPassword (String password ) {
268308 this .password = password ;
309+
269310 }
270311
271312 public ServiceAuthenticationProvider getServiceAuthenticationProvider () {
272313 return serviceAuthenticationProvider ;
273314 }
274315
275- public boolean isLoginAction () {
316+ public boolean getLoginAction () {
276317 return loginAction ;
277318 }
278319 }
279320
280- private static class UsernameTableCell extends TableCell <ServiceItem , String >{
321+ private static class UsernameTableCell extends TableCell <ServiceItem , String > {
281322 private final TextField textField = new TextField ();
282323
283- public UsernameTableCell (){
324+ public UsernameTableCell () {
284325 textField .getStyleClass ().add ("text-field-styling" );
285326 // Update model on key up
286- textField .setOnKeyReleased (ke -> getTableRow ().getItem ().setUsername (textField .getText ()));
327+ textField .setOnKeyReleased (ke -> {
328+ getTableRow ().getItem ().setUsername (textField .getText ());
329+ });
287330 }
288331
289332 @ Override
290- protected void updateItem (String item , final boolean empty )
291- {
333+ protected void updateItem (String item , final boolean empty ) {
292334 super .updateItem (item , empty );
293- if (empty ){
335+ if (empty ) {
294336 setGraphic (null );
295- }
296- else {
337+ } else {
297338 textField .setText (item );
298- if (getTableRow () != null && getTableRow ().getItem () != null ){
339+ if (getTableRow () != null && getTableRow ().getItem () != null ) {
299340 // Disable field if user is logged in.
300341 textField .disableProperty ().set (!getTableRow ().getItem ().loginAction );
301342 }
@@ -304,25 +345,24 @@ protected void updateItem(String item, final boolean empty)
304345 }
305346 }
306347
307- private class PasswordTableCell extends TableCell <ServiceItem , String >{
348+ private class PasswordTableCell extends TableCell <ServiceItem , String > {
308349 private final PasswordField passwordField = new PasswordField ();
309350
310- public PasswordTableCell (){
351+ public PasswordTableCell () {
311352 passwordField .getStyleClass ().add ("text-field-styling" );
312353 // Update model on key up
313354 passwordField .setOnKeyReleased (ke -> getTableRow ().getItem ().setPassword (passwordField .getText ()));
314355 }
315356
316357 @ Override
317- protected void updateItem (String item , final boolean empty )
318- {
358+ protected void updateItem (String item , final boolean empty ) {
319359 super .updateItem (item , empty );
320- if (empty ){
360+ if (empty ) {
321361 setGraphic (null );
322- }
323- else {
362+ } else {
324363 passwordField .setText (item == null ? item : "dummypass" ); // Hack to not reveal password length
325- if (getTableRow () != null && getTableRow ().getItem () != null ) {
364+
365+ if (getTableRow () != null && getTableRow ().getItem () != null ) {
326366 // Disable field if user is logged in.
327367 passwordField .disableProperty ().set (!getTableRow ().getItem ().loginAction );
328368 }
@@ -336,7 +376,7 @@ protected void updateItem(String item, final boolean empty)
336376 }
337377 }
338378
339- public void setStage (Stage stage ){
379+ public void setStage (Stage stage ) {
340380 this .stage = stage ;
341381 }
342382}
0 commit comments