Ember.js update model after save - authentication

I have a small Ember app and adding in authentication at the moment with a simple API in the background:
POST /login
//returns
{
"token": "Much53cr4t"
}
Ember model for login (route setup correctly and calls the endpoint as expected)
App.Login = DS.Model.extend({
username: DS.attr(),
password: DS.attr(),
token: DS.attr()
});
Controller
App.LoginController = Ember.ObjectController.extend({
// Implement your controller here.
actions: {
submit: function() {
var self = this;
var login = self.get('model');
login.set('username', self.get('username'));
login.set('password', self.get('password'));
login.save().then(function (result) {
//do something here?
});
}
}
});
I would like to get the returned token value to be added either to the created model before save, or new one. Whichever is easier. Can't seem to find any other advice other than 'return an id' but that I would consider not the best when it comes to an AUTH API endpoint like this.

So I ended up adding a custom REST adapter for this:
App.LoginAdapter = DS.RESTAdapter.extend({
host: 'http://127.0.0.1',
createRecord: function(store, type, record) {
var p = this._super(store, type, record);
return p.then(function(data){
record.set('token', data['token']);
});
},
});
Still wonder is there an easier, or more 'Ember-way' for doing this?

Related

how to add attributes to a PUT request in GUN?

I have the following code in my HTML page
Gun.on('opt', function (ctx) {
if (ctx.once) {
return
}
this.to.next(ctx)
window.auth = ctx.opt.auth
ctx.on('get', function (msg) {
msg.auth = window.auth
this.to.next(msg)
})
ctx.on('put', function (msg) {
msg.put.auth = window.auth
this.to.next(msg)
})
})
var gun = Gun({
peers: ['http://localhost:8765/gun'],
auth: {
user: 'mroon',
password: 'titi'
}
})
On the server, I simply watch the requests
Gun.on('create', function(db) {
console.log('gun created')
this.to.next(db);
db.on('get', function(request) {
// this request contains the auth attribute from the client
this.to.next(request);
});
db.on('put', function(request) {
// this request does not contain the auth attribute from the client
this.to.next(request);
});
});
every time I query the graph with gun.get('someAttribute') the request on the server contains the auth attribute.
but when a gun.get('someAttribute').put({attribute: 'my new value'}) is called, the request on the server does not contain the auth attribute.
How can I add the auth attribute to the put request in such a way that all the peers will get it too?
#micha-roon you jumped straight to GUN's core/internal wire details, which is not the easiest thing to start with, but here is something I do that I'm guessing is what you are looking for:
(if not, please just comment & I'll update)
What this does is it adds a DEBUG flag to all outbound messages in GUN, you can change this to add other metadata or info
Gun.on('opt', function(root){
if(!root.once){
root.on('out', function(msg){
msg.DBG = msg.DBG || +new Date;
this.to.next(msg);
});
}
this.to.next(root);
})
Also another good reference: https://github.com/zrrrzzt/bullet-catcher

VueJs auh0 social authentication, how to customize handle redicrect

Using VueJs SDK .
My redirect url is example.com/callback, inside routes I have callback component which suppose to send user data to backend and check if user exists and log user in otherwise create new user and get back jwt from our backend application .
Problem is following, inside created/mounted cycle I can not reach auth0Client and so user properties.
this.$auth.auth0Client
I have to do this hack
const interval = setInterval(async () => {
count++;
if (this.$auth.auth0Client) {
clearInterval(interval);
let loggedUser = await this.$auth.auth0Client.getUser();
if(loggedUser) {
const email = loggedUser.email;
const name = loggedUser.name;
try {
//backend logic
} catch(e) {
console.log(e)
}
}
} else {
if (count > 80) {
clearInterval(interval);
}
}
}, 100)
My problem/question is how to handle this better as it seems not very logical and nice.
I want to send authenticated user data to our backend and do the rest there,
Auth0 seems to lack the details for this type of usecases
Thanks
I solve my own problem by using Vue event system
this.auth0Client = await createAuth0Client({
domain: options.domain,
client_id: options.clientId,
audience: options.audience,
redirect_uri: redirectUri,
responseType: 'token'
});
this.$eventBus.$emit('auth0Client',this.auth0Client) // creating event here after auth0Client
handling it in callback component
this.$eventBus.$on('auth0Client', async (auth0Client) => {
//logic here
})
Do not forget to register your event bus in main js
Vue.prototype.$eventBus = new Vue();
Hope it will help

Rally API for User story creation in a particular Project?

i have tried the following code with no luck
var rally = require('rally'),
restApi = rally({
user: 'userName', //required if no api key, defaults to process.env.RALLY_USERNAME
pass: 'password', //required if no api key, defaults to process.env.RALLY_PASSWORD
apiKey: 'XXXXX', //preferred, required if no user/pass, defaults to process.env.RALLY_API_KEY
apiVersion: 'v2.0', //this is the default and may be omitted
server: 'https://rally1.rallydev.com', //this is the default and may be omitted
requestOptions: {
headers: {
'X-RallyIntegrationName': 'My cool node.js program', //while optional, it is good practice to
'X-RallyIntegrationVendor': 'My company', //provide this header information
'X-RallyIntegrationVersion': '1.0'
}
//any additional request options (proxy options, timeouts, etc.)
}
});
restApi.create({
type: 'hierarchicalrequirement', //the type to create
data: {
Name: 'RallYUS',
//the data with which to populate the new object
},
fetch: ['FormattedID'], //the fields to be returned on the created object
scope: {
//optional, only required if creating in non-default workspace
project: 'rally',
workspace: 'abcd'
},
requestOptions: {} //optional additional options to pass through to request
}, function(error, result) {
if(error) {
console.log(error);
} else {
console.log(result.Object);
}
});
I was able to create a US but in a different project . I have been trying to fix the project issue and event entered ObjectID and Object UUID as well but still keeps creating in default project attached to user profile . Any help to force Userstory using hierarchialrelation with creation of US would definitely help
All object relationships are specified using refs in the Web Services API. This should work:
scope: {
project: '/project/12345' //where 12345 is the object id
}

Ember simple-auth mixins deprected

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
});
}
}
});

