Skip to content

Commit bc64589

Browse files
committed
Add AddBone route and handler for bone registration; implement validation and database storage
1 parent 64a5409 commit bc64589

8 files changed

Lines changed: 124 additions & 178 deletions

File tree

src/main/java/io/nodelink/server/app/cluster/ClusterStarter.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import io.nodelink.server.NodeLink;
66
import io.nodelink.server.app.infra.CONSTANT;
77
import io.nodelink.server.app.infra.RouteHandler;
8-
import io.nodelink.server.app.infra.handler.SyncH;
98
import org.slf4j.LoggerFactory;
109
import ch.qos.logback.classic.Level;
1110
import ch.qos.logback.classic.LoggerContext;
@@ -38,11 +37,6 @@ public void startServer() {
3837
RouteHandler.registerAllRoutes(app, "io.nodelink.server.app.cluster.api.routes");
3938

4039
NodeLink.getInstance().getLogger().SUCCESS("Cluster API Server started");
41-
42-
SyncH syncHandler = new SyncH();
43-
44-
app.get("/api/v1/sync", syncHandler::handle);
45-
app.post("/api/v1/sync", syncHandler::handle);
4640
})
4741
.subscribeOn(Schedulers.boundedElastic())
4842
.subscribe();

src/main/java/io/nodelink/server/app/infra/DatabaseService.java

Lines changed: 0 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@
44
import com.fasterxml.jackson.databind.ObjectMapper;
55

66
import java.sql.*;
7-
import java.util.ArrayList;
8-
import java.util.List;
9-
import java.util.Map;
107

118
public class DatabaseService {
129
private static final String URL = "jdbc:sqlite:nodelink_storage.db";
@@ -18,66 +15,9 @@ public class DatabaseService {
1815
// Tables existantes
1916
stmt.execute("CREATE TABLE IF NOT EXISTS ClusterTable (id TEXT PRIMARY KEY, content TEXT, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP);");
2017
stmt.execute("CREATE TABLE IF NOT EXISTS BoneTable (id TEXT PRIMARY KEY, content TEXT, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP);");
21-
22-
// NOUVELLE TABLE : PeerTable pour stocker les URLs distantes
23-
stmt.execute("CREATE TABLE IF NOT EXISTS PeerTable (url TEXT PRIMARY KEY, type TEXT, added_at DATETIME DEFAULT CURRENT_TIMESTAMP);");
24-
25-
stmt.execute("CREATE TRIGGER IF NOT EXISTS tr_update_cluster_time AFTER UPDATE ON ClusterTable BEGIN UPDATE ClusterTable SET updated_at = CURRENT_TIMESTAMP WHERE id = old.id; END;");
26-
} catch (SQLException e) {
27-
e.printStackTrace();
28-
}
29-
}
30-
31-
// Méthode pour ajouter un Peer (Bone ou Cluster distant)
32-
public static void addPeer(String url, String type) throws SQLException {
33-
String sql = "INSERT OR REPLACE INTO PeerTable(url, type) VALUES(?, ?)";
34-
try (Connection conn = DriverManager.getConnection(URL);
35-
PreparedStatement pstmt = conn.prepareStatement(sql)) {
36-
pstmt.setString(1, url);
37-
pstmt.setString(2, type);
38-
pstmt.executeUpdate();
39-
}
40-
}
41-
42-
// Récupère toutes les URLs à synchroniser
43-
public static List<String> getAllPeerUrls() {
44-
List<String> urls = new ArrayList<>();
45-
String sql = "SELECT url FROM PeerTable";
46-
try (Connection conn = DriverManager.getConnection(URL);
47-
Statement stmt = conn.createStatement();
48-
ResultSet rs = stmt.executeQuery(sql)) {
49-
while (rs.next()) {
50-
urls.add(rs.getString("url"));
51-
}
5218
} catch (SQLException e) {
5319
e.printStackTrace();
5420
}
55-
return urls;
56-
}
57-
58-
public static Map<String, String> getAllPeersWithType() {
59-
Map<String, String> peers = new java.util.HashMap<>();
60-
String sql = "SELECT url, type FROM PeerTable";
61-
try (Connection conn = DriverManager.getConnection(URL);
62-
Statement stmt = conn.createStatement();
63-
ResultSet rs = stmt.executeQuery(sql)) {
64-
while (rs.next()) {
65-
peers.put(rs.getString("url"), rs.getString("type"));
66-
}
67-
} catch (SQLException e) {
68-
e.printStackTrace();
69-
}
70-
return peers;
71-
}
72-
73-
public static boolean removePeer(String url) throws SQLException {
74-
String sql = "DELETE FROM PeerTable WHERE url = ?";
75-
try (Connection conn = DriverManager.getConnection(URL);
76-
PreparedStatement pstmt = conn.prepareStatement(sql)) {
77-
pstmt.setString(1, url);
78-
int affectedRows = pstmt.executeUpdate();
79-
return affectedRows > 0;
80-
}
8121
}
8222

