1

i tried following some of youtube tutorial video and saw a firestore emulators connect. but after i connect the app. the screen that works properly suddenly dont want to fetch list of data from normal firestore. tried to write firebase logout in terminal and still the same. tried flutter clean, and flutter pub get still get the same thing. how can i remove the firestore emulators completely from my app?

enter image description here

this is my product models file

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';

class Product with ChangeNotifier {
  final String id;
  final String title;
  final String description;
  final double price;
  // final String discount;
  final String imageUrl;
  final String productCategoryName;
  final String brand;
  final String userId;
  final String city;
  final int quantity;
  final bool isFavorite;
  final bool isPopular;

  Product({
    required this.id,
    required this.title,
    required this.brand,
    required this.userId,
    required this.description,
    required this.imageUrl,
    required this.isFavorite,
    required this.isPopular,
    required this.price,
    // required this.discount,
    required this.city,
    required this.productCategoryName,
    required this.quantity,
  });
}

class ProductProvider with ChangeNotifier {
  List<Product> _products = [];

  Future<void> fetchProducts() async {
    await FirebaseFirestore.instance
        .collection('products')
        .get()
        .then((QuerySnapshot productSnapshot) {
      _products = [];
      for (var element in productSnapshot.docs) {
        _products.insert(
          0,
          Product(
            // discount: element.get('discount'),
            id: element.get('productId'),
            title: element.get('productTitle'),
            brand: element.get('productBrand'),
            description: element.get('productDescription'),
            imageUrl: element.get('productImage'),
            city: element.get('productCity'),
            price: double.parse(element.get('productPrice')),
            productCategoryName: element.get('productCategory'),
            quantity: int.parse(element.get('productQuantity')),
            userId: element.get('userId'),
            isFavorite: false,
            isPopular: false,
          ),
        );
      }
    });
  }

  List<Product> products() => _products;

  List<Product> getByCatName(String catName) {
    List<Product> catList = _products
        .where((element) =>
            element.productCategoryName.toLowerCase() == catName.toLowerCase())
        .toList();
    return catList;
  }

  List<Product> getByBrandName(String brandName) {
    List<Product> catList = _products
        .where(
            (element) => element.brand.toLowerCase() == brandName.toLowerCase())
        .toList();
    return catList;
  }

  List<Product> get popularProducts {
    return _products.where((element) => element.isPopular).toList();
  }

  Product getById(String prodId) {
    return _products.firstWhere((element) => element.id == prodId);
  }

  Product getBySellerId(String sellerId) {
    return _products.firstWhere((element) => element.userId == sellerId);
  }

  List<Product> getBySellerIds(String sellerId) {
    List<Product> sellerList = _products
        .where(
            (element) => element.userId.toLowerCase() == sellerId.toLowerCase())
        .toList();
    return sellerList;
  }

  List<Product> getBySearch(String search) {
    List<Product> prodList = _products
        .where((element) =>
            element.title.toLowerCase().contains(search.toLowerCase()))
        .toList();
    notifyListeners();
    return prodList;
  }
}

and this is the page/screen that show data using it



class PopularProductMain extends StatelessWidget {
  PopularProductMain({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final productProvider = Provider.of<ProductProvider>(context);
    List<Product> productsList = productProvider.products();
    return Column(
      children: [
        Column(
          children: [
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 8.0),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  const Text(
                    'Suggestion Products',
                    style: TextStyle(fontSize: 20, fontWeight: FontWeight.w600),
                  ),
                  TextButton(
                      onPressed: () {
                        Navigator.of(context).pushNamed(
                          FeedsScreen.routeName,
                          arguments: 'popular',
                        );
                      },
                      child: const Text('view all')),
                ],
              ),
            ),
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 10.0),
              child: SizedBox(
                width: double.infinity,
                child: GridView.builder(
                  padding: EdgeInsets.zero,
                  shrinkWrap: true,
                  physics: const NeverScrollableScrollPhysics(),
                  itemCount: productsList.length,
                  gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                      crossAxisCount: 2,
                      childAspectRatio: 175 / 300,
                      mainAxisSpacing: 10,
                      crossAxisSpacing: 10),
                  itemBuilder: (ctx, i) {
                    return ChangeNotifierProvider.value(
                      value: productsList[i],
                      child: const FeedsProduct(),
                    );
                  },
                ),
              ),
            ),
          ],
        ),
      ],
    );
  }
}

and 1 more this is the FeedsProduct.dart


class FeedsProduct extends StatefulWidget {
  const FeedsProduct({Key? key}) : super(key: key);

  @override
  _FeedsProductState createState() => _FeedsProductState();
}

class _FeedsProductState extends State<FeedsProduct> {
  CurrencyFormatter cf = CurrencyFormatter();

  // ignore: non_constant_identifier_names
  CurrencyFormatterSettings IDRSettings = CurrencyFormatterSettings(
    // formatter settings for euro
    symbol: 'Rp',
    symbolSide: SymbolSide.left,
    thousandSeparator: '.',
    decimalSeparator: ',',
  );

