176 lines
7.7 KiB
Java
176 lines
7.7 KiB
Java
|
|
package org.openautonomousconnection.oac2web.frontend;
|
||
|
|
|
||
|
|
import org.openautonomousconnection.oac2web.utils.Oac2WebApp;
|
||
|
|
import org.openautonomousconnection.oac2web.utils.RegistrarDao;
|
||
|
|
import org.openautonomousconnection.protocol.packets.v1_0_0.beta.web.WebResponsePacket;
|
||
|
|
import org.openautonomousconnection.protocol.side.web.ProtocolWebServer;
|
||
|
|
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.WebRequestMethod;
|
||
|
|
import org.openautonomousconnection.webserver.api.Route;
|
||
|
|
import org.openautonomousconnection.webserver.api.SessionContext;
|
||
|
|
import org.openautonomousconnection.webserver.api.WebPage;
|
||
|
|
import org.openautonomousconnection.webserver.api.WebPageContext;
|
||
|
|
import org.openautonomousconnection.webserver.utils.Html;
|
||
|
|
import org.openautonomousconnection.webserver.utils.RequestParams;
|
||
|
|
|
||
|
|
import java.util.HashMap;
|
||
|
|
import java.util.Map;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Dashboard page: lists owned infonames and allows modifications.
|
||
|
|
*
|
||
|
|
* Requires valid session.
|
||
|
|
*
|
||
|
|
* POST headers (action-based):
|
||
|
|
* - action=create_infoname, tln, infoname
|
||
|
|
* - action=delete_infoname, id
|
||
|
|
* - action=add_record, id (infoname_id), sub, type, value, ttl, priority, port, weight
|
||
|
|
*/
|
||
|
|
@Route(path = "ins/dashboard")
|
||
|
|
public final class dashboard implements WebPage {
|
||
|
|
|
||
|
|
@Override
|
||
|
|
public WebResponsePacket handle(WebPageContext ctx) throws Exception {
|
||
|
|
SessionContext session = SessionContext.from(ctx.client, (ProtocolWebServer) ctx.client.getServer(), ctx.request.getHeaders());
|
||
|
|
if (!session.isValid() || session.getUser() == null) {
|
||
|
|
return new WebResponsePacket(401, "text/plain", new HashMap<>(), Html.utf8("Authentication required (session)."));
|
||
|
|
}
|
||
|
|
|
||
|
|
int userId;
|
||
|
|
try {
|
||
|
|
userId = Integer.parseInt(session.getUser());
|
||
|
|
} catch (Exception e) {
|
||
|
|
return new WebResponsePacket(401, "text/plain", new HashMap<>(), Html.utf8("Invalid session user."));
|
||
|
|
}
|
||
|
|
|
||
|
|
String msg = null;
|
||
|
|
String err = null;
|
||
|
|
|
||
|
|
if (ctx.request.getMethod() == WebRequestMethod.POST) {
|
||
|
|
RequestParams p = new RequestParams(ctx.request);
|
||
|
|
String action = p.getOr("action", "").trim();
|
||
|
|
|
||
|
|
try {
|
||
|
|
Oac2WebApp app = Oac2WebApp.get();
|
||
|
|
RegistrarDao dao = app.dao();
|
||
|
|
|
||
|
|
if ("create_infoname".equalsIgnoreCase(action)) {
|
||
|
|
String tln = p.get("tln");
|
||
|
|
String info = p.get("infoname");
|
||
|
|
|
||
|
|
if (tln == null || tln.isBlank() || info == null || info.isBlank()) {
|
||
|
|
err = "Missing tln / infoname.";
|
||
|
|
} else {
|
||
|
|
Integer tlnId = dao.findTlnId(tln.trim()).orElse(null);
|
||
|
|
if (tlnId == null) {
|
||
|
|
err = "Unknown TLN: " + tln;
|
||
|
|
} else {
|
||
|
|
int newId = dao.createInfoName(tlnId, info.trim(), userId);
|
||
|
|
msg = "Created infoname id=" + newId + " (" + info + "." + tln + ")";
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} else if ("delete_infoname".equalsIgnoreCase(action)) {
|
||
|
|
int id = p.getInt("id", -1);
|
||
|
|
if (id <= 0) {
|
||
|
|
err = "Invalid id.";
|
||
|
|
} else if (!dao.isOwnerOfInfoName(id, userId)) {
|
||
|
|
err = "Not owner (edit/delete requires ownership).";
|
||
|
|
} else {
|
||
|
|
dao.deleteInfoName(id);
|
||
|
|
msg = "Deleted infoname id=" + id;
|
||
|
|
}
|
||
|
|
} else if ("add_record".equalsIgnoreCase(action)) {
|
||
|
|
int infonameId = p.getInt("id", -1);
|
||
|
|
if (infonameId <= 0) {
|
||
|
|
err = "Invalid infoname id.";
|
||
|
|
} else if (!dao.isOwnerOfInfoName(infonameId, userId)) {
|
||
|
|
err = "Not owner (edit/delete requires ownership).";
|
||
|
|
} else {
|
||
|
|
String sub = p.get("sub");
|
||
|
|
String type = p.getOr("type", "").trim().toUpperCase();
|
||
|
|
String value = p.get("value");
|
||
|
|
|
||
|
|
int ttl = p.getInt("ttl", 3600);
|
||
|
|
Integer priority = (p.get("priority") == null) ? null : p.getInt("priority", 0);
|
||
|
|
Integer port = (p.get("port") == null) ? null : p.getInt("port", 0);
|
||
|
|
Integer weight = (p.get("weight") == null) ? null : p.getInt("weight", 0);
|
||
|
|
|
||
|
|
if (type.isBlank() || value == null || value.isBlank()) {
|
||
|
|
err = "Missing type/value.";
|
||
|
|
} else {
|
||
|
|
Integer subId = dao.ensureSubname(infonameId, sub);
|
||
|
|
int rid = dao.addRecord(infonameId, subId, type, value.trim(), ttl, priority, port, weight);
|
||
|
|
msg = "Added record id=" + rid + " type=" + type;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} else if (!action.isBlank()) {
|
||
|
|
err = "Unknown action: " + action;
|
||
|
|
}
|
||
|
|
} catch (Exception e) {
|
||
|
|
err = "Action failed: " + e.getMessage();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return render(ctx, userId, msg, err);
|
||
|
|
}
|
||
|
|
|
||
|
|
private WebResponsePacket render(WebPageContext ctx, int userId, String msg, String err) throws Exception {
|
||
|
|
Oac2WebApp app = Oac2WebApp.get();
|
||
|
|
RegistrarDao.InfoNameRow[] owned = app.dao().listOwnedInfoNames(userId);
|
||
|
|
|
||
|
|
StringBuilder list = new StringBuilder();
|
||
|
|
if (owned.length == 0) {
|
||
|
|
list.append("<p class='muted'>No infonames yet.</p>");
|
||
|
|
} else {
|
||
|
|
list.append("<ul>");
|
||
|
|
for (RegistrarDao.InfoNameRow r : owned) {
|
||
|
|
list.append("<li>")
|
||
|
|
.append("<code>").append(Html.esc(r.info())).append(".").append(Html.esc(r.tln())).append("</code>")
|
||
|
|
.append(" (id=").append(r.id()).append(")")
|
||
|
|
.append("</li>");
|
||
|
|
}
|
||
|
|
list.append("</ul>");
|
||
|
|
}
|
||
|
|
|
||
|
|
String body = """
|
||
|
|
<div class="card">
|
||
|
|
<h2>Dashboard</h2>
|
||
|
|
<p class="muted">Owned by users.id = <code>%d</code></p>
|
||
|
|
%s
|
||
|
|
%s
|
||
|
|
|
||
|
|
<h3>Create InfoName</h3>
|
||
|
|
<p class="muted">POST headers: <code>action=create_infoname</code>, <code>tln</code>, <code>infoname</code></p>
|
||
|
|
|
||
|
|
<h3>Add Record</h3>
|
||
|
|
<p class="muted">POST headers: <code>action=add_record</code>, <code>id</code> (infoname id), optional <code>sub</code>, <code>type</code>, <code>value</code>, optional <code>ttl</code>, <code>priority</code>, <code>port</code>, <code>weight</code></p>
|
||
|
|
|
||
|
|
<h3>Delete InfoName</h3>
|
||
|
|
<p class="muted">POST headers: <code>action=delete_infoname</code>, <code>id</code></p>
|
||
|
|
|
||
|
|
<h3>Your InfoNames</h3>
|
||
|
|
%s
|
||
|
|
|
||
|
|
<div class="row">
|
||
|
|
<div class="col"><a href="/">Home</a></div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
""".formatted(
|
||
|
|
userId,
|
||
|
|
msg == null ? "" : "<p class='ok'>" + Html.esc(msg) + "</p>",
|
||
|
|
err == null ? "" : "<p class='err'>" + Html.esc(err) + "</p>",
|
||
|
|
list
|
||
|
|
);
|
||
|
|
|
||
|
|
String html = Html.page("Dashboard", body);
|
||
|
|
|
||
|
|
Map<String, String> headers = new HashMap<>();
|
||
|
|
// keep the same session header visible to client, if needed
|
||
|
|
if (ctx.request.getHeaders() != null) {
|
||
|
|
String sess = ctx.request.getHeaders().get("session");
|
||
|
|
if (sess != null) headers.put("session", sess);
|
||
|
|
}
|
||
|
|
|
||
|
|
return new WebResponsePacket(200, "text/html", headers, Html.utf8(html));
|
||
|
|
}
|
||
|
|
}
|