163 lines
4.5 KiB
Java
163 lines
4.5 KiB
Java
package net.mindoverflow.webmarker.webserver.controllers;
|
|
|
|
import com.auth0.jwt.JWT;
|
|
import com.auth0.jwt.JWTVerifier;
|
|
import com.auth0.jwt.algorithms.Algorithm;
|
|
import com.auth0.jwt.exceptions.JWTVerificationException;
|
|
import com.auth0.jwt.interfaces.Claim;
|
|
import com.auth0.jwt.interfaces.DecodedJWT;
|
|
import com.google.gson.JsonElement;
|
|
import com.google.gson.JsonObject;
|
|
import net.mindoverflow.webmarker.utils.FileUtils;
|
|
import net.mindoverflow.webmarker.utils.config.ConfigEntries;
|
|
import net.mindoverflow.webmarker.utils.security.SafetyCheck;
|
|
import net.mindoverflow.webmarker.utils.sql.MarkerSQLUtils;
|
|
import ro.pippo.controller.Controller;
|
|
import ro.pippo.controller.POST;
|
|
import ro.pippo.controller.Path;
|
|
import ro.pippo.core.route.RouteContext;
|
|
|
|
import java.net.MalformedURLException;
|
|
import java.net.URI;
|
|
import java.net.URISyntaxException;
|
|
import java.net.URL;
|
|
import java.util.UUID;
|
|
|
|
@Path("/api/v1/store")
|
|
public class StorageController extends Controller
|
|
{
|
|
|
|
private RouteContext routeContext;
|
|
|
|
@POST
|
|
public void store()
|
|
{
|
|
// Load RouteContext
|
|
routeContext = getRouteContext();
|
|
|
|
// Load JSON object from body
|
|
String body = routeContext.getRequest().getBody();
|
|
JsonObject jsonObject = FileUtils.stringToJson(body);
|
|
|
|
// Load JWT element
|
|
JsonElement jwtElement = getJwtFromJson(jsonObject);
|
|
if(jwtElement == null) return;
|
|
|
|
// Decrypt/Verify JWT
|
|
DecodedJWT jwt = decryptAndVerifyJwt(jwtElement);
|
|
if(jwt == null) return;
|
|
|
|
// Load username from JWT
|
|
String username = getFromJwt(jwt, "username");
|
|
if(username == null) return;
|
|
|
|
// Check some stuff about the user
|
|
if(!userCheckPassed(username)) return;
|
|
|
|
// Load UUID from username
|
|
UUID uuid = MarkerSQLUtils.getUserUUID(username);
|
|
if(uuid == null)
|
|
{
|
|
routeContext.send("Server error: missing UUID!");
|
|
return;
|
|
}
|
|
|
|
// Load url from Json body
|
|
String url = getFromJson(jsonObject, "url");
|
|
if(url == null) return;
|
|
|
|
// Verify url validity
|
|
URI confirmedUrl = verifyUrl(url);
|
|
if(confirmedUrl == null) return;
|
|
|
|
MarkerSQLUtils.addHistoryRecord(uuid, confirmedUrl.toString());
|
|
routeContext.send("OK!");
|
|
|
|
}
|
|
|
|
private JsonElement getJwtFromJson(JsonObject jsonObject)
|
|
{
|
|
JsonElement jwtElement = jsonObject.get("jwt");
|
|
if(jwtElement == null || jwtElement.isJsonNull())
|
|
{
|
|
routeContext.send("Invalid JWT!"); //todo: throw exception instead?
|
|
return null;
|
|
}
|
|
return jwtElement;
|
|
}
|
|
|
|
private DecodedJWT decryptAndVerifyJwt(JsonElement jwtElement)
|
|
{
|
|
String token = jwtElement.getAsString();
|
|
|
|
try {
|
|
Algorithm algorithm = Algorithm.HMAC256((String) ConfigEntries.JWT_SECRET.getValue());
|
|
JWTVerifier jwtVerifier = JWT.require(algorithm)
|
|
.build();
|
|
|
|
return jwtVerifier.verify(token);
|
|
}
|
|
catch (JWTVerificationException e)
|
|
{
|
|
routeContext.send("Invalid JWT!");
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private String getFromJwt(DecodedJWT jwt, String claimName)
|
|
{
|
|
Claim claim = jwt.getClaim(claimName);
|
|
if(claim == null || claim.isNull())
|
|
{
|
|
routeContext.send("JWT missing '" + claimName + "' claim!");
|
|
return null;
|
|
}
|
|
|
|
return claim.asString();
|
|
}
|
|
|
|
private boolean userCheckPassed(String username)
|
|
{
|
|
if(!SafetyCheck.isSafeUsername(username))
|
|
{
|
|
routeContext.send("Invalid username!");
|
|
return false;
|
|
}
|
|
|
|
if(!MarkerSQLUtils.userExists(username))
|
|
{
|
|
routeContext.send("User does not exist!");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private String getFromJson(JsonObject jsonObject, String name)
|
|
{
|
|
|
|
JsonElement jsonElement = jsonObject.get(name);
|
|
if(jsonElement == null || jsonElement.isJsonNull())
|
|
{
|
|
routeContext.send("JSON body missing '" + name + "' entry!");
|
|
return null;
|
|
}
|
|
|
|
return jsonElement.getAsString();
|
|
}
|
|
|
|
private URI verifyUrl(String url)
|
|
{
|
|
try {
|
|
return new URL(url).toURI();
|
|
} catch (URISyntaxException e) {
|
|
routeContext.send("Invalid URI!");
|
|
}
|
|
catch (MalformedURLException e) {
|
|
routeContext.send("Invalid URL!");
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|