Skip to content

Commit d3b796a

Browse files
committed
System Touch
1 parent 2f724ba commit d3b796a

4 files changed

Lines changed: 199 additions & 9 deletions

File tree

configuration/nwe-config.xml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,37 @@
99
Port privilege for MODULE_LOADER_DAEMON is established externally by the
1010
national port-aware program and its database. All other ports are bound
1111
locally on startup.
12+
13+
Admin credentials below are for the initial administrator. Change the
14+
password before first production deployment. The admin account governs:
15+
- database configuration
16+
- server document management
17+
- module installation / unload authority
18+
- inclusion decisions (enabling / disabling servers at startup)
1219
-->
1320
<nwe-config>
1421

22+
<!-- ═══════════════════════════════════════════════════════════════════
23+
INITIAL ADMINISTRATOR
24+
Username and password are loaded by NweConfig at startup.
25+
The admin may log in to any TCP service that accepts admin auth
26+
(ModuleInstallationService, ModuleLoaderDaemon) using these credentials.
27+
════════════════════════════════════════════════════════════════════ -->
28+
<admin>
29+
<username>mearvk</username>
30+
<password>n21admin</password>
31+
<description>
32+
Initial NWE administrator. Responsible for database configuration,
33+
server document management, and module authority.
34+
Change the password before production deployment.
35+
</description>
36+
</admin>
37+
1538
<!-- ═══════════════════════════════════════════════════════════════════
1639
MAIN SERVER
1740
════════════════════════════════════════════════════════════════════ -->
1841
<server id="NITRO_WEB_EXPRESS">
42+
<enabled>true</enabled>
1943
<name>NitroWebExpress</name>
2044
<thread>WEBEXPRESS_TELNET_PROXY_SERVER</thread>
2145
<host>localhost</host>
@@ -28,6 +52,7 @@
2852
ENCRYPTION SERVERS
2953
════════════════════════════════════════════════════════════════════ -->
3054
<server id="AES_COMPLIANT">
55+
<enabled>true</enabled>
3156
<name>AES 2.0 DSS5.0 Server</name>
3257
<thread>WEBEXPRESS_AES2_SERVER</thread>
3358
<host>localhost</host>
@@ -37,6 +62,7 @@
3762
</server>
3863

3964
<server id="RSA_COMPLIANT">
65+
<enabled>true</enabled>
4066
<name>RSA Compliant Server</name>
4167
<thread>WEBEXPRESS_RSA_SERVER</thread>
4268
<host>localhost</host>
@@ -46,6 +72,7 @@
4672
</server>
4773

4874
<server id="DSA_COMPLIANT">
75+
<enabled>true</enabled>
4976
<name>DSA Compliant Server</name>
5077
<thread>WEBEXPRESS_DSA_SERVER</thread>
5178
<host>localhost</host>
@@ -58,6 +85,7 @@
5885
BITCOIN SERVER
5986
════════════════════════════════════════════════════════════════════ -->
6087
<server id="BITCOIN_COMPLIANT">
88+
<enabled>true</enabled>
6189
<name>Bitcoin v24.0+ Masterthread</name>
6290
<thread>WEBEXPRESS_BITCOIN_SERVER</thread>
6391
<host>localhost</host>
@@ -70,6 +98,7 @@
7098
STATUS AND UTILITY SERVERS
7199
════════════════════════════════════════════════════════════════════ -->
72100
<server id="CONNECTION_STATUS">
101+
<enabled>true</enabled>
73102
<name>ConnectionStatusServer</name>
74103
<thread>ConnectionStatusServer</thread>
75104
<host>localhost</host>
@@ -78,6 +107,7 @@
78107
</server>
79108

80109
<server id="ASCII_CREATOR">
110+
<enabled>true</enabled>
81111
<name>ASCIICreatorServer</name>
82112
<thread>ASCIICreatorServer</thread>
83113
<host>localhost</host>
@@ -89,6 +119,7 @@
89119
MODULE SERVICES
90120
════════════════════════════════════════════════════════════════════ -->
91121
<server id="MODULE_INSTALLATION">
122+
<enabled>true</enabled>
92123
<name>ModuleInstallationService</name>
93124
<thread>ModuleInstallationService</thread>
94125
<host>localhost</host>
@@ -100,6 +131,7 @@
100131
</server>
101132

