diff --git a/doc/user/matchHistory.md b/doc/user/matchHistory.md index 9293169..6145a8d 100644 --- a/doc/user/matchHistory.md +++ b/doc/user/matchHistory.md @@ -22,9 +22,9 @@ Input needed : ```json { "game": "" - "opponent": "", + "opponent": "", <= item only present if the match involved 2 players "myScore": , - "opponentScore": , + "opponentScore": , <= item only present if the match involved 2 players "date": } ``` @@ -36,7 +36,7 @@ Can return: "msg": "Match successfully saved to the blockchain" } ``` -- 400 with response (if no user is specified in header, or no opponent/p1Score/p2Score is specified in body, or opponent is the user specified in header, or a score is negative, or the game specified is invalid) +- 400 with response (if no user is specified in header, or no opponent/p1Score/p2Score is specified in body, or opponent is the user specified in header, or a score is negative, or the game specified is invalid, or the game should involve more players than was specified) ```json { "error": "" @@ -69,9 +69,9 @@ Can return: "score": { "p1": "", - "p2": "", + "p2": "", <= item only present if the match involved 2 players "p1Score": "", - "p2Score": "", + "p2Score": "", <= item only present if the match involved 2 players "date": }, "tx": "" diff --git a/src/api/TODO b/src/api/TODO deleted file mode 100644 index 0b8e16c..0000000 --- a/src/api/TODO +++ /dev/null @@ -1,21 +0,0 @@ -Todo : -- view friend's activity status -- add a privacy setting so not anybody can GET friends, match history, etc. (what are the RGPD requirements ?) ? -- test updated score storing (delays) - - - -User API : -POST /users/:userId/avatar + {image} (calls POST /images, stores returned imageId in DB at :userId) -GET /users/:userId/avatar -> {image} -DELETE /users/:userId/avatar (calls DELETE /images/:imageId, clears imageId in DB at :userId) -PATCH /users/:userId/avatar + {image} (emulates a DELETE /users/:userId/avatar and a POST /users/:userId/avatar) -> use uMember instead ? -- provide a random kanel image from Adam's website ? - -Image API : -- convert everything to webp (using @fastify/sharp) -- test size max - - - -Always update API docs diff --git a/src/api/scoreStore/default.js b/src/api/scoreStore/default.js index 954fcc8..c6b39ea 100644 --- a/src/api/scoreStore/default.js +++ b/src/api/scoreStore/default.js @@ -20,7 +20,7 @@ export default async function(fastify, options) { required: ['p1', 'p2', 'p1Score', 'p2Score'], properties: { p1: { type: 'string', minLength: 1 }, - p2: { type: 'string', minLength: 1 }, + p2: { type: 'string', minLength: 0 }, p1Score: { type: 'integer', minimum: 0 }, p2Score: { type: 'integer', minimum: 0 }, } diff --git a/src/api/user/dAvatar.js b/src/api/user/dAvatar.js index 822c786..56f9db4 100644 --- a/src/api/user/dAvatar.js +++ b/src/api/user/dAvatar.js @@ -1,6 +1,10 @@ -export async function dAvatar(request, reply, fastify, deleteAvatarId) { +export async function dAvatar(request, reply, fastify, getUserInfo, deleteAvatarId) { try { - ; + const userId = request.params.userId; + if (!getUserInfo.get(userId)) { + return reply.cose(404).send({ error: "User does not exist" }); + } + deleteAvatarId.run(userId); return reply.code(200).send({ msg: "Avatar deleted successfully" }); } catch (err) { fastify.log.error(err); diff --git a/src/api/user/default.js b/src/api/user/default.js index cef0c30..204e2c7 100644 --- a/src/api/user/default.js +++ b/src/api/user/default.js @@ -69,9 +69,9 @@ function prepareDB() { player1 TEXT, player2 TEXT, matchId INTEGER, - CHECK(player1 != player2), CHECK(game = 'pong' OR game = 'tetris'), - CHECK(date >= 0) + CHECK(date >= 0), + CHECK(player1 != player2) ) STRICT `); database.exec(` @@ -125,9 +125,8 @@ const deleteStatsTetris = database.prepare('UPDATE userData SET tetrisWins = 0, const deleteAvatarId = database.prepare('UPDATE userData SET avatarId = -1 WHERE username = ?;'); const querySchema = { type: 'object', required: ['iStart', 'iEnd'], properties: { iStart: { type: 'integer', minimum: 0 }, iEnd: { type: 'integer', minimum: 0 } } } -const bodySchema = { type: 'object', required: ['opponent', 'myScore', 'opponentScore'], properties: { opponent: { type: 'string' }, myScore: { type: 'integer', minimum: 0 }, opponentScore: { type: 'integer', minimum: 0 } } } const querySchemaMatchHistory = { type: 'object', required: ['game', 'iStart', 'iEnd'], properties: { game: { type: 'string' }, iStart: { type: 'integer', minimum: 0 }, iEnd: { type: 'integer', minimum: 0 } } } -const bodySchemaMatchHistory = { type: 'object', required: ['game', 'date', 'opponent', 'myScore', 'opponentScore'], properties: { game: { type: 'string' }, date: { type: 'integer', minimum: 0 }, opponent: { type: 'string' }, myScore: { type: 'integer', minimum: 0 }, opponentScore: { type: 'integer', minimum: 0 } } } +const bodySchemaMatchHistory = { type: 'object', required: ['game', 'date', 'myScore'], properties: { game: { type: 'string' }, date: { type: 'integer', minimum: 0 }, opponent: { type: 'string' }, myScore: { type: 'integer', minimum: 0 }, opponentScore: { type: 'integer', minimum: 0 } } } const querySchemaMatchHistoryGame = { type: 'object', required: ['game'], properties: { game: { type: 'string' } } } export default async function(fastify, options) { @@ -182,7 +181,7 @@ export default async function(fastify, options) { return gNumberMatches(request, reply, fastify, getUserInfo, getNumberMatches); }); fastify.get('/users/:userId/avatar', { preHandler: [fastify.authenticate] }, async (request, reply) => { - return gAvatar(request, reply, fastify, getAvatarId); + return gAvatar(request, reply, fastify, getUserInfo, getAvatarId); }); fastify.get('/ping/:userId', { preHandler: [fastify.authenticate] }, async (request, reply) => { return gPing(request, reply, fastify, getActivityTime); @@ -199,7 +198,7 @@ export default async function(fastify, options) { return pMatchHistory(request, reply, fastify, getUserInfo, addMatch, incWinsPong, incLossesPong, incWinsTetris, incLossesTetris); }); fastify.post('/users/:userId/avatar', { preHandler: [fastify.authenticate] }, async (request, reply) => { - return pAvatar(request, reply, fastify, setAvatarId); + return pAvatar(request, reply, fastify, getUserInfo, setAvatarId); }); fastify.post('/ping', { preHandler: [fastify.authenticate] }, async (request, reply) => { return pPing(request, reply, fastify, setActivityTime); @@ -227,6 +226,6 @@ export default async function(fastify, options) { return dMatchHistory(request, reply, fastify, getUserInfo, deleteMatchHistory, deleteStatsPong, deleteStatsTetris); }); fastify.delete('/users/:userId/avatar', { preHandler: [fastify.authenticate] }, async (request, reply) => { - return dAvatar(request, reply, fastify, deleteAvatarId); + return dAvatar(request, reply, fastify, getUserInfo, deleteAvatarId); }); } diff --git a/src/api/user/gAvatar.js b/src/api/user/gAvatar.js index 2323220..362aa2f 100644 --- a/src/api/user/gAvatar.js +++ b/src/api/user/gAvatar.js @@ -1,7 +1,27 @@ -export async function gAvatar(request, reply, fastify, getAvatarId) { +export async function gAvatar(request, reply, fastify, getUserInfo, getAvatarId) { try { - ; - return reply.code(200).send({ }); + const userId = request.params.userId; + if (!getUserInfo.get(userId)) { + return reply.code(404).send({ error: "User does not exist" }); + } + const imageId = 1;//getAvatarId.get(userId); + if (imageId === -1) { + ;// return random kanel image + } + const res = await fetch(`http://localhost:3004/images/${imageId}`, { method: "GET" }); + if (!res.ok) { + console.log("====================================\nAn error on the image API has occured"); + return reply.code(500).send({ error: "Internal server error" }); + } + for (const [key, value] of res.headers) { + reply.header(key, value); + } + if (res.body) { + reply.code(res.statusCode).send(res.body); + } else { + reply.code(res.statusCode).send(); + } + //return reply.code(200).type(res.header).send(res.body); } catch (err) { fastify.log.error(err); return reply.code(500).send({ error: "Internal server error" }); diff --git a/src/api/user/gMatchHistory.js b/src/api/user/gMatchHistory.js index 7531ca0..6999c9b 100644 --- a/src/api/user/gMatchHistory.js +++ b/src/api/user/gMatchHistory.js @@ -22,6 +22,10 @@ export async function gMatchHistory(request, reply, fastify, getUserInfo, getMat } const resJson = await res.json(); resJson.score.date = match.date; + if (resJson.score.p2 === "" && resJson.score.p2Score === 0) { + delete resJson.score.p2; + delete resJson.score.p2Score; + } return resJson; }); const matchHistory = await Promise.all(promises); diff --git a/src/api/user/pAvatar.js b/src/api/user/pAvatar.js index e7e9db6..71fd6ca 100644 --- a/src/api/user/pAvatar.js +++ b/src/api/user/pAvatar.js @@ -1,10 +1,16 @@ -export async function pAvatar(request, reply, fastify, setAvatarId) { +export async function pAvatar(request, reply, fastify, getUserInfo, setAvatarId) { try { -/* const res = await fetch('http://localhost:3004/images', { method: "POST", headers: { } }); + const userId = request.params.userId; + if (!getUserInfo.get(userId)) { + return reply.cose(404).send({ error: "User does not exist" }); + } + console.log("====================================\n", request.headers);//========== + const res = await fetch('http://localhost:3004/images', { method: "POST", headers: { "Content-Type": "image/webp" }, body: request.body ? JSON.stringify(request.body) : undefined }); if (!res.ok) { return reply.code(500).send({ error: "Internal server error" }); } - const data = await res.json();*/ + const data = await res.json(); + setAvatarId.run(data.imageId, userId); return reply.code(200).send({ msg: "Avatar uploaded successfully" }); } catch (err) { fastify.log.error(err); diff --git a/src/api/user/pMatchHistory.js b/src/api/user/pMatchHistory.js index f22ef38..584b53e 100644 --- a/src/api/user/pMatchHistory.js +++ b/src/api/user/pMatchHistory.js @@ -1,10 +1,16 @@ async function fetchSave(request, reply, userId, addMatch) { - const res = await fetch('http://localhost:3003/', { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ p1: userId, p2: request.body.opponent, p1Score: request.body.myScore, p2Score: request.body.opponentScore }) }); + let opponentName = ''; + let opponentScore = 0; + if (request.body.opponent && request.body.opponentScore) { + opponentName = request.body.opponent; + opponentScore = request.body.opponentScore; + } + const res = await fetch('http://localhost:3003/', { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ p1: userId, p2: opponentName, p1Score: request.body.myScore, p2Score: opponentScore }) }); if (!res.ok) { throw new Error('Internal server error'); } const data = await res.json(); - addMatch.run(request.body.game, request.body.date, userId, request.body.opponent, data.id); + addMatch.run(request.body.game, request.body.date, userId, opponentName, data.id); } export async function pMatchHistory(request, reply, fastify, getUserInfo, addMatch, incWinsPong, incLossesPong, incWinsTetris, incLossesTetris) { @@ -19,14 +25,19 @@ export async function pMatchHistory(request, reply, fastify, getUserInfo, addMat if (request.body.game !== 'pong' && request.body.game !== 'tetris') { return reply.code(400).send({ error: "Specified game does not exist" }); } + if (request.body.game === 'pong' && (!request.body.opponent || !request.body.opponentScore)) { + return reply.code(400).send({ error: "Game requires two players" }); + } if (!getUserInfo.get(userId)) { return reply.code(404).send({ error: "User does not exist" }); } - if (!getUserInfo.get(request.body.opponent)) { - return reply.code(404).send({ error: "Opponent does not exist" }); - } - if (request.body.opponent === userId) { - return reply.code(400).send({ error: "Do you have dementia ? You cannot have played a match against yourself gramps" }); + if (request.body.opponent) { + if (!getUserInfo.get(request.body.opponent)) { + return reply.code(404).send({ error: "Opponent does not exist" }); + } + if (request.body.opponent === userId) { + return reply.code(400).send({ error: "Do you have dementia ? You cannot have played a match against yourself gramps" }); + } } await fetchSave(request, reply, userId, addMatch); if (request.body.game === 'pong') { @@ -38,7 +49,7 @@ export async function pMatchHistory(request, reply, fastify, getUserInfo, addMat incLossesPong.run(userId); } } - else if (request.body.game === 'tetris') { + else if (request.body.game === 'tetris' && request.body.opponent && request.body.opponentScore) { if (request.body.myScore > request.body.opponentScore) { incWinsTetris.run(userId); incLossesTetris.run(request.body.opponent);