working on search

This commit is contained in:
2025-07-04 23:03:33 +02:00
parent c934e19837
commit b07533eaa9
6 changed files with 161 additions and 141 deletions

View File

@@ -55,11 +55,11 @@ public class LegacyApi extends BaseHandler {
allowOrigin(ex, "*"); // add CORS header
yield load(path,ex);
}
case LOGIN -> getLegacyLogin(ex);
case LOGIN -> getLogin(ex);
case LOGOUT-> logout(ex);
case SEARCH -> {
try {
yield legacySearch(ex);
yield search(ex);
} catch (UmbrellaException e){
yield send(ex,e);
}
@@ -68,54 +68,21 @@ public class LegacyApi extends BaseHandler {
};
}
private boolean legacySearch(HttpExchange ex) throws IOException, UmbrellaException {
var optToken = SessionToken.from(ex).map(Token::of);
if (optToken.isEmpty()) return sendEmptyResponse(HTTP_UNAUTHORIZED,ex);
var token = optToken.get();
var params = queryParam(ex);
var key = params.get(KEY) instanceof String s ? s : null;
if (key == null) throw new UmbrellaException(HTTP_BAD_REQUEST,"Missing search key");
var fulltext = key.contains("+") || "on".equals(params.get("fulltext"));
StringBuilder searchResult = new StringBuilder();
if (fulltext){
for (var module : config.keys()){
var baseUrl = config.get(module + ".baseUrl");
if (baseUrl.isEmpty()) continue;
var res = request(baseUrl.get()+"/search",token.asMap().plus(KEY,key),MIME_FORM_URL,token.asBearer());
if (!(res instanceof String content) || content.isBlank()) continue;
searchResult.append("<fieldset><label>").append(module).append("</label>");
searchResult.append(content).append("</fieldset>\n");
}
} else {
var bookmark = config.get("bookmark.baseUrl");
if (bookmark.isEmpty()) throw new UmbrellaException(500,"Tag search not available: Bookmark module not configured!");
var res = request(bookmark.get()+"/search",token.asMap().plus(KEY,key),MIME_FORM_URL,null);
if (!(res instanceof String content)) throw new UmbrellaException(500,"Search did not return html content!");
searchResult.append(content);
}
return sendContent(ex,searchResult.toString());
};
private boolean logout(HttpExchange ex) throws IOException {
var returnTo = queryParam(ex).get("returnTo");
var optToken = SessionToken.from(ex).map(Token::of);
if (optToken.isPresent()) try{
var token = optToken.get();
users.dropSession(token);
var expiredToken = new SessionToken(token.toString(),"/", Instant.now().minus(1, DAYS),true);
expiredToken.addTo(ex);
if (returnTo instanceof String location) return sendRedirect(ex,location);
return sendContent(ex, Map.of(REDIRECT,"home"));
} catch (UmbrellaException e) {
@Override
public boolean doPost(Path path, HttpExchange ex) throws IOException {
try {
return switch (path.pop()) {
case JSON -> jsonUser(ex);
case NOTIFY -> legacyNotify(ex);
case VALIDATE_TOKEN -> validateToken(ex);
default -> super.doPost(path,ex);
};
} catch (UmbrellaException e){
return send(ex,e);
}
if (returnTo instanceof String location) return sendRedirect(ex,location);
return sendContent(ex,Map.of(REDIRECT,"home"));
}
private boolean getLegacyLogin(HttpExchange ex) throws IOException {
private boolean getLogin(HttpExchange ex) throws IOException {
var returnTo = queryParam(ex).get("returnTo");
if (returnTo instanceof String url) {
var token = SessionToken.from(ex).map(SessionToken::sessionId)
@@ -131,59 +98,8 @@ public class LegacyApi extends BaseHandler {
return sendRedirect(ex,location);
}
@Override
public boolean doPost(Path path, HttpExchange ex) throws IOException {
try {
return switch (path.pop()) {
case JSON -> legacyJson(ex);
case NOTIFY -> legacyNotify(ex);
case VALIDATE_TOKEN -> validateToken(ex);
default -> super.doPost(path,ex);
};
} catch (UmbrellaException e){
return send(ex,e);
}
}
private static String stripTrailingSlash(Object o){
String url = o.toString();
if (url.endsWith("/")) return url.substring(0,url.length()-1);
return url;
}
private boolean validateToken(HttpExchange ex) throws UmbrellaException, IOException {
String body;
try {
body = body(ex);
} catch (Exception e){
throw new UmbrellaException(400,"Failed to read request body").causedBy(e);
}
var map = decode(body);
LOG.log(DEBUG,"validateToken(…, {0}), data: {1}",map);
String domain = stripTrailingSlash(map.get(DOMAIN) instanceof String s ? s : "");
var keys = config.keys();
var match = false;
for (var key : keys){
var baseUrl = config.get(key + ".baseUrl").map(LegacyApi::stripTrailingSlash).orElse(null);
if (domain.equals(baseUrl)){
match = true;
break;
}
}
if (!match) throw new UmbrellaException(500,"Failed to verify request domain!");
var o = map.get(TOKEN);
if (!(o instanceof String token)) throw new UmbrellaException(500,"Request did not contain token!");
var session = users.load(Token.of(token));
var user = users.load(session);
var userMap = user.toMap();
userMap.put(TOKEN,Map.of(TOKEN,token,EXPIRATION,session.expiration().getEpochSecond()));
return sendContent(ex,userMap);
}
private boolean legacyJson(HttpExchange ex) throws UmbrellaException, IOException {
Map<String, Object> data = null;
private boolean jsonUser(HttpExchange ex) throws UmbrellaException, IOException {
Map<String, Object> data = null;
try {
data = decode(body(ex));
} catch (IOException e) {
@@ -228,12 +144,6 @@ public class LegacyApi extends BaseHandler {
return sendContent(ex, userList.getFirst().toMap());
}
protected Session requestSession(Token token) throws UmbrellaException {
var session = users.load(token);
session = users.extend(session);
return session;
}
private boolean legacyNotify(HttpExchange ex) throws UmbrellaException, IOException {
if (messageUrl == null) throw new UmbrellaException(500,"missing configuration: umbrella.modules.message.baseUrl");
var mime = contentType(ex).orElse(null);
@@ -291,4 +201,94 @@ public class LegacyApi extends BaseHandler {
// TODO: should we return json?
return sendEmptyResponse(HTTP_OK,ex);
}
private boolean logout(HttpExchange ex) throws IOException {
var returnTo = queryParam(ex).get("returnTo");
var optToken = SessionToken.from(ex).map(Token::of);
if (optToken.isPresent()) try{
var token = optToken.get();
users.dropSession(token);
var expiredToken = new SessionToken(token.toString(),"/", Instant.now().minus(1, DAYS),true);
expiredToken.addTo(ex);
if (returnTo instanceof String location) return sendRedirect(ex,location);
return sendContent(ex, Map.of(REDIRECT,"home"));
} catch (UmbrellaException e) {
return send(ex,e);
}
if (returnTo instanceof String location) return sendRedirect(ex,location);
return sendContent(ex,Map.of(REDIRECT,"home"));
}
protected Session requestSession(Token token) throws UmbrellaException {
var session = users.load(token);
session = users.extend(session);
return session;
}
private boolean search(HttpExchange ex) throws IOException, UmbrellaException {
var optToken = SessionToken.from(ex).map(Token::of);
if (optToken.isEmpty()) return sendEmptyResponse(HTTP_UNAUTHORIZED,ex);
var token = optToken.get();
var params = queryParam(ex);
var key = params.get(KEY) instanceof String s ? s : null;
if (key == null) throw new UmbrellaException(HTTP_BAD_REQUEST,"Missing search key");
var fulltext = key.contains("+") || "on".equals(params.get("fulltext"));
StringBuilder searchResult = new StringBuilder();
if (fulltext){
for (var module : config.keys()){
var baseUrl = config.get(module + ".baseUrl");
if (baseUrl.isEmpty()) continue;
var res = request(baseUrl.get()+"/search",token.asMap().plus(KEY,key),MIME_FORM_URL,token.asBearer());
if (!(res instanceof String content) || content.isBlank()) continue;
searchResult.append("<fieldset><label>").append(module).append("</label>");
searchResult.append(content).append("</fieldset>\n");
}
} else {
var bookmark = config.get("bookmark.baseUrl");
if (bookmark.isEmpty()) throw new UmbrellaException(500,"Tag search not available: Bookmark module not configured!");
var res = request(bookmark.get()+"/search",token.asMap().plus(KEY,key),MIME_FORM_URL,null);
if (!(res instanceof String content)) throw new UmbrellaException(500,"Search did not return html content!");
searchResult.append(content);
}
addCors(ex);
return sendContent(ex,searchResult.toString());
};
private static String stripTrailingSlash(Object o){
String url = o.toString();
if (url.endsWith("/")) return url.substring(0,url.length()-1);
return url;
}
private boolean validateToken(HttpExchange ex) throws UmbrellaException, IOException {
String body;
try {
body = body(ex);
} catch (Exception e){
throw new UmbrellaException(400,"Failed to read request body").causedBy(e);
}
var map = decode(body);
LOG.log(DEBUG,"validateToken(…, {0}), data: {1}",map);
String domain = stripTrailingSlash(map.get(DOMAIN) instanceof String s ? s : "");
var keys = config.keys();
var match = false;
for (var key : keys){
var baseUrl = config.get(key + ".baseUrl").map(LegacyApi::stripTrailingSlash).orElse(null);
if (domain.equals(baseUrl)){
match = true;
break;
}
}
if (!match) throw new UmbrellaException(500,"Failed to verify request domain!");
var o = map.get(TOKEN);
if (!(o instanceof String token)) throw new UmbrellaException(500,"Request did not contain token!");
var session = users.load(Token.of(token));
var user = users.load(session);
var userMap = user.toMap();
userMap.put(TOKEN,Map.of(TOKEN,token,EXPIRATION,session.expiration().getEpochSecond()));
return sendContent(ex,userMap);
}
}