Meteor User Accounts - Facebook login not showing but Google is - facebook

I am trying to integrate the Meteor UserAccounts Bootstrap package following this guide.
I have set the ServiceConfiguration properly for both the services but only Google shows up. I also tried adding Twitter but even that does not work. Does anyone have any idea what I'm missing?
Packages -
meteor-platform
accounts-password
iron:router
aldeed:collection2
useraccounts:bootstrap
nemo64:bootstrap
less
accounts-google
service-configuration
fortawesome:fontawesome
accounts-facebook
accounts-twitter
Accounts configuration on the server -
// /server/lib/config/accoutns.js
Meteor.startup(function() {
// Add Facebook configuration entry
ServiceConfiguration.configurations.update(
{ service: "facebook" },
{ $set: {
appId: "xxxxxxxxxxxxxxxxxxxx",
secret: "xxxxxxxxxxxxxxxxxxx"
}
},
{ upsert: true }
);
// Add Google configuration entry
ServiceConfiguration.configurations.update(
{ service: "google" },
{ $set: {
clientId: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
client_email: "XXXXXXXXXXXXXXXXXXXXXXXXXXX",
secret: "XXXXXXXXXXXXXXXXXXXXXXXX"
}
},
{ upsert: true }
);
ServiceConfiguration.configurations.update(
{ service: "twitter" },
{ $set: {
consumerKey: "XXXXXXXXXXXX",
secret: "XXXXXXXX"
}
},
{ upsert: true }
);
});
But this is all that comes up -
EDIT1: I just noticed something very interesting. I cloned this exact project on my friend's macbook and everything is coming up perfectly as expected. (I was using a Linux mint 17 earlier). I think this is some kind of a bug but not sure what is culprit here.

You may be using ublock or adblock on your browser. Simply disable it and it'll work.
Its a bit weird but it looks like while Meteor is unminified it blocks anything with facebook or twitter in its url such as the facebook/twitter packages' js code.

Related

Protractor W3C capability

I am using Protractor with Selenoid. I need to use the dockerized Windows images so that I can test Internet Explorer and Edge from Linux boxes.
I was able to make it work from curl by running:
curl -X POST http://127.0.0.1:4444/wd/hub/session -d '{"capabilities":{"browserName":"MicrosoftEdge","count":1,"alwaysMatch":{"browserName":"MicrosoftEdge","selenoid:options":{"enableVNC":true,"enableVideo":false,"enableLog":true,"logName":"edge-18.0.log"}}}}'
My protractor config looks like:
multiCapabilities: [
{
browserName: "MicrosoftEdge",
"alwaysMatch": {
browserName: "MicrosoftEdge",
"selenoid:options": {
enableVNC: true,
enableVideo: false,
enableLog: true,
logName: "edge-18.0.log"
}
}
}
]
But protractor send it over the selenoid server like this:
{
"desiredCapabilities": {
"browserName": "MicrosoftEdge",
"count": 1,
"alwaysMatch": {
"browserName": "MicrosoftEdge",
"selenoid:options": {
"enableVNC": true,
"enableVideo": false,
"enableLog": true,
"logName": "edge-18.0.log"
}
}
}
}
The issue is that desiredCapabilities should just be 'capabilities`. I have been looking everywhere trying to find out where is that created so that I can created some sort of flag to be able to switch it.
Any ideas?
Using Protractor 6.0 solve my issue, but broke all my tests.
I was able to keep using 5.4.1 by patching the selenium-webdriver package. Looking at the way Protractor 6 did it, I did it to Protractor 5.4.1:
I edited the file located at node_modules/selenium-webdriver/lib/webdriver.js and added the following:
// Capability names that are defined in the W3C spec.
const W3C_CAPABILITY_NAMES = new Set([
'acceptInsecureCerts',
'browserName',
'browserVersion',
'platformName',
'pageLoadStrategy',
'proxy',
'setWindowRect',
'timeouts',
'unhandledPromptBehavior',
]);
Then in the same file I modify the static createSession(executor, capabilities, opt_flow, opt_onQuit) method to add the following:
let W3CCaps = new Capabilities(capabilities);
for (let k of W3CCaps.keys()) {
// Any key containing a colon is a vendor-prefixed capability.
if (!(W3C_CAPABILITY_NAMES.has(k) || k.indexOf(':') >= 0)) {
W3CCaps.delete(k);
}
}
cmd.setParameter('capabilities', W3CCaps);
After all those changes the request getting to Selenoid is like this:
{
"desiredCapabilities": {
"browserName": "MicrosoftEdge",
"version": "18.0",
"enableVNC": true,
"enableVideo": false,
"count": 1
},
"capabilities": {
"browserName": "MicrosoftEdge"
}
}
And my Protractor 5 config looks like this:
multiCapabilities: [{
browserName: 'MicrosoftEdge',
version: '18.0',
enableVNC: true,
enableVideo: false
}]
Note:
So that I don't have to worry about refresh installs or updates I use the package patch-package (https://github.com/ds300/patch-package) to create a patch that is applied when any of those events happen. Here is a great video explaining how to use that package https://www.youtube.com/watch?v=zBPcVGr6XPk

