What does this error mean on Mobile Safari?
Only ArrayBuffer and ArrayBufferView objects can be passed as
CryptoOperationData
The offending code is this:
return (window.crypto.subtle||window.crypto.webkitSubtle).importKey(
"raw"
, key.buffer
, { name: "HMAC"
, hash: { name: "SHA-1" }
}
, false
, ["sign", "verify"]
)
Note that key is new Uint8Array([251, 23, 127, ... ]) and therefore key.buffer ought to be an instance of ArrayBuffer.
What does iOS want from me!?!?
UPDATE
False alarm. Mobile Safari is missing TypedArray.prototype.slice, which was being polyfilled elsewhere with Array.prototype.slice, which caused the object to not be a buffer.
Related
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.
I have an issue using cordova-sqlite adapter in PouchDB. It works perfect locally (I can create, update and delete docs) but is not able to sync from/to any remote CouchDB server. I tried both IBM Cloudant and a CouchDB server of my own.
If I use IDB adapter instead it works like a charm, but when I change to SQLite is when it cannot sync properly.
This is how I use it (in my case inside a Vue app):
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import PouchDB from 'pouchdb'
...
Object.defineProperty(Vue.prototype, '$pouch', { value: PouchDB }); //this is to be able to use $pouch in any Vue component later on
...
var PouchAdapterCordovaSqlite = require('pouchdb-adapter-cordova-sqlite');
PouchAdapterCordovaSqlite.use_prefix = true; // use the legacy '_pouch' prefix. I tried both with and without this option
PouchDB.plugin(PouchAdapterCordovaSqlite);
...
this.db = new this.$pouch('todos', { adapter: 'cordova-sqlite', location: 'default', androidDatabaseImplementation: 2 });
console.log('PouchDB adapter: ' + this.db.adapter); //it returns 'cordova-sqlite'
let remoteCouch='http://myserveraddress.com:5984/todos'; //todos is the remote database, with CORS enabled and set as public so no user/pass is needed
this.$pouch.sync('todos', remoteCouch, {
live: true,
retry: true
}).on('change', function (info) { console.log('change:' + info}).on('paused', function (err) {//...//}).on --- and so on with 'active', 'denied', 'complete' and 'error'
and later in one Vue component I use this (where this.db refers to the database and this.todos is used to show results on screen:
mounted() {
this.list();
this.db
.changes({
since: "now",
live: true
})
.on("change", this.list);
},
methods: {
list: function() {
let self = this;
this.db.allDocs({ include_docs: true, descending: true }, function(
err,
doc
) {
self.todos = doc.rows;
});
}
}
As I mentioned before it works with IndexedDB but not with SQLite adapter (I used both cordova-sqlite-storage and cordova-plugin-sqlite-2 with same results). Everything starts after deviceready event and sqlite is loaded properly (I am able to use window.sqlitePlugin).
And when it comes to Cordova config.xml I ensured to define this:
<plugin name="cordova-plugin-whitelist"/>
<access origin="*"/>
<allow-intent href="http://*/*"/>
<allow-intent href="https://*/*"/>
...
<plugin name="cordova-plugin-sqlite-2" spec="*"/>
Any clue? I really need to use SQLite instead of IDB because my app will store big amount of data, and I also need an offline-first approach, that's why I use PouchDB.
Another test that I tried was to create a SQLite database manually from my app and it also works, so it seems that the problem is related to pouchdb-adapter-cordova-sqlite.
Screenshot with IDB:
result with idb
And screenshot with SQLite:
result with sqlite
Thanks in advance!
Solved!
The problem was here:
this.$pouch.sync('todos', remoteCouch, {...
It has to be changed to:
this.db.sync(remoteCouch, {...
So it was pointing to pouchdb object instead of the database instance.
I hope it helps someone.
Regards!
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.
I am new to Ext Js,
Created a grid view which has paging toolbar where in i am fetching the data from a store(a json) and i am restrictong the pagelimit using proxy : {
type : 'ajax',
url : '/bills/resources/getXYZ.json',
reader : {
type : 'json',
root : 'data',
totalProperty: 'total'
}
},
pageSize: 2,
noCache: false,
//autoLoad: true
autoLoad: {
params: {
start: 0
}
}..
Despite of this, I still see all the records in the page ,eventhough i limited it to 2.Please help on this.
Thanks in Advance!!..
In ExtJs paging works only if the server supports it. This means that the server must honor the parameters page, start and offset and send only pagesize ( default = 30 ) records.
For this reason, you cannot use paging with a fixed json file, but only with a webservice that sends data in json format.
Im using firebase and for some reason my code is not pushing data and im not seeing the data in the firebase url. My code is this
var chatref = new Firebase('https://flockedin.firebaseio.com/');
chatref.push({ ChatId: $('#conversationId').text(), User: $('#username').html(), Message: $('#txtchat').val() }, function (response) { if (response) { alert('saved'); } });
i get the alert 'saved' but i cant find the data in firebase url.
Also what is the use of API Key that is given for each url in the firebase.
UPDATE:This happens in IE10. In other browsers it works fine
IE10 seems to be working for me. Can you give more details about what version you are using (desktop / tablet / phone?).
Also, is it possible that your jquery selectors were returning null? If all of the values in the object that you set evaluate to null, Firebase treats it like a call to remove. See the note in the docs for set: https://www.firebase.com/docs/javascript-client/firebase/set.html
Try going to your FireBase Console->Database->Rules and set them to:
{
"rules": {
".read": true,
".write": true
}
}
Make sure your app is not public when you do this. Lmk if it helps.