Skip to content

Commit

Permalink
feat(database-rules): add rules and tests to support zIndex
Browse files Browse the repository at this point in the history
  • Loading branch information
albertodigioacchino committed Feb 4, 2021
1 parent 6f6e72d commit 76ec7b7
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 6 deletions.
5 changes: 4 additions & 1 deletion packages/database/database.rules.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
".read": "auth.uid !== null && root.child('games').child($gameId).exists() && root.child('connections').child($gameId).child(auth.uid).exists()",
"$cardId": {
".read": "auth.uid !== null && root.child('games').child($gameId).exists() && root.child('connections').child($gameId).child(auth.uid).exists()",
".write": "auth.uid !== null && root.child('games').child($gameId).exists() && root.child('connections').child($gameId).child(auth.uid).exists() && ((data.child('lockedBy').isString() && data.child('lockedBy').val() === auth.uid && newData.child('lockedBy').val() === null) || (data.child('lockedBy').val() === newData.child('lockedBy').val() && data.child('lockedBy').val() === auth.uid) || (data.child('lockedBy').val() === null && newData.child('lockedBy').val() === auth.uid) || (newData.child('estimation').exists() && newData.child('lockedBy').val() == null && newData.child('position').exists() && newData.child('parent').exists())) && (!newData.child('parent').exists() || newData.child('parent').val() == data.child('parent').val() || (newData.child('parent').val() != data.child('parent').val() && ((newData.child('parent').val() == 'board' && newData.child('position').child('x').isNumber() && newData.child('position').child('y').isNumber()) || (newData.child('parent').val() == 'panel' && !newData.child('position').exists()))))",
".write": "auth.uid !== null && root.child('games').child($gameId).exists() && root.child('connections').child($gameId).child(auth.uid).exists() && ((data.child('lockedBy').isString() && data.child('lockedBy').val() === auth.uid && newData.child('lockedBy').val() === null) || (data.child('lockedBy').val() === newData.child('lockedBy').val() && data.child('lockedBy').val() === auth.uid) || (data.child('lockedBy').val() === null && newData.child('lockedBy').val() === auth.uid) || (newData.child('estimation').exists() && newData.child('lockedBy').val() == null && newData.child('position').exists() && newData.child('parent').exists())) && (!newData.child('parent').exists() || newData.child('parent').val() == data.child('parent').val() || (newData.child('parent').val() != data.child('parent').val() && ((newData.child('parent').val() == 'board' && newData.child('position').child('x').isNumber() && newData.child('position').child('y').isNumber() && newData.child('zIndex').isNumber()) || (newData.child('parent').val() == 'panel' && !newData.child('position').exists() && !newData.child('zIndex').exists()))))",
"lockedBy": {
".validate": "(data.isString() && data.val() === auth.uid && newData.val() === null) || (data.val() === null && newData.val() === auth.uid)"
},
Expand All @@ -43,6 +43,9 @@
".validate": "!newData.exists() || (newData.isNumber() && newData.val() >= 0 && newData.val() <= root.child('games').child($gameId).child('boardDimensions').child('y').val())"
}
},
"zIndex": {
".validate": "!newData.exists() || newData.val() >= -1000"
},
"$other": { ".validate": false }
}
}
Expand Down
95 changes: 90 additions & 5 deletions packages/database/test/write-cards.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ describe("Cards write", () => {
}));
});

it("should allow card write if authenticated, game exists, connected and with parent == board, specifying valid card position but with uncorrect lockedBy", async () => {
it("should not allow card write if authenticated, game exists, connected and with parent == board, specifying valid card position but with uncorrect lockedBy", async () => {
const userUID = 'id1';
const email = 'test@email.com';
await createGame(GAME_ID, adminDatabase);
Expand All @@ -163,7 +163,7 @@ describe("Cards write", () => {
}));
});

it("should allow card write if authenticated, game exists, connected and with parent == board and specifying valid card position and with correct lockedBy", async () => {
it("should allow card write if authenticated, game exists, connected and with parent == board and specifying valid card position and with correct lockedBy and zIndex", async () => {
const userUID = 'id1';
const email = 'test@email.com';
await createGame(GAME_ID, adminDatabase);
Expand All @@ -175,7 +175,25 @@ describe("Cards write", () => {
x: 0,
y: 0
},
lockedBy: userUID
lockedBy: userUID,
zIndex: 0,
}));
});

it("should allow card write if authenticated, game exists, connected and with parent == board and specifying valid card position, with correct lockedBy and valid zIndex", async () => {
const userUID = 'id1';
const email = 'test@email.com';
await createGame(GAME_ID, adminDatabase);
await createConnection(GAME_ID, userUID, adminDatabase);
const db = getAuthedDatabase(PROJECT_ID, {uid: userUID, email, email_verified: true});
await firebase.assertSucceeds(db.ref(`/${RTDBPaths.Cards}/${GAME_ID}/${CARD_ID}`).update({
parent: 'board',
position: {
x: 0,
y: 0
},
lockedBy: userUID,
zIndex: 50
}));
});

Expand Down Expand Up @@ -209,6 +227,34 @@ describe("Cards write", () => {
}));
});

