Home > Back-end >  How to store data for each user in Flutter Firebase Realtime Database?
How to store data for each user in Flutter Firebase Realtime Database?

Time:09-13

I am building a mobile application using Flutter. For the to-do list feature, I connected it to the firebase real-time database so that when values are added to the application, those are automatically updated in the firebase database. It was successfully done but what I want to implement is storing data separated by users. It is like users have their own separated database in one firebase real-time database.

For example, if person A adds to-do list data, only A can view it and add more data of him when he signs in. And person B and C cannot view and access A's data but only their own data which they added. And they can add data that can be shown to only themselves when they sign in. I searched and checked many documents but couldn't find one that helped me.

Could anyone help me implement this feature? I also want to make sure that whether I need to add some codes of it to the application if I change the database rule.

Below is the current firebase real-time database rule.

{
  "rules": {
    ".read": true,
    ".write": true
   }
 }

And this is my todo list code.

class ToDo extends StatefulWidget {
 @override
  _ToDoState createState() => _ToDoState();
 }

class _ToDoState extends State<ToDo> {
  final fb = FirebaseDatabase.instance;
  @override
  Widget build(BuildContext context) {
   final ref = fb.ref().child('todos');
    return Scaffold(
    floatingActionButton: FloatingActionButton(
    backgroundColor: Colors.indigo[900],
    onPressed: () {
      Navigator.push(
        context,
        MaterialPageRoute(
          builder: (_) => addnote(),
        ),
      );
    },
    child: Icon(
      Icons.add,
    ),
  ),
  appBar: AppBar(
    title: Text(
      'Todos',
      style: TextStyle(
        fontSize: 30,
      ),
    ),
    backgroundColor: Colors.white,
  ),
  body: FirebaseAnimatedList(
    query: ref,
    shrinkWrap: true,
    itemBuilder: (context, snapshot, animation, index) {
      return GestureDetector(
        onTap: () {},
        child: Container(
          child: Padding(
            padding: const EdgeInsets.all(8.0),
            child: ListTile(
              shape: RoundedRectangleBorder(
                side: BorderSide(
                  color: Colors.white,
                ),
                borderRadius: BorderRadius.circular(10),
              ),
              tileColor: Colors.indigo[100],
              trailing: IconButton(
                icon: Icon(
                  Icons.delete,
                  color: Colors.red[900],
                ),
                onPressed: () {
                  ref.child(snapshot.key!).remove();
                },
              ),
              title: Text(
                snapshot.value.toString(),
                style: TextStyle(
                  fontSize: 25,
                  fontWeight: FontWeight.bold,
                ),
              ),
            ),
          ),
        ),
      );
        },
        ),
      );
    }
   }
class addnote extends StatelessWidget {
 TextEditingController title = TextEditingController();

 final fb = FirebaseDatabase.instance;

@override
 Widget build(BuildContext context) {
   final ref = fb.ref().child('todos');

    return Scaffold(
      appBar: AppBar(
       title: Text("Add Todos"),
       backgroundColor: Colors.indigo[900],
    ),
     body: Container(
      child: Column(
       children: [
        SizedBox(
          height: 10,
        ),
        Container(
          decoration: BoxDecoration(border: Border.all()),
          child: TextField(
            controller: title,
            decoration: InputDecoration(
              hintText: 'title',
            ),
          ),
        ),
        SizedBox(
          height: 10,
        ),
        MaterialButton(
          color: Colors.indigo[900],
          onPressed: () {
            ref
                .push()
                .set(
              title.text,
            )
                .asStream();
            Navigator.pushReplacement(
                context, MaterialPageRoute(builder: (_) => ToDo()));
          },
          child: Text(
            "save",
            style: TextStyle(
              color: Colors.white,
              fontSize: 20,
            ),
          ),
        ),
      ],
      ),
    ),
  );
 }
   }

Thank you

CodePudding user response:

You could create a child nodes with users' UID as they as shown below:

todos/
├─ user1/
│  ├─ todoId1
├─ user2/
│  ├─ todoId2

This way you can restrict a user's access to their entries only with the following rules:

{
  "rules": {
    "todos": {
      "$uid": {
        ".read": "$uid === auth.uid",
        ".write": "$uid === auth.uid"
      }
    }
  }
}

You'll have to change the DatabaseReference in your code to the UID node instead of just the todos so any new items pushed will be under that user:

// Use this ref to:
// 1. Fetch all TODOs
// 2. push() new TODO
final ref = fb.ref().child('todos').child(CURRENT_USER_ID);

Checkout the documentation to learn more about security rules.

  • Related