Skip to content

Commit 7753c37

Browse files
committed
try to auto-login on startup
1 parent edf4749 commit 7753c37

File tree

12 files changed

+311
-28
lines changed

12 files changed

+311
-28
lines changed

app/ux-analytics/monitor/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,12 @@
8888
<artifactId>s3</artifactId>
8989
<version>2.25.66</version>
9090
</dependency>
91+
<dependency>
92+
<groupId>org.mariadb.jdbc</groupId>
93+
<artifactId>mariadb-java-client</artifactId>
94+
<version>3.4.0</version>
95+
<scope>runtime</scope>
96+
</dependency>
9197
<dependency>
9298
<groupId>org.phoebus</groupId>
9399
<artifactId>app-logbook-elog</artifactId>

app/ux-analytics/monitor/src/main/java/org/phoebus/applications/uxanalytics/monitor/backend/database/BackendConnection.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,37 @@
66
import org.phoebus.applications.uxanalytics.monitor.backend.image.ImageClient;
77
import org.phoebus.applications.uxanalytics.monitor.util.ResourceOpenSources;
88
import org.phoebus.applications.uxanalytics.monitor.representation.ActiveTab;
9+
import org.phoebus.security.store.SecureStore;
10+
import org.phoebus.security.tokens.AuthenticationScope;
11+
import org.phoebus.security.tokens.ScopedAuthenticationToken;
12+
13+
import java.util.logging.Logger;
914