  @override
  Widget build(BuildContext context) {
    final productAttribute = Provider.of<Product>(context);

    double discount = 1 / 100;
    double discountPercentage = 1 - (discount * 10);
    double priceAfter = productAttribute.price * discountPercentage;
    // print(priceAfter);

    return InkWell(
      onTap: () {
        Navigator.of(context).pushNamed(ProductDetailsScreen.routeName,
            arguments: productAttribute.id);
      },
      child: Container(
        decoration: BoxDecoration(
          color: Colors.white,
          boxShadow: [
            BoxShadow(
              color: Colors.grey.withOpacity(0.5),
              spreadRadius: 1,
              blurRadius: 5,
              offset: const Offset(0, 3), // changes position of shadow
            ),
          ],
        ),
        child: Column(
          children: [
            Stack(
              children: [
                Column(
                  children: [
                    Positioned(
                      child: SizedBox(
                        height: 210,
                        width: 210,
                        child: FittedBox(
                            clipBehavior: Clip.hardEdge,
                            fit: BoxFit.cover,
                            child: Image.network(productAttribute.imageUrl)),
                      ),
                    ),
                  ],
                ),
              ],
            ),
            Padding(
              padding: const EdgeInsets.only(left: 8, right: 8),
              child: Container(
                width: double.infinity,
                height: 90,
                decoration: const BoxDecoration(
                  color: Colors.white,
                ),
                child: Column(
                  children: [
                    const SizedBox(
                      height: 8,
                    ),
                    Container(
                      alignment: Alignment.centerLeft,
                      child: Text(
                        productAttribute.title,
                        maxLines: 2,
                        style: const TextStyle(
                          fontSize: 15,
                          overflow: TextOverflow.ellipsis,
                        ),
                        textAlign: TextAlign.start,
                      ),
                    ),
                    const Spacer(),
                    Container(
                      alignment: Alignment.centerLeft,
                      child: Text(
                        CurrencyFormatter()
                            .format(productAttribute.price, IDRSettings),
                        maxLines: 1,
                        style: const TextStyle(
                            fontSize: 13,
                            color: Colors.grey,
                            overflow: TextOverflow.ellipsis,
                            decoration: TextDecoration.lineThrough),
                      ),
                    ),
                    Container(
                      alignment: Alignment.centerLeft,
                      child: Text(
                        CurrencyFormatter().format(priceAfter, IDRSettings),
                        maxLines: 1,
                        style: const TextStyle(
                          fontSize: 17,
                          color: Colors.red,
                          overflow: TextOverflow.ellipsis,
                        ),
                      ),
                    ),
                    Padding(
                      padding: const EdgeInsets.only(top: 1),
                      child: Container(
                        alignment: Alignment.centerLeft,
                        child: Text(
                          'Stock ${productAttribute.quantity}',
                          maxLines: 1,
                          style: const TextStyle(
                            fontSize: 12,
                            color: Colors.grey,
                            overflow: TextOverflow.ellipsis,
                          ),
                        ),
                      ),
                    ),
                  ],
                ),
              ),
            ),
            Padding(
              padding: const EdgeInsets.only(left: 5, right: 5),
              child: Container(
                width: double.infinity,
                height: 35,
                decoration: const BoxDecoration(
                  color: Colors.white,
                ),
                child: Column(
                  children: [
                    const Spacer(),
                    Padding(
                      padding: const EdgeInsets.only(top: 1),
                      child: Container(
                        alignment: Alignment.topLeft,
                        child: Row(
                          children: const [
                            Icon(Icons.star, size: 15, color: Colors.amber),
                            Icon(Icons.star, size: 15, color: Colors.amber),
                            Icon(Icons.star, size: 15, color: Colors.amber),
                            Icon(Icons.star, size: 15, color: Colors.amber),
                            Icon(Icons.star_half,
                                size: 15, color: Colors.amber),
                            SizedBox(width: 1),
                            Text(
                              '6 terjual',
                              maxLines: 1,
                              style: TextStyle(
                                fontWeight: FontWeight.w400,
                                fontSize: 12,
                                color: Colors.black,
                                overflow: TextOverflow.ellipsis,
                              ),
                            ),
                          ],
                        ),
                      ),
                    ),
                    Padding(
                      padding: const EdgeInsets.only(top: 2),
                      child: Container(
                        alignment: Alignment.topLeft,
                        child: Row(
                          children: [
                            const Icon(
                              Icons.room_outlined,
                              size: 15,
                              color: Colors.grey,
                            ),
                            Text(
                              productAttribute.city,
                              maxLines: 1,
                              style: const TextStyle(
                                fontWeight: FontWeight.w400,
                                fontSize: 12,
                                color: Colors.grey,
                                overflow: TextOverflow.ellipsis,
                              ),
                            ),
                          ],
                        ),
                      ),
                    ),
                  ],
                ),
              ),
            )
          ],
        ),
      ),
    );
  }
}

this is the firebase.json file

