This commit is contained in:
Sai Naw Wun
2020-10-07 02:33:06 +06:30
parent 01a2798a74
commit 65dda16fe6
475 changed files with 1543 additions and 90780 deletions

View File

@@ -0,0 +1,288 @@
import 'dart:async';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:fcs/domain/constants.dart';
import 'package:fcs/domain/entities/auth_result.dart' as fcs;
import 'package:fcs/domain/entities/auth_status.dart';
import 'package:fcs/domain/entities/setting.dart';
import 'package:fcs/domain/entities/user.dart';
import 'package:fcs/domain/exceiptions/signin_exception.dart';
import 'package:fcs/helpers/api_helper.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:logging/logging.dart';
class AuthFb {
final log = Logger('AuthFb');
static final AuthFb instance = AuthFb._();
AuthFb._();
StreamController<User> controller;
static final FirebaseAuth _fb = FirebaseAuth.instance;
static String _verificationId;
Future<fcs.AuthResult> sendSmsCodeToPhoneNumber(String phoneNumber) {
Completer<fcs.AuthResult> completer = Completer();
bool codeSentCompleted = false;
final PhoneVerificationCompleted verificationCompleted =
(AuthCredential credential) async {
AuthResult _authResult;
try {
_authResult = await _fb.signInWithCredential(credential);
print("PhoneVerificationCompleted :$_authResult");
if (_authResult == null) {
throw SigninException("Sigin error!");
}
} catch (e) {
print("Exception:$e");
// throw e;
completer.completeError(SigninException(e.toString()));
return;
}
fcs.AuthResult auth =
fcs.AuthResult(authStatus: AuthStatus.AUTH_VERIFIED);
completer.complete(auth);
print(
'Inside _sendCodeToPhoneNumber: signInWithPhoneNumber auto succeeded: ${_authResult.user}');
};
final PhoneVerificationFailed verificationFailed =
(AuthException authException) async {
print(
'Phone number verification failed. Code: ${authException.code}. Message: ${authException.message}');
completer.completeError(SigninException(
"Phone number verification failed:${authException.message}"));
};
final PhoneCodeSent codeSent =
(String verificationId, [int forceResendingToken]) async {
_verificationId = verificationId;
print("codeSent " + phoneNumber);
codeSentCompleted = true;
completer.complete(fcs.AuthResult(authStatus: AuthStatus.SMS_SENT));
};
final PhoneCodeAutoRetrievalTimeout codeAutoRetrievalTimeout =
(String verificationId) {
print("codeAutoRetrievalTimeout $verificationId ");
_verificationId = verificationId;
if (codeSentCompleted) {
completer.complete(fcs.AuthResult(authStatus: AuthStatus.SMS_SENT));
} else {
completer.completeError(SigninException("SMS code failed"));
}
};
_fb.verifyPhoneNumber(
phoneNumber: phoneNumber,
timeout: const Duration(seconds: 0),
verificationCompleted: verificationCompleted,
verificationFailed: verificationFailed,
codeSent: codeSent,
codeAutoRetrievalTimeout: codeAutoRetrievalTimeout);
return completer.future;
}
Future<fcs.AuthResult> signInWithPhoneNumber(String smsCode) async {
User user;
try {
final AuthCredential credential = PhoneAuthProvider.getCredential(
verificationId: _verificationId,
smsCode: smsCode,
);
AuthResult _authResult = await _fb.signInWithCredential(credential);
if (_authResult == null) {
throw SigninException("Sigin error!");
}
await _addUserToStream(refreshIdToken: true);
} on Exception catch (e) {
return Future.error(SigninException(e.toString()));
}
if (user == null) Future.error(SigninException("No current user!"));
return Future.value(fcs.AuthResult(authStatus: AuthStatus.AUTH_VERIFIED));
}
Future<void> signout() async {
if (userListener != null) await userListener.cancel();
return _fb.signOut();
}
Future<void> _addUserToStream({bool refreshIdToken = false}) async {
FirebaseUser firebaseUser = await _fb.currentUser();
if (firebaseUser == null) return null;
IdTokenResult idToken =
await firebaseUser.getIdToken(refresh: refreshIdToken);
log.info("Claims:${idToken.claims}");
String cid = idToken.claims["cid"];
User user;
if (cid != null && cid != "") {
user = await _getUserFromFirestore(cid);
}
if (user == null) {
controller.add(null);
return;
}
// add privileges
String privileges = idToken.claims["pr"];
if (privileges != null && privileges != "") {
user.privileges = privileges.split(":").toList();
}
controller.add(user);
}
Future<User> _getUserFromFirestore(String userID) async {
DocumentSnapshot snap = await Firestore.instance
.collection(user_collection)
.document(userID)
.get();
if (snap.exists) {
User user = User.fromMap(snap.data, snap.documentID);
return user;
}
return null;
}
Future<bool> isLogin() async {
final FirebaseUser firebaseUser = await _fb.currentUser();
return Future.value(firebaseUser != null);
}
Future<void> signup(String userName) async {
await requestAPI("/signup", "POST",
payload: {
'user_name': userName,
},
token: await getToken());
await _addUserToStream(refreshIdToken: true);
_startUserListener();
return;
}
Future<void> joinInvite(String userName) async {
await requestAPI("/join_invite", "POST",
payload: {
'user_name': userName,
},
token: await getToken());
// refresh token once signup
await _addUserToStream(refreshIdToken: true);
_startUserListener();
return;
}
Future<bool> hasInvite() async {
var invited =
await requestAPI("/check_invitation", "GET", token: await getToken());
return invited["invited"];
}
Future<void> updateProfile(String newUserName) async {
return await requestAPI("/profile", "PUT",
payload: {"user_name": newUserName}, token: await getToken());
}
Future<String> getToken() async {
FirebaseUser firebaseUser = await _fb.currentUser();
IdTokenResult token = await firebaseUser.getIdToken();
return token.token;
}
Future<Setting> getSetting() async {
var snap = await Firestore.instance
.collection(config_collection)
.document(setting_doc_id)
.get();
if (!snap.exists) {
return null;
}
// _listSetting();
return Setting.fromMap(snap.data);
}
Stream<Setting> settings() async* {
Stream<DocumentSnapshot> snapshot = Firestore.instance
.collection(config_collection)
.document(setting_doc_id)
.snapshots();
await for (var snap in snapshot) {
Setting setting = Setting.fromMap(snap.data);
yield setting;
}
}
Future<String> _getCurrentUserID() async {
FirebaseUser firebaseUser = await _fb.currentUser();
if (firebaseUser == null) return null;
IdTokenResult idToken = await firebaseUser.getIdToken();
String cid = idToken.claims["cid"];
return cid;
}
Future<void> _startUserListener() async {
if (userListener != null) userListener.cancel();
String _userID = await _getCurrentUserID();
if (_userID == null) {
return;
}
Stream<DocumentSnapshot> snapshot = Firestore.instance
.collection(user_collection)
.document(_userID)
.snapshots();
userListener = snapshot.listen((snap) async {
User user = User.fromMap(snap.data, snap.documentID);
FirebaseUser firebaseUser = await _fb.currentUser();
if (firebaseUser == null) {
userListener.cancel();
return;
}
// get privilege from claim
IdTokenResult idToken = await firebaseUser.getIdToken(refresh: true);
String privileges = idToken.claims["pr"];
if (privileges != null && privileges != "") {
user.privileges = privileges.split(":").toList();
}
controller.add(user);
});
}
StreamSubscription<DocumentSnapshot> userListener;
Stream<User> user() {
// ignore: close_sinks
StreamSubscription<FirebaseUser> authListener;
Future<void> _start() async {
authListener = _fb.onAuthStateChanged.listen((firebaseUser) async {
if (firebaseUser == null) {
controller.add(null);
} else {
_addUserToStream(refreshIdToken: true);
_startUserListener();
}
});
}
void _stop() {
if (userListener != null) {
userListener.cancel();
}
if (authListener != null) {
authListener.cancel();
}
}
controller = StreamController<User>(
onListen: _start, onPause: _stop, onResume: _start, onCancel: _stop);
return controller.stream;
}
}

