agent-relay-server 0.4.19 → 0.4.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/public/dashboard.js +17 -5
- package/public/index.html +2 -2
- package/src/security.ts +13 -2
package/package.json
CHANGED
package/public/dashboard.js
CHANGED
|
@@ -95,7 +95,7 @@
|
|
|
95
95
|
|
|
96
96
|
function upsertById(list, item) {
|
|
97
97
|
const idx = list.findIndex((existing) => existing.id === item.id);
|
|
98
|
-
if (idx >= 0) list
|
|
98
|
+
if (idx >= 0) list.splice(idx, 1, item);
|
|
99
99
|
else list.push(item);
|
|
100
100
|
}
|
|
101
101
|
|
|
@@ -126,11 +126,18 @@
|
|
|
126
126
|
function createLifecycleMethods() {
|
|
127
127
|
return {
|
|
128
128
|
async init() {
|
|
129
|
+
this.startClock();
|
|
130
|
+
watchPersistedPrefs(this);
|
|
131
|
+
|
|
132
|
+
try {
|
|
133
|
+
this.stats = await this.api("GET", "/stats");
|
|
134
|
+
} catch {
|
|
135
|
+
if (this.authNeeded) return;
|
|
136
|
+
}
|
|
137
|
+
|
|
129
138
|
await this.refresh();
|
|
130
139
|
this.connectSSE();
|
|
131
|
-
this.startClock();
|
|
132
140
|
this.startAutoRefresh();
|
|
133
|
-
watchPersistedPrefs(this);
|
|
134
141
|
},
|
|
135
142
|
|
|
136
143
|
save(key, value) {
|
|
@@ -192,8 +199,13 @@
|
|
|
192
199
|
registerTaskEvents(this, es);
|
|
193
200
|
}
|
|
194
201
|
|
|
202
|
+
function baseUrl() {
|
|
203
|
+
const href = window.location.href.split("?")[0].split("#")[0];
|
|
204
|
+
return href.endsWith("/") ? href : href + "/";
|
|
205
|
+
}
|
|
206
|
+
|
|
195
207
|
function buildEventsUrl(authToken) {
|
|
196
|
-
const eventUrl = new URL(
|
|
208
|
+
const eventUrl = new URL("api/events", baseUrl());
|
|
197
209
|
if (authToken) eventUrl.searchParams.set("token", authToken);
|
|
198
210
|
return eventUrl.toString();
|
|
199
211
|
}
|
|
@@ -258,7 +270,7 @@
|
|
|
258
270
|
opts.body = JSON.stringify(body);
|
|
259
271
|
}
|
|
260
272
|
|
|
261
|
-
const response = await fetch(
|
|
273
|
+
const response = await fetch(new URL("api" + path, baseUrl()), opts);
|
|
262
274
|
if (!response.ok) {
|
|
263
275
|
if (response.status === 401) this.authNeeded = true;
|
|
264
276
|
const text = await response.text();
|
package/public/index.html
CHANGED
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
<div class="ar-sidebar-footer">
|
|
103
103
|
<div class="d-flex align-items-center gap-2 mb-2">
|
|
104
104
|
<span class="status-dot" :class="connected ? 'online' : 'offline'"></span>
|
|
105
|
-
<span class="small" x-text="connected ? 'Live' : 'Reconnecting…'"></span>
|
|
105
|
+
<span class="small" x-text="authNeeded ? 'Auth required' : connected ? 'Live' : 'Reconnecting…'"></span>
|
|
106
106
|
</div>
|
|
107
107
|
<div class="d-flex align-items-center gap-2 mb-2">
|
|
108
108
|
<label class="form-check form-switch mb-0">
|
|
@@ -855,7 +855,7 @@
|
|
|
855
855
|
<script src="https://cdn.jsdelivr.net/npm/@tabler/core@latest/dist/js/tabler.min.js"></script>
|
|
856
856
|
<script src="https://cdn.jsdelivr.net/npm/apexcharts@latest/dist/apexcharts.min.js"></script>
|
|
857
857
|
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3/dist/cdn.min.js"></script>
|
|
858
|
-
<script src="
|
|
858
|
+
<script src="dashboard.js"></script>
|
|
859
859
|
|
|
860
860
|
</body>
|
|
861
861
|
</html>
|
package/src/security.ts
CHANGED
|
@@ -19,10 +19,21 @@ export function isOriginAllowed(req: Request): boolean {
|
|
|
19
19
|
if (!origin) return true;
|
|
20
20
|
const origins = corsOrigins();
|
|
21
21
|
if (origins.includes("*")) return true;
|
|
22
|
+
if (origins.includes(origin)) return true;
|
|
22
23
|
|
|
23
24
|
const url = new URL(req.url);
|
|
24
25
|
const sameOrigin = `${url.protocol}//${url.host}`;
|
|
25
|
-
|
|
26
|
+
if (origin === sameOrigin) return true;
|
|
27
|
+
|
|
28
|
+
// Behind a reverse proxy, req.url is the backend address (e.g. http://127.0.0.1:4850)
|
|
29
|
+
// while the browser sends the public origin. Check forwarded headers.
|
|
30
|
+
try {
|
|
31
|
+
const originHost = new URL(origin).host;
|
|
32
|
+
const fwdHost = req.headers.get("x-forwarded-host");
|
|
33
|
+
if (fwdHost && originHost === fwdHost) return true;
|
|
34
|
+
} catch {}
|
|
35
|
+
|
|
36
|
+
return false;
|
|
26
37
|
}
|
|
27
38
|
|
|
28
39
|
export function applyCors(req: Request, response: Response): Response {
|
|
@@ -117,7 +128,7 @@ export function unauthorized(req: Request): Response {
|
|
|
117
128
|
}
|
|
118
129
|
|
|
119
130
|
function authToken(): string {
|
|
120
|
-
return process.env.AGENT_RELAY_TOKEN
|
|
131
|
+
return process.env.AGENT_RELAY_TOKEN ?? AUTH_TOKEN;
|
|
121
132
|
}
|
|
122
133
|
|
|
123
134
|
function extractToken(req: Request): string | null {
|