{
  "firestore": {
    "rules": "firestore.rules",
    "indexes": "firestore.indexes.json"
  },
  "emulators": {
    "auth": {
      "port": 9098
    },
    "functions": {
      "port": 5002
    },
    "firestore": {
      "port": 8081
    },
    "storage": {
      "port": 9199
    },
    "ui": {
      "enabled": true
    }
  },
  "functions": {
    "source": "functions",
    "predeploy": "npm --prefix \"$RESOURCE_DIR\" run build"
  },
  "storage": {
    "rules": "storage.rules"
  }
}


this is my firebase rules on firestore

service cloud.firestore {   match /databases/{database}/documents {
 match /{document=**} {
   allow read: if auth != null;
   allow write: if auth != null;
 }   } }

tried to find the difference from the previous code on my github extension and didnt found anything suspicious

Stanly
  • 533
  • 1
  • 5
  • 22
  • Check and make sure that your firestore rules on Firebase don't have a date of access associated with it. I've done this a few times where I set up a firebase database and suddenly lose access because in the rules it had a set date of only a few days. – TetroRL May 11 '22 at 13:47
  • well i've using it around 3 month and the data show it normally. but when i install the firestore emulators thing. suddenly they didnt give me any value of it. delete firebase.json and related file. and still get the same result – Stanly May 11 '22 at 13:56
  • i already put the other code that might help with this question :0 – Stanly May 11 '22 at 13:59
  • Can you add your firebase.json as well? When I set my emulators up, I recall having to change the host to `"host": "0.0.0.0",` and I also have the emulators connecting to my computer's IP address instead of localhost/127.0.0.1 – TetroRL May 11 '22 at 14:03
  • i delete it already, but wait let me re undo to do it – Stanly May 11 '22 at 14:03
  • Also, did the tutorial you followed have you set a boolean value to turn emulator connection on and off? Like `if (USE_EMULATOR) { await _connectToFirebaseEmulator(); }` – TetroRL May 11 '22 at 14:04
  • nope there's none of that code i've been used for – Stanly May 11 '22 at 14:13
  • Can you share the tutorial link that you followed to connect firestore emulator? – Roopa M May 12 '22 at 08:58
  • 1
    @RoopaM i think, its not the firestore emulator problem anymore, after spending a day for checking the error. they say `[ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: [cloud_firestore/permission-denied] The caller does not have permission to execute the specified operation.` and i change the firestore rule already and still didnt show me anything huh – Stanly May 12 '22 at 09:19
  • Do you have this line : `allow read, write: if request.auth != null;` in your security rule? – Roopa M May 12 '22 at 10:31
  • @RoopaM yeps i have it, and still didnt work still giving me the same error, this is it `service cloud.firestore { match /databases/{database}/documents { match /{document=**} { allow read, write: if request.auth != null; } } }` – Stanly May 12 '22 at 11:02
  • Can you add your complete security rule in the question? – Roopa M May 13 '22 at 05:46
  • @RoopaM sure check it – Stanly May 13 '22 at 06:27
  • The security rule that you mentioned in the comment is working fine. But the one in the question is not. Can you check which security rule you are applying? And Can you check whether you activated AppCheck on your project. AppCheck does not accept all the requests of the Debug mode under the emulator. – Roopa M May 13 '22 at 08:43
  • @RoopaM i just check that i connect with the AppCheck thing, and i just unenforced them and waiting – Stanly May 13 '22 at 09:10
  • @RoopaM well still the same, is there any way i can completely remove the appcheck? – Stanly May 13 '22 at 09:17
  • In the AppCheck window, you'll see the products in which AppCheck is enforced, click on it and then "deactivate". Or you can refer to this [thread](https://stackoverflow.com/questions/69990889/unregister-app-in-app-check-from-safetynet-in-firebase). – Roopa M May 13 '22 at 10:17
  • @RoopaM well still on the same place ..... i deactive already and remove the sha-256. or should i delete the firebase project? and connect it again? is there any consecuen of deleteing it maybe? – Stanly May 13 '22 at 11:14
  • I suggest you to re-check security rules whether you mentioned the `rules_version = '2';` and are given proper indentation. [This](https://i2.paste.pics/GXEY0.png) rule is working fine for me. Can you try it once – Roopa M May 13 '22 at 13:55
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/244722/discussion-between-royalindo-and-roopa-m). – Stanly May 13 '22 at 16:11

1 Answers1

0

This Problem can be resolved by Changing security rules from :

service cloud.firestore {   
match /databases/{database}/documents {
 match /{document=**} {
   allow read: if auth != null;
   allow write: if auth != null;
         }   
     } 
}

To:

rules_version = '2'; 
service cloud.firestore { 
   match /databases/{database}/documents { 
     match /{document=**} { 
        allow read, write: if request.auth != null; 
        }
     } 
  }

And by deactivating AppCheck on your project. AppCheck does not accept all the requests of the Debug mode under the emulator.
To deactivate the AppCheck : Go to the AppCheck window, you'll see the products in which AppCheck is enforced, click on it and then "deactivate". Or you can refer to this thread.

Note : AppCheck is currently in beta, therefore there are lot of issues.

Roopa M
  • 2,171
  • 4
  • 12