استفاده از احراز هویت فایربیس با فلاتر – از صفر تا صد


در این مقاله شیوه ایجاد یک اپلیکیشن با فلاتر را شرح داده و اتصال آن به سیستم احراز هویت فایربیس را مورد بررسی قرار میدهیم. قصد ما این است که با فایربیس تعامل پیدا کنیم تا هویت کاربر را احراز کرده و تابعهای دیگری را نیز در فایربیس اجرا کنیم. در این راهنما میتوانید یک اپلیکیشن ساده فلاتر بسازید که در آن کاربر میتواند از طریق اپلیکیشن ثبت نام کرده و در آن لاگین کند. اگر کاربر تمایل داشته باشد، میتواند ایمیل و رمز عبور را تغییر دهد و یا حتی حساب کاربری را حذف کند.
اهداف
اهداف این پروژه شامل موارد زیر هستند:
- پیکربندی فایربیس روی پروژه فلاتر
- ایجاد فرمهای ثبت نام، لاگین و دیگر کارکردها در فایربیس
روش اجرای پروژه
در این بخش و همانطور که از عنوان بر میآید، روش اجرای پروژه را با هم مرور میکنیم.
گام 1
قبل از هر چیز باید یک پروژه فلاتر ایجاد کنیم. اگر نمیدانید چگونه باید پروژه فلاتر ایجاد کنید، میتوانید از این راهنمای مجله فرادرس کمک بگیرید:
پس از ایجاد پروژه فلاتر باید فایربیس را روی پروژه پیکربندی کنیم. در مورد اندروید به کنسول فایربیس بروید و روی دکمه «افزودن اپلیکیشن» (Add App) کلیک کنید تا با انتخاب آیکون اندروید فرمی مانند زیر نمایش یابد:
نام پروژه را اضافه کنید. با باز کردن فایل AndroidManifest در مسیر android/app/src/main/AndroidManifest.xml میتوانید نام پروژه را به دست آورید. پس از آن فایل google-services.json را دانلود کنید. سپس به پروژه بروید و فایل google-services.json را درون پوشه دایرکتوری اندروید یعنی android/app قرار دهید.
باید افزونه Google Services Gradle را نیز برای خواندن فایل Google Services Gradle اضافه کنیم. بنابراین فایل build.gradle را به صورت زیر ویرایش کنید:
پس از پایان یافتن ویرایشها پروژه را همگامسازی (Sync) کنید.
در مورد iOS، برای اجرای Xcode ابتدا ios/Runner.xcworkspace را باز کنید. نام پکیج را میتوانید در شناسه bundle در نمای Runner ببینید. فایل config را که به صورت GoogleService-info.plist است دانلود کنید. این فایل را درون زیرپوشه Runner درون Runner که به صورت زیر است، بکشید:
سپس به کنسول فایربیس بروید و روی دکمه احراز هویت در سمت چپ نوار ناوبری بزنید. سپس ایمیل/رمز عبور را فعال کنید. با این فعالسازی میتوانید کاربران را در فایربیس ثبت نام کنید.
اکنون پیکربندی فایربیس انجام یافته است. کار بعدی که باید انجام دهیم در سطح کد است.
گام 2
در این بخش باید وابستگیها را به پروژه فلاتر خود اضافه کنیم. به این منظور به فایل pubspec.yaml بروید و زیر وابستگیها خط زیر را اضافه کنید:
firebase_auth: ^0.9.0
پروژه را ذخیره کنید.
گام 3
اکنون باید سرویسهایی که به اپلیکیشن موبایل با فایربیس وصل میشوند را بنویسیم. درون پوشه lib یک پوشه جدید به نام Services ایجاد میکنیم. سپس یک فایل dart درون پوشه Services به نام authentication.dart ایجاد کرده و کد زیر را در آن قرار میدهیم:
1import 'dart:async';
2import 'package:firebase_auth/firebase_auth.dart';
3
4abstract class BaseAuth {
5 Future<String> signIn(String email, String password);
6
7 Future<String> signUp(String email, String password);
8
9 Future<FirebaseUser> getCurrentUser();
10
11 Future<void> sendEmailVerification();
12
13 Future<void> signOut();
14
15 Future<bool> isEmailVerified();
16
17 Future<void> changeEmail(String email);
18
19 Future<void> changePassword(String password);
20
21 Future<void> deleteUser();
22
23 Future<void> sendPasswordResetMail(String email);
24}
25
26class Auth implements BaseAuth {
27 final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
28
29 Future<String> signIn(String email, String password) async {
30 FirebaseUser user = await _firebaseAuth.signInWithEmailAndPassword(email: email, password: password);
31 return user.uid;
32 }
33
34 Future<String> signUp(String email, String password) async {
35 FirebaseUser user = await _firebaseAuth.createUserWithEmailAndPassword(
36 email: email, password: password);
37 return user.uid;
38 }
39
40 Future<FirebaseUser> getCurrentUser() async {
41 FirebaseUser user = await _firebaseAuth.currentUser();
42 return user;
43 }
44
45 Future<void> signOut() async {
46 return _firebaseAuth.signOut();
47 }
48
49 Future<void> sendEmailVerification() async {
50 FirebaseUser user = await _firebaseAuth.currentUser();
51 user.sendEmailVerification();
52 }
53
54 Future<bool> isEmailVerified() async {
55 FirebaseUser user = await _firebaseAuth.currentUser();
56 return user.isEmailVerified;
57 }
58
59 @override
60 Future<void> changeEmail(String email) async {
61 FirebaseUser user = await _firebaseAuth.currentUser();
62 user.updateEmail(email).then((_) {
63 print("Succesfull changed email");
64 }).catchError((error) {
65 print("email can't be changed" + error.toString());
66 });
67 return null;
68 }
69
70 @override
71 Future<void> changePassword(String password) async {
72 FirebaseUser user = await _firebaseAuth.currentUser();
73 user.updatePassword(password).then((_) {
74 print("Succesfull changed password");
75 }).catchError((error) {
76 print("Password can't be changed" + error.toString());
77 });
78 return null;
79 }
80
81 @override
82 Future<void> deleteUser() async {
83 FirebaseUser user = await _firebaseAuth.currentUser();
84 user.delete().then((_) {
85 print("Succesfull user deleted");
86 }).catchError((error) {
87 print("user can't be delete" + error.toString());
88 });
89 return null;
90 }
91
92 @override
93 Future<void> sendPasswordResetMail(String email) async{
94 await _firebaseAuth.sendPasswordResetEmail(email: email);
95 return null;
96 }
97
98}
در کد فوق، یک کلاس به نام BaseAuth ایجاد میکنیم تا متدی که قصد داریم پیادهسازی کنیم را بنویسیم و پارامترها را ارسال کنیم. سپس یک کلاس مجزا به نام Auth ایجاد میکنیم آن را در کلاس BaseAuth پیادهسازی میکنیم به طوری که متدهای الحاق یافته بتوانند در Auth پیادهسازی شوند.
گام 4
در این گام باید صفحههای ثبت نام و لاگین کاربر را طراحی کنیم. یک پوشه درون دایرکتوری lib به نام pages ایجاد کنید. درون پوشه pages یک فایل دارت به نام login_signup_page.dart ایجاد کرده و کد دارت زیر را در آن بنویسید:
1import 'package:flutter/material.dart';
2import '../services/authentication.dart';
3
4class LoginSignUpPage extends StatefulWidget {
5 LoginSignUpPage({this.auth, this.onSignedIn});
6
7 final BaseAuth auth;
8 final VoidCallback onSignedIn;
9
10 @override
11 State<StatefulWidget> createState() => new _LoginSignUpPageState();
12}
13
14enum FormMode { LOGIN, SIGNUP }
15
16class _LoginSignUpPageState extends State<LoginSignUpPage> {
17 final _formKey = new GlobalKey<FormState>();
18
19 String _email;
20 String _password;
21 String _errorMessage;
22
23 // Initial form is login form
24 FormMode _formMode = FormMode.LOGIN;
25 bool _isIos;
26 bool _isLoading;
27
28 // Check if form is valid before perform login or signup
29 bool _validateAndSave() {
30 final form = _formKey.currentState;
31 if (form.validate()) {
32 form.save();
33 return true;
34 }
35 return false;
36 }
37
38 // Perform login or signup
39 void _validateAndSubmit() async {
40 setState(() {
41 _errorMessage = "";
42 _isLoading = true;
43 });
44 if (_validateAndSave()) {
45 String userId = "";
46 try {
47 if (_formMode == FormMode.LOGIN) {
48 userId = await widget.auth.signIn(_email, _password);
49 print('Signed in: $userId');
50 } else {
51 userId = await widget.auth.signUp(_email, _password);
52 widget.auth.sendEmailVerification();
53 _showVerifyEmailSentDialog();
54 print('Signed up user: $userId');
55 }
56 setState(() {
57 _isLoading = false;
58 });
59
60 if (userId.length > 0 && userId != null && _formMode == FormMode.LOGIN) {
61 widget.onSignedIn();
62 }
63
64 } catch (e) {
65 print('Error: $e');
66 setState(() {
67 _isLoading = false;
68 if (_isIos) {
69 _errorMessage = e.details;
70 } else
71 _errorMessage = e.message;
72 });
73 }
74 }
75 }
76
77
78 @override
79 void initState() {
80 _errorMessage = "";
81 _isLoading = false;
82 super.initState();
83 }
84
85 void _changeFormToSignUp() {
86 _formKey.currentState.reset();
87 _errorMessage = "";
88 setState(() {
89 _formMode = FormMode.SIGNUP;
90 });
91 }
92
93 void _changeFormToLogin() {
94 _formKey.currentState.reset();
95 _errorMessage = "";
96 setState(() {
97 _formMode = FormMode.LOGIN;
98 });
99 }
100
101 @override
102 Widget build(BuildContext context) {
103 _isIos = Theme.of(context).platform == TargetPlatform.iOS;
104 return new Scaffold(
105 appBar: new AppBar(
106 title: new Text('Flutter Firebase Authentication'),
107 ),
108 body: Stack(
109 children: <Widget>[
110 _showBody(),
111 _showCircularProgress(),
112 ],
113 ));
114 }
115
116 Widget _showCircularProgress(){
117 if (_isLoading) {
118 return Center(child: CircularProgressIndicator());
119 } return Container(height: 0.0, width: 0.0,);
120
121 }
122
123 void _showVerifyEmailSentDialog() {
124 showDialog(
125 context: context,
126 builder: (BuildContext context) {
127 // return object of type Dialog
128 return AlertDialog(
129 title: new Text("Verify your account"),
130 content: new Text("Link to verify account has been sent to your email"),
131 actions: <Widget>[
132 new FlatButton(
133 child: new Text("Dismiss"),
134 onPressed: () {
135 _changeFormToLogin();
136 Navigator.of(context).pop();
137 },
138 ),
139 ],
140 );
141 },
142 );
143 }
144
145 Widget _showBody(){
146 return new Container(
147 padding: EdgeInsets.all(16.0),
148 child: new Form(
149 key: _formKey,
150 child: new ListView(
151 shrinkWrap: true,
152 children: <Widget>[
153 _showLogo(),
154 _showEmailInput(),
155 _showPasswordInput(),
156 _showPrimaryButton(),
157 _showSecondaryButton(),
158 _showErrorMessage(),
159 ],
160 ),
161 ));
162 }
163
164 Widget _showErrorMessage() {
165 if (_errorMessage.length > 0 && _errorMessage != null) {
166 return new Text(
167 _errorMessage,
168 style: TextStyle(
169 fontSize: 13.0,
170 color: Colors.red,
171 height: 1.0,
172 fontWeight: FontWeight.w300),
173 );
174 } else {
175 return new Container(
176 height: 0.0,
177 );
178 }
179 }
180
181 Widget _showLogo() {
182 return new Hero(
183 tag: 'hero',
184 child: Padding(
185 padding: EdgeInsets.fromLTRB(0.0, 30.0, 0.0, 0.0),
186 child: CircleAvatar(
187 backgroundColor: Colors.transparent,
188 radius: 48.0,
189 child: Image.asset('assets/images/logo.png'),
190 ),
191 ),
192 );
193 }
194
195 Widget _showEmailInput() {
196 return Padding(
197 padding: const EdgeInsets.fromLTRB(0.0, 100.0, 0.0, 0.0),
198 child: new TextFormField(
199 maxLines: 1,
200 keyboardType: TextInputType.emailAddress,
201 autofocus: false,
202 decoration: new InputDecoration(
203 hintText: 'Email',
204 icon: new Icon(
205 Icons.mail,
206 color: Colors.grey,
207 )),
208 validator: (value) => value.isEmpty ? 'Email can\'t be empty' : null,
209 onSaved: (value) => _email = value.trim(),
210 ),
211 );
212 }
213
214 Widget _showPasswordInput() {
215 return Padding(
216 padding: const EdgeInsets.fromLTRB(0.0, 15.0, 0.0, 0.0),
217 child: new TextFormField(
218 maxLines: 1,
219 obscureText: true,
220 autofocus: false,
221 decoration: new InputDecoration(
222 hintText: 'Password',
223 icon: new Icon(
224 Icons.lock,
225 color: Colors.grey,
226 )),
227 validator: (value) => value.isEmpty ? 'Password can\'t be empty' : null,
228 onSaved: (value) => _password = value.trim(),
229 ),
230 );
231 }
232
233
234
235 Widget _showSecondaryButton() {
236 return new FlatButton(
237 child: _formMode == FormMode.LOGIN
238 ? new Text('Create an account',
239 style: new TextStyle(fontSize: 18.0, fontWeight: FontWeight.w300))
240 : new Text('Have an account? Sign in',
241 style:
242 new TextStyle(fontSize: 18.0, fontWeight: FontWeight.w300)),
243 onPressed: _formMode == FormMode.LOGIN
244 ? _changeFormToSignUp
245 : _changeFormToLogin,
246 );
247 }
248
249 Widget _showPrimaryButton() {
250 return new Padding(
251 padding: EdgeInsets.fromLTRB(0.0, 45.0, 0.0, 0.0),
252 child: SizedBox(
253 height: 40.0,
254 child: new RaisedButton(
255 elevation: 5.0,
256 shape: new RoundedRectangleBorder(borderRadius: new BorderRadius.circular(30.0)),
257 color: Colors.blue,
258 child: _formMode == FormMode.LOGIN
259 ? new Text('Login',
260 style: new TextStyle(fontSize: 20.0, color: Colors.white))
261 : new Text('Create account',
262 style: new TextStyle(fontSize: 20.0, color: Colors.white)),
263 onPressed: _validateAndSubmit,
264 ),
265 ));
266 }
267
268}
در این کد برای هر دو صفحه ثبت نام و ورود، از صفحه یکسانی استفاده کردهایم. اما UI آنها متفاوت است.
سپس یک فایل به نام home_page.dart ایجاد میکنیم. در این صفحه اصلی، فعالیتهای زیر انجام خواهند یافت:
- تغییر رمز عبور کاربر
- تغییر ایمیل کاربر
- ارسال ایمیل تأیید حساب به کاربر
- حذف کاربر
- خروج از حساب کاربری
1import 'package:flutter/material.dart';
2import '../services/authentication.dart';
3import 'package:firebase_database/firebase_database.dart';
4import 'dart:async';
5
6class HomePage extends StatefulWidget {
7 HomePage({Key key, this.auth, this.userId, this.onSignedOut})
8 : super(key: key);
9
10 final BaseAuth auth;
11 final VoidCallback onSignedOut;
12 final String userId;
13
14 @override
15 State<StatefulWidget> createState() => new _HomePageState();
16}
17
18class _HomePageState extends State<HomePage> {
19
20 final FirebaseDatabase _database = FirebaseDatabase.instance;
21 final GlobalKey<FormState> formKey = GlobalKey<FormState>();
22
23 final TextEditingController _emailFilter = new TextEditingController();
24 final TextEditingController _passwordFilter = new TextEditingController();
25 final TextEditingController _resetPasswordEmailFilter =
26 new TextEditingController();
27
28 String _email = "";
29 String _password = "";
30 String _resetPasswordEmail = "";
31
32 String _errorMessage;
33 bool _isIos;
34 bool _isLoading;
35
36 _HomePageState() {
37 _emailFilter.addListener(_emailListen);
38 _passwordFilter.addListener(_passwordListen);
39 _resetPasswordEmailFilter.addListener(_resetPasswordEmailListen);
40 }
41
42 void _resetPasswordEmailListen() {
43 if (_resetPasswordEmailFilter.text.isEmpty) {
44 _resetPasswordEmail = "";
45 } else {
46 _resetPasswordEmail = _resetPasswordEmailFilter.text;
47 }
48 }
49
50 void _emailListen() {
51 if (_emailFilter.text.isEmpty) {
52 _email = "";
53 } else {
54 _email = _emailFilter.text;
55 }
56 }
57
58 void _passwordListen() {
59 if (_passwordFilter.text.isEmpty) {
60 _password = "";
61 } else {
62 _password = _passwordFilter.text;
63 }
64 }
65
66 final _textEditingController = TextEditingController();
67
68 StreamSubscription<Event> _onTodoAddedSubscription;
69 StreamSubscription<Event> _onTodoChangedSubscription;
70
71 Query _todoQuery;
72
73 bool _isEmailVerified = false;
74
75 @override
76 void initState() {
77 super.initState();
78 _checkEmailVerification();
79 }
80
81 void _checkEmailVerification() async {
82 _isEmailVerified = await widget.auth.isEmailVerified();
83 if (!_isEmailVerified) {
84 _showVerifyEmailDialog();
85 }
86 }
87
88 void _resentVerifyEmail() {
89 widget.auth.sendEmailVerification();
90 _showVerifyEmailSentDialog();
91 }
92
93 void _showVerifyEmailDialog() {
94 showDialog(
95 context: context,
96 builder: (BuildContext context) {
97 // return object of type Dialog
98 return AlertDialog(
99 title: new Text("Verify your account"),
100 content: new Text("Please verify account in the link sent to email"),
101 actions: <Widget>[
102 new FlatButton(
103 child: new Text("Resent link"),
104 onPressed: () {
105 Navigator.of(context).pop();
106 _resentVerifyEmail();
107 },
108 ),
109 new FlatButton(
110 child: new Text("Dismiss"),
111 onPressed: () {
112 Navigator.of(context).pop();
113 },
114 ),
115 ],
116 );
117 },
118 );
119 }
120
121 void _showVerifyEmailSentDialog() {
122 showDialog(
123 context: context,
124 builder: (BuildContext context) {
125 // return object of type Dialog
126 return AlertDialog(
127 title: new Text("Verify your account"),
128 content:
129 new Text("Link to verify account has been sent to your email"),
130 actions: <Widget>[
131 new FlatButton(
132 child: new Text("Dismiss"),
133 onPressed: () {
134 Navigator.of(context).pop();
135 },
136 ),
137 ],
138 );
139 },
140 );
141 }
142
143 @override
144 void dispose() {
145 _onTodoAddedSubscription.cancel();
146 _onTodoChangedSubscription.cancel();
147 super.dispose();
148 }
149
150
151
152 _signOut() async {
153 try {
154 await widget.auth.signOut();
155 widget.onSignedOut();
156 } catch (e) {
157 print(e);
158 }
159 }
160
161
162 Widget _showButtonList() {
163 return new Container(
164 padding: EdgeInsets.all(26.0),
165 child: new ListView(
166 children: <Widget>[
167 _showChangeEmailContainer(),
168 new SizedBox(
169 height: 40.0,
170 ),
171 _showChangePasswordContainer(),
172 new SizedBox(
173 height: 40.0,
174 ),
175 _showSentResetPasswordEmailContainer(),
176 new SizedBox(
177 height: 40.0,
178 ),
179 _removeUserContainer(),
180 ],
181 ),
182 );
183 }
184
185 @override
186 Widget build(BuildContext context) {
187 return new Scaffold(
188 appBar: new AppBar(
189 title: new Text('Flutter login demo'),
190 actions: <Widget>[
191 new FlatButton(
192 child: new Text('Logout',
193 style: new TextStyle(fontSize: 17.0, color: Colors.white)),
194 onPressed: _signOut)
195 ],
196 ),
197 body: _showButtonList(),
198 );
199 }
200
201 Widget _showEmailChangeErrorMessage() {
202 if (_errorMessage != null) {
203 return new Text(
204 _errorMessage,
205 style: TextStyle(
206 fontSize: 13.0,
207 color: Colors.red,
208 height: 1.0,
209 fontWeight: FontWeight.w300),
210 );
211 } else {
212 return new Container(
213 height: 0.0,
214 );
215 }
216 }
217
218 _showChangeEmailContainer() {
219 return Container(
220 decoration: BoxDecoration(
221 borderRadius: new BorderRadius.circular(30.0),
222 color: Colors.amberAccent,
223 ),
224 padding: EdgeInsets.fromLTRB(10, 20, 10, 20),
225 child: Column(
226 children: <Widget>[
227 new TextFormField(
228 controller: _emailFilter,
229 decoration: new InputDecoration(
230 contentPadding: EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
231 hintText: "Enter New Email",
232 border:
233 OutlineInputBorder(borderRadius: BorderRadius.circular(22.0)),
234 ),
235 ),
236 new MaterialButton(
237 shape: RoundedRectangleBorder(
238 borderRadius: new BorderRadius.circular(30.0)),
239 onPressed: () {
240 // widget.auth.changeEmail("abc@gmail.com");
241 _changeEmail();
242 },
243 minWidth: MediaQuery.of(context).size.width,
244 padding: EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
245 color: Colors.blueAccent,
246 textColor: Colors.white,
247 child: Text(
248 "Change Email",
249 textAlign: TextAlign.center,
250 ),
251 ),
252 ],
253 ),
254 );
255 }
256
257 void _changeEmail() {
258 if (_email != null && _email.isNotEmpty) {
259 try {
260 print("============>" + _email);
261 widget.auth.changeEmail(_email);
262 } catch (e) {
263 print("============>" + e);
264 setState(() {
265 _isLoading = false;
266 if (_isIos) {
267 _errorMessage = e.details;
268 } else
269 _errorMessage = e.message;
270 });
271 }
272 } else {
273 print("email feild empty");
274 }
275 }
276
277 void _changePassword() {
278 if (_password != null && _password.isNotEmpty) {
279 print("============>" + _password);
280 widget.auth.changePassword(_password);
281 } else {
282 print("password feild empty");
283 }
284 }
285
286 void _removeUser() {
287 widget.auth.deleteUser();
288 }
289
290 void _sendResetPasswordMail() {
291 if (_resetPasswordEmail != null && _resetPasswordEmail.isNotEmpty) {
292 print("============>" + _resetPasswordEmail);
293 widget.auth.sendPasswordResetMail(_resetPasswordEmail);
294 } else {
295 print("password feild empty");
296 }
297 }
298
299 _showChangePasswordContainer() {
300 return Container(
301 decoration: BoxDecoration(
302 borderRadius: BorderRadius.circular(30.0),
303 color: Colors.brown
304 ),
305 padding: EdgeInsets.fromLTRB(10, 20, 10, 20),
306 child: Column(
307 children: <Widget>[
308 new TextFormField(
309 controller: _passwordFilter,
310 decoration: new InputDecoration(
311 contentPadding: EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
312 hintText: "Enter New Password",
313 border:
314 OutlineInputBorder(borderRadius: BorderRadius.circular(22.0)),
315 ),
316 ),
317 new MaterialButton(
318 shape: RoundedRectangleBorder(
319 borderRadius: new BorderRadius.circular(30.0)),
320 onPressed: () {
321 _changePassword();
322 },
323 minWidth: MediaQuery.of(context).size.width,
324 padding: EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
325 color: Colors.blueAccent,
326 textColor: Colors.white,
327 child: Text(
328 "Change Password",
329 textAlign: TextAlign.center,
330 ),
331 ),
332 ],
333 ),
334 );
335 }
336
337 _showSentResetPasswordEmailContainer() {
338 return Column(
339 children: <Widget>[
340 new Container(
341 child: new TextFormField(
342 controller: _resetPasswordEmailFilter,
343 decoration: new InputDecoration(
344 contentPadding: EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
345 hintText: "Enter Email",
346 border:
347 OutlineInputBorder(borderRadius: BorderRadius.circular(22.0)),
348 ),
349 ),
350 ),
351 new MaterialButton(
352 shape: RoundedRectangleBorder(
353 borderRadius: new BorderRadius.circular(30.0)),
354 onPressed: () {
355 _sendResetPasswordMail();
356 },
357 minWidth: MediaQuery.of(context).size.width,
358 padding: EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
359 color: Colors.blueAccent,
360 textColor: Colors.white,
361 child: Text(
362 "Send Password Reset Mail",
363 textAlign: TextAlign.center,
364 ),
365 ),
366 ],
367 );
368 }
369
370 _removeUserContainer() {
371 return new MaterialButton(
372 shape:
373 RoundedRectangleBorder(borderRadius: new BorderRadius.circular(30.0)),
374 onPressed: () {
375 _removeUser();
376 },
377 minWidth: MediaQuery.of(context).size.width,
378 padding: EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
379 color: Colors.red,
380 textColor: Colors.white,
381 child: Text(
382 "Remove User",
383 textAlign: TextAlign.center,
384 ),
385 );
386 }
387}
سپس یک صفحه به نام root_page.dart ایجاد کرده و کد زیر را در آن قرار میدهیم:
1import 'package:flutter/material.dart';
2import './login_signup_page.dart';
3import '../services/authentication.dart';
4import './home_page.dart';
5
6class RootPage extends StatefulWidget {
7 RootPage({this.auth});
8
9 final BaseAuth auth;
10
11 @override
12 State<StatefulWidget> createState() => new _RootPageState();
13}
14
15enum AuthStatus {
16 NOT_DETERMINED,
17 NOT_LOGGED_IN,
18 LOGGED_IN,
19}
20
21class _RootPageState extends State<RootPage> {
22 AuthStatus authStatus = AuthStatus.NOT_DETERMINED;
23 String _userId = "";
24
25 @override
26 void initState() {
27 super.initState();
28 widget.auth.getCurrentUser().then((user) {
29 setState(() {
30 if (user != null) {
31 _userId = user?.uid;
32 }
33 authStatus =
34 user?.uid == null ? AuthStatus.NOT_LOGGED_IN : AuthStatus.LOGGED_IN;
35 });
36 });
37 }
38
39 void _onLoggedIn() {
40 widget.auth.getCurrentUser().then((user){
41 setState(() {
42 _userId = user.uid.toString();
43 });
44 });
45 setState(() {
46 authStatus = AuthStatus.LOGGED_IN;
47
48 });
49 }
50
51 void _onSignedOut() {
52 setState(() {
53 authStatus = AuthStatus.NOT_LOGGED_IN;
54 _userId = "";
55 });
56 }
57
58 Widget _buildWaitingScreen() {
59 return Scaffold(
60 body: Container(
61 alignment: Alignment.center,
62 child: CircularProgressIndicator(),
63 ),
64 );
65 }
66
67 @override
68 Widget build(BuildContext context) {
69 switch (authStatus) {
70 case AuthStatus.NOT_DETERMINED:
71 return _buildWaitingScreen();
72 break;
73 case AuthStatus.NOT_LOGGED_IN:
74 return new LoginSignUpPage(
75 auth: widget.auth,
76 onSignedIn: _onLoggedIn,
77 );
78 break;
79 case AuthStatus.LOGGED_IN:
80 if (_userId.length > 0 && _userId != null) {
81 return new HomePage(
82 userId: _userId,
83 auth: widget.auth,
84 onSignedOut: _onSignedOut,
85 );
86 } else return _buildWaitingScreen();
87 break;
88 default:
89 return _buildWaitingScreen();
90 }
91 }
92}
در این کد تصمیمگیری میشود که در زمان بارگذاری اپلیکیشن کدام صفحه باید بارگذاری شود. اگر کاربر ورود کرده باشد، به صفحه ورود هدایت میشود. در غیر این صورت اگر کاربر از قبل احراز هویت شده باشد، به صفحه اصلی هدایت خواهد شد.
در نهایت فایل main.dart را به صورت زیر تغییر میدهیم:
1import 'package:flutter/material.dart';
2import './pages/root_page.dart';
3import './services/authentication.dart';
4
5void main() => runApp(MyApp());
6
7
8class MyApp extends StatelessWidget {
9
10 @override
11 Widget build(BuildContext context) {
12 return MaterialApp(
13 title: 'Startup Name Generator',
14 home: new RootPage(auth: new Auth())
15 );
16 }
17
18}
اکنون میتوانید اپلیکیشن را با اجرای دستور flutter run روی ترمینال باز کنید.
سخن پایانی
در این راهنما با شیوه استفاده از فایربیس برای لاگین کاربران از طریق اپلیکیشنهای موبایل و اجرای کارکردهای دیگر در فایربیس آشنا شدیم. بدین ترتیب میتوانید یک اپلیکیشن احراز هویت با استفاده از فایربیس ایجاد کنید. اگر در هر مرحله از اجرای اپلیکیشن با مشکل مواجه شدید، میتوانید کد کامل این پروژه را در این ریپوی گیتهاب (+) ملاحظه کنید.
اگر این مطلب برای شما مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای برنامهنویسی اندروید
- مجموعه آموزشهای برنامهنویسی جاوا
- مجموعه آموزشهای برنامهنویسی
- مفاهیم مقدماتی فلاتر (Flutter) — به زبان ساده
- تشخیص چهره با فلاتر — راهنمای کاربردی
- اپلیکیشن چند پلتفرمی دسته بندی تصاویر با فلاتر و Fastai — از صفر تا صد
==