Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
314 views
in Technique[技术] by (71.8m points)

Firebase Realtime Database - Multi Group Access?

I currently have a database structure resembling the following. Without the ability to loop inside Firebase Realtime Database secutiry rules, how can I secure data based on a users access to multiple groups? Example to follow...

The database structure:

// list of different groups a user can belong to.
// they can belong to multiple groups.

"userGroups": {
  "groupA": ...
  "groupB": ...
  "groupC": ...
}

// each user has a list of group ids they belong to

"users": {
  "userA": {
    groups: ['groupA', 'groupB'],
  },
  "userB": {
    groups: ['groupB'],
  }
}

// various nodes in the database an admin sets restriction on content
// so specific data can only be access by specified group

"someFunData": {
  "data1": {
    authorisedGroups: ['groupA', 'groupB'],
  },
  "data2": {
    authorisedGroups: ['groupB'],
  }
}

How can I specify security rules on someFunData to restrict it based on a match between any group specified in someFunData/$dataId/authorisedGroups to the current user's groups?

question from:https://stackoverflow.com/questions/65621416/firebase-realtime-database-multi-group-access

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

First, userGroups can be misleading. It could mean "the groups of each user". If you don't have any other kinds of groups, you can call it just groups.

In a similar scenario, I created a Cloud Function for every path that affects what a user should see.

const updateUserFunData = (path: string) => {
    return functions.database.ref(path).onWrite(async (data, context) => {
        // Download any required data, calculate what changes should be made,
        // then use a multi-path update to save these changes, like this:
        await rootRef.child('userFunData').update({
            [uid1 + '/' + data1]: true, // or a complete copy of the data
            [uid1 + '/' + data2]: null, // use null to delete
        });
    });
};
export const onUserGroupsChange = updateUserFunData('users/{uid}/groups');
export const onFunDataGroupsChange = updateUserFunData('someFunData/{dataId}/groups');

Then clients can read userFunData/$uid to get their data IDs (and then get each funData), and rules can check if userFunData/$uid/$dataId exists, to allow or deny a read.

If you want to skip that intermediate funData IDs query and the synchronization of all the following queries, you can replace true with a full copy of the data, add a trigger for the other db changes that should change that data, and have clients query only userFunData/$uid, which should contain all the data they should see.


You commented that maintaining a per-user list of data would not be practical. You can maintain a per-group list of data, and have each user get the data of each of their groups. The rules would check if the user exists in the users of the group being read. You would have to save the users of each group (or the groups of each user) as a map instead of an array.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...