it("should not allow card write if authenticated, game exists, connected and with parent == panel and specifying valid card zIndex", async () => {
const userUID = 'id1';
const email = 'test@email.com';
await createGame(GAME_ID, adminDatabase);
await createConnection(GAME_ID, userUID, adminDatabase);
const db = getAuthedDatabase(PROJECT_ID, {uid: userUID, email, email_verified: true});
await firebase.assertFails(db.ref(`/${RTDBPaths.Cards}/${GAME_ID}/${CARD_ID}`).update({
parent: 'panel',
zIndex: 0
}));
});

it("should not allow card write if authenticated, game exists, connected and with parent == panel and specifying valid card position and zIndex", async () => {
const userUID = 'id1';
const email = 'test@email.com';
await createGame(GAME_ID, adminDatabase);
await createConnection(GAME_ID, userUID, adminDatabase);
const db = getAuthedDatabase(PROJECT_ID, {uid: userUID, email, email_verified: true});
await firebase.assertFails(db.ref(`/${RTDBPaths.Cards}/${GAME_ID}/${CARD_ID}`).update({
parent: 'panel',
position: {
x: 0,
y: 0,
},
zIndex: 0
}));
});

it("should allow card write if authenticated, game exists, connected and with parent == panel and specifying null card position and valid lockedBy", async () => {
const userUID = 'id1';
const email = 'test@email.com';
Expand Down Expand Up @@ -342,7 +388,7 @@ describe("Cards write", () => {
}));
});

it("should update card position if authenticated, game exists, connected and the card was locked by me", async () => {
it("should update card position if authenticated, game exists, connected and the card was locked by me and valid zIndex", async () => {
const userUID = 'id1';
const email = 'test@email.com';
await createGame(GAME_ID, adminDatabase);
Expand All @@ -356,7 +402,46 @@ describe("Cards write", () => {
x: 0,
y: 0
},
parent: 'board'
parent: 'board',
zIndex: 0,
}));
});

it("should update card position and zIndex if authenticated, game exists, connected and the card was locked by me", async () => {
const userUID = 'id1';
const email = 'test@email.com';
await createGame(GAME_ID, adminDatabase);
await createConnection(GAME_ID, userUID, adminDatabase);
await adminDatabase.ref(`/${RTDBPaths.Cards}/${GAME_ID}/${CARD_ID}`).set({
lockedBy: userUID
});
const db = getAuthedDatabase(PROJECT_ID, {uid: userUID, email, email_verified: true});
await firebase.assertSucceeds(db.ref(`/${RTDBPaths.Cards}/${GAME_ID}/${CARD_ID}`).update({
position: {
x: 0,
y: 0
},
parent: 'board',
zIndex: 0
}));
});

it("should not update card position if authenticated, game exists, connected and the card was locked by me but wrong zIndex", async () => {
const userUID = 'id1';
const email = 'test@email.com';
await createGame(GAME_ID, adminDatabase);
await createConnection(GAME_ID, userUID, adminDatabase);
await adminDatabase.ref(`/${RTDBPaths.Cards}/${GAME_ID}/${CARD_ID}`).set({
lockedBy: userUID
});
const db = getAuthedDatabase(PROJECT_ID, {uid: userUID, email, email_verified: true});
await firebase.assertFails(db.ref(`/${RTDBPaths.Cards}/${GAME_ID}/${CARD_ID}`).update({
position: {
x: 0,
y: 0
},
parent: 'board',
zIndex: -1001
}));
});

Expand Down

0 comments on commit 76ec7b7

Please sign in to comment.