does root node rule cascase to child and its subchild in firebase? - firebase-security

In the docs its told that rules cascade and children can't revoke the privileges but later in chat example root read and write rules are default to false,so why it doesn't cascade?
Doc link

Good question.
When we say that rules cascade, read it as permissions cases. Once you have permission to read a node, you cannot take that permission away at a lower level.
So you can start with ".read": false at the top-level and then allow reads lower (snippet from the Firebase documentation on security rules):
{
"rules": {
".read": false,
"room_names": {
// the room names can be enumerated and read
// they cannot be modified since no write rule
// explicitly allows this
".read": true,
But the opposite does not work. You cannot say that nobody is allowed to see a specific room name once you've said that every can see all room names:
// THIS SNIPPET WILL NOT WORK
{
"rules": {
".read": false,
"room_names": {
// the room names can be enumerated and read
// they cannot be modified since no write rule
// explicitly allows this
".read": true,
"my_secret_room": {
// THIS WILL NOT WORK
// since we've said that every can read all room names
// we cannot take that permission away anymore
".read": false
}

Related

Is there precedence for object oriented syntax for a relative path?

I'm creating my own extended version of JSON for various reasons. One thing that I'm adding is the ability to self reference and I'm trying to come up with an OO syntax for relative paths.
To illustrate, lets say I have a nested object that is supposed to reference its parent object
{ my_item: { parent: ??? } }
??? symbolizes the missing syntax.
Now in most operating systems, going up one level is notated as .. so we could try doing the same
{ my_item: { parent: .. } }
Looks pretty neat, however, if I tried to reference anything else in the parent, I'd end up with
{ my_item_sibling: {}, my_item: { sibling_of_parent: ...my_item_sibling } }
Which is not as neat as its the same as spread syntax ... which I'm also adding
I could do something with parentheses, like so
{ my_item_sibling: {}, my_item: { sibling_of_parent: (..).my_item_sibling } }
Which is not terrible but I'd prefer something cleaner.
Maybe I'll reserve a symbol?
{ my_item_sibling: {}, my_item: { sibling_of_parent: #.my_item_sibling } }
In any case, these examples are just to illustrate what I'm doing. If there is an established or a particularly nice looking way to do it, I'll just copy that.
The question is: Is there a precedence to this? A relative path implemented in a c-like language?

Unable to login with a specific user in FaunaDB

It always worked before, but it is no longer working.
I have a rate limiting logic, but even if I clear all rate limiting data, it still happens. Only with a specific user.
I created another account on FaunaDB for testing purposes and a new database. If I restore the old database data to that new database, everything works!
So I recreated the entire database on the old FaunaDB account and the problem persists.
Is anyone experiencing something similar?
Is there any information in cache?
Login(Match(Index("accounts_by_email"), "email#email.com"), {
password: "secret",
})
/* returns
Error: [
{
"position": [],
"code": "authentication failed",
"description": "The document was not found or provided password was incorrect."
}
]
*/
The password is not incorrect. It works on the other FaunaDB account with the data restored.
./fdm -source path=backup -dest key={admin_key}
Yes, that was a temporary problem. I experienced it was well at a certain moment in my own Fwitter example. Our uniqueness detection didn't play well with code that created/updated/deleted things in one complex FQL flow which the code is doing :). I ticketed that and it should be fixed in the meantime.
It's good to know that the rate limiting in there was a bit me experimenting with events. It can also be written much simpler, I guess I was a bit to deep zoned and to be fair.. I just joined FaunaDB back then. I'm working on a skeleton app that will contain that simpler version. In the meantime here is the code:
Simpler rate limiting
import { rateLimiting } from '../../fauna-queries/helpers/errors'
import faunadb from 'faunadb'
/*
* Ideally we limit the amount of calls that come to Login.
*/
const q = faunadb.query
const {
If,
Epoch,
Match,
Index,
Collection,
Let,
Var,
Paginate,
Select,
TimeDiff,
Or,
GTE,
Abort,
Create,
IsEmpty,
Count,
LT,
Do,
Now,
Subtract
} = q
function AddRateLimiting(action, FqlQueryToExecute, Identifier, calls, perMilliseconds) {
const ExecuteAndCreateLog = Do(
Create(Collection('logs'), {
data: {
action: action,
identity: Identifier
}
}),
FqlQueryToExecute
)
return Let(
{
logsPage: Paginate(Match(Index('logs_by_action_and_identity_ordered_by_ts'), action, Identifier), {
size: calls
})
},
If(
Or(IsEmpty(Var('logsPage')), LT(Count(Select(['data'], Var('logsPage'))), calls)),
// If no logs exist yet, create one.
ExecuteAndCreateLog,
Let(
{
// the page looks like { data: [timestamp1, timestamp2,...]},
// we will retrieve the last timestamp of that page. If the pagesize would be 3, it would be the oldest of these 3 events.
// since the index is ordered from new to old.
timestamp: Select(['data', Subtract(calls, 1)], Var('logsPage')),
// transform the Fauna timestamp to a Time object
time: Epoch(Var('timestamp'), 'microseconds'),
// How long ago was that event in ms
ageInMs: TimeDiff(Var('time'), Now(), 'milliseconds')
},
If(
GTE(Var('ageInMs'), perMilliseconds),
// Then great we execute
ExecuteAndCreateLog,
// Else.. Abort! Rate-limiting in action
Abort(rateLimiting)
)
)
)
)
}
Blocking after faulty logins
I also separated blocking three faulty logins since I was kinda abusing that rate-limiting system for it. A few undefines in this code of course, it's just meant to give you an idea of how it looks for more info, keep an eye out for the skeletons + blogs to come out.
// Let's wrap some other functionality around the login.
const BlockThreeFaultyLogins = Do(
If(
GTE(Count(Match(Index('logs_by_action_and_identity'), 'faulty_login', email)), MAX_LOGIN_ATTEMPTS),
// Abort if exceeded
Abort(tooManyFaultyLogins),
// Else, just continue as usual!
Let(
{
login: LoginFQL
},
Do(
If(
Equals(false, Var('login')),
// if the login is faulty, we'll add a log entry
Create(Collection('logs'), {
data: {
action: 'faulty_login',
identity: email
}
}),
// Else, we will clean up the faulty_login logs
q.Map(
Paginate(Match(Index('logs_by_action_and_identity'), 'faulty_login', email)),
Lambda(['logRef'], Delete(Var('logRef')))
)
),
Var('login')
)
)
)
)

vue.nextTick false positive

context:
const Constructor = Vue.extend(MyComponent);
function createComponent() {
vm = new Constructor({
props,
}).$mount();
return vm;
}
Question:
While on tests, I find
vm.$nextTick().then(() => {
expect(result).to.equal(expectedResult);
})
and
vm.$nextTick().then(() => {
expect(result).to.not.equal(expectedResult);
})
both passing.
How to get rid of this situation ? Would aync await in someway make sure the truth only passes ?
First: Just because you can negate any assertion with .not doesn’t mean you should. With great power comes great responsibility. It’s often best to assert that the one expected output was produced, rather than asserting that one of countless unexpected outputs wasn’t produced.
Equal asserts that the target is strictly (===) equal to the given val.
expect(2).to.equal(2); // Recommended
expect(2).to.not.equal(1); // Not recommended
Ok, now, in your case you may want to add .deep earlier in the chain to use deep equality instead:
// Target object deeply (but not strictly) equals `{a: 1}`
expect({a: 1}).to.deep.equal({a: 1});
expect({a: 1}).to.not.equal({a: 1});
// Target array deeply (but not strictly) equals `[1, 2]`
expect([1, 2]).to.deep.equal([1, 2]);
expect([1, 2]).to.not.equal([1, 2]);
Explaining why is easy:
1 === 1 // These are primitives, they hold the same reference - they are strictly equal
1 == '1' // These are two different primitives, through type coercion they hold the same value - they are loosely equal
{ a: 1 } !== { a: 1 } // These are two different objects, they hold different references and so are not strictly equal - even though they hold the same values inside
{ a: 1 } != { a: 1 } // They have the same type, meaning loose equality performs the same check as strict equality - they are still not equal.
Chai "to.equal" use "deep-eql" algorithm => package.
var deepEql = require("deep-eql");
deepEql({ a: 1 }, { a: 1 }) === true // deepEql can determine that they share the same keys and those keys share the same values, therefore they are deeply equal!
Do you want to know more about chai methods? Their docs are amazing.

Elasticsearch / Lucene Misspelled Whitespace

How can I make Elasticsearch correct queries in which keyword should contain whitespace but instead typed adjacent. E.g.
"thisisaquery" -> "this is a query"
my current settings are:
"settings": {
"index": {
"analysis": {
"analyzer": {
"autocomplete": {
"tokenizer": "whitespace",
"filter": [
"lowercase", "engram"
]
}
},
"filter": {
"engram": {
"type": "edgeNGram",
"min_gram": 3,
"max_gram": 10
}
}
}
}
}
There isn't an out of the box tokenizer/token filter to explicitly handle what you're asking for. The closest would be the compound word token filter which requires manually providing a dictionary file which in your case would may require the full english dictionary to work correctly. Even with that it would likely have issues with words that are stems of other words, abbreviations, etc without a lot of additional logic. It may be good enough though depending on your exact requirements.
This ruby project claims to do this. You might try it if you're using ruby, or just look at their code and copy their analyzer settings for it :)
https://github.com/ankane/searchkick

Optimizing a method with boolean flag

I have a method whose purpose is to retrieve collection items.
A collection can contain a mix of items, let's say: pens, pencils, and papers.
The 1st parameter allows me to tell the method to retrieve only the itemTypes I pass (e.g, just pens and pencils).
The 2nd parameter flags the function to use the collection's default item types, instead.
getCollectionItems($itemTypes,$useCollectionDefaultItemTypes) {
foreach() {
foreach() {
foreach() {
// lots of code...
if($useCollectionDefaultItemTypes) {
// get collection's items using collection->itemTypes
}
else {
// get collection's items using $itemTypes
}
// lots of code...
}
}
}
}
What feels odd is that if I set the $useCollectionDefaultItemTypes to true, there is no need for the function to use the first parameter. I was considering refactoring this method into two such as:
getCollectionItems($itemTypes); // get the items using $itemTypes
getCollectionItems(); // get the items using default settings
The problem is that the methods will have lots of duplicate code except for the if-statement area.
Is there a better way to optimize this?
Pass in $itemTypes as null when you're not using it. Have your if statement check if $itemTypes === null; if it is, use default settings.
If this is php, which I assume it is, you can make your method signature function getCollectionItems($itemTypes = null) and then you can call getCollectionItems() and it will call it as if you had typed getCollectionItems(null).
It's generally a bad idea to write methods that use flags like that. I've seen that written in several places (here at #16, Uncle Bob here and elsewhere). It makes the method hard to understand, read, and refactor.
An alternative design would be to use closures. Your code could look something like this:
$specificWayOfProcessing = function($a) {
//do something with each $a
};
getCollectionItems($processer) {
foreach() {
foreach() {
foreach() {
// lots of code...
$processor(...)
// lots of code...
}
}
}
}
getCollectionItems($specificWayOfProcessing);
This design is better because
It's more flexible. What happens when you need to decide between three different things?
You can now test the code inside the loop much easier
It is now easier to read, because the last line tells you that you are "getting collection items using a specific way of processing" - it reads like an English sentence.
Yes, there is a better way of doing this -- though this question is not an optimization question, but a style question. (Duplicated code has little effect on performance!)
The simplest way to implement this along the lines of your original idea is to make the no-argument form of getCollectionItems() define the default arguments, and then call the version of it that requires an argument:
getCollectionItems($itemTypes) {
foreach() {
foreach() {
foreach() {
// lots of code...
// get collection's items using $itemTypes
}
// lots of code...
}
}
}
getCollectionItems() {
getCollectionItems(collection->itemTypes)
}
Depending on what language you are using, you may even be able to collapse these into a single function definition with a default argument:
getCollectionItems($itemTypes = collection->itemTypes) {
foreach() {
foreach() {
foreach() {
// lots of code...
// get collection's items using $itemTypes
}
// lots of code...
}
}
}
That has the advantage of clearly expressing your original idea, which is that you use $itemTypes if provided, and collection->itemTypes if not.
(This does, of course, assume that you're talking about a single "collection", rather than having one of those foreach iterations be iterating over collections. If you are, the idea to use a null value is a good one.)