Ember.js Ember Simple Auth persist authentication information in LocalStorage does not work

I use Ember Simple Auth with the following settings:
Note: I use Ember App Kit.
app.js
// init Ember.SimpleAuth
App.initializer({
name: 'authentication',
initialize: function(container, application) {
Ember.SimpleAuth.setup(application, { // #todo at version 0.1.2 of Ember-simple-auth, add container variable
crossOriginWhitelist: ['http://customdomain'],
// store: Ember.SimpleAuth.Stores.LocalStorage, // default now
authenticationRoute: 'article.login'
});
}
});
export
default App;
a simple loginController
(took it mostly from Ember App Kit Simple Auth)
var CustomAuthenticator = Ember.SimpleAuth.Authenticators.OAuth2.extend({
serverTokenEndpoint: 'http://customdomain/access_token/',
makeRequest: function(data) {
return Ember.$.ajax({
url: this.serverTokenEndpoint,
type: 'POST',
data: {
grant_type: 'password',
username: data.username,
password: data.password
},
dataType: 'json',
contentType: 'application/x-www-form-urlencoded'
});
}
});
var LoginController = Ember.Controller.extend(Ember.SimpleAuth.LoginControllerMixin, {
authenticator: CustomAuthenticator,
actions: {
// display an error when logging in fails
sessionAuthenticationFailed: function(message) {
console.log('sessionAuthenticationFailed');
this.set('errorMessage', message);
},
// handle login success
sessionAuthenticationSucceeded: function() {
console.log('sessionAuthenticationSucceeded');
this.set('errorMessage', "");
this.set('identification', "");
this.set('password', "");
this._super();
}
}
});
export
default LoginController;
So far so good, I can authenticate a user thought a login form. However when I press F5, I have to login again. The LocalStorage adapter is empty. So the question is what do I need to persist the token and session?
Note: I cannot update to ember-simple-auth 0.1.2, bower cannot find the new version. Seems that the github version of https://github.com/simplabs/ember-simple-auth-component is not up to date.
Edit:
I have updated my code as follows:
app.js
// init Ember.SimpleAuth
App.initializer({
name: 'authentication',
initialize: function(container, application) {
Ember.SimpleAuth.Authenticators.OAuth2.reopen({
serverTokenEndpoint: 'http://customdomain/access_token'
});
Ember.SimpleAuth.setup(container, application, { // #todo at version 0.1.2 of Ember-simple-auth, add container
crossOriginWhitelist: ['http://customdomain'], // #todo remove when live
// store: Ember.SimpleAuth.Stores.LocalStorage,
authenticationRoute: 'article.login'
});
}
});
export default App;
loginController:
var LoginController = Ember.Controller.extend(Ember.SimpleAuth.LoginControllerMixin, {
// authenticator: CustomAuthenticator, // not needed anymore
actions: {
// display an error when logging in fails
sessionAuthenticationFailed: function(message) {
this.set('errorMessage', message);
},
// handle login success
sessionAuthenticationSucceeded: function() {
this.set('errorMessage', "");
this.set('identification', "");
this.set('password', "");
this._super();
}
}
});
export default LoginController;
I haven't used the oauth2 authenticator before (just a custom one for my backend that I wrote) but I think the same concepts should apply.
When you refresh the page ember-simple-auth makes a call to the restore method of the oauth2 authenticator that you are using. The restore method is looking for a property called 'access_token' to confirm that the user has already authenticated with your server. Does your REST API return a property called access_token when you authenticate with the endpoint at http://customdomain/access_token/? If not, you want to make sure this is happening or you will encounter the refresh issue you're having. Here's the restore method in the oauth2 authenticator provided with ember-simple auth:
restore: function(properties) {
var _this = this;
return new Ember.RSVP.Promise(function(resolve, reject) {
// It looks for the 'access_token' property here which should have been set
// by the authenticate method if you returned it from your REST API
if (!Ember.isEmpty(properties.access_token)) {
_this.scheduleAccessTokenRefresh(properties.expires_in,
properties.expires_at,
properties.refresh_token);
resolve(properties);
} else {
reject();
}
});
}
Additionally, I think in your sessionAuthenticationSucceeded action you need to return true. Otherwise the action won't propagate up to the ember-simple-auth ApplicationRouteMixin (unless you are not using that mixin or don't depend on its sessionAuthenticationSucceeded method in which case it doesn't matter).
This should be fixed with 0.1.2: github.com/simplabs/ember-simple-auth/releases/tag/0.1.2
I also just updated github.com/simplabs/ember-simple-auth-component