View File

@@ -0,0 +1,35 @@
import 'package:fcs/domain/entities/payment_method.dart';
import 'package:fcs/domain/vo/message.dart';
import 'package:fcs/helpers/api_helper.dart';
import 'package:fcs/helpers/firebase_helper.dart';
import 'package:logging/logging.dart';
class CommonDataProvider {
final log = Logger('CommonDataProvider');
Future<void> createPaymentMethod(PaymentMethod paymentMethod) async {
return await requestAPI("/payment_methods", "POST",
payload: paymentMethod.toMap(), token: await getToken());
}
Future<void> updatePaymentMethod(PaymentMethod paymentMethod) async {
return await requestAPI("/payment_methods", "PUT",
payload: paymentMethod.toMap(), token: await getToken());
}
Future<void> deletePaymentMethod(String id) async {
return await requestAPI("/payment_methods", "DELETE",
payload: {"id": id}, token: await getToken());
}
Future<void> sendMessage(Message message) async {
return await requestAPI("/messages", "POST",
payload: message.toMap(), token: await getToken());
}
Future<void> seenMessage(String ownerID, bool seenByOwner) async {
return await requestAPI("/messages/seen", "POST",
payload: {"owner_id": ownerID, "seen_by_owner": seenByOwner},
token: await getToken());
}
}

