Skip to content

Commit ac5bebc

Browse files
committed
refactor user management: consolidate user fetching logic and add toggle/delete endpoints
1 parent 0790b16 commit ac5bebc

File tree

1 file changed

+177
-81
lines changed

1 file changed

+177
-81
lines changed

index.js

+177-81
Original file line numberDiff line numberDiff line change
@@ -49,83 +49,6 @@ async function connectMikroTik() {
4949
}
5050
}
5151

52-
async function getAllUsers() {
53-
try {
54-
await connectMikroTik();
55-
const users = await connection.write("/ip/hotspot/user/print");
56-
return users.map((user) => ({
57-
username: user.name,
58-
profile: user.profile,
59-
uptime: user.uptime,
60-
bytesIn: user["bytes-in"],
61-
bytesOut: user["bytes-out"],
62-
disabled: user.disabled === "true",
63-
comment: user.comment || "",
64-
limitBytesIn: user["limit-bytes-in"],
65-
limitBytesOut: user["limit-bytes-out"],
66-
}));
67-
} catch (error) {
68-
console.error("Error fetching users:", error);
69-
return [];
70-
}
71-
}
72-
73-
// Get user details by username
74-
async function getUserDetails(username) {
75-
try {
76-
await connectMikroTik();
77-
const user = await connection.write("/ip/hotspot/user/print", [
78-
"=.proplist=name,profile,uptime,bytes-in,bytes-out,disabled,comment,limit-bytes-in,limit-bytes-out,last-logged-out",
79-
"?name=" + username,
80-
]);
81-
82-
if (user.length === 0) {
83-
return null;
84-
}
85-
86-
// Get active sessions for the user
87-
const activeSessions = await connection.write("/ip/hotspot/active/print", [
88-
"?user=" + username,
89-
]);
90-
91-
// Get user's connection history
92-
const history = await connection.write("/ip/hotspot/host/print", [
93-
"?user=" + username,
94-
]);
95-
96-
return {
97-
basicInfo: {
98-
username: user[0].name,
99-
profile: user[0].profile,
100-
uptime: user[0].uptime,
101-
bytesIn: user[0]["bytes-in"],
102-
bytesOut: user[0]["bytes-out"],
103-
disabled: user[0].disabled === "true",
104-
comment: user[0].comment || "",
105-
limitBytesIn: user[0]["limit-bytes-in"],
106-
limitBytesOut: user[0]["limit-bytes-out"],
107-
lastLoggedOut: user[0]["last-logged-out"],
108-
},
109-
activeSessions: activeSessions.map((session) => ({
110-
ipAddress: session.address,
111-
macAddress: session["mac-address"],
112-
loginTime: session["login-by"],
113-
uptime: session.uptime,
114-
sessionId: session[".id"],
115-
})),
116-
connectionHistory: history.map((entry) => ({
117-
ipAddress: entry.address,
118-
macAddress: entry["mac-address"],
119-
lastSeen: entry["last-seen"],
120-
status: entry.status,
121-
})),
122-
};
123-
} catch (error) {
124-
console.error("Error fetching user details:", error);
125-
return null;
126-
}
127-
}
128-
12952
// Get active IP addresses
13053
async function getActiveIPs() {
13154
try {
@@ -234,28 +157,201 @@ app.get("/api/logs/all", async (req, res) => {
234157
}
235158
});
236159

160+
function formatUptime(uptime) {
161+
if (!uptime) return 0;
162+
// Convert RouterOS uptime format to seconds
163+
const parts = uptime.split(/[whms]/);
164+
const units = uptime.match(/[whms]/g);
165+
let seconds = 0;
166+
167+
if (!parts || !units) return 0;
168+
169+
parts.forEach((part, i) => {
170+
if (!part) return;
171+
switch (units[i]) {
172+
case "w":
173+
seconds += parseInt(part) * 7 * 24 * 3600;
174+
break;
175+
case "h":
176+
seconds += parseInt(part) * 3600;
177+
break;
178+
case "m":
179+
seconds += parseInt(part) * 60;
180+
break;
181+
case "s":
182+
seconds += parseInt(part);
183+
break;
184+
}
185+
});
186+
187+
return seconds;
188+
}
189+
190+
function formatBytes(bytes) {
191+
if (!bytes) return '0';
192+
return parseInt(bytes);
193+
}
194+
237195
app.get("/api/users", async (req, res) => {
238196
try {
239-
const users = await getAllUsers();
240-
res.json(users);
197+
await connectMikroTik();
198+
199+
// Get all users
200+
const users = await connection.write("/ip/hotspot/user/print");
201+
202+
// Get active sessions for correlation
203+
const activeSessions = await connection.write("/ip/hotspot/active/print");
204+
205+
const formattedUsers = users.map((user) => {
206+
// Find active sessions for this user
207+
const userSessions = activeSessions.filter(
208+
(session) => session.user === user.name
209+
);
210+
211+
return {
212+
username: user.name,
213+
profile: user.profile,
214+
uptime: formatUptime(user.uptime),
215+
bytesIn: formatBytes(user["bytes-in"]),
216+
bytesOut: formatBytes(user["bytes-out"]),
217+
disabled: user.disabled === "true",
218+
comment: user.comment || "",
219+
limitBytesIn: formatBytes(user["limit-bytes-in"]),
220+
limitBytesOut: formatBytes(user["limit-bytes-out"]),
221+
isOnline: userSessions.length > 0,
222+
activeSessions: userSessions.length,
223+
};
224+
});
225+
226+
res.json(formattedUsers);
241227
} catch (error) {
228+
console.error("Error fetching users:", error);
242229
res.status(500).json({ error: "Failed to fetch users" });
243230
}
244231
});
245232

233+
// Get user details
246234
app.get("/api/users/:username", async (req, res) => {
247235
try {
248-
const userDetails = await getUserDetails(req.params.username);
249-
if (!userDetails) {
236+
await connectMikroTik();
237+
const username = req.params.username;
238+
239+
// Get user basic info
240+
const user = await connection.write("/ip/hotspot/user/print", [
241+
"=.proplist=name,profile,uptime,bytes-in,bytes-out,disabled,comment,limit-bytes-in,limit-bytes-out,last-logged-out",
242+
"?name=" + username,
243+
]);
244+
245+
if (user.length === 0) {
250246
res.status(404).json({ error: "User not found" });
251247
return;
252248
}
249+
250+
// Get active sessions
251+
const activeSessions = await connection.write("/ip/hotspot/active/print", [
252+
"?user=" + username,
253+
]);
254+
255+
// Get connection history
256+
const history = await connection.write("/ip/hotspot/host/print", [
257+
"?user=" + username,
258+
]);
259+
260+
const userDetails = {
261+
basicInfo: {
262+
username: user[0].name,
263+
profile: user[0].profile,
264+
uptime: formatUptime(user[0].uptime),
265+
bytesIn: formatBytes(user[0]["bytes-in"]),
266+
bytesOut: formatBytes(user[0]["bytes-out"]),
267+
disabled: user[0].disabled === "true",
268+
comment: user[0].comment || "",
269+
limitBytesIn: formatBytes(user[0]["limit-bytes-in"]),
270+
limitBytesOut: formatBytes(user[0]["limit-bytes-out"]),
271+
lastLoggedOut: user[0]["last-logged-out"] || null,
272+
},
273+
activeSessions: activeSessions.map((session) => ({
274+
ipAddress: session.address,
275+
macAddress: session["mac-address"],
276+
loginTime: session["login-by"],
277+
uptime: formatUptime(session.uptime),
278+
sessionId: session[".id"],
279+
bytesIn: formatBytes(session["bytes-in"]),
280+
bytesOut: formatBytes(session["bytes-out"]),
281+
})),
282+
connectionHistory: history.map((entry) => ({
283+
ipAddress: entry.address,
284+
macAddress: entry["mac-address"],
285+
lastSeen: entry["last-seen"],
286+
status: entry.status,
287+
host: entry.host,
288+
bytesIn: formatBytes(entry["bytes-in"]),
289+
bytesOut: formatBytes(entry["bytes-out"]),
290+
})),
291+
};
292+
253293
res.json(userDetails);
254294
} catch (error) {
295+
console.error("Error fetching user details:", error);
255296
res.status(500).json({ error: "Failed to fetch user details" });
256297
}
257298
});
258299

300+
// User management endpoints
301+
// Enable/Disable user
302+
app.post("/api/users/:username/toggle", async (req, res) => {
303+
try {
304+
await connectMikroTik();
305+
const username = req.params.username;
306+
307+
const user = await connection.write("/ip/hotspot/user/print", [
308+
"?name=" + username,
309+
]);
310+
311+
if (user.length === 0) {
312+
res.status(404).json({ error: "User not found" });
313+
return;
314+
}
315+
316+
const currentState = user[0].disabled === "true";
317+
await connection.write("/ip/hotspot/user/set", [
318+
"=.id=" + user[0][".id"],
319+
"=disabled=" + !currentState,
320+
]);
321+
322+
res.json({ success: true, disabled: !currentState });
323+
} catch (error) {
324+
console.error("Error toggling user state:", error);
325+
res.status(500).json({ error: "Failed to toggle user state" });
326+
}
327+
});
328+
329+
// Delete user
330+
app.delete("/api/users/:username", async (req, res) => {
331+
try {
332+
await connectMikroTik();
333+
const username = req.params.username;
334+
335+
const user = await connection.write("/ip/hotspot/user/print", [
336+
"?name=" + username,
337+
]);
338+
339+
if (user.length === 0) {
340+
res.status(404).json({ error: "User not found" });
341+
return;
342+
}
343+
344+
await connection.write("/ip/hotspot/user/remove", [
345+
"=.id=" + user[0][".id"],
346+
]);
347+
348+
res.json({ success: true });
349+
} catch (error) {
350+
console.error("Error deleting user:", error);
351+
res.status(500).json({ error: "Failed to delete user" });
352+
}
353+
});
354+
259355
// REST endpoint for initial data
260356
app.get("/api/network-data", async (req, res) => {
261357
try {

0 commit comments

Comments
 (0)