I have been able to get Firebase Authentication to work for Google sign in, Anonymous sign in and from Email and Password sign in, including sending a verification email during email and password sign in thanks to help on stackoverflow. Everything works as intended. Now for my next step I am trying to create a user collection in Firestore using the uid created by Firebase Authentication. I am confident my code is written correctly because I have tested it with (unsecure) Security Rules and the process worked exactly as desired. I have reviewed the Firebase documentation several times but I cannot figure out what is wrong with my Security Rules code. How can I fix my Security rules to allow a new user to create a Screen name that will be added to the user collection in Firestore? Thanks in advance for the help.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{uid}/jobs/{document=**} {
allow read, write: if request.auth.uid == uid;
}
match /users/{uid}/{document=**} {
allow read, write: if request.auth.uid == uid;
}
}
}
class HomePage extends StatefulWidget {
const HomePage({
Key? key,
}) : super(key: key);
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
void initState() {
super.initState();
createUserInFirestore();
}
Future<void> createUserInFirestore() async {
final GoogleSignIn googleSignIn = GoogleSignIn();
final GoogleSignInAccount? user = googleSignIn.currentUser;
final usersRef = FirebaseFirestore.instance.collection('users');
final DocumentSnapshot doc = await usersRef.doc(user?.id).get();
if (!doc.exists) {
final userName = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const CreateAccountPage(),
),
);
usersRef.doc(user?.id).set({
'id': user?.id,
'userName': userName,
'photoUrl': user?.photoUrl,
'email': user?.email,
'displayName': user?.displayName,
'bio': '',
'timestamp': documentIdFromCurrentDate(),
});
doc = await usersRef.doc(user?.id).get();
}
}
@override
Widget build(BuildContext context) {
return AdaptiveLayoutScaffold(
drawer: const SideSheet(
userImage: FakeUserAvatars.stacy,
userName: 'Stacy James',
),
landscapeBodyWidget: Container(),
portraitBodyWidget: Container(),
);
}
}
class CreateAccountPage extends StatefulWidget {
const CreateAccountPage({
Key? key,
}) : super(key: key);
@override
_CreateAccountPageState createState() => _CreateAccountPageState();
}
class _CreateAccountPageState extends State<CreateAccountPage> {
final _formKey = GlobalKey<FormState>();
late String userName;
void submit() {
_formKey.currentState?.save();
Navigator.pop(context, userName);
}
@override
Widget build(BuildContext context) {
return AdaptiveLayoutScaffold(
appBar: const Header(
automaticallyImplyLeading: false,
pageName: 'User Name',
),
landscapeBodyWidget: Container(),
portraitBodyWidget: ListView(
children: [
Column(
children: [
const Padding(
padding: EdgeInsets.only(top: 16.0),
child: Center(
child: Text('Create a User Name'),
),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Form(
key: _formKey,
child: TextFormField(
autovalidateMode: AutovalidateMode.always,
decoration: InputDecoration(
hintText: 'Must be between 3 and 20 characters',
labelText: 'User Name',
prefixIcon: Icon(
Icons.person,
color: Theme.of(context).iconTheme.color,
),
),
keyboardType: TextInputType.text,
onSaved: (val) => userName = val as String,
),
),
),
PlatformElevatedButton(
onPressed: submit,
buttonText: 'Create User Name',
),
],
),
],
),
);
}
}