Skip to content

Commit a52844e

Browse files
committed
v0.5.10 update
added email, uptime, decrypt, set ram, and about commands fixed bug that commands are skipped when a reboot is skipped due to early termination use the current server's ID when none is provided for creating new commands and trend mappings added %NAME% variable expansion to duplicate commands bumped dependency versions small styling changes to front-end improved buffer size estimate for config file added optional secondary SFTP port for some servers improved front-end status message logic updated sort-order of server list for front-end implemented hidden HTTP request parameter that allows authenticated users to reset the server's ID to a specified value update README
1 parent 51c0915 commit a52844e

14 files changed

+546
-52
lines changed

README.md

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ WebCTRL is a trademark of Automated Logic Corporation. Any other trademarks men
2727
- [Examples](#examples)
2828
- [Find Trends](#find-trends)
2929
- [Trend Mappings](#trend-mappings)
30+
- [Technical Information](#technical-information)
31+
- [Packaged Dependencies](#packaged-dependencies)
32+
- [Server ID Reset](#server-id-reset)
3033

3134
## Feature Summary
3235

@@ -168,14 +171,16 @@ In addition to the SFTP connection settings shown in the previous section, there
168171
| `debug` | `false` | When enabled, log messages will be more verbose. |
169172
| `log_expiration` | `60` | Specifies how many days to retain log messages in the database. |
170173
| `auto_update` | `true` | Specifies whether to attempt automatic updates for this add-on. |
171-
| `version` | `0.5.9.1` | When `auto_update` is enabled, any connected client whose add-on version is less than this value will be updated. |
174+
| `version` | `0.5.10` | When `auto_update` is enabled, any connected client whose add-on version is less than this value will be updated. |
172175
| `download_path` | `/webctrl/addons/PostgreSQL_Connect.addon` | When `auto_update` is enabled, this is the SFTP server path where the latest version add-on file will be retrieved. |
173176
| `license_directory` | `/webctrl/licenses` | Specifies an SFTP server directory path for where to store WebCTRL license files. |
174177
| `ftp_host` | `postgresql.domain.com` | SFTP server hostname or IP address. |
175178
| `ftp_port` | `22` | SFTP server port. |
176179
| `ftp_username` | `webctrl` | SFTP server username to use for connections. |
177180
| `ftp_known_hosts` | `postgresql.domain.com ecdsa-sha2-nistp256 ...` | Public key of the SFTP server to verify the server's identity. [Documentation](https://help.salesforce.com/s/articleView?id=001120703&type=1) |
178181
| `ftp_key` | `-----BEGIN OPENSSH PRIVATE KEY----- ...` | Private key which authenticates the client to the SFTP server. |
182+
| `ftp_port_secondary` | `443` | Secondary SFTP port which may be utilized by some servers. This may be useful to bypass certain firewalls. |
183+
| `ftp_port_secondary_ids` | `46;51;60;61;62` | Semi-colon delimited list of server IDs which should use the secondary SFTP port. |
179184

180185
When trying to push out an update for the add-on, you should do things in the following order:
181186

@@ -199,7 +204,7 @@ This page lists all connected servers. If a server is decomissioned or permanent
199204
| ID | `1` | Internal ID which uniquely identifies the server within the PostgreSQL database. (Read-only) |
200205
| Name | `ACES Main Building` | User-friendly display name for the server. This defaults to the display name of the root of the Geo tree. |
201206
| WebCTRL Version | `8.5.002.20230323-123687` | Full version of the WebCTRL server. (Read-only) |
202-
| Add-On Version | `0.5.9.1` | Installed version of the PostgreSQL_Connect add-on. (Read-only) |
207+
| Add-On Version | `0.5.10` | Installed version of the PostgreSQL_Connect add-on. (Read-only) |
203208
| IP Address | `123.45.67.89` | External IP address of the server as viewed by the PostgreSQL database. (Read-only) |
204209
| Last Sync | `2024-12-02 14:05:32` | Timestamp of the last successful synchronization. If synced within the last 24 hours, the background color is green; otherwise, the background is red. (Read-only) |
205210
| License | `WebCTRL Premium` | Click this field to download WebCTRL's license. (Read-only) |
@@ -285,16 +290,20 @@ Commands entered into this table are executed on servers during their next sync
285290
| Ordering | `3` | When there are multiple command entries for a single server, this column specifies the ascending order in which commands are executed. |
286291
| Command | `notify "Hello!"` | The command(s) to execute. Multiple commands can be separated by newlines for fail-fast semantics. |
287292

288-
Commands chained together using new-lines in a single entry are fail-fast, which means that execution is terminated immediately when an error is encountered. However, errors in one command entry do not affect other entries. Generally, commands are case-insensitive. Commands are tokenized using whitespace as delimiters. Double quotes can be used if a token must include whitespace. The caret character `^` can be used as an escape character. The local file path are specified, paths starting with `/` or `\` are treated as relative to WebCTRL's installation directory, and paths starting with `./` or `.\` are treated as relative to WebCTRL's active system directory. The two dots in `a/../b` go to the parent folder of `a`, so that `b` would be a sibling folder of `a`. Single-line comments are supported when a line is starts with `//`. The following commands are supported.
293+
Commands chained together using new-lines in a single entry are fail-fast, which means that execution is terminated immediately when an error is encountered. However, errors in one command entry do not affect other entries. Generally, commands are case-insensitive. Commands are tokenized using whitespace as delimiters. Double quotes can be used if a token must include whitespace. The caret character `^` can be used as an escape character. The local file path are specified, paths starting with `/` or `\` are treated as relative to WebCTRL's installation directory, and paths starting with `./` or `.\` are treated as relative to WebCTRL's active system directory. The two dots in `a/../b` go to the parent folder of `a`, so that `b` would be a sibling folder of `a`. Environment variables enclosed in percent signs (e.g, `%USERNAME%`) are expanded when present in local paths. Single-line comments are supported when a line is starts with `//`. The following commands are supported.
289294

290295
| Command | Description |
291296
| - | - |
292-
| `duplicate [id1,id2,...]` | When a new pending command is created, and `duplicate` is on the first line, the command is copied to all servers with the specified IDs. If no server IDs are specified, then the command is copied to all servers. You can use `%ID%` anywhere in the command after the `duplicate` statement, and it will be replaced with the server ID of each server the command is copied to. |
297+
| `duplicate [id1,id2,...]` | When a new pending command is created, and `duplicate` is on the first line, the command is copied to all servers with the specified IDs. If no server IDs are specified, then the command is copied to all servers. You can use `%ID%` or `%NAME%` anywhere in the command after the `duplicate` statement, and it will be replaced with the server ID or name of each server the command is copied to. |
298+
| `about` | Logs a bunch of information relevant to the WebCTRL server. This functions similarly to the `about` manual command. |
293299
| `log <message>` | Writes a message to the add-on's log file. |
294300
| `notify <message>` | Functions identically to the `notify` manual command. Logged in operators get a popup message in their web browsers. |
301+
| `email <recipients> <subject> <message>` | Sends a email using WebCTRL's primary email server configuration. Recipient addresses should be semi-colon delimited. |
295302
| `sleep <milliseconds>` | Sleeps for the specified number of milliseconds. |
296303
| `reboot` | Functions identically to the `rebootserver` manual command. The WebCTRL server reboots. |
297-
| `set <key> <value>` | Sets an add-on connection parameter to the specified value. These parameters can all be changed on the add-on's main page on each server, but this command allows remotely editing connection parameters in bulk. The following keys are supported: `connectionURL`, `username`, `password`, `keystorePassword`, `maxRandomOffset`, `cronSync`. |
304+
| `uptime` | Logs a message saying how long the WebCTRL server has been online. |
305+
| `set <key> <value>` | Sets a parameter to the specified value. Most of the parameters can be changed on the add-on's main page on each server, but this command allows remote editing in bulk. The following keys are supported: `connectionURL`, `username`, `password`, `keystorePassword`, `maxRandomOffset`, `cronSync`, `RAM`. The `RAM` key changes the amount of memory allocated to WebCTRL in MB and goes into affect at the next reboot. |
306+
| `decrypt <value>` | Logs a message containing the decrypted value. This function is only meant to work on encrypted WebCTRL database passwords found in *db.properties* in the system folder. |
298307
| `mkdir <folder_path>` | Creates a new directory on the local file system of the WebCTRL server. |
299308
| `rmdir <folder_path>` | Deletes a directory and contents on the local file system of the WebCTRL server. |
300309
| `rm <file_path>` | Deletes a file on the local file system of the WebCTRL server. |
@@ -303,7 +312,7 @@ Commands chained together using new-lines in a single entry are fail-fast, which
303312
| `cat <file_path>` | Logs the contents of the specified file. |
304313
| `exists <path>` | Asserts that the specified file or directory exists. If non-existent, then command execution is terminated. |
305314
| `!exists <path>` | Asserts that the specified file or directory does not exists. If it exists, then command execution is terminated. |
306-
| `regex <file_path> <find> [replace]` | If a replacement string is not given, then this commands logs all matches of the regular expression in the specified file. If a replacement string is given, then this command edits the specified file by replacing all matches of the regular expression. The file's contents are assumed to be UTF-8 encoded text. The [MULTILINE](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/regex/Pattern.html#MULTILINE) and [DOTALL](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/regex/Pattern.html#DOTALL) flags are used by default. |
315+
| `regex <file_path> <find> [replace]` | If a replacement string is not given, then this commands logs all matches of the regular expression in the specified file. If a replacement string is given, then this command edits the specified file by replacing all matches of the regular expression. The file's contents are assumed to be UTF-8 encoded text. The [MULTILINE](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/regex/Pattern.html#MULTILINE) and [DOTALL](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/regex/Pattern.html#DOTALL) flags are used by default. |
307316
| `download <sftp_file_path> <local_file_path>` | Downloads a file from the SFTP server into the local file system of the WebCTRL server. |
308317
| `upload <local_file_path> <sftp_file_path>` | Uploads a file from the local file system of the WebCTRL server into the SFTP server. |
309318
| `canApplyUpdate <file_path>` | Asserts that WebCTRL is able to apply the specified *.update* patch file. If the update cannot be applied, then command execution is terminated. |
@@ -402,4 +411,16 @@ CREATE TABLE webctrl.trend_data (
402411
);
403412
CREATE INDEX webctrl_trend_data_id ON webctrl.trend_data ("id" ASC);
404413
CREATE INDEX webctrl_trend_data_time ON webctrl.trend_data ("time" DESC);
405-
```
414+
```
415+
416+
## Technical Information
417+
418+
### Packaged Dependencies
419+
420+
- [PostgreSQL JDBC 42.7.5](https://jdbc.postgresql.org/) - Used to connect to PostgreSQL databases.
421+
- [JSch 0.2.22](https://github.com/mwiede/jsch) - Used to connect to SFTP servers.
422+
- [JSON-java 20250107](https://github.com/stleary/JSON-java) - Used to encode and decode JSON data.
423+
424+
### Server ID Reset
425+
426+
There is a *Reset ID* button on the add-on's main page. This will make the add-on forget its current server ID and re-register with the database at the start of the next sync. This server ID is the primary mechanism for how the database separates out data corresponding to different WebCTRL servers. If you ever need to force the add-on to choose a particular ID, you can craft and submit a particular HTTP request to the WebCTRL server. For example, *https://localhost/PostgreSQL_Connect/index?type=resetNow&newID=3* will force the ID of the WebCTRL server accessible at *localhost* to 3.

config/BUILD_DETAILS

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,23 @@ common-9.0.002
1919
commonbaseutils-2.0.5
2020
commonexceptions-9.0.002
2121
core-9.0.002
22+
core-api-9.0.002
23+
databasebridge-9.0.002
2224
datatable-9.0.002
2325
directaccess-9.0.002
2426
directaccess-api-9.0.002
2527
extensionsupport-api-9.0.002
28+
launcher-3.0.10
2629
serviceframework-9.0.002
2730
spring-context-5.3.33
2831
update-api-9.0.002
2932
webserver-api-9.0.002
3033
webui-9.0.002
3134

3235
Packaged Dependencies:
33-
jsch-0.2.21-sources
34-
jsch-0.2.21
35-
json-20240303-sources
36-
json-20240303
37-
postgresql-42.7.4-sources
38-
postgresql-42.7.4
36+
jsch-0.2.22-sources
37+
jsch-0.2.22
38+
json-20250107-sources
39+
json-20250107
40+
postgresql-42.7.5-sources
41+
postgresql-42.7.5

config/EXTERNAL_DEPS

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
url:postgresql-42.7.4.jar:https://repo1.maven.org/maven2/org/postgresql/postgresql/42.7.4/postgresql-42.7.4.jar
2-
url:postgresql-42.7.4-sources.jar:https://repo1.maven.org/maven2/org/postgresql/postgresql/42.7.4/postgresql-42.7.4-sources.jar
3-
url:jsch-0.2.21.jar:https://repo1.maven.org/maven2/com/github/mwiede/jsch/0.2.21/jsch-0.2.21.jar
4-
url:jsch-0.2.21-sources.jar:https://repo1.maven.org/maven2/com/github/mwiede/jsch/0.2.21/jsch-0.2.21-sources.jar
5-
url:json-20240303.jar:https://repo1.maven.org/maven2/org/json/json/20240303/json-20240303.jar
6-
url:json-20240303-sources.jar:https://repo1.maven.org/maven2/org/json/json/20240303/json-20240303-sources.jar
1+
url:postgresql-42.7.5.jar:https://repo1.maven.org/maven2/org/postgresql/postgresql/42.7.5/postgresql-42.7.5.jar
2+
url:postgresql-42.7.5-sources.jar:https://repo1.maven.org/maven2/org/postgresql/postgresql/42.7.5/postgresql-42.7.5-sources.jar
3+
url:jsch-0.2.22.jar:https://repo1.maven.org/maven2/com/github/mwiede/jsch/0.2.22/jsch-0.2.22.jar
4+
url:jsch-0.2.22-sources.jar:https://repo1.maven.org/maven2/com/github/mwiede/jsch/0.2.22/jsch-0.2.22-sources.jar
5+
url:json-20250107.jar:https://repo1.maven.org/maven2/org/json/json/20250107/json-20250107.jar
6+
url:json-20250107-sources.jar:https://repo1.maven.org/maven2/org/json/json/20250107/json-20250107-sources.jar

config/RUNTIME_DEPS

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ file:datatable:modules\datatable
33
file:webserver-api:modules\webserver
44
file:extensionsupport-api:modules\extensionsupport
55
file:core:modules\core
6+
file:core-api:modules\core
67
file:common:modules\common
78
file:commonexceptions:modules\commonexceptions
89
file:commonbaseutils:bin\lib
@@ -11,4 +12,6 @@ file:directaccess-api:modules\directaccess
1112
file:cjupdate:bin\lib
1213
file:update-api:modules\update
1314
file:webui:webroot\WEB-INF\lib
14-
file:serviceframework:modules\serviceframework
15+
file:serviceframework:modules\serviceframework
16+
file:databasebridge:modules\databasebridge
17+
file:launcher:bin\lib

root/info.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<extension version="1">
22
<name>PostgreSQL_Connect</name>
33
<description>Periodically synchronizes operators, add-ons, and specified trends with an external PostgreSQL database.</description>
4-
<version>0.5.9.1</version>
4+
<version>0.5.10</version>
55
<vendor>Automatic Controls Equipment Systems, Inc.</vendor>
66
<system-menu-provider>aces.webctrl.postgresql.web.SystemMenuEditor</system-menu-provider>
77
</extension>

src/aces/webctrl/postgresql/core/Command.java

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
import java.nio.*;
66
import java.nio.file.*;
77
import java.nio.channels.*;
8+
import com.controlj.green.common.launcher.MonitoredLauncher;
9+
import com.controlj.green.common.policy.PolicyUtils;
10+
import com.controlj.green.common.policy.PolicyUtils.KeyType;
11+
import com.controlj.launcher.ConfigurationDecorator;
812
public class Command {
913
private final static HashMap<String,Cmd> commandMap = new HashMap<>();
1014
static {
@@ -19,6 +23,62 @@ public class Command {
1923
}
2024
}
2125
});
26+
commandMap.put("uptime", new Cmd(){
27+
@Override public boolean exec(Command c, String[] tokens) throws Throwable {
28+
if (tokens.length==1){
29+
long uptime = com.controlj.green.core.main.Core.getSystemUptime();
30+
int days = (int)(uptime/86400000L);
31+
uptime-=(long)days*86400000L;
32+
int hours = (int)(uptime/3600000L);
33+
uptime-=(long)hours*3600000L;
34+
int minutes = (int)(uptime/60000L);
35+
//uptime-=(long)minutes*60000L;
36+
c.sb.append("\nWebCTRL has been online for "+days+" days, "+hours+" hours, and "+minutes+" minutes.");
37+
return true;
38+
}else{
39+
c.sb.append("\n'uptime' does not accept any arguments.");
40+
return false;
41+
}
42+
}
43+
});
44+
commandMap.put("about", new Cmd(){
45+
@Override public boolean exec(Command c, String[] tokens) throws Throwable {
46+
if (tokens.length==1){
47+
HelperAPI.about(c.sb);
48+
return true;
49+
}else{
50+
c.sb.append("\n'about' does not accept any arguments.");
51+
return false;
52+
}
53+
}
54+
});
55+
commandMap.put("decrypt", new Cmd(){
56+
@Override public boolean exec(Command c, String[] tokens) throws Throwable {
57+
if (tokens.length==2){
58+
String p;
59+
try{
60+
try {
61+
p = PolicyUtils.AESdecrypt(tokens[1], KeyType.DBPROPERTIES);
62+
} catch (Throwable t) {
63+
p = PolicyUtils.decode(tokens[1]);
64+
if (Initializer.debug()){
65+
Initializer.log(t);
66+
}
67+
}
68+
} catch (Throwable t) {
69+
p = "";
70+
if (Initializer.debug()){
71+
Initializer.log(t);
72+
}
73+
}
74+
c.sb.append('\n').append(p);
75+
return true;
76+
}else{
77+
c.sb.append("\n'decrypt' accepts exactly one argument.");
78+
return false;
79+
}
80+
}
81+
});
2282
commandMap.put("updatedst", new Cmd(){
2383
@Override public boolean exec(Command c, String[] tokens) throws Throwable {
2484
if (tokens.length==1){
@@ -45,6 +105,20 @@ public class Command {
45105
}
46106
}
47107
});
108+
commandMap.put("email", new Cmd(){
109+
@Override public boolean exec(Command c, String[] tokens) throws Throwable {
110+
if (tokens.length==4){
111+
if (HelperAPI.sendEmail(tokens[1], tokens[2], tokens[3])){
112+
return true;
113+
}else{
114+
c.sb.append("\n'email' failed to send message.");
115+
}
116+
}else{
117+
c.sb.append("\n'email' accepts exactly three arguments.");
118+
}
119+
return false;
120+
}
121+
});
48122
commandMap.put("log", new Cmd(){
49123
@Override public boolean exec(Command c, String[] tokens) throws Throwable {
50124
if (tokens.length==2){
@@ -287,6 +361,28 @@ public class Command {
287361
}
288362
break;
289363
}
364+
case "ram":{
365+
try{
366+
final int ram = Integer.parseInt(value);
367+
if (ram<512 || ram>131072){
368+
c.sb.append("\n'set' ram value is out-of-range.");
369+
return false;
370+
}
371+
final ConfigurationDecorator config = new ConfigurationDecorator(MonitoredLauncher.loadConfiguration());
372+
if (config.getMaxMemory()!=ram){
373+
config.setMaxMemory(ram);
374+
MonitoredLauncher.saveConfiguration(config.getConfiguration());
375+
}
376+
}catch(NumberFormatException e){
377+
c.sb.append("\n'set' failed to parse number from expected value.");
378+
return false;
379+
}catch(Throwable t){
380+
c.sb.append("\n'set' encountered error while configuring RAM.");
381+
Initializer.log(t);
382+
return false;
383+
}
384+
break;
385+
}
290386
default:{
291387
c.sb.append("\n'set' does not recognize key: "+key);
292388
return false;
@@ -480,7 +576,7 @@ public boolean execute(){
480576
try{
481577
for (String[] tokens: lines){
482578
if (!execute(tokens)){
483-
break;
579+
return false;
484580
}
485581
}
486582
return true;

0 commit comments

Comments
 (0)