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

Firestore and Realtime Database administration and grants #80

Closed
linusmartensson opened this issue Jan 31, 2020 · 4 comments
Closed

Firestore and Realtime Database administration and grants #80

linusmartensson opened this issue Jan 31, 2020 · 4 comments

Comments

@linusmartensson
Copy link
Contributor

The way the firestore example rules in firebase/firestore.rules are written, they look for grants and administrative privileges to access and modify data:

//Checks if user has admin rights
    function isAdmin() {
	    return exists(/databases/$(database)/documents/admins/$(request.auth.uid));
    }
    //Checks if user has a specific grant
    function hasGrant(grant) {
      return get(/databases/$(database)/documents/user_grants/$(request.auth.uid)).data[grant]==true
    }

However, this data is stored by RMW in the Realtime Database, not Firestore, and it does not seem to be legal to access the RDB from Firestore since I'm getting permission failures when using the provided functions.
I obviously can't just do client-side security and leave Firestore open to anyone, so how can I use the provided grant and isAdmin functionality? Do I need to duplicate grants and administrators on changes using firebase functions, or have I missed something?

@linusmartensson
Copy link
Contributor Author

linusmartensson commented Jan 31, 2020

functions/db/admins/onWrite.f.js:

import { database } from 'firebase-functions'
import admin from 'firebase-admin'

exports = module.exports = database
    .ref('/admins/{userUid}')
    .onWrite((change, context) => {
        const userUid = context.params.userUid
        if(change.before.exists()){
            if(!change.after.exists())
                return admin.firestore().collection('admins').doc(userUid).delete();
        } else if(change.after.exists())
            return admin.firestore().collection('admins').doc(userUid).set({});
        return null;
    })                     

functions/db/userGrants/onWrite.f.js:

import { database } from 'firebase-functions'
import admin from 'firebase-admin'

exports = module.exports = database
  .ref('/user_grants/{userUid}/{grantName}')
    .onWrite((eventSnapshot, context) => {
        const userUid = context.params.userUid
        const grantName = context.params.grantName
        let prm = {}
        if (eventSnapshot.after.val()) {
            prm[grantName] = true;
        } else {
            prm[grantName] = false;
        }
        return admin.firestore().collection('user_grants').doc(userUid).set(prm, {merge:true});
  })

I added the above for now to duplicate privilege changes from the RDB into Firestore. It seems to be working in case anyone else is stumped by the issue.
Would appreciate an official word on how this should be handled! :)

@TarikHuber
Copy link
Collaborator

Hi @linusmartensson there should be a sync from RTD to Firestore. We do it the same in our company.

@TarikHuber
Copy link
Collaborator

omg it seems I frogot to put the sync in the demo -.-

@TarikHuber
Copy link
Collaborator

Updated the project to have integrated sync of admins and grants to firestore. Also to sync admins and grants with "storage" in it's name to the custom auth tokens. Because you can't access RTD and Firestore on the storage rules the only solution is to do it over those custom tokens. Sync of all of them would not fit so we sync only those witch have "storage" in they're name.

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

2 participants