The goal: scan firebase data and delete items older than a given time.
The problem: the query generates a permissions error, though other read operations are allowed. Yet the problem seems to be the .read rule, since when it's taken out, everything works.
I authenticate using a token with "username" and "dataClass" embedded. Authentication normally works fine, and subscribed clients are receiving updates. Debugging log and examining the auth() payload show that the "username" and "dataClass" are correctly embedded in the token and correctly extracted by Firebase.
However, trying to use once() to get a subset of data older than a certain age generates a permission error. I can see the data location using ref(), however, with no error. Why does ref() work and a query doesn't? Possible basic misunderstanding: does a query return a copy of data, as it would in a SQL database, or does it return pointers to the data?
Here's the code, followed by the rules being used. Thanks mucho.
var Firebase = require('firebase');
Firebase.enableLogging(true, true);
// auth token is passed in as an argument
var token;
process.argv.forEach(function(val, index, array) {if (index==2) {token=val;} });
var oneHourAgo=(new Date).getTime() - (minutes*60000);
var fb=new Firebase("https://<mysite>.firebaseio.com/changeMessages");
connect2Firebase(fb,token);
function connect2Firebase(firebase,authToken) {
firebase.auth(authToken, function(error,payload) {
if(error) {
console.log("Login Failed!", error);
} else {
console.log("Login Succeeded!");
console.log(payload);
doSomething();
}
});
}
function doSomething() {
// THIS GIVES PERMISSION ERROR
fb.endAt(oneHourAgo).once('value', function(ss) { console.log(ss.val()); });
// THIS WORKS
//console.log(fb.endAt(oneHourAgo).ref().toString());
}
// THE RULES. Changing to ".read":true makes it work.
{
"rules": {
"changeMessages": {
"$dataClass": {
".read": "auth.dataClass == $dataClass && auth.username == 'admin'",
".write": "auth.username == 'admin'"
}
}
}
}
Related
async selectLocalAdmin(){
if(this.localAdmin.visible){
await t.click(this.localAdmin);
}
else{
console.log('not visible');
}
}
I was trying to add some if else statements here and i observe that even when the if statment is true the click function is not happening, any idea on why this is happening?
Without a complete sample, I can only say that the selector.visible property returns a promise (assuming localAdmin is a Selector), so you need to add await:
async selectLocalAdmin() {
if (await this.localAdmin.visible) {
await t.click(this.localAdmin);
}
else{
console.log('not visible');
}
}
If this does not fix the issue, please share the complete test code (include the URL of the tested application, which should be publicly accessible).
In my work, we tried integrate Safari Push unsuccessful. We have the files .p12 and the .cer
When executing in Safari, not work, no response. If change the name of callback, for example for console.log('hi')... print "hi" and in the console, I see the error
"TypeError: undefined in not an object (evaluating
'window.safari.pushNotification.requestPErmission('https://fabse.tv,
pushId, { user: '123456'}, console.log('hi'))')"
This is my code:
my pushId: 'web.fbase.tv'
setupPushWeb() {
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
var checkRemotePermission = function (permissionData) {
if (permissionData.permission === 'default') {
// This is a new web service URL and its validity is unknown.
window.safari.pushNotification.requestPermission(
'https://fbase.tv', // The web service URL.
'web.fbase.tv', // The Website Push ID.
{user_id: '4741619481'}, // Data used to help you identify the user.
console.log('hola') // The callback function.
);
}
else if (permissionData.permission === 'denied') {
// The user said no.
}
else if (permissionData.permission === 'granted') {
// The web service URL is a valid push provider, and the user said yes.
// permissionData.deviceToken is now available to use.
}
}
if(isSafari) {
if ('safari' in window && 'pushNotification' in window.safari) {
var permissionData = window.safari.pushNotification.permission('web.fbase.tv');
checkRemotePermission(permissionData);
}
} else {
//Firebase integration Fine
I have read in Loopback3 docs that getCurrentContext() has been deprecated. What I'd like to do is grab the access token and use that to find the associated user in the db, so I can get a company_id that the user belongs to and alter the query to include that in the where clause. I am using MySQL and a custom UserAccount model which extends from User.
I am new to Loopback so struggling to figure this out especially as most of the online help seems to point to getCurrentContext();.
I've set up some middleware to run on the parse phase:
middleware.json
"parse": {
"./modifyrequest": {
"enabled": true
}
}
modifyrequest.js
var loopback = require('loopback');
module.exports = function(app) {
return function tracker(req, res, next) {
console.log('Middleware triggered on %s', req.url);
console.log('-------------------------------------------------------------------');
console.log(req.accessToken);
}
};
However req.accessToken is always undefined. I have added to server.js:
app.use(loopback.token());
Any ideas? Is this the wrong approach ?
SOLUTION
As per Kamal's comment below...
Try setting "loopback#token": {} in middleware.json under "initial:before"
This populates req.accessToken
First, try setting "loopback#token": {} in middleware.json under "initial:before".
Then, if you are accessing accessToken from request object, you can find the userId within that accessToken object. Try to log req.accessToken, you will find the userId therein.
You can use that user id to search for corresponding user in the database.
User.findById(req.accessToken.userId, function(err, user){
if(err) {
//handle error
}
else {
//access user object here
}
});
I am an experienced (55+ years) programmer but a total noob in ember and js. I'm trying to get a simple authentication page working using the ember-cli addons ember-cli-simple-auth, ember-cli-simple-auth-oauth2 and cut-and-paste from the simplelabs tutorial.
I get the following in the console:
DEPRECATION: The LoginControllerMixin is deprecated. Use the session's authenticate method directly instead.
and:
DEPRECATION: The AuthenticationControllerMixin is deprecated. Use the session's authenticate method directly instead.
The solution may be trivial, but I have been chasing it for hours and get deep into javascript before reaching a dead-end. The code that is causing these errors is:
import LoginControllerMixin from 'simple-auth/mixins/login-controller-mixin';
export default Ember.Controller.extend(LoginControllerMixin, {
authenticator: 'simple-auth-authenticator:oauth2-password-grant'
});
which invokes the ApplicationControllerMixin somewhere in the bower code.
Before I "re-invent the wheel" by translating some old html/ruby/pascal code into js, can anyone help me "Use the session's authenticate method directly instead."?
Thanks.
I feel you're pain. I spent weeks trying to sort this out. A big part of the problem is that so much has changed in the past couple of years and there are a lot of code examples out there that are outdated or don't work together. It's really difficult to put the various pieces together coherently, and figure out what one does NOT need to do.
That said, please keep in mind that i'm a n00b as well. What i've done seems to work ok but i've no idea whether there's a much better way.
Also, what you're trying to do may not be the same as what i've done. My app authenticates against google (and twitter, fb, etc.) using Simple-Auth-Torii and then exchanges the returned Authenication Code for an Authentication Token. That last part happens on the server. So, after the session authenticates, i then pass the auth code to the server and get back the auth code.
// routes/login.js
import Ember from "ember";
import ENV from "../config/environment";
export default Ember.Route.extend({
setupController: function(controller, model) {
controller.set("errorMessage", null);
},
actions: {
googleLogin: function() {
var _this = this;
// Using "session's authenticate method directly" right here
this.get("session").authenticate("simple-auth-authenticator:torii", "google-oauth2")
.then(function() {
// We're now authenticated. The session should now contain authorization
// code from provider. We now need to exchange that for an auth token.
var secureData = _this.get("session.content.secure");
// call server to initiate token exchange from provider
var exchangeData = {
authorizationCode: secureData.authorizationCode,
redirectUri : secureData.redirectUri,
provider : 'google'
};
// sends ajax request to server, which will in turn call provider
// with authentication code and receive auth token
_this.tokenService.fetch(exchangeData).then(function(response) {
if (response.success) {
_this.set("session.content.secure.access_token", response.data.token);
_this.set("session.content.secure.userData", response.data.user);
// take user somewhere ...
_this.transitionTo("data_sets");
}
else {
// set an error message, log the response to console, whatever, but
// we need to invalidate session because as far as simple-auth
// is concerned we're already authenticated. The following logs the user out.
_this.get("session").invalidate();
}
}, function(error) {
console.log("tokenService.fetch error", error);
_this.get("session").invalidate();
});
}, function(error) {
console.log("simple-auth-authenticator:torii error", error);
_this.get("session").invalidate();
});
},
twitterLogin: function() {
// etc.
}
}
});
Logging a user out also uses the session directly.
{{!templates/application.hbs}}
<ul class="nav navbar-nav navbar-right">
{{#if session.isAuthenticated}}
<li><button {{ action 'invalidateSession' }} class="btn btn-sm">Logout</button></li>
{{/if}}
...
</ul>
// routes/application.js
import Ember from "ember";
import ENV from "../config/environment";
import ApplicationRouteMixin from "simple-auth/mixins/application-route-mixin";
export default Ember.Route.extend(ApplicationRouteMixin, {
actions: {
// action is globally available because in application route
invalidateSession: function() {
// the most basic logout
this.get("session").invalidate();
return;
// If you need to invalidate also on the server do something like:
//
// var _this = this;
// return new Ember.RSVP.Promise(function(resolve, reject) {
// var params = {
// url : ENV.logoutEndpoint,
// type : "POST",
// dataType : "json"
// };
// Ember.$.ajax(params).then(function(response) {
// console.log('session invalidated!');
// console.dir(response);
// _this.get("session").invalidate();
// });
// });
}
}
});
I've met the same deprecation problem. I thinks this snippet for a lovely login controller will do, it's a bit more what you asked, but I hope it is still understandable. I use it with devise, it's almost the same except I use it this way: authenticate('simple-auth-authenticator:devise', credentials)
import Ember from 'ember';
export default Ember.Controller.extend({
actions: {
authenticate: function() {
// identification and password are the names of the input fields in the template
var credentials = this.getProperties('identification', 'password');
if (!credentials.identification || !credentials.password) {
return false;
}
this.get('session').authenticate('simple-auth-authenticator:oauth2-password-grant', credentials).then(function() {
// authentication was successful
}, function(errorMessage) {
// authentication failed
});
}
}
});
I'm working on a CMS and I'd like to know if I can get the content by owner, in other to show the pictures from the app's users.
I know that i can get the content list of the current user with:
QB.content.list(function(error, response){
if(error) {
console.log(error);
} else {
// Success
}
});
but can I access to other user's content?
thank you very much
Unfortunately, this functionality isn't in the API right now. If it's profile pictures you want, you can just use the blob parameter on a user.
If you can provide us some good use cases for - send me an email at alex.bass#quickblox.com and we'll consider adding it.
Hopefully this hasn't inconvenienced you too much.
EDIT:
I've just been informed by my colleague that there is a way around this - it's not perfect, but it does get the job done.
You can create a custom objects class with just 2 fields: blob_id and user_id. Then when content is uploaded, just add a record in the callback.
Here's the complete code - I haven't tested it though. Let me know if you have any troubles.
When uploading:
QB.init(app_id, auth_key, auth_secret);
var user_id;
QB.createSession({login: <username>, password: <password>}, function(error, response){
if(error) {
console.log(error);
} else {
// Just making a record of the user_id for use later
user_id = response.id;
}
});
//
// later...
//
var files = $("input[type=file]")[0].files;
// This function will create "content" record in QB, then when QB returns AWS URL to
// post to, it will automatically upload it, then on completion, mark uploaded.
QB.content.createAndUpload({'file': files, 'public': true}, function(err, response){
if (err) {
console.log(err);
} else {
// Response will contain blob ID.
var data = {
blob_id: response.id,
blob_owner: user_id
}
QB.data.create("BlobsToUsers", data, function(err, response){
if (err) {
console.log(err);
} else {
// Done
}
});
}
});
Then, later on when you're listing content:
QB.data.list("BlobsToUsers", { blob_owner: user_id } function(err, response){
if (err) {
console.log(err);
} else {
// response.items will be array of all records with the specified blob_owner.
// You could also filter by date, timestamp or whatever you want.
}
});
To break it down into steps:
Use "QB.content.createAndUpload()" to upload data
Create custom objects record matching blob ID to owner
Later, when listing, get records from Custom Objects.
Do whatever you want from there. There is a function named "QB.content.getFileUrl()" that will return an AWS URL that you use for an <img> tag.
Hope this helps