102133
<server id="MODULE_LOADER_DAEMON">
134+
<enabled>true</enabled>
103135
<name>ModuleLoaderDaemon</name>
104136
<thread>ModuleLoaderDaemon</thread>
105137
<host>localhost</host>

source/Main.java

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ public Main()
6868
{
6969
shutdown.ShutdownHooks.register();
7070

71+
configuration.NweConfig.load();
72+
7173
CommonRails.printStartRecipeSpinner();
7274

7375
System.out.println("\033[38;5;74m[ Java National Finance Engine v.28.1.1 Software Processes Starting ]\033[0m");
@@ -102,21 +104,29 @@ public Main()
102104

103105
NITRO.TELNET_PROXY_ENABLED = Boolean.TRUE;
104106

105-
NITRO.BRIDGE.AES_COMPONENT = new NitroWebExpress.Aspect.AESCompliant(AES_WEBEXPRESS_REMOTE_HOST, AES2_WEBEXPRESS_SERVER_SOCKET, AES2_WEBEXPRESS_SERVER_THREAD_NAME, Boolean.TRUE);
107+
if (configuration.NweConfig.isEnabled("AES_COMPLIANT"))
108+
NITRO.BRIDGE.AES_COMPONENT = new NitroWebExpress.Aspect.AESCompliant(AES_WEBEXPRESS_REMOTE_HOST, AES2_WEBEXPRESS_SERVER_SOCKET, AES2_WEBEXPRESS_SERVER_THREAD_NAME, Boolean.TRUE);
106109

107-
NITRO.BRIDGE.BITCOIN_COMPONENT = new NitroWebExpress.Aspect.BitcoinCompliant(BITCOIN_WEBEXPRESS_REMOTE_HOST, BITCOIN_WEBEXPRESS_SERVER_SOCKET, BITCOIN_WEBEXPRESS_SERVER_THREAD_NAME, Boolean.TRUE);
110+
if (configuration.NweConfig.isEnabled("BITCOIN_COMPLIANT"))
111+
NITRO.BRIDGE.BITCOIN_COMPONENT = new NitroWebExpress.Aspect.BitcoinCompliant(BITCOIN_WEBEXPRESS_REMOTE_HOST, BITCOIN_WEBEXPRESS_SERVER_SOCKET, BITCOIN_WEBEXPRESS_SERVER_THREAD_NAME, Boolean.TRUE);
108112

109-
NITRO.BRIDGE.RSA_COMPONENT = new NitroWebExpress.Aspect.RSACompliant(RSA_WEBEXPRESS_REMOTE_HOST, RSA_WEBEXPRESS_SERVER_SOCKET, RSA_WEBEXPRESS_SERVER_THREAD_NAME, Boolean.TRUE);
113+
if (configuration.NweConfig.isEnabled("RSA_COMPLIANT"))
114+
NITRO.BRIDGE.RSA_COMPONENT = new NitroWebExpress.Aspect.RSACompliant(RSA_WEBEXPRESS_REMOTE_HOST, RSA_WEBEXPRESS_SERVER_SOCKET, RSA_WEBEXPRESS_SERVER_THREAD_NAME, Boolean.TRUE);
110115

111-
NITRO.BRIDGE.DSA_COMPONENT = new NitroWebExpress.Aspect.DSACompliant(DSA_WEBEXPRESS_REMOTE_HOST, DSA_WEBEXPRESS_SERVER_SOCKET, DSA_WEBEXPRESS_SERVER_THREAD_NAME, Boolean.TRUE);
116+
if (configuration.NweConfig.isEnabled("DSA_COMPLIANT"))
117+
NITRO.BRIDGE.DSA_COMPONENT = new NitroWebExpress.Aspect.DSACompliant(DSA_WEBEXPRESS_REMOTE_HOST, DSA_WEBEXPRESS_SERVER_SOCKET, DSA_WEBEXPRESS_SERVER_THREAD_NAME, Boolean.TRUE);
112118

113-
NITRO.BRIDGE.CONNECTION_STATUS = new NitroWebExpress.Aspect.ConnectionStatusServer(CONNECTION_STATUS_SERVER_HOST, NITRO.CURRENT_CONNECTIONS, NITRO.PORT);
119+
if (configuration.NweConfig.isEnabled("CONNECTION_STATUS"))
120+
NITRO.BRIDGE.CONNECTION_STATUS = new NitroWebExpress.Aspect.ConnectionStatusServer(CONNECTION_STATUS_SERVER_HOST, NITRO.CURRENT_CONNECTIONS, NITRO.PORT);
114121

115-
NITRO.BRIDGE.MODULE_INSTALLER_SERVICE = new NitroWebExpress.Aspect.ModuleInstallationService(MODULE_INSTALLER_SERVICE_HOST);
122+
if (configuration.NweConfig.isEnabled("MODULE_INSTALLATION"))
123+
NITRO.BRIDGE.MODULE_INSTALLER_SERVICE = new NitroWebExpress.Aspect.ModuleInstallationService(MODULE_INSTALLER_SERVICE_HOST);
116124

117-
NITRO.BRIDGE.ASCII_CREATOR_SERVER = new NitroWebExpress.Aspect.ASCIICreatorServer(ASCII_CREATOR_SERVER_HOST);
125+
if (configuration.NweConfig.isEnabled("ASCII_CREATOR"))
126+
NITRO.BRIDGE.ASCII_CREATOR_SERVER = new NitroWebExpress.Aspect.ASCIICreatorServer(ASCII_CREATOR_SERVER_HOST);
118127

119-
NITRO.BRIDGE.MODULE_LOADER_DAEMON = new loader.ModuleLoaderDaemon(MODULE_LOADER_DAEMON_HOST);
128+
if (configuration.NweConfig.isEnabled("MODULE_LOADER_DAEMON"))
129+
NITRO.BRIDGE.MODULE_LOADER_DAEMON = new loader.ModuleLoaderDaemon(MODULE_LOADER_DAEMON_HOST);
120130

121131
NITRO.BRIDGE.MYSQL_COMPONENT = new NitroWebExpress.Aspect.MySQLComponent();
122132

source/admin/ModuleAdmin.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,13 @@
1616
*/
1717
public class ModuleAdmin
1818
{
19-
private static final String PASSWORD = resolvePassword();
19+
private static volatile String PASSWORD = resolvePassword();
20+
21+
/** Called by NweConfig after loading nwe-config.xml to apply the configured admin password. */
22+
public static void setPassword(final String NEW_PASSWORD)
23+
{
24+
if (NEW_PASSWORD != null && !NEW_PASSWORD.isEmpty()) PASSWORD = NEW_PASSWORD;
25+
}
2026

2127
/** Active session tokens — keyed by token string, value = nationalId of admin. */
2228
private static final ConcurrentHashMap<String, Long> SESSIONS = new ConcurrentHashMap<>();
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
package configuration;
2+
3+
import commons.CommonRails;
4+
import org.w3c.dom.Document;
5+
import org.w3c.dom.Element;
6+
import org.w3c.dom.NodeList;
7+
8+
import javax.xml.parsers.DocumentBuilderFactory;
9+
import java.io.File;
10+
import java.util.HashMap;
11+
import java.util.Map;
12+
13+
/**
14+
* NweConfig — loads configuration/nwe-config.xml at startup.
15+
*
16+
* Provides:
17+
* - isEnabled(serverId) inclusion decision for each &lt;server&gt; block
18+
* - adminUsername() initial administrator username
19+
* - adminPassword() initial administrator password
20+
*
21+
* Call NweConfig.load() once at the top of Main() before any service is
22+
* instantiated. ModuleAdmin.PASSWORD is updated from the XML value so the
23+
* admin may log in to any TCP service with the configured credentials.
24+
*/
25+
public class NweConfig
26+
{
27+
private static final String CONFIG_FILE = "configuration/nwe-config.xml";
28+
29+
private static NweConfig INSTANCE;
30+
31+
private final Map<String, Boolean> ENABLED = new HashMap<>();
32+
private final String ADMIN_USERNAME;
33+
private final String ADMIN_PASSWORD;
34+
35+
private NweConfig(final Map<String, Boolean> ENABLED,
36+
final String ADMIN_USERNAME,
37+
final String ADMIN_PASSWORD)
38+
{
39+
this.ENABLED.putAll(ENABLED);
40+
this.ADMIN_USERNAME = ADMIN_USERNAME;
41+
this.ADMIN_PASSWORD = ADMIN_PASSWORD;
42+
}
43+
44+
// ── Public API ────────────────────────────────────────────────────────────
45+
46+
/** Returns true if the &lt;server id="..."&gt; block has &lt;enabled&gt;true&lt;/enabled&gt;.
47+
* Defaults to true when the tag is absent (safe default — no service is silently dropped). */
48+
public static boolean isEnabled(final String SERVER_ID)
49+
{
50+
return get().ENABLED.getOrDefault(SERVER_ID, true);
51+
}
52+
53+
public static String adminUsername() { return get().ADMIN_USERNAME; }
54+
public static String adminPassword() { return get().ADMIN_PASSWORD; }
55+
56+
/** Load (or reload) configuration from disk. Called once from Main(). */
57+
public static synchronized NweConfig load()
58+
{
59+
File file = new File(CONFIG_FILE);
60+
61+
if (!file.exists())
62+
{
63+
CommonRails.printSystemComponent(
64+
NweConfig.class, NweConfig.class.hashCode(),
65+
". NweConfig — " + CONFIG_FILE + " not found; all servers enabled, default admin .",
66+
CommonRails.COLOR_YELLOW);
67+
INSTANCE = defaults();
68+
}
69+
else
70+
{
71+
try
72+
{
73+
Document doc = DocumentBuilderFactory.newInstance()
74+
.newDocumentBuilder().parse(file);
75+
doc.getDocumentElement().normalize();
76+
77+
Map<String, Boolean> enabled = new HashMap<>();
78+
79+
NodeList servers = doc.getElementsByTagName("server");
80+
for (int i = 0; i < servers.getLength(); i++)
81+
{
82+
Element el = (Element) servers.item(i);
83+
String id = el.getAttribute("id");
84+
String val = text(el, "enabled", "true");
85+
if (!id.isEmpty()) enabled.put(id, Boolean.parseBoolean(val));
86+
}
87+
88+
Element root = doc.getDocumentElement();
89+
NodeList adminNodes = root.getElementsByTagName("admin");
90+
String adminUser = "mearvk";
91+
String adminPass = "n21admin";
92+
if (adminNodes.getLength() > 0)
93+
{
94+
Element adminEl = (Element) adminNodes.item(0);
95+
adminUser = text(adminEl, "username", adminUser);
96+
adminPass = text(adminEl, "password", adminPass);
97+
}
98+
99+
INSTANCE = new NweConfig(enabled, adminUser, adminPass);
100+
101+
CommonRails.printSystemComponent(
102+
NweConfig.class, NweConfig.class.hashCode(),
103+
". NweConfig loaded — " + enabled.size() + " server entries, admin='" + adminUser + "' .",
104+
CommonRails.COLOR_LIME_GREEN);
105+
}
106+
catch (Exception e)
107+
{
108+
CommonRails.printSystemComponent(
109+
NweConfig.class, NweConfig.class.hashCode(),
110+
". NweConfig parse error: " + e.getMessage() + " — using defaults .",
111+
CommonRails.COLOR_STANDARD_RED);
112+
INSTANCE = defaults();
113+
}
114+
}
115+
116+
// Propagate admin password into ModuleAdmin so TCP services pick it up
117+
admin.ModuleAdmin.setPassword(INSTANCE.ADMIN_PASSWORD);
118+
119+
return INSTANCE;
120+
}
121+
122+
// ── Internals ─────────────────────────────────────────────────────────────
123+
124+
private static NweConfig get()
125+
{
126+
if (INSTANCE == null) load();
127+
return INSTANCE;
128+
}
129+
130+
private static NweConfig defaults()
131+
{
132+
return new NweConfig(new HashMap<>(), "mearvk", "n21admin");
133+
}
134+
135+
private static String text(final Element EL, final String TAG, final String DEF)
136+
{
137+
NodeList nl = EL.getElementsByTagName(TAG);
138+
if (nl.getLength() == 0) return DEF;
139+
String v = nl.item(0).getTextContent().trim();
140+
return v.isEmpty() ? DEF : v;
141+
}
142+
}

0 commit comments

Comments
 (0)