I cannot get my ApplicationRoute to handle errors. 401 or 500 (From Login operation) response from server did not fire the error event in my ApplicationRoute. Please Help!
I can see the 401 or 500 error in the console log.
FullCircle.ApplicationRoute = Ember.Route.extend
events:
error: (reason, transition) ->
alert reason
actions:
logout: ->
this.controllerFor('application').logged_out()
delete localStorage.authToken
this.transitionTo 'login'
FullCircle.LoginRoute = Ember.Route.extend
actions:
login: ->
self = this
loginController = #controllerFor 'login'
data = loginController.getProperties("username", "password")
# this would normally be done asynchronously
$.post("/login", data).then (response) ->
alert response.message
if response.user
localStorage.authToken = response.token
applicationController = self.controllerFor 'application'
transition = applicationController.get 'savedTransition'
# set isLoggedIn so the UI shows the logout button
applicationController.logged_in()
# if the user was going somewhere, send them along, otherwise
# default to `/posts`
if transition
transition.retry()
else
self.transitionTo '/documents'
As of ember 1.0, the events hash was renamed to actions. A route's error handler should be in the actions hash. So:
FullCircle.ApplicationRoute = Ember.Route.extend
actions:
error: (reason, transition) ->
alert reason
logout: ->
...
Related
I'm trying to authenticate using oauth2 provider of vue-authenticate with custom axios response interceptor as follow:
bindRequestInterceptor() {
this.$http.interceptors.request.use((config) => {
console.log('Axios intercetping request')
console.log(`Before checking Token : ${this.getToken()}`)
if (this.isAuthenticated()) {
console.log('Authenticated')
config.headers.Authorization = [
this.options.tokenType, this.getToken(),
].join(' ')
} else {
console.log('Not authenticated')
delete config.headers.Authorization
let this_ = this;
this.authenticate('oauth2').then(function(authResponse){
console.log(authResponse)
this_.isAuthenticated = this_.$auth.isAuthenticated();
})//This fires an oauth popup window
}
console.log(`After checking Token : ${this.getToken()}`)
return config
})
},
When running an ajax call:
- I get redirected to my authorize url (/oauth/authorize) in new window
- After approving, I get successfully redirected to my custom redirect_uri with authorization code.
My problem is that, why am I not able to be authenticated after this flow.
In fact, if I re-call an ajax via axios, it reloop me from the authorization flow (approval window, etc)
Is anyone here familiar with this tools, and how to solve this issue ?
Note: when close the approval window, I get this error in the page which called the ajax
Possible Unhandled Promise Rejection: Error: Auth popup window closed
Note2: The console log according to above code
Axios intercetping request
app.js?id=01021d92b5ff42f0b696:30471 Before checking Token : null
app.js?id=01021d92b5ff42f0b696:30479 Not authenticated
app.js?id=01021d92b5ff42f0b696:30487 After checking Token : null
I am having some issues with testing my signin/signout and related features of my app. The app works, but the test fail.
For testing, I use a QUnit with testem (I also tried teaspoon)
test "after signin, should redirect user back to previous page", ->
visit '/library'
fillIn '.signin-email', 'example#example.com'
fillIn '.signin-password', 'examplepass'
click '.signin-btn'
andThen ->
equal(testing().path(), 'library', "Should redirect back to library (was #{testing().path()})")
After running the test, I get a failure:
(screenshot here )
Authentication: visiting restricted page as non authenticated user: after signin, should redirect user back to previous page (2, 0, 2)Rerun544 ms
{user_id: 2, auth_token: wVveiyDLuXBXu69pQ2XQwg}
Source:
at Test.QUnitAdapter.Test.Adapter.extend.exception (http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:50149:5)
at superWrapper [as exception] (http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:13374:16)
at Object.onerror (http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:50009:22)
at onerror (http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:20453:16)
at EventTarget.trigger (http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:20286:22)
at null.<anonymous> (http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:20439:14)
at EventTarget.trigger (http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:20286:22)
at http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:20588:17
Should redirect back to library (was signin)
Expected:
"library"
Result:
"signin"
Diff:
"library" "signin"
Source:
at http://localhost:7357/public/assets/spec/javascripts/integration/authentication_pages_spec.js.js:22:14
at andThen (http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:50258:20)
at http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:49817:21
at isolate (http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:49989:14)
at http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:49972:12
at invokeCallback (http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:20463:19)
at null.<anonymous> (http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:20513:11)
Also, auth.coffee:
App.Auth = Em.Auth.extend
request: 'jquery'
response: 'json'
strategy: 'token'
session: 'cookie'
modules: [
'emberData',
'authRedirectable',
'actionRedirectable'
]
signInEndPoint: '/signin'
signOutEndPoint: '/signout'
tokenKey: 'auth_token'
tokenIdKey: 'user_id'
tokenLocation: 'param'
emberData:
userModel: 'user' # create user model on login
authRedirectable:
route: 'signin'
actionRedirectable:
signInRoute: 'library'
# signInSmart: true
# signInBlacklist: ['signin']
signOutRoute: 'index'
I am unable to find the source of the error, so maybe it is something to do with ember-auth. Any ideas would be very appreciated.
Update 1 [Jan 4th]:
I've written an additional test, which passes only halfway. The test is simpler than the previous in that it does not check a redirect, but only checks that the user name appears in the UI after signin.
test "after signin, TEST", ->
visit '/library'
fillIn '.signin-email', 'user#example.com'
fillIn '.signin-password', 'foobargaz'
click '.signin-btn'
andThen ->
ok exists('.menu-signout'), "signout button exists"
The assertions passes, but I get an additional error reporting the returned JSON as seen in this screenshot. The screenshot basically shows:
[Fail] {user_id: 2, auth_token: wVveiyDLuXBXu69pQ2XQwg}
[Pass] signout button exists
Additionally, I've also run the tests by mocking the ajax requests with mockjax, but with the same failure.
Third, I should note that I had to patch "ember-auth-request-jquery.js" to make it work with ember testing as suggested here
I'm pretty sure you're failing to wait on the first visit to happen, so here's how I read it (I'm no CS person)
You're telling Ember to go to library
Before being sure it's finished navigating you're trying to fill in 2 fields and click a button (all of which probably doesn't exist)
then you check to see if it's library, but while waiting after you thought you clicked, really the page finishes rendering the login page from the visit
Here's what js2coffe says it'd kind of look like (my main point is the then after the visit).
test "after signin, should redirect user back to previous page", ->
visit("/library").then ->
fillIn ".signin-email", "example#example.com"
fillIn ".signin-password", "examplepass"
click(".signin-btn").then ->
equal testing().path(), "library", "Should redirect back to library (was " + (testing().path()) + ")"
Update 1/4: Documentation changed on me
Now we move to educated guess time. Looking through the Ember-auth code it might not be creating any timers/promises that Ember is aware of, in affect Ember thinks it's finished the signin process immediately. So the click promise is resolved immediately and you run your test immediately (andThen waits on the global testing promise to resolve). To test the theory you can do some terrible timeout and see if it does indeed redirect after some time
test "after signin, should redirect user back to previous page", ->
visit "/library"
fillIn ".signin-email", "example#example.com"
fillIn ".signin-password", "examplepass"
click ".signin-btn"
stop()
Ember.run.later this, (->
start()
equal testing().path(), "library", "Should redirect back to library (was " + (testing().path()) + ")"
), 5000
It turns out my coffeescript was not the best in the world.
The module function in QUnit should NOT compile to:
module('Authentication: visiting restricted page as non authenticated user', function() {
return setup(function() {
return Em.run(App, App.advanceReadiness);
});
});
but to:
module('Authentication: visiting restricted page as non authenticated user', {
setup: function() {
Ember.run(App, App.advanceReadiness);
},
// This is also new
teardown: function() {
App.reset();
}
});
Additionally, in my spec_helper.coffee file I had something like this:
QUnit.testStart(function() {
// FIXME: this below made it fail every time
// Ember.run(function() {
// return App.reset();
// });
Ember.testing = true;
});
QUnit.testDone(function() {
Ember.testing = false;
});
QUnit.done(function() {
return Ember.run(function() {
return App.reset();
});
});
which seems to have caused some issues, so I just deleted it and the tests now pass.
The frontend: AngularJS 1.1.5, which has ngResource returning a promise's $then function
The backend: Rails 3.2
The problem: Whenever I call the Card.update action from inside a function in an AngJS controller, I get no response from attempting to log both the success and error responses. The Card $resource behaves as expected works when calling the Card.update action from outside the function.
Rails Associations
Deck has_and_belongs_to_many :cards
Card has_and_belongs_to_many :decks
Rails routes
resources :cards do
get '/decks' => 'cards#decks', on: :member
end
Rails Card Controller 'update' action
def update
#card = Card.where( id: params[:id] ).first
unless params[:deck_id].nil?
#deck = Deck.where( id: params[:deck_id] ).first
#deck.cards << #card
end
render json: Card.update( params[:id], params[:card] )
end
Cards Resource Factory
app.factory "Card", ($resource) ->
$resource "/cards/:id",
id: "#id"
,
index:
method: "GET"
isArray: true
show:
method: "GET"
isArray: false
create:
method: "POST"
update:
method: "PUT"
destroy:
method: "DELETE"
decks:
method: "GET"
isArray: true
url: 'cards/:id/decks'
Cards update function (inside AngJS Controller): (Success/error messages aren't logged to the console).
$scope.updateCard = ( card_id, old_deck, new_deck ) ->
console.log 'CardCtrl updateCard function'
card_id = parseInt(card_id)
old_deck = parseInt(old_deck)
new_deck = parseInt(new_deck)
Card.update( id: card_id, deck_id: new_deck ).$then (success, error) ->
console.log 'Success'
console.log success
console.log 'Error'
console.log error
Introduction
I solved my own problem. I used this Github comment from Misko Hevery as reference.
Why my PUT request wasn't executing:
Apparently, in Angular 1.1.x, if you ever leave the angular execution context, you'll be outside of Angular's $scope.$apply function. In my case, I was working with JQuery UI's sortable function - whenever a Card was placed in a new Deck, I wanted to update the Deck's cards to reflect that update.
To the best of my understanding, because of this, I was outside the angular execution context. ngResource wouldn't execute the PUT statement and the $then function of the Angular's promise object will never be called.
The solution:
Simply wrapping the $scope.$apply function around the Card.updateaction allowed the action to execute, which subsequently allowed the $then function to execute. See the code example below for further clarification:
$scope.$apply ->
Card.update(
id: 1
deck_id: 2
front: "HELLO WORLD!"
).$then ((success) ->
console.log "Success"
console.log success
), (error) ->
console.log "Error"
console.log error
I have a module App which will check if the user has sign in.
App.run ['$rootScope', 'UserService', ($rootScope, UserService) ->
UserService.current_user()
]
The UserService.current_user() will trigger a $http request.
So how can i write the $httpBackend to mockup the request? I have tried some method:
describe 'App', ->
$httpBackend = null
beforeEach(module('App')) # one
beforeEach inject ($injector) -> # two
$httpBackend = $injector.get('$httpBackend')
$httpBackend
.when('GET', '/api/1/users/current_user')
.respond(403, {"error":"not signin"})
it "should get current_user request", () ->
$httpBackend.expectGET('/api/1/users/current_user').respond(403, {'error': 'not signin'})
This will show the error:
Error: Unexpected request: GET /api/1/users/current_user No more request expected
If I change the sequence of # one and # two. It will show error
Error: Injector already created, can not register a module!
This makes me fall in depression. I need some help.
I made it working with this :
describe 'App', ->
beforeEach angular.mock.module('App')
it "should get current_user request", inject ($httpBackend) ->
$httpBackend.expectGET('/api/1/users/current_user').respond(403, {'error': 'not signin'})
$httpBackend.flush()
And it works also if you put the backend expectation in a before each :
describe 'App', ->
beforeEach angular.mock.module('App')
beforeEach inject ($httpBackend) ->
$httpBackend.expectGET('/api/1/users/current_user').respond(403, {'error': 'not signin'})
$httpBackend.flush()
it 'should test someting else', ->
See it in action in this Plunker.
This is the code for my ajax call
var data = {user: {password: password, email: email}};
$.post('auto_login',data,function(res){
if(res.success){
// successfully logged in
}
else{
// failed log in
}
});
This is the code in my controller
def auto_login
#user = parmas[:user]
# how do i invoke login here...
# res = Sessions.new(#user)
# x = true if res.save
respond_to do |format|
format.json{ render :json => { :success => x } }
end
end
I am doing this because I have a button which if a unregistered user clicks it will pop-up a modal window which ask for login info or register to the site. After the user fills up the required information, and if the system recognize that the data are valid, it will automatically redirect the user to a particular url.
Any help will do.
Thank you.
Devise allows you to put the log in form anywhere. You can put it in a partial or use javascript to show/hide. Just follow these instructions:
https://github.com/plataformatec/devise/wiki/How-To:-Display-a-custom-sign_in-form-anywhere-in-your-app