Automating webrtc Screenshare

I am trying to automate screen share workflow in a webRTC application.
I need to bypass the screenshare prompt. I am using --use-fake-ui-for-media-stream, use-fake-device-for-media-stream and --auto-select-desktop-capture-source flags in my config file.
Doesn't seem work.
Here is my config file :
exports.makeDefaultCapabilities = function(that) {
return {
browserName: 'chrome',
chromeOptions: {
// disable Password manager popup
prefs: {
credentials_enable_service: false,
download: {
prompt_for_download: false,
directory_upgrade: true,
default_directory: '~/Downloads'
}
},
args: [
'disable-infobars=true',
'--use-fake-device-for-media-stream',
'--use-fake-ui-for-media-stream',
'--auto-select-desktop-capture-source = "Entire screen"'
]
},
loggingPrefs: {
driver: 'WARNING',
server: 'WARNING',
browser: 'INFO'
},
I tried flipping between using fake-device and fake-ui flags and they do not get along if i understand correctly.
I do not understand what is missing here. Appreciate your inputs.
Thanks
https://bugs.chromium.org/p/chromium/issues/detail?id=459532#c22 explains why those flags don't play well together and how to workaround it by creating a custom profile that has already accepted getUserMedia permissions which makes the use-fake-ui-for-media-stream flag unnecessary.
See here for some code.

ionic cache nothing or clear cache each day

I have deployed an ionic app as an web app on a server. Whenever I deploy any new changes in ionic part, my users keep using whatever is cached (i.e. older javascripts) and this kills the intended new functionality. I have to ask them to manually clear the cache so that they can use the app with latest changes.
Why does this happen? Is there any way that each day cache is removed? Is it a browser related issue or Ionic issue?
I already have set cache: false for my routes like following:
.state('tab.plan', {
url: '/plan',
resolve: {
authenticated: ['djangoAuth', function(djangoAuth){
return djangoAuth.authenticationStatus();
}],
},
views: {
'tab-plan': {
templateUrl: 'templates/tab-plan.html',
controller: 'planCtrl'
}
},
cache: false
})
.state('tab.simon', {
url: '/plan/8',
resolve: {
authenticated: ['djangoAuth', function(djangoAuth){
return djangoAuth.authenticationStatus();
}],
},
views: {
'tab-plan': {
templateUrl: 'templates/simon.html',
controller: 'simonCtrl',
data: {
css: '/css/simon.css'
}
}
},
cache: false
})

Meteor + facebook login (loginWithFacebook) issue. client_id is always undefined in login popup's URL

I put this issue in gist as well:
https://gist.github.com/yhagio/7561f34d12bc5edb9b5fe0fc1b4bb2b6
Github Repo : https://github.com/yhagio/meteor-tatter
Issue
When I click facebook login button, it opens the login popup, but
the URL in the popup always shows that client_id=undefined, and gives "Sorry, something went wrong".
I installed service-configuration and accounts-facebook meteor packages and configured as follows.
Also, cretead the app & added Facebook Login product in https://developers.facebook.com
Am I missing something?
Screenshot
The URL is like this:
https://www.facebook.com/v2.2/dialog/oauth?client_id=undefined&redirect_uri=http://localhost:3000/_oauth/facebook&display=popup&scope=public_profile&state=eyJsb2dpblN0eW...
In server https://github.com/yhagio/meteor-tatter/blob/master/imports/startup/server/index.js
import { Meteor } from 'meteor/meteor';
import { clientId, secret } from './secret.js';
Meteor.startup(() => {
ServiceConfiguration.configurations.upsert(
{ service: "facebook" },
{
$set: {
clientId: clientId,
loginStyle: "popup",
secret: secret
}
}
);
});
In client https://github.com/yhagio/meteor-tatter/blob/master/imports/ui/helpers/auth.js
import { Meteor } from 'meteor/meteor';
export default function auth() {
return new Promise((resolve, reject) => {
Meteor.loginWithFacebook({
requestPermissions: ['public_profile']
}, (err, user) => {
if (err !== null) return reject(err);
resolve(user);
});
});
}
Problem was that it should be appId instead of clientId. Even though the guide shows clientId. Ref: http://docs.meteor.com/api/accounts.html#service-configuration

Using Grunt to Mock Endpoints

I'm using Yeoman, Grunt, and Bower, to construct a platform for building a frontend independently of a a backend. The idea would be that all of my (AngularJS) controller, services, factories, etc live in this project, and get injected afterwards into my serverside codebase based off the result of grunt build.
My question is:
How can I mock endpoints so that the Grunt server responds to the same endpoints as my (Rails) App will?
At the moment I am using:
angular.module('myApp', ['ngResource'])
.run(['$rootScope', function ($rootScope) {
$rootScope.testState = 'test';
}]);
And then in each of my individual services:
mockJSON = {'foo': 'myMockJSON'}
And on every method:
if($rootScope.testState == 'test'){
return mockJSON;
}
else {
real service logic with $q/$http goes here
}
Then after grunt build, testState = 'test' gets removed.
This is clearly a relatively janky architecture. How can I avoid it? How can I have Grunt respond to the same endpoints as my app (some of which have dynamic params) apply some logic (if necessary), and serve out a json file (possibly dependent on path params)?
I've fixed this issue by using express to write a server that responds with static json.
First I created a directory in my project called 'api'. Within that directory I have the following files:
package.json:
{
"name": "mockAPI",
"version": "0.0.0",
"dependencies": {
"express": "~3.3.4"
}
}
Then I run npm install in this directory.
index.js:
module.exports = require('./lib/server');
lib/server.js:
express = require('express');
var app = express();
app.get('/my/endpoint', function(req, res){
res.json({'foo': 'myMockJSON'});
});
module.exports = app
and finally in my global Gruntfile.js:
connect: {
options: {
port: 9000,
hostname: 'localhost',
},
livereload: {
options: {
middleware: function (connect, options) {
return [
lrSnippet,
mountFolder(connect, '.tmp'),
mountFolder(connect, yeomanConfig.app),
require('./api')
];
}
}
},
Then the services make the requests, and the express server serves the correct JSON.
After grunt build, the express server is simply replaced by a rails server.
As of grunt-contrib-connect v.0.7.0 you can also just add your custom middleware to the existing middleware stack without having to manually rebuild the existing middleware stack.
livereload: {
options: {
open: true,
base: [
'.tmp',
'<%= config.app %>'
],
middleware: function(connect, options, middlewares) {
// inject a custom middleware into the array of default middlewares
middlewares.push(function(req, res, next) {
if (req.url !== '/my/endpoint') {
return next();
}
res.writeHead(200, {'Content-Type': 'application/json' });
res.end("{'foo': 'myMockJSON'}");
});
return middlewares;
}
}
},
See https://github.com/gruntjs/grunt-contrib-connect#middleware for the official documentation.
Alternatively you can use the grunt-connect-proxy to proxy everything that is missing in your test server to an actual backend.
It's quite easy to install, just one thing to remember when adding proxy to your livereload connect middleware is to add it last, like this:
middleware: function (connect) {
return [
lrSnippet,
mountFolder(connect, '.tmp'),
mountFolder(connect, yeomanConfig.app),
proxySnippet
];
}
grunt-connect-prism is similar to the Ruby project VCR. It provides an easy way for front end developers to record HTTP responses returned by their API (or some other remote source) and replay them later. It's basically an HTTP cache, but for developers working on a Single Page Application (SPA). You can also generate stubs for API calls that don't exist, and populate them the way you want.
It's useful for mocking complex & high latency API calls during development. It's also useful when writing e2e tests for your SPA only, removing the server from the equation. This results in much faster execution of your e2e test suite.
Prism works by adding a custom connect middleware to the connect server provided by the grunt-contrib-connect plugin. While in 'record' mode it will generate a file per response on the filesystem with content like the following:
{
"requestUrl": "/api/ponies",
"contentType": "application/json",
"statusCode": 200,
"data": {
"text": "my little ponies"
}
}
DISCLAIMER: I'm the author of this project.
You can use Apache proxy and connect your REST server with gruntjs.
Apache would do this:
proxy / -> gruntjs
proxy /service -> REST server
you would use your application hitting Apache and angular.js application would think that is talking with itself so no cross domain problem.
Here is a great tutorial on how to set this up:
http://alfrescoblog.com/2014/06/14/angular-js-activiti-webapp-with-activiti-rest/
Just my alternative way that based on Abraham P's answer. It does not need to install express within 'api' folder. I can separate the mock services for certain files. For example, my 'api' folder contains 3 files:
api\
index.js // assign all the "modules" and then simply require that.
user.js // all mocking for user
product.js // all mocking for product
file user.js
var user = function(req, res, next) {
if (req.method === 'POST' && req.url.indexOf('/user') === 0) {
res.end(
JSON.stringify({
'id' : '5463c277-87c4-4f1d-8f95-7d895304de12',
'role' : 'admin'
})
);
}
else {
next();
}
}
module.exports = user;
file product.js
var product = function(req, res, next) {
if (req.method === 'POST' && req.url.indexOf('/product') === 0) {
res.end(
JSON.stringify({
'id' : '5463c277-87c4-4f1d-8f95-7d895304de12',
'name' : 'test',
'category': 'test'
})
);
}
else {
next();
}
}
module.exports = product;
index.js just assigns all the "modules" and we simply require that.
module.exports = {
product: require('./product.js'),
user: require('./user.js')
};
My Gruntfile.js file
connect: {
options: {
port: 9000,
// Change this to '0.0.0.0' to access the server from outside.
hostname: 'localhost',
livereload: 35729
},
livereload: {
options: {
open: true,
middleware: function (connect) {
return [
connect.static('.tmp'),
connect().use(
'/bower_components',
connect.static('./bower_components')
),
connect.static(appConfig.app),
require('./api').user,
require('./api').product,
];
}
}
}