Firebase delete and retrieve data with Angularjs - firebase

I am new to firebase, and wondering how I can implement deleting the data in Angular view (interface), but still keep it in the Firebase database. Currently, due to the three way binding (use Firebase.remove() function), the data will be deleted in the database when it is deleted in Angular view. See in Plunker here:
http://plnkr.co/edit/BBtD2YoUBHBAyhu0puXd?p=info
Here is the remove user part:
// Remove user
$scope.removeRecord = function(userId) {
var userUrl = fbURL + user_table + '/' + userId;
$scope.user = $firebase(new Firebase(userUrl));
$scope.user.$remove()
$scope.alerts.splice(0, 1);
$scope.alerts.push({
type: 'success',
msg: "User removed successfully!"
});
};
Or is that possible I can retrieve a data from Firebase based on my custom query? So maybe I can distinguish the deleted data from the existing data in Firebase database?

because i want to have all the data in database even it is get deleted
This is typically referred to as a "soft delete" and it essentially means you simply mark the data as "deleted.
Say you have this data:
messages
-J4378sdfisdf
name: "Lisa"
message: "I am new to firebase, and wondering..."
-J4378sdfjteg
name: "Chrillewoodz"
message: "Try doing this instead..."
-J4378sdfkufh
name: "Frank van Puffelen"
message: "This is typically referred to as a..."
Instead of only removing the messages from view, you instead mark them as "deleted"/hidden. In the sample below, I added a visible field for the purpose:
messages
-J4378sdfisdf
name: "Lisa"
message: "I am new to firebase, and wondering..."
visible: true
-J4378sdfjteg
name: "Chrillewoodz"
message: "Try doing this instead..."
visible: true
-J4378sdfkufh
name: "Frank van Puffelen"
message: "This is typically referred to as a..."
visible: false
And then you can use a Firebase query to get only the messages that have not been hidden:
var ref = new Firebase('https://yours.firebaseio.com');
var query = ref.child('messages').orderByChild('visible').equalTo(true);
$scope.messages = $firebaseArray(query);

Try doing this instead:
<button ng-click="removeRecord(user)">Delete</button>
$scope.removeRecord = function(user) {
user.remove();
$scope.alerts.splice(0, 1);
$scope.alerts.push({
type: 'success',
msg: "User removed successfully!"
});
};
This way you're not accessing the user in Firebase, but in the view instead.
You should pass the user object into the function instead of its ID. The way you were doing it you were accessing the user in Firebase rather in the view only.

Related

Set or Add in Firebase which I need to use for creating a new Database entry?