8323
public static void save(String table, String id, String content, String timestamp, boolean fromSync) throws SQLException {
@@ -119,53 +59,6 @@ private static String injectTimestamp(String json, String ts) {
11959
}
12060
}
12161

122-
public static Map<String, String> getAllRows(String table) {
123-
// Sécurité : on vérifie que la table demandée est autorisée
124-
if (!table.equals("BoneTable") && !table.equals("ClusterTable")) {
125-
return new java.util.HashMap<>();
126-
}
127-
128-
Map<String, String> rows = new java.util.HashMap<>();
129-
String sql = "SELECT id, content FROM " + table;
130-
131-
try (Connection conn = DriverManager.getConnection(URL);
132-
Statement stmt = conn.createStatement();
133-
ResultSet rs = stmt.executeQuery(sql)) {
134-
135-
while (rs.next()) {
136-
rows.put(rs.getString("id"), rs.getString("content"));
137-
}
138-
} catch (SQLException e) {
139-
System.err.println("Erreur lors de la récupération des données : " + e.getMessage());
140-
}
141-
return rows;
142-
}
143-
144-
public static boolean deleteRow(String table, String id) {
145-
// Sécurité : on vérifie que la table est autorisée pour éviter l'injection SQL
146-
if (!table.equals("BoneTable") && !table.equals("ClusterTable") && !table.equals("PeerTable")) {
147-
return false;
148-
}
149-
150-
String sql = "DELETE FROM " + table + " WHERE id = ?";
151-
// Note : Pour PeerTable, le champ est 'url', adaptons la requête si c'est cette table
152-
if (table.equals("PeerTable")) {
153-
sql = "DELETE FROM PeerTable WHERE url = ?";
154-
}
155-
156-
try (Connection conn = DriverManager.getConnection(URL);
157-
PreparedStatement pstmt = conn.prepareStatement(sql)) {
158-
159-
pstmt.setString(1, id);
160-
int affectedRows = pstmt.executeUpdate();
161-
return affectedRows > 0; // Retourne vrai si une ligne a bien été supprimée
162-
163-
} catch (SQLException e) {
164-
System.err.println("Erreur SQL lors de la suppression (" + table + ") : " + e.getMessage());
165-
return false;
166-
}
167-
}
168-
16962
public static String getTimestamp(String table, String id) {
17063
// On valide le nom de la table pour éviter des injections SQL
17164
if (!table.equals("BoneTable") && !table.equals("ClusterTable")) {

src/main/java/io/nodelink/server/app/node/NodeStarter.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import io.nodelink.server.NodeLink;
66
import io.nodelink.server.app.infra.CONSTANT;
77
import io.nodelink.server.app.infra.RouteHandler;
8-
import io.nodelink.server.app.infra.handler.SyncH;
98
import org.slf4j.LoggerFactory;
109
import ch.qos.logback.classic.Level;
1110
import ch.qos.logback.classic.LoggerContext;
@@ -38,11 +37,6 @@ public void startServer() {
3837
RouteHandler.registerAllRoutes(app, "io.nodelink.server.app.node.api.routes");
3938

4039
NodeLink.getInstance().getLogger().SUCCESS("Node API Server started");
41-
42-
SyncH syncHandler = new SyncH();
43-
44-
app.get("/api/v1/sync", syncHandler::handle);
45-
app.post("/api/v1/sync", syncHandler::handle);
4640
})
4741
.subscribeOn(Schedulers.boundedElastic())
4842
.subscribe();
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package io.nodelink.server.app.node.api.routes.v1.definition;
2+
3+
import io.javalin.http.Context;
4+
import io.javalin.http.HandlerType;
5+
import io.nodelink.server.app.infra.RouteDefinition;
6+
import io.nodelink.server.app.node.api.routes.v1.handler.AddBoneH;
7+
8+
public class AddBone implements RouteDefinition {
9+
10+
@Override
11+
public HandlerType method() {
12+
return HandlerType.POST;
13+
}
14+
15+
@Override
16+
public String path() {
17+
return "/addBone";
18+
}
19+
20+
@Override
21+
public boolean enabled() {
22+
return true;
23+
}
24+
25+
@Override
26+
public void handle(Context ctx) throws Exception {
27+
new AddBoneH().handle(ctx);
28+
}
29+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package io.nodelink.server.app.node.api.routes.v1.handler;
2+
3+
import com.fasterxml.jackson.core.JsonProcessingException;
4+
import com.fasterxml.jackson.databind.JsonNode;
5+
import com.fasterxml.jackson.databind.ObjectMapper;
6+
import com.fasterxml.jackson.databind.node.ObjectNode;
7+
import io.javalin.http.Context;
8+
import io.nodelink.server.app.data.BONE_LOCATION;
9+
import io.nodelink.server.app.infra.ApiHandler;
10+
import io.nodelink.server.app.infra.DatabaseService;
11+
12+
public class AddBoneH implements ApiHandler {
13+
private final ObjectMapper objectMapper = new ObjectMapper();
14+
15+
@Override
16+
public void handle(Context ctx) throws JsonProcessingException {
17+
JsonNode requestBody = objectMapper.readTree(ctx.body());
18+
19+
// Check if in the request body we have "location" and "boneType"
20+
if (requestBody == null || !requestBody.has("boneType")) {
21+
ctx.status(400).result("Invalid request body. 'boneType' are required.");
22+
}
23+
24+
// Then i generate an ID
25+
int range = (1 - 9999) + 1;
26+
int id = (int) (Math.random() * range) + 9999;
27+
String boneId = "B" + id;
28+
29+
// I will put data in variables
30+
// Assert not null for requestBody
31+
assert requestBody != null;
32+
33+
String boneType = requestBody.get("boneType").asText();
34+
35+
// Check SQLite
36+
if (DatabaseService.getTimestamp("BoneTable", boneId) != null) {
37+
ctx.status(409).result("Erreur : Le Bone " + boneId + " existe déjà.");
38+
}
39+
40+
// Check if location is valid
41+
BONE_LOCATION boneType_Enum;
42+
try {
43+
boneType_Enum = BONE_LOCATION.valueOf(boneType.toUpperCase());
44+
} catch (IllegalArgumentException e) {
45+
ctx.status(400).result("Erreur : Location '" + boneType + "' inconnue.");
46+
e.getStackTrace();
47+
return;
48+
}
49+
50+
String boneLocation = boneType_Enum.getLocation();
51+
String finalUrl = String.format("https://%s.%s.nodelinkapp.xyz", boneId, boneLocation);
52+
53+
// Response JSON
54+
ObjectNode boneData = objectMapper.createObjectNode();
55+
boneData.put("id", id);
56+
boneData.put("boneId", boneId);
57+
boneData.put("boneType", boneType);
58+
boneData.put("url", finalUrl);
59+
60+
boneData.putArray("coords")
61+
.add(boneType_Enum.getLatitude())
62+
.add(boneType_Enum.getLongitude());
63+
64+
// Save to Database
65+
try {
66+
DatabaseService.saveBone(boneId, boneData.toString());
67+
68+
System.out.println("[DB] Bone " + boneId + " saved to database.");
69+
ctx.status(201).json(boneData);
70+
71+
} catch (Exception e) {
72+
e.printStackTrace();
73+
ctx.status(500).result("Error : " + e.getMessage());
74+
}
75+
}
76+
}

0 commit comments

Comments
 (0)