Merge remote-tracking branch 'origin/getPuzzleResponse'
This commit is contained in:
commit
688ff3cedd
4 changed files with 183 additions and 70 deletions
|
@ -10,7 +10,6 @@ import java.util.regex.Pattern;
|
||||||
|
|
||||||
import javax.net.ssl.SSLServerSocket;
|
import javax.net.ssl.SSLServerSocket;
|
||||||
import javax.net.ssl.SSLServerSocketFactory;
|
import javax.net.ssl.SSLServerSocketFactory;
|
||||||
import javax.net.ssl.SSLSocket;
|
|
||||||
|
|
||||||
import org.jose4j.jwa.AlgorithmConstraints.ConstraintType;
|
import org.jose4j.jwa.AlgorithmConstraints.ConstraintType;
|
||||||
import org.jose4j.jwk.JsonWebKey;
|
import org.jose4j.jwk.JsonWebKey;
|
||||||
|
@ -31,6 +30,7 @@ import be.jeffcheasey88.peeratcode.routes.ChapterElement;
|
||||||
import be.jeffcheasey88.peeratcode.routes.ChapterList;
|
import be.jeffcheasey88.peeratcode.routes.ChapterList;
|
||||||
import be.jeffcheasey88.peeratcode.routes.Login;
|
import be.jeffcheasey88.peeratcode.routes.Login;
|
||||||
import be.jeffcheasey88.peeratcode.routes.PuzzleElement;
|
import be.jeffcheasey88.peeratcode.routes.PuzzleElement;
|
||||||
|
import be.jeffcheasey88.peeratcode.routes.PuzzleResponse;
|
||||||
import be.jeffcheasey88.peeratcode.routes.Register;
|
import be.jeffcheasey88.peeratcode.routes.Register;
|
||||||
import be.jeffcheasey88.peeratcode.routes.Result;
|
import be.jeffcheasey88.peeratcode.routes.Result;
|
||||||
import be.jeffcheasey88.peeratcode.webserver.Client;
|
import be.jeffcheasey88.peeratcode.webserver.Client;
|
||||||
|
@ -42,78 +42,10 @@ import be.jeffcheasey88.peeratcode.webserver.Router;
|
||||||
import be.jeffcheasey88.peeratcode.webserver.User;
|
import be.jeffcheasey88.peeratcode.webserver.User;
|
||||||
|
|
||||||
public class Main {
|
public class Main {
|
||||||
// Define SSL Protocol parameters
|
public static void main(String[] args) throws Exception {
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
Configuration config = new Configuration("config.txt");
|
Configuration config = new Configuration("config.txt");
|
||||||
config.load();
|
config.load();
|
||||||
|
|
||||||
/*try
|
|
||||||
{
|
|
||||||
JwtClaims claims = new JwtClaims();
|
|
||||||
claims.setIssuer("Issuer"); // who creates the token and signs it
|
|
||||||
claims.setAudience("Audience"); // to whom the token is intended to be sent
|
|
||||||
claims.setExpirationTimeMinutesInTheFuture(10); // time when the token will expire (10 minutes from now)
|
|
||||||
claims.setGeneratedJwtId(); // a unique identifier for the token
|
|
||||||
claims.setIssuedAtToNow(); // when the token was issued/created (now)
|
|
||||||
claims.setNotBeforeMinutesInThePast(2); // time before which the token is not yet valid (2 minutes ago)
|
|
||||||
|
|
||||||
claims.setClaim("username","USERNAME");
|
|
||||||
|
|
||||||
JsonWebSignature jws = new JsonWebSignature();
|
|
||||||
|
|
||||||
jws.setPayload(claims.toJson());
|
|
||||||
|
|
||||||
jws.setKey(rsaJsonWebKey.getPrivateKey());
|
|
||||||
|
|
||||||
jws.setKeyIdHeaderValue(rsaJsonWebKey.getKeyId());
|
|
||||||
|
|
||||||
jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
|
|
||||||
|
|
||||||
String jwt = jws.getCompactSerialization();
|
|
||||||
|
|
||||||
System.out.println("jwt token = " + jwt);
|
|
||||||
|
|
||||||
|
|
||||||
JwtConsumer jwtConsumer = new JwtConsumerBuilder()
|
|
||||||
.setRequireExpirationTime() // the JWT must have an expiration time
|
|
||||||
.setAllowedClockSkewInSeconds(30) // allow some leeway in validating time based claims to account for clock skew
|
|
||||||
.setRequireSubject() // the JWT must have a subject claim
|
|
||||||
.setExpectedIssuer("Issuer") // whom the JWT needs to have been issued by
|
|
||||||
.setExpectedAudience("Audience") // to whom the JWT is intended for
|
|
||||||
.setVerificationKey(rsaJsonWebKey.getKey()) // verify the signature with the public key
|
|
||||||
.setJwsAlgorithmConstraints( // only allow the expected signature algorithm(s) in the given context
|
|
||||||
ConstraintType.PERMIT, AlgorithmIdentifiers.RSA_USING_SHA256) // which is only RS256 here
|
|
||||||
.build(); // create the JwtConsumer instance
|
|
||||||
|
|
||||||
// Validate the JWT and process it to the Claims
|
|
||||||
JwtClaims jwtClaims = jwtConsumer.processToClaims(jwt);
|
|
||||||
System.out.println("JWT validation = " + jwtClaims);
|
|
||||||
}
|
|
||||||
catch (InvalidJwtException e)
|
|
||||||
{
|
|
||||||
// InvalidJwtException will be thrown, if the JWT failed processing or validation in anyway.
|
|
||||||
// Hopefully with meaningful explanations(s) about what went wrong.
|
|
||||||
System.out.println("Invalid JWT! " + e);
|
|
||||||
|
|
||||||
// Programmatic access to (some) specific reasons for JWT invalidity is also possible
|
|
||||||
// should you want different error handling behavior for certain conditions.
|
|
||||||
|
|
||||||
// Whether or not the JWT has expired being one common reason for invalidity
|
|
||||||
if (e.hasExpired())
|
|
||||||
{
|
|
||||||
System.out.println("JWT expired");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Or maybe the audience was invalid
|
|
||||||
if (e.hasErrorCode(ErrorCodes.AUDIENCE_INVALID))
|
|
||||||
{
|
|
||||||
System.out.println("JWT had wrong audience");
|
|
||||||
}
|
|
||||||
} catch (JoseException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}*/
|
|
||||||
|
|
||||||
|
|
||||||
Class.forName("com.mysql.cj.jdbc.Driver");
|
Class.forName("com.mysql.cj.jdbc.Driver");
|
||||||
|
|
||||||
Router router = new Router();
|
Router router = new Router();
|
||||||
|
@ -146,6 +78,7 @@ public class Main {
|
||||||
router.register(new Register(repo));
|
router.register(new Register(repo));
|
||||||
router.register(new Login(repo));
|
router.register(new Login(repo));
|
||||||
router.register(new Result(repo));
|
router.register(new Result(repo));
|
||||||
|
router.register(new PuzzleResponse(repo));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void startWebServer(Configuration config, Router router) throws IOException {
|
private static void startWebServer(Configuration config, Router router) throws IOException {
|
||||||
|
|
|
@ -24,6 +24,12 @@ public class DatabaseRepository {
|
||||||
private static final String REGISTER_QUERY = "INSERT INTO players (pseudo, email, passwd, firstname, lastname, description, sgroup, avatar) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
|
private static final String REGISTER_QUERY = "INSERT INTO players (pseudo, email, passwd, firstname, lastname, description, sgroup, avatar) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
|
||||||
private static final String CHECK_PASSWORD = "SELECT passwd FROM players WHERE pseudo=?";
|
private static final String CHECK_PASSWORD = "SELECT passwd FROM players WHERE pseudo=?";
|
||||||
private static final String SCORE = "SELECT score FROM completions WHERE fk_player = ? AND fk_puzzle = ?";
|
private static final String SCORE = "SELECT score FROM completions WHERE fk_player = ? AND fk_puzzle = ?";
|
||||||
|
private static final String GET_PUZZLE_SOLUTION = "SELECT soluce FROM puzzles WHERE id_puzzle=?";
|
||||||
|
private static final String GET_PUZZLE_SCORE_MAX = "SELECT score_max FROM puzzles WHERE id_puzzle=?";
|
||||||
|
private static final String GET_PLAYER_ID_BY_PSEUDO = "SELECT id_player FROM players WHERE pseudo=?";
|
||||||
|
private static final String GET_PUZZLE_NB_TRIES_AND_SCORE_BY_PLAYER = "SELECT tries, score FROM completions WHERE fk_puzzle = ? AND fk_player = ?";
|
||||||
|
private static final String INSERT_COMPLETION = "INSERT INTO completions (fk_puzzle, fk_player, tries, code, fileName, score) values (?, ?, ?, ?, ?, ?)";
|
||||||
|
private static final String UPDATE_COMPLETION = "UPDATE completions SET tries = ?, code = ?, filename = ?, score = ?";
|
||||||
|
|
||||||
private Connection con;
|
private Connection con;
|
||||||
private Configuration config;
|
private Configuration config;
|
||||||
|
@ -228,4 +234,91 @@ public class DatabaseRepository {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte[] getPuzzleSolution(int puzzleId) {
|
||||||
|
try {
|
||||||
|
PreparedStatement puzzleStmt = con.prepareStatement(GET_PUZZLE_SOLUTION);
|
||||||
|
puzzleStmt.setInt(1, puzzleId);
|
||||||
|
ResultSet result = puzzleStmt.executeQuery();
|
||||||
|
if (result.next()) {
|
||||||
|
return result.getBytes("soluce");
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int insertOrUpdatePuzzleResponse(int puzzleId, String pseudo, String fileName, byte[] code) {
|
||||||
|
try {
|
||||||
|
ensureConnection();
|
||||||
|
int[] triesAndScore = getPuzzleNbTriesAndScore(puzzleId, pseudo);
|
||||||
|
int playerId = getPlayerIdByPseudo(pseudo);
|
||||||
|
int puzzleScoreMax = getPuzzleScoreMax(puzzleId);
|
||||||
|
if (triesAndScore[0] < 0) {
|
||||||
|
// Insert completions
|
||||||
|
PreparedStatement statement = con.prepareStatement(INSERT_COMPLETION);
|
||||||
|
statement.setInt(1, puzzleId);
|
||||||
|
statement.setInt(2, playerId);
|
||||||
|
statement.setInt(3, 0);
|
||||||
|
statement.setBytes(4, code);
|
||||||
|
statement.setString(5, fileName);
|
||||||
|
statement.setInt(6, puzzleScoreMax);
|
||||||
|
return puzzleScoreMax;
|
||||||
|
} else {
|
||||||
|
// Update completions
|
||||||
|
int score = puzzleScoreMax * (((triesAndScore[0]-1)*10)/100);
|
||||||
|
PreparedStatement statement = con.prepareStatement(UPDATE_COMPLETION);
|
||||||
|
statement.setInt(1, triesAndScore[0]+1);
|
||||||
|
statement.setBytes(2, code);
|
||||||
|
statement.setString(3, fileName);
|
||||||
|
statement.setInt(4, score);
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
public int getPuzzleScoreMax(int puzzleId) {
|
||||||
|
try {
|
||||||
|
PreparedStatement puzzleStmt = con.prepareStatement(GET_PUZZLE_SCORE_MAX);
|
||||||
|
puzzleStmt.setInt(1, puzzleId);
|
||||||
|
ResultSet result = puzzleStmt.executeQuery();
|
||||||
|
if (result.next()) {
|
||||||
|
return result.getInt("score_max");
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
public int[] getPuzzleNbTriesAndScore(int puzzleId, String pseudo) {
|
||||||
|
try {
|
||||||
|
PreparedStatement puzzleStmt = con.prepareStatement(GET_PUZZLE_NB_TRIES_AND_SCORE_BY_PLAYER);
|
||||||
|
puzzleStmt.setInt(1, puzzleId);
|
||||||
|
ResultSet result = puzzleStmt.executeQuery();
|
||||||
|
int[] res = new int[2];
|
||||||
|
if (result.next()) {
|
||||||
|
res[0] = result.getInt("tries");
|
||||||
|
res[1] = result.getInt("score");
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
private int getPlayerIdByPseudo(String pseudo) {
|
||||||
|
try {
|
||||||
|
PreparedStatement puzzleStmt = con.prepareStatement(GET_PLAYER_ID_BY_PSEUDO);
|
||||||
|
puzzleStmt.setString(1, pseudo);
|
||||||
|
ResultSet result = puzzleStmt.executeQuery();
|
||||||
|
if (result.next()) {
|
||||||
|
return result.getInt("id_player");
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
79
src/be/jeffcheasey88/peeratcode/routes/PuzzleResponse.java
Normal file
79
src/be/jeffcheasey88/peeratcode/routes/PuzzleResponse.java
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
package be.jeffcheasey88.peeratcode.routes;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
|
import be.jeffcheasey88.peeratcode.repository.DatabaseRepository;
|
||||||
|
import be.jeffcheasey88.peeratcode.webserver.HttpReader;
|
||||||
|
import be.jeffcheasey88.peeratcode.webserver.HttpUtil;
|
||||||
|
import be.jeffcheasey88.peeratcode.webserver.HttpWriter;
|
||||||
|
import be.jeffcheasey88.peeratcode.webserver.Response;
|
||||||
|
|
||||||
|
public class PuzzleResponse implements Response {
|
||||||
|
private final DatabaseRepository databaseRepo;
|
||||||
|
|
||||||
|
public PuzzleResponse(DatabaseRepository databaseRepo) {
|
||||||
|
this.databaseRepo = databaseRepo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exec(Matcher matcher, HttpReader reader, HttpWriter writer) throws Exception {
|
||||||
|
HttpUtil.skipHeaders(reader);
|
||||||
|
|
||||||
|
int puzzleId = Integer.parseInt(matcher.group(1));
|
||||||
|
byte[] response;
|
||||||
|
byte[] fileName;
|
||||||
|
byte[] sourceCode;
|
||||||
|
|
||||||
|
// Response
|
||||||
|
int hSize = reader.readInt();
|
||||||
|
response = new byte[hSize];
|
||||||
|
if (hSize == reader.read(response)) {
|
||||||
|
// File Name
|
||||||
|
hSize = reader.readInt();
|
||||||
|
fileName = new byte[hSize];
|
||||||
|
if (hSize == reader.read(fileName)) {
|
||||||
|
// Source Code
|
||||||
|
hSize = reader.readInt();
|
||||||
|
sourceCode = new byte[hSize];
|
||||||
|
if (hSize == reader.read(sourceCode)) {
|
||||||
|
int score = databaseRepo.insertOrUpdatePuzzleResponse(puzzleId, "Pseudo", fileName.toString(), sourceCode);
|
||||||
|
if (Arrays.equals(response, databaseRepo.getPuzzleSolution(puzzleId))) {
|
||||||
|
HttpUtil.responseHeaders(writer, 200,
|
||||||
|
"Access-Control-Allow-Origin: *",
|
||||||
|
"Content-Type: application/json");
|
||||||
|
JSONObject responseJSON = new JSONObject();
|
||||||
|
responseJSON.put("id", puzzleId);
|
||||||
|
responseJSON.put("score", score);
|
||||||
|
writer.write(responseJSON.toJSONString());
|
||||||
|
writer.flush();
|
||||||
|
writer.close();
|
||||||
|
} else {
|
||||||
|
HttpUtil.responseHeaders(writer, 406, "Access-Control-Allow-Origin: *");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
HttpUtil.responseHeaders(writer, 400, "Access-Control-Allow-Origin: *");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
HttpUtil.responseHeaders(writer, 400, "Access-Control-Allow-Origin: *");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
HttpUtil.responseHeaders(writer, 403, "Access-Control-Allow-Origin: *");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Pattern getPattern() {
|
||||||
|
return Pattern.compile("^\\/puzzleResponse\\/([0-9]+)$");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return "POST";
|
||||||
|
}
|
||||||
|
}
|
|
@ -38,4 +38,12 @@ public class HttpReader {
|
||||||
return this.reader.ready();
|
return this.reader.ready();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int readInt() throws Exception{
|
||||||
|
int result = 0;
|
||||||
|
result+=this.in.read() << 24;
|
||||||
|
result+=this.in.read() << 16;
|
||||||
|
result+=this.in.read() << 8;
|
||||||
|
result+=this.in.read();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Add table
Reference in a new issue