1015
@FunctionalInterface
1116
public interface BackendConnection {
1217
public Boolean connect(String hostOrRegion, Integer port, String usernameOrAccessKey, String passwordOrSecretKey);
18+
public default boolean tryAutoConnect(AuthenticationScope scope){
19+
//try to auto-connect with saved credentials
20+
try{
21+
SecureStore store = new SecureStore();
22+
ScopedAuthenticationToken scopedAuthenticationToken = store.getScopedAuthenticationToken(scope);
23+
if (scopedAuthenticationToken != null) {
24+
String username = scopedAuthenticationToken.getUsername();
25+
String password = scopedAuthenticationToken.getPassword();
26+
return connect(null, null, username, password);
27+
}
28+
else{
29+
//try anonymous login
30+
if(!connect(null, null, "root", ""))
31+
throw new Exception(this.getClass().toString());
32+
return true;
33+
}
34+
}
35+
catch(Exception e){
36+
Logger.getAnonymousLogger().fine("Failed to auto-connect for UX Analytics backend connection: " + e.getMessage());
37+
return false;
38+
}
39+
}
1340
public default String getProtocol(){return "";}
1441
public default String getHost(){return "localhost";}
1542
public default String getPort(){return "";}
@@ -21,4 +48,6 @@ public default void handleClick(ActiveTab who, Widget widget, Integer x, Integer
2148
public default void handleAction(ActiveTab who, Widget widget, ActionInfo info){}
2249
public default void handlePVWrite(ActiveTab who, Widget widget, String PVName, String value){};
2350
public default void handleDisplayOpen(DisplayInfo target, DisplayInfo src, ResourceOpenSources how){};
51+
52+
2453
}

app/ux-analytics/monitor/src/main/java/org/phoebus/applications/uxanalytics/monitor/backend/database/MongoDBConnection.java

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,10 @@
22

33
import com.mongodb.ConnectionString;
44
import com.mongodb.MongoClientSettings;
5-
import com.mongodb.MongoCredential;
65
import com.mongodb.client.MongoClient;
76
import com.mongodb.client.MongoClients;
87
import com.mongodb.client.MongoDatabase;
98
import javafx.application.Platform;
10-
import javafx.embed.swing.SwingFXUtils;
11-
import javafx.scene.Node;
12-
import javafx.scene.SnapshotParameters;
13-
import javafx.scene.image.WritableImage;
149

1510
import java.awt.image.BufferedImage;
1611
import java.net.URI;
@@ -31,6 +26,9 @@
3126
import org.phoebus.applications.uxanalytics.monitor.UXAMonitor;
3227
import org.phoebus.applications.uxanalytics.monitor.representation.ActiveTab;
3328
import org.phoebus.framework.preferences.PhoebusPreferenceService;
29+
import org.phoebus.security.store.SecureStore;
30+
import org.phoebus.security.tokens.AuthenticationScope;
31+
import org.phoebus.security.tokens.ScopedAuthenticationToken;
3432

3533
public class MongoDBConnection implements BackendConnection {
3634

@@ -58,7 +56,9 @@ public static MongoDBConnection getInstance(){
5856
return instance;
5957
}
6058

61-
private MongoDBConnection(){}
59+
private MongoDBConnection(){ //try to auto-connect with saved credentials
60+
tryAutoConnect(AuthenticationScope.MONGODB);
61+
}
6262

6363
@Override
6464
public Boolean connect(String hostname, Integer port, String username, String password) {
@@ -133,13 +133,6 @@ public Integer tearDown() {
133133
return 0;
134134
}
135135

136-
static BufferedImage getSnapshot(ActiveTab who) {
137-
Node jfxNode = who.getParentTab().getContent();
138-
SnapshotParameters params = new SnapshotParameters();
139-
WritableImage snapshot = jfxNode.snapshot(params, null);
140-
return SwingFXUtils.fromFXImage(snapshot, null);
141-
}
142-
143136
@Override
144137
public void handleClick(ActiveTab who, Integer x, Integer y) {
145138
//if another image client hasn't been set up yet, default to a collection in the MongoDB database
@@ -157,7 +150,7 @@ public void handleClick(ActiveTab who, Integer x, Integer y) {
157150
logger.log(Level.INFO, "Uploading image for " + who + " to " + path);
158151
try {
159152
((DisplayRuntimeInstance) who.getParentTab().getApplication()).getRepresentation_init().get(1, TimeUnit.SECONDS);
160-
BufferedImage snapshot = getSnapshot(who);
153+
BufferedImage snapshot = FileUtils.getSnapshot(who);
161154
imageClient.uploadImage(URI.create(path), snapshot);
162155
}
163156
catch (Exception ex) {

app/ux-analytics/monitor/src/main/java/org/phoebus/applications/uxanalytics/monitor/backend/database/Neo4JConnection.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.phoebus.applications.uxanalytics.monitor.util.ResourceOpenSources;
1313
import org.phoebus.applications.uxanalytics.monitor.representation.ActiveTab;
1414
import org.phoebus.framework.preferences.PhoebusPreferenceService;
15+
import org.phoebus.security.tokens.AuthenticationScope;
1516

1617
import java.time.Instant;
1718
import java.util.Map;
@@ -50,11 +51,17 @@ public static Neo4JConnection getInstance(){
5051

5152
private Session session;
5253

53-
private Neo4JConnection(){}
54+
private Neo4JConnection(){
55+
tryAutoConnect(AuthenticationScope.NEO4J);
56+
}
5457

5558
@Override
5659
public Boolean connect(String host, Integer port, String username, String password) {
5760
try {
61+
if(host == null)
62+
host = getHost();
63+
if(port == null)
64+
port = Integer.parseInt(getPort());
5865
driver = GraphDatabase.driver(PROTOCOL + host + ":" + port.toString(), AuthTokens.basic(username, password));
5966
driver.verifyConnectivity();
6067
logger.log(Level.INFO, "Connected to " + host + " on port " + port + " as " + username);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
package org.phoebus.applications.uxanalytics.monitor.backend.database;
2+
3+
import javafx.application.Platform;
4+
import org.phoebus.applications.uxanalytics.monitor.backend.image.FilesystemImageClient;
5+
import org.phoebus.applications.uxanalytics.monitor.backend.image.ImageClient;
6+
import org.phoebus.applications.uxanalytics.monitor.representation.ActiveTab;
7+
import org.phoebus.applications.uxanalytics.monitor.util.FileUtils;
8+
import org.phoebus.framework.preferences.PhoebusPreferenceService;
9+
import org.phoebus.security.tokens.AuthenticationScope;
10+
11+
import java.net.URI;
12+
import java.sql.*;
13+
import java.util.logging.Level;
14+
import java.util.logging.Logger;
15+
16+
public class SQLConnection implements BackendConnection{
17+
18+
Logger logger = Logger.getLogger(SQLConnection.class.getName());
19+
Connection conn;
20+
String userHost = null;
21+
Integer userPort = null;
22+
String userName = null;
23+
String password = null;
24+
String database = null;
25+
String table = null;
26+
private ImageClient imageClient;
27+
private SQLConnection() {
28+
tryAutoConnect(AuthenticationScope.MARIADB);
29+
}
30+
private static SQLConnection instance;
31+
public static SQLConnection getInstance(){
32+
if(instance == null){
33+
instance = new SQLConnection();
34+
}
35+
return instance;
36+
}
37+
38+
static class JDBCConnectionBuilder {
39+
private String protocol = "jdbc:mysql://";
40+
private String host = null;
41+
private String port = null;
42+
private String username = null;
43+
private String password = null;
44+
private String database = null;
45+
46+
47+
public JDBCConnectionBuilder() {
48+
}
49+
50+
public JDBCConnectionBuilder protocol(String protocol) {
51+
this.protocol = protocol;
52+
return this;
53+
}
54+
55+
public JDBCConnectionBuilder host(String host) {
56+
this.host = host;
57+
return this;
58+
}
59+
60+
public JDBCConnectionBuilder port(Integer port) {
61+
if(port != null)
62+
this.port = port.toString();
63+
return this;
64+
}
65+
66+
public JDBCConnectionBuilder username(String username) {
67+
this.username = username;
68+
return this;
69+
}
70+
71+
public JDBCConnectionBuilder password(String password) {
72+
this.password = password;
73+
return this;
74+
}
75+
76+
public JDBCConnectionBuilder database(String database) {
77+
this.database = database;
78+
return this;
79+
}
80+
81+
public Connection build() {
82+
String url = protocol;
83+
if(host != null)
84+
url += host;
85+
else
86+
url += PhoebusPreferenceService.userNodeForClass(SQLConnection.class).get("host", "localhost");
87+
if(port != null)
88+
url += ":" + port;
89+
else
90+
url += ":" + PhoebusPreferenceService.userNodeForClass(SQLConnection.class).get("port", "3306");
91+
if(username == null)
92+
username = PhoebusPreferenceService.userNodeForClass(SQLConnection.class).get("username", "root");
93+
if(database != null)
94+
url += "/" + database;
95+
else
96+
url += "/" + PhoebusPreferenceService.userNodeForClass(SQLConnection.class).get("database", "phoebus_analytics");
97+
try{
98+
Logger.getLogger(SQLConnection.class.getName()).info("Connecting to JDBC: " + url);
99+
return DriverManager.getConnection(url, username, password);
100+
} catch(SQLException e){
101+
Logger.getLogger(JDBCConnectionBuilder.class.getName()).info("UX Analytics Failed to connect to JDBC: " + e.getMessage());
102+
return null;
103+
}
104+
}
105+
}
106+
107+
@Override
108+
public Boolean connect(String hostOrRegion, Integer port, String usernameOrAccessKey, String passwordOrSecretKey) {
109+
if(conn != null) {
110+
try {
111+
conn.close();
112+
} catch (SQLException e) {
113+
logger.log(Level.WARNING, "Failed to close existing JDBC connection: " + e.getMessage());
114+
}
115+
}
116+
conn = null;
117+
userHost = hostOrRegion;
118+
userPort = port;
119+
userName = usernameOrAccessKey;
120+
database = PhoebusPreferenceService.userNodeForClass(SQLConnection.class).get("database", "phoebus_analytics");
121+
conn = new JDBCConnectionBuilder()
122+
.host(userHost)
123+
.port(userPort)
124+
.username(userName)
125+
.password(passwordOrSecretKey)
126+
.database(database)
127+
.build();
128+
return (conn != null);
129+
}
130+
131+
@Override
132+
public String getProtocol() {
133+
return "jdbc:mysql://";
134+
}
135+
136+
@Override
137+
public String getHost() {
138+
if(userHost != null)
139+
return userHost;
140+
return PhoebusPreferenceService.userNodeForClass(SQLConnection.class).get("host", "localhost");
141+
}
142+
143+
@Override
144+
public String getPort() {
145+
if(userPort != null)
146+
return userPort.toString();
147+
return PhoebusPreferenceService.userNodeForClass(SQLConnection.class).get("port", "3306");
148+
}
149+
150+
@Override
151+
public String getDefaultUsername() {
152+
return "root";
153+
}
154+
155+
@Override
156+
public Integer tearDown() {
157+
try{
158+
conn.close();
159+
return 0;
160+
} catch(SQLException e){
161+
logger.warning("Failed to close JDBC connection: " + e.getMessage());
162+
return -1;
163+
}
164+
}
165+
166+
@Override
167+
public void setImageClient(ImageClient imageClient) {
168+
this.imageClient = imageClient;
169+
}
170+
171+
@Override
172+
public void handleClick(ActiveTab who, Integer x, Integer y) {
173+
if(conn!=null){
174+
Platform.runLater(()->{
175+
String path = FileUtils.analyticsPathForTab(who);
176+
String tableName = path.substring(path.lastIndexOf('_') + 1);
177+
if(imageClient==null){
178+
logger.warning("No ImageClient set for SQLConnection, defaulting to filesystem");
179+
imageClient = FilesystemImageClient.getInstance();
180+
}
181+
if(!imageClient.imageExists(URI.create(path))){
182+
imageClient.uploadImage(URI.create(path), FileUtils.getSnapshot(who));
183+
184+
}
185+
186+
//create table if it doesn't exist
187+
try{
188+
Statement stmt = conn.createStatement();
189+
stmt.execute("CREATE TABLE IF NOT EXISTS " + tableName + " (x INT, y INT, timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP)");
190+
stmt.close();
191+
} catch(SQLException e){
192+
logger.warning("Failed to create table for " + tableName + ": " + e.getMessage());
193+
}
194+
195+
//insert click into table
196+
try{
197+
PreparedStatement stmt = conn.prepareStatement("INSERT INTO " + tableName + " (x, y) VALUES (?, ?)");
198+
stmt.setInt(1, x);
199+
stmt.setInt(2, y);
200+
stmt.execute();
201+
stmt.close();
202+
logger.fine("Inserted click into table " + tableName);
203+
} catch(SQLException e){
204+
logger.warning("Failed to insert click into table for " + tableName + ": " + e.getMessage());
205+
}
206+
});
207+
}
208+
}
209+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package org.phoebus.applications.uxanalytics.monitor.backend.database.authentication;
2+
3+
import org.phoebus.applications.uxanalytics.monitor.backend.database.SQLConnection;
4+
import org.phoebus.security.authorization.ServiceAuthenticationProvider;
5+
import org.phoebus.security.tokens.AuthenticationScope;
6+
7+
public class MariaDBAuthenticationProvider implements ServiceAuthenticationProvider {
8+
9+
@Override
10+
public void authenticate(String username, String password) {
11+
SQLConnection connection = SQLConnection.getInstance();
12+
SQLConnection.getInstance().connect(connection.getHost(), Integer.parseInt(connection.getPort()), username, password);
13+
14+
}
15+
16+
@Override
17+
public void logout(String token) {
18+
19+
}
20+
21+
@Override
22+
public AuthenticationScope getAuthenticationScope() {
23+
return AuthenticationScope.MARIADB;
24+
}
25+
}

0 commit comments

Comments
 (0)