View File

@@ -0,0 +1,69 @@
import 'dart:io';
import 'package:fcs/data/services/messaging_service.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:logging/logging.dart';
final msgLog = Logger('backgroundMessageHandler');
Future<dynamic> backgroundMessageHandler(Map<String, dynamic> message) async {
if (message.containsKey('data')) {
// Handle data message
final dynamic data = message['data'];
msgLog.info("background onMessage: $message");
}
if (message.containsKey('notification')) {
// Handle notification message
final dynamic notification = message['notification'];
}
}
class MessagingFCM {
final log = Logger('MessagingFCM');
FirebaseMessaging _firebaseMessaging;
MessagingFCM(OnNotify onMessage,
{OnNotify onLaunch, OnNotify onResume, OnSetupComplete onSetupComplete}) {
_firebaseMessaging = FirebaseMessaging();
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async {
log.info("onMessage: $message");
if (onMessage != null) _onNotify(message, onMessage);
},
onBackgroundMessage: Platform.isIOS ? null : backgroundMessageHandler,
onLaunch: (Map<String, dynamic> message) async {
log.info("onLaunch: $message");
if (onLaunch != null) _onNotify(message, onLaunch);
},
onResume: (Map<String, dynamic> message) async {
log.info("onResume: $message");
if (onResume != null) _onNotify(message, onResume);
},
);
_firebaseMessaging
.requestNotificationPermissions(const IosNotificationSettings());
_firebaseMessaging.onIosSettingsRegistered
.listen((IosNotificationSettings settings) {
log.info("Settings registered: $settings");
});
_firebaseMessaging.getToken().then((String token) {
if (onSetupComplete != null) onSetupComplete(token);
log.info("Messaging Token:$token");
});
}
Future<void> subscribeToTopic(String topic) {
return _firebaseMessaging.subscribeToTopic(topic);
}
_onNotify(Map<String, dynamic> message, OnNotify onNotify) {
var data = message['data'] ?? message;
onNotify(Map<String, dynamic>.from(message));
}
Future<void> unsubscribeToTopic(String topic) {
return _firebaseMessaging.unsubscribeFromTopic(topic);
}
}

View File

@@ -0,0 +1,52 @@
import 'dart:convert';
import 'package:fcs/config.dart';
import 'package:fcs/domain/constants.dart';
import 'package:fcs/domain/entities/package.dart';
import 'package:fcs/helpers/api_helper.dart';
import 'package:fcs/helpers/firebase_helper.dart';
import 'package:logging/logging.dart';
class PackageDataProvider {
final log = Logger('PackageDataProvider');
Future<void> createPackages(List<Package> packages, String fcsID) async {
List<Map<String, dynamic>> json = packages.map((e) => e.toJson()).toList();
return await requestAPI("/packages", "POST",
payload: {"packages": json, "fcs_id": fcsID}, token: await getToken());
}
Future<void> deletePackage(Package package) async {
return await requestAPI("/packages", "DELETE",
payload: {"id": package.id}, token: await getToken());
}
Future<List<Package>> searchPackage(String term) async {
if (term == null || term == '') return List();
var bytes = utf8.encode(term);
var base64Str = base64.encode(bytes);
HtmlEscape htmlEscape = const HtmlEscape();
String escapePackage = htmlEscape.convert(base64Str);
int limit = 20;
List<Package> packages = [];
try {
var data = await requestAPI(
"/api/fts/$packages_collection/$escapePackage/$limit", "GET",
url: Config.instance.reportURL, token: await getToken());
if (data == null) return List();
data.forEach((p) {
var package = Package.fromJson(p);
packages.add(package);
});
} catch (e) {
log.warning("buyer error:" + e.toString());
return null;
}
return packages;
}
}

View File

@@ -0,0 +1,83 @@
import 'dart:convert';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:fcs/config.dart';
import 'package:fcs/domain/constants.dart';
import 'package:fcs/domain/entities/user.dart';
import 'package:fcs/helpers/api_helper.dart';
import 'package:fcs/helpers/firebase_helper.dart';
import 'package:logging/logging.dart';
class UserDataProvider {
final log = Logger('UserDataProvider');
Future<void> inviteUser(String userName, String phoneNumber) async {
return await requestAPI("/invites", "POST",
payload: {"user_name": userName, "phone_number": phoneNumber},
token: await getToken());
}
Future<void> deleteInvite(String phoneNumber) async {
return await requestAPI("/invites", "DELETE",
payload: {"phone_number": phoneNumber}, token: await getToken());
}
Future<void> acceptRequest(String userID) async {
return await requestAPI("/accept_request", "PUT",
payload: {"id": userID}, token: await getToken());
}
Future<void> uploadMsgToken(String token) async {
return await requestAPI("/messages/token", "POST",
payload: {"token": token}, token: await getToken());
}
Future<void> removeMsgToken(String token) async {
return await requestAPI("/messages/token", "DELETE",
payload: {"token": token}, token: await getToken());
}
Future<User> findUser(String phoneNumber) async {
QuerySnapshot querySnap = await Firestore.instance
.collection(user_collection)
.where("phone_number", isEqualTo: phoneNumber)
.limit(1)
.getDocuments();
if (querySnap.documents.length > 0) {
var snap = querySnap.documents.first;
User user = User.fromMap(snap.data, snap.documentID);
return user;
}
return null;
}
Future<List<User>> searchUser(String term) async {
if (term == null || term == '') return List();
var bytes = utf8.encode(term);
var base64Str = base64.encode(bytes);
HtmlEscape htmlEscape = const HtmlEscape();
String escapeBuyer = htmlEscape.convert(base64Str);
int limit = 20;
List<User> users = [];
try {
var data = await requestAPI(
"/api/fts/$user_collection/$escapeBuyer/$limit", "GET",
url: Config.instance.reportURL, token: await getToken());
if (data == null) return List();
data.forEach((buyer) {
var user = User.fromJson(buyer);
users.add(user);
});
} catch (e) {
log.warning("buyer error:" + e.toString());
return null;
}
return users;
}
}