I want to save User's name in a Database of Firebase called profiles
While I am using the below code it is not creating any entry in my database:
register() {
fb.auth().createUserWithEmailAndPassword(this.email, this.password)
.then((user)=>{
db.collection('profiles').doc(user.user.uid).set({
name: this.profile.name
})
}
I have a profile object. So, it is not a problem.
If I use add like the below, it is creating entry.
db.collection('profiles').add({
name: this.profile.name
})
But Problem is while I am trying to retrieve it's ID, it is not giving me the correct result.
db.collection("profiles").doc(user.uid).update({
name: this.profile.name,
mobile: this.profile.mobile,
postcode: this.profile.postcode
});
uid is not matching.
ERROR:
[Vue warn]: Error in v-on handler: "FirebaseError: [code=invalid-argument]: Function DocumentReference.update() called with invalid data. Unsupported field value: undefined (found in field name)"

How to use Sign-In User ID to send push notifications

I have some users signed into my actions-on-google app via Google Sign-In ( https://developers.google.com/actions/identity/google-sign-in )
I want to sent push notifications to one of those users.
For getting push notifications work with actions in the first place, I tried this sample: https://github.com/actions-on-google/dialogflow-updates-nodejs/blob/master/functions/index.js but I only can get this to work without this commit: https://github.com/actions-on-google/dialogflow-updates-nodejs/commit/c655062047b49e372da37af32376bd06d837fc7f#diff-1e53ef2f51bd446c876676ba83d7c888
It works fine, but I think const userID = conv.user.id; returns the deprecated Anonymous User ID. The commit suggests to use const userID = conv.arguments.get('UPDATES_USER_ID'); which returns undefined.
I use this nodejs code to send the push notifications.
const request = require('request');
const {JWT} = require('google-auth-library');
const serviceAccount = require('./service-account.json');
let jwtClient = new JWT(
serviceAccount.client_email, null, serviceAccount.private_key,
['https://www.googleapis.com/auth/actions.fulfillment.conversation'],
null
);
jwtClient.authorize((authErr, tokens) => {
let notification = {
userNotification: {
title: process.argv[2],
},
target: {
userId: USERID,
intent: 'tell_latest_status',
// Expects a IETF BCP-47 language code (i.e. en-US)
locale: 'en-US'
},
};
request.post('https://actions.googleapis.com/v2/conversations:send', {
'auth': {
'bearer': tokens.access_token,
},
'json': true,
'body': {
'customPushMessage': notification, 'isInSandbox': true
},
}, (reqErr, httpResponse, body) => {
console.log(httpResponse.statusCode + ': ' + httpResponse.statusMessage);
});
});
I simply can't get this to work with the const userID = conv.arguments.get('UPDATES_USER_ID'); version, because as I said
When I use conv.user.profile.payload.sub as suggested here: https://developers.google.com/actions/identity/user-info the AoG API returns "SendToConversation response: Invalid user id for target."
Is there any way to make this work with Google Sign-In?
Has anyone made this work? I mean with the UPDATES_USER_ID field?
I already created an issue on the samples repo: https://github.com/actions-on-google/dialogflow-updates-nodejs/issues/15 but I was sent here.
Thanks!
While researching why I sometimes got undefined I found an answer on this question that solved my issue.
I've found solution for this problem. While getting UPDATES_USER_ID
conv.arguments.get() only works for first attempt. So, while building
your action you must save it. If you didn't store or save, you can
reset your profile and try again, you will be able to get.
You can reset your user profile for the action here.

Should firebase auth onCreate trigger have more data?

I'm using functions.auth.user().onCreate() as part of a firestore project, and trying to set up some default data when a new user registers. For the front end, I'm using firebase-ui, with Google and Email/Password providers enabled.
When I sign in with an email and password, the UI widget prompts to enter a name and set a password. I was expecting to see the name as part of the user parameter in the onCreate() function call, but I'm getting practically nothing:
user: { email: 'xxx#yyyy.co.uk',
emailVerified: false,
displayName: null,
photoURL: null,
phoneNumber: null,
disabled: false,
providerData: [],
customClaims: {},
passwordSalt: null,
passwordHash: null,
tokensValidAfterTime: null,
metadata:
UserRecordMetadata {
creationTime: '2018-11-20T15:06:01Z',
lastSignInTime: '2018-11-20T15:06:01Z' },
uid: 'QDJ5OJTwbvNo2QNDVQV9VsxC2pz2',
toJSON: [Function] }
Not even getting the provider info so I can tell which 'kind' of user registered. It's almost like this function is triggered before the user record has been populated (except the email address does get through). Also, registrations via the Google provider come with a fully-populated user record, so I guess this is a problem with Email/Password specifically.
Is this a bug, or am I missing something? I didn't see anything else useful in the context parameter either.
The fact that displayName is not populated in the Cloud Functions onCreate trigger for email+password is expected. The function is triggered from the first API call (createUserWithEmailAndPassword()), while the display name is set with a second API call (updateProfile).
The usual workaround would be to create a Cloud Function to update the user profile, as shown here: Firebase Auth+Functions | create user with displayName
I also highly recommend filing a feature request to be able to have a Cloud Function triggered on profile changes.

How do I delete user analytics data from Firebase using userDeletionRequests:upsert?

Problem Description
My Android app collects data via Google Analytics for Firebase. For privacy reasons, users must be able to wipe their data off the Firebase servers, should they choose to do so.
The app requests a deletion by forwarding its Firebase APP_INSTANCE_ID to my own server. This server has been prepared in advance with credentials, from my personal Google account (via oauth2), for managing the Firebase project. The server authenticates with www.googleapis.com, and, using the supplied APP_INSTANCE_ID, invokes the upsert.
As noted by the documentation, the generic Google Analytics API is appropriate for this task.
After some initial trouble (b/c I didn't have the correct auth scope, and the Analytics API wasn't properly enabled), googleapis.com now returns HTTP 200 for each upsert request. (As an aside, even if you supply a bogus APP_INSTANCE_ID, it returns 200.)
Here is a sample response from the upsert, which shows nothing amiss:
{ kind: 'analytics#userDeletionRequest',
id:
{ type: 'APP_INSTANCE_ID',
userId: (REDACTED 32-char hexidecimal string) },
firebaseProjectId: (REDACTED),
deletionRequestTime: '2018-08-28T12:46:30.874Z' }
I know the firebaseProjectId is correct, because if I alter it, I get an error. I have verified that the APP_INSTANCE_ID is correct, and stable up until the moment it is reset with resetAnalyticsData().
Test Procedure
To test the deletions, I populated Firebase with several custom events, using the procedure below (Nexus 5X emulator, no Google Play, no Google accounts configured, but that shouldn't make any difference):
Install the app
Fire off some custom events (FirebaseAnalytics.logEvent)
Observe those events appear on the Firebase console
(About a minute later:) Make the upsert call, observe HTTP 200, and note the "deletionRequestTime"
Immediately call FirebaseAnalytics.resetAnalyticsData (to clear any event data cached on the device)
Uninstall the app
Rinse & repeat 7 or 8 times
However, even 24 hours later, 100% of the Firebase events are still present in the events table. No discernable state change has taken place on the Firebase server as a result of the upserts.
Question
So, what am I doing wrong? how do I successfully delete user data from Google Analytics for Firebase?
EDIT
Here's the code I'm using to make a request (from node.js):
const request = require( 'request' );
...
_deletePersonalData( data )
{
return new Promise( (resolve, reject) => {
request.post({
url: 'https://www.googleapis.com/analytics/v3/userDeletion/userDeletionRequests:upsert',
body: {
kind: 'analytics#userDeletionRequest',
id: {
type: 'APP_INSTANCE_ID',
userId: data.firebaseAppInstanceId
},
firebaseProjectId: (REDACTED)
},
headers: {
Authorization: 'Bearer ' + iap.getCurAccessToken()
},
json: true
}, (err, res, body) => {
console.log( 'user-deletion POST complete' );
console.log( 'Error ' + err );
console.log( 'Body ', body );
if( err )
{
reject( err );
return;
}
if( body.error )
{
reject( new Error( 'The Google service returned an error: ' + body.error.message + ' (' + body.error.code + ')' ) );
return;
}
resolve({ deletionRequestTime: body.deletionRequestTime });
});
});
}
Here's a sample request body:
{
kind: 'analytics#userDeletionRequest',
id: {
type: 'APP_INSTANCE_ID',
userId: (REDACTED 32-char hexidecimal string)
},
firebaseProjectId: (REDACTED)
}
And here's the console output for that same request (same userId and everything):
user-deletion POST complete
Error: null
Body: { kind: 'analytics#userDeletionRequest',
id:
{ type: 'APP_INSTANCE_ID',
userId: (REDACTED 32-char hexidecimal string) },
firebaseProjectId: (REDACTED),
deletionRequestTime: '2018-08-29T17:32:06.949Z' }
Firebase support just got back to me, and I quote:
Upsert method deletes any individual user data we have logged, but aggregate metrics are not recomputed. This means that you might not see any changes in the events tab in your Analytics console.
So, basically my mistake was expecting the events to disappear from the console.
This, of course, raises the question of how one determines that the API is actually working... but maybe the HTTP 200 is enough.

Meteor.users is undefined

I got an error saying
TypeError: Cannot read property 'insert' of undefined
when I run my application, and I discovered that the undefined thing mentioned before is "Meteor.users"
as it's used to insert some data to the database like so (that is the cause of the error):
var tomId = Meteor.users.insert({username: "Tom",
profile: { name: 'Tom Coleman', username:"Tom" }
});
and I don't know how to make it work normally without being undefined
any help ?
To create a new user in your application's users collection the easiest and safest way is to add accounts-base package first and then using it's API.
Add accounts-base by
meteor add accounts-base
Then what you need to do is:
import { Accounts } from 'meteor/accounts-base';
//now create your user
Accounts.createUser({
username: YOUR_USERNAME,
email: EMAIL_ADDRESS,
password: PASSWORD,
profile: {
// WHATEVER OBJECT
}
});

Resources