[轉]Keep your promises when using Cloud Functions for Firebase!

https://firebase.googleblog.com/2017/06/keep-your-promises-when-using-cloud.html?fbclid=IwAR2FuvlU2CbwjV-I75q7-WIkJyLHRYT-R3cyleEUWF3Fsq42THMCwZN6by8 const ref_p1_state = root.child(`player_states/${game_state.p1uid}`) const ref_p2_state = root.child(`player_states/${game_state.p2uid}`) const pr_update_p1 = ref_p1_state.update(update_p1) const pr_update_p2 = ref_p2_state.update(update_p2) return Promise.all([pr_update_p1, pr_update_p2]) ========== https://stackoverflow.com/questions/55430079/promise-all-does-not-wait-for-firestore-query-to-loop

2020-03-10 · 1 min · 22 words · Me

firestore import

使用 https://github.com/dalenguyen/firestore-backup-restore base on https://github.com/dalenguyen/firestore-import-export 能處理timestamp

2020-03-04 · 1 min · 6 words · Me

filestore2json json2filestore

https://gist.github.com/sturmenta/cbbe898227cb1eaca7f85d0191eaec7e#gistcomment-2837988 ok can use. good job. timestamp have error.

2020-03-04 · 1 min · 9 words · Me

Firebase auth and upload image

bootstrap + web firebase realtime + firebase storage Auth:Use Email&password then input one user with email & password. Login use be added user. index.html <!doctype html> <html lang="zh-Hant-TW"> <head> <!-- Required meta tags --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <!-- Bootstrap CSS --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> <link type="text/css" rel="stylesheet" href="https://cdn.firebase.com/libs/firebaseui/4.0.0/firebaseui.css" /> <title>Hello, world!</title> </head> <body> <div class="container"> <div id="firebaseui-auth-container" class="alert alert-light" role="alert"></div> </div> <div class="container my-1"> <div class="row"> <div class="col-sm">Login Status <div class="user-signed-in" style="display: none;"><span class="badge badge-pill badge-success">user-signed-in</span></div> <div class="user-signed-out" style="display: none;"><span class="badge badge-pill badge-secondary">user-signed-out</span></div> </div> <div class="col-sm"><a class="btn btn-outline-primary" data-toggle="collapse" href="#multiCollapseExample1" role="button" aria-expanded="false" aria-controls="multiCollapseExample1">Account Details</a> <div class="collapse multi-collapse" id="multiCollapseExample1"> <div class="card card-body"> <pre id="account-details">...</pre> </div> </div> </div> </div> </div> <div class="container my-1"> <div class="row justify-content-end"> <div class="col-2"> <div id="sign-in" class="btn btn-outline-primary" style="display: none;">sign-in</div> <div id="sign-out" class="btn btn-outline-danger" style="display: none;">sign-out</div> </div> </div> </div> <div class="container my-1"> <div class="row justify-content-center"> <div id="loading" class="spinner-border" role="status"> <span class="sr-only">Loading...</span> </div> </div> </div> <div class="container my-1"> <div id="loaded" class="user-signed-in" style="display: none;">檔案上傳 <div id="filesubmit"> <input type="file" class="file-select" accept="image/*"/> <button class="file-submit">SUBMIT</button> </div> </div> </div> <div class="container my-1"> <div class="row"> <div class="col-2"> <div id="test" class="btn btn-outline-primary">test</div> </div> </div> </div> <!-- Optional JavaScript --> <!-- jQuery first, then Popper.js, then Bootstrap JS --> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script> <script src="https://cdn.firebase.com/libs/firebaseui/4.0.0/firebaseui.js"></script> <script src="https://www.gstatic.com/firebasejs/ui/4.0.0/firebase-ui-auth__zh_tw.js"></script> <script defer src="https://www.gstatic.com/firebasejs/6.3.0/firebase-app.js"></script> <script defer src="https://www.gstatic.com/firebasejs/6.3.0/firebase-auth.js"></script> <script defer src="https://www.gstatic.com/firebasejs/6.3.0/firebase-database.js"></script> <!--<script defer src="https://www.gstatic.com/firebasejs/6.3.0/firebase-firestore.js"></script>--> <script defer src="https://www.gstatic.com/firebasejs/6.3.0/firebase-storage.js"></script> <script defer src="./init-firebase.js"></script> <script> </script> <script> document.getElementById('test').addEventListener('click', function() { var fbdbpath = getfbdbPath('images/@/default/'); putimageurl(fbdbpath, 'url'); }); function fileupload(){ //== File upload ======================== document.querySelector('.file-select').addEventListener('change', handleFileUploadChange); document.querySelector('.file-submit').addEventListener('click', handleFileUploadSubmit); let selectedFile; function handleFileUploadChange(e) { selectedFile = e.target.files[0]; } function handleFileUploadSubmit(e) { var metadata = { contentType: 'image/jpeg' }; var fbdbpath = getfbdbPath('images/@/default/'); var newfbdbPostKey= getfbdbPostKey(fbdbpath); var uploadTask = imagesRef.child(`${newfbdbPostKey}`).put(selectedFile, metadata); uploadTask.on('state_changed', function(snapshot){ var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100; console.log('Upload is ' + progress + '% done'); switch (snapshot.state) { case firebase.storage.TaskState.PAUSED: // or 'paused' console.log('Upload is paused'); break; case firebase.storage.TaskState.RUNNING: // or 'running' console.log('Upload is running'); break; } }, function(error) { // Handle unsuccessful uploads alert('Upload is Failed;'); console.log(error); }, function() { uploadTask.snapshot.ref.getDownloadURL().then(function(downloadURL) { console.log('File available at', downloadURL); putimageurl(fbdbpath, downloadURL); }); } ); } } function initsign(){ //== Auth =============================== document.getElementById('sign-in').addEventListener('click', function() { if($('.user-signed-out').css('display') === 'block') ui.start('#firebaseui-auth-container', getUiConfig()); }); document.getElementById('sign-out').addEventListener('click', function() { var user = firebase.auth().currentUser; if (user) { firebase.auth().signOut().then((res)=>{ console.log('signOut ok', res); }).catch((err)=>{ alert('Logout Failed!'); console.warn('signOut error',res); }).finally((res)=>{ console.log('signOut resolved', res); location.reload(); }); } }); } </script> </body> </html> init-firebase.js var firebaseConfig = { apiKey: 'AIzaSyBxxxxxxooooo', authDomain: 'product-xxxxxxooooo.firebaseapp.com', databaseURL: 'https://product-xxxxxxooooo.firebaseio.com', storageBucket: 'gs://product-xxxxxxooooo.appspot.com' }; firebase.initializeApp(firebaseConfig); //== database =========================== var database = firebase.database(); function getfbdbPath(type){ var userId = firebase.auth().currentUser.uid; return type.replace("@", userId); } function getfbdbPostKey(path){ return firebase.database().ref().child(path).push().key; } function putimageurl(path, url){ //var userId = firebase.auth().currentUser.uid; var path = getfbdbPath('images/@/default/'); var postImg = { active: true, url: url, }; var newPostKey = getfbdbPostKey(path); var images = {}; images[path + newPostKey] = postImg; //updates['/user-posts/' + userId + '/' + newPostKey] = postData; var uploadImagesResult = firebase.database().ref().update(images); console.log('uploadImagesResult'); console.log(uploadImagesResult); } function test(){ var userId = firebase.auth().currentUser.uid; firebase.database().ref('users/' + userId).set({ username: 'name', email: 'email', profile_picture : 'imageUrl' }, function(error) { if (error) { console.log(error) // The write failed... } else { // Data saved successfully! console.log("successfullly!") } }); var c = firebase.database().ref('/users/' + userId).once('value').then(function(snapshot) { var username = (snapshot.val() && snapshot.val().username) || 'Anonymous'; // ... console.log("username:", username); }); console.log('c'); console.log(c); var postData = { author: 'username', uid: userId, }; var newPostKey = firebase.database().ref().child('posts').push().key; var updates = {}; updates['/posts/' + newPostKey] = postData; //updates['/user-posts/' + userId + '/' + newPostKey] = postData; //firebase.database().ref('posts/' + userId).set(postData); var t = firebase.database().ref().update(updates); console.log('t'); console.log(t); } //== File upload ======================== var storageRef = firebase.storage().ref(); var imagesRef = storageRef.child('images'); // var otherProject = firebase.initializeApp(firebaseConfig, 'other'); // console.log(otherProject.name); // "otherProject" // var otherStorage = otherProject.storage(); //== Auth =============================== function getUiConfig() { return { signInSuccessUrl: this.location.href, signInOptions: [ firebase.auth.EmailAuthProvider.PROVIDER_ID, ], //immediateFederatedRedirect: false, }; } // Initialize the FirebaseUI Widget using Firebase. var ui = new firebaseui.auth.AuthUI(firebase.auth()); // The start method will wait until the DOM is loaded. if (ui.isPendingRedirect()) { ui.start('#firebaseui-auth-container', getUiConfig()); } // Disable auto-sign in. // ui.disableAutoSignIn(); var handleSignedInUser = function(user) { $('.user-signed-in').show(); $('.user-signed-out').hide(); $('#sign-in').hide(); $('#sign-out').show(); document.getElementById('account-details').textContent = user.displayName; user.getIdToken().then(function(accessToken) { document.getElementById('account-details').textContent = JSON.stringify({ displayName: user.displayName, email: user.email, emailVerified: user.emailVerified, phoneNumber: user.phoneNumber, photoURL: user.photoURL, uid: user.uid, accessToken: user.accessToken, providerData: user.providerData }, null, ' '); }); }; var handleSignedOutUser = function() { $('.user-signed-in').hide(); $('.user-signed-out').show(); $('#sign-in').show(); $('#sign-out').hide(); //ui.start('#firebaseui-container', getUiConfig()); }; function handleConfigChange() { // Reset the inline widget so the config changes are reflected. ui.reset(); ui.start('#firebaseui-container', getUiConfig()); } firebase.auth().onAuthStateChanged(function(user) { document.getElementById('loading').style.display = 'none'; document.getElementById('loaded').style.display = 'block'; user ? handleSignedInUser(user) : handleSignedOutUser(); }, function(error) { console.log(error); }); initsign(); fileupload(); firebase realtime database rule 95dWpHhg5wOk1loIj0iTneWdfwG2 is admin user <= userId = firebase.auth().currentUser.uid;``` ...

2019-07-22 · 4 min · 826 words · Me

Firebase Database Rules

https://www.oxxostudio.tw/articles/201904/firebase-realtime-database-rules.html https://angularfirebase.com/lessons/understanding-firebase-database-rules-by-example/

2019-07-16 · 1 min · 2 words · Me