Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invalid location in tests are not reported #131

Closed
dannycochran opened this issue Oct 6, 2017 · 11 comments
Closed

Invalid location in tests are not reported #131

dannycochran opened this issue Oct 6, 2017 · 11 comments
Milestone

Comments

@dannycochran
Copy link

".validate" rules are not respected when the auth uid has a period in it. For instance:

const targaryen = require('targaryen');
// Note that "firstSignIn" must be a number
const rules = {
  rules: {
    ".write": true,
    ".read": true,
    users: {
      '$uid': {
        activity: {
          firstSignIn: {
            '.validate': 'newData.isNumber()'
          }
        }
      }
    }
  }
};
const user = { uid: 'foo.bar' };
const data = { users: { } };
const path = `/users/${user.uid}/activity/firstSignIn`;
const database = targaryen.database(rules, data).as(user).with({debug: true});
const result = database.write(path, 'notAnumber,shouldFail');
console.log(result.validated) // -> true

However if you change the above user to be "foobar", result.validated will correctly return "false".

I encountered this as I was creating dummy users using Math.random() for the uid, which is easy enough to work around, but it was a headache to track down why this is happening.

@dinoboff
Copy link
Collaborator

dinoboff commented Oct 6, 2017

The problem is with dot in url:

    it('should handle dot in url', function() {
      const rules = {
        rules: {
          '.write': true,
          '.read': true,
          $a: {
            '.validate': false
          }
        }
      };
      const db = database.create(rules, {}).with({debug: true});

      expect(db.write('foo', true).allowed).to.be.false();
      expect(db.write('foo.bar', true).allowed).to.be.false(); // fails
    });

@dinoboff
Copy link
Collaborator

dinoboff commented Oct 6, 2017

Are dot allowed?

@dannycochran
Copy link
Author

I don't think that's the problem. That's an ES6 template string, these two things are equivalent:

const user = { uid: 'foo.bar' };
`/users/${user.uid}/activity/firstSignIn` === '/users/' + user.uid + '/activity/firstSignIn';

@dinoboff
Copy link
Collaborator

dinoboff commented Oct 6, 2017

@dannycochran Firebase doesn't allow path containing dot.

ps: try

{
  "rules": {
    ".write": true,
    "$a": {
      ".validate": false
    }
  }
}

simulate write to path "/foo.bar/".

@dannycochran
Copy link
Author

Ah right, that makes sense. In which case, should targaryen throw an error that the path URL is invalid, rather than returning a result which indicates the write was valid?

@dinoboff
Copy link
Collaborator

dinoboff commented Oct 6, 2017

It should throw. It must throw for an illegal location and it might need to validate the uid too (the illegal character rule might apply to uid, I need to check).

dinoboff added a commit to dinoboff/targaryen that referenced this issue Oct 7, 2017
Validate path navigation rules or node and when creating/updating data nodes.

Fixes goldibex#131
@dinoboff dinoboff changed the title auth uids with periods break validation rules Invalid location in tests are not reported Oct 7, 2017
@dinoboff dinoboff added this to the 3.0.3 milestone Oct 7, 2017
@dinoboff
Copy link
Collaborator

dinoboff commented Oct 7, 2017

The bug related to invalid path and node key is fixed in 3.0.3 and it's released.

Regarding UIDs, firebase-admin allow the creation of token with UID containing invalid characters, so targaryen is not validating them.

@chetbox
Copy link

chetbox commented Oct 19, 2017

This change breaks our tests and I believe it restricts a use case that is allowed in Firebase.

For safety, we user dummy UIDs that looks like email addresses to run our cloud functions with restricted privileges. Our write rules test paths of the form /permissions/user@domain.com which Firebase does allow us to do, but this version of targaryen does not allow such write rules.

Here's the error from our tests.

     AssertionError: Expected the write operation to succeed.
      
      Attempt to write /permissions/chet as {"uid":"user-admin@cloud-function.beeline.co"}.
      New Value: "null".
      
      /permissions/chet: write "newData.parent().parent().child('permissions').child(auth.uid).child('change_permissions').val() == true || auth.uid == 'user-admin' + '@cloud-function.beeline.co' && newData.val() == null"  => Error: Invalid location "permissions/user-admin@cloud-function.beeline.co/change_permissions" contains one of [., #, $, [, ]]

@dinoboff
Copy link
Collaborator

I will check with a proper write operation, but the simulator says "/permissions/user@domain.com" is an invalid location.

@dinoboff
Copy link
Collaborator

dinoboff commented Oct 22, 2017

@chetbox with rule:

{
  "rules": {
    "$key": {
      ".write": "$key !== 'admin' && root.child('banned').child(auth.uid).val() !== true"
    }
  }
}

And the following program:

'use strict';

const admin = require('firebase-admin');

const uid = 'bob@example.com';
const adminApp = admin.initializeApp({
  databaseURL: 'https://targaryen-42380.firebaseio.com',
  credential: admin.credential.cert('./sa.json')
});
const userApp = admin.initializeApp({
  databaseURL: 'https://targaryen-42380.firebaseio.com',
  credential: admin.credential.cert('./sa.json'),
  databaseAuthVariableOverride: {uid}
}, 'bob');

init()
  .then(write)
  .then(close)
  .catch(close);

function init() {
  const db = adminApp.database()

  return db.ref('/').set({});
}

function write() {
  const db = userApp.database()

  return db.ref('/foo').set('bar');
}

function close(err) {
  if (err !== null) {
    console.error(err);
  } {
    console.log('done');
  }

  adminApp.delete();
  userApp.delete();
}

It works regardless of the /banned/bob@example.com not being a valid location. Targaryen should throw if data was written with bad location but not when evaluating a rule with root.child($badKeyValue).

I will open a new issue.

@dinoboff
Copy link
Collaborator

@chetbox it should be fixed in v3.0.5

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants