Skip to content

Commit

Permalink
Worked on client side authentication. Closed #56.
Browse files Browse the repository at this point in the history
Various other tweaks to get authentication on client up to beta.

modified:   app/assets/javascripts/angular/controllers/login.js
	-- improved the controller to show basic login information and provide logout links

modified:   app/assets/javascripts/angular/services/services.js
	-- implemented OpenID authentication modules (Closes #56)
	-- fixed several bugs with the `Authenticator` module

modified:   app/assets/stylesheets/_annotation_viewer.css.scss
modified:   app/assets/stylesheets/_layout.css.scss
	-- fixed footer draw bug

modified:   app/controllers/api/callbacks_controller.rb
	-- added some consistency to omiauth callback apis
	-- corrected the close window self-executing function returned in callbacks

modified:   app/views/layouts/application.html.erb
	-- added basic login info / logout / login links

modified:   lib/assets/javascripts/functions.js
	-- rewrote popupwindow function to poll

modified:   lib/assets/javascripts/jquery.drawabox.js
	-- renamed some variables for consistency
  • Loading branch information
atruskie committed Dec 10, 2012
1 parent f403892 commit 973df35
Show file tree
Hide file tree
Showing 11 changed files with 204 additions and 109 deletions.
2 changes: 1 addition & 1 deletion app/assets/javascripts/angular/controllers/listen.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ function ListenCtrl($scope, $resource, $routeParams, AudioRecording, AudioEvent,
$scope.recordingurl = "/media/" + recordingId + "_0_120_0_11025.mp3";


var spectrogramResource = $resource('/media/:recordingId', {recordingId: '@recordingId'}, {
var spectrogramResource = $resource('/media/:recordingId', {recording: '@recordingId'}, {
get: { method: 'GET', params: {recordingId: '@recordingId'}, isArray: false }
});
$scope.spectrogram = spectrogramResource.get($routeParams);
Expand Down
37 changes: 36 additions & 1 deletion app/assets/javascripts/angular/controllers/login.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,44 @@ function LoginCtrl($scope, $http, authService, AuthenticationProviders) {
}
};

$scope.login = function() {
$scope.$emit('event:auth-loginRequired');
};

$scope.logout = function() {

}
var p, ap;
try {
p = $scope.$root.userData.provider_id;
}
catch(e){}

if (p) {
ap = AuthenticationProviders[p];
if (ap) {
ap.logout();
}
}
};

$scope.loggedIn = false;
$scope.displayName = "";
$scope.email = "";

$scope.$watch('$root.userData', function (){
var token = $scope.$root.authorisationToken,
userData = $scope.$root.userData;
$scope.loggedIn = (token && userData) ? true : false;
if ($scope.loggedIn) {
$scope.displayName = userData.friendly_name;
$scope.email = userData.email;
}
else{
$scope.userName = "";
$scope.email = "";
}
});

}

LoginCtrl.$inject = ['$scope', '$http', 'authService', 'AuthenticationProviders'];
2 changes: 2 additions & 0 deletions app/assets/javascripts/angular/directives/directives.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@

// init drawabox
scope.model.audio_events = scope.model.audio_events || [];
scope.model.selectedEvents = scope.model.selectedEvents || [];

scope.$canvas.drawabox({
"newBox": function(){
console.log("newBox");
Expand Down
87 changes: 53 additions & 34 deletions app/assets/javascripts/angular/services/services.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,23 +55,32 @@
throw "Authenticator.loginSuccess: this function should not be called unless a successful response was received"
}

$rootScope.authorisationToken = data.auth_token;
$http.defaults.headers.common["Authorization"] = 'Token token="' +$rootScope.authorisationToken + '"';
$rootScope.$safeApply($rootScope, function() {
$rootScope.authorisationToken = data.auth_token;
$rootScope.userData = data;
$http.defaults.headers.common["Authorization"] = 'Token token="' + $rootScope.authorisationToken + '"';

console.log("Login successful", data);
console.log("Login successful", data);

authService.loginConfirmed();
authService.loginConfirmed();
});
},
loginFailure:function loginFailure(data, status, headers, config) {
$http.defaults.headers.common["Authorization"] = null;
console.error("Login failure: ", data, status, headers, config);
$rootScope.$safeApply($rootScope, function() {
$rootScope.authorisationToken = null;
$rootScope.userData = null;
$http.defaults.headers.common["Authorization"] = null;
console.error("Login failure: ", data, status, headers, config);
});
},
logoutSuccess:function logoutSuccess(data, status, headers, config) {
$rootScope.$safeApply($rootScope, function() {
$rootScope.authorisationToken = null;
$rootScope.userData = null;
$http.defaults.headers.common["Authorization"] = null;

$http.defaults.headers.common["Authorization"] = null;
$rootScope.authorisationToken = null;

console.log("Logout successful", data);
console.log("Logout successful", data);
});
},
logoutFailure:function logoutFailure(data, status, headers, config) {
console.error("Logout failure: ", data, status, headers, config);
Expand All @@ -81,9 +90,15 @@

bawss.factory('AuthenticationProviders', ['$rootScope', 'authService', '$http', 'Authenticator', function($rootScope, authService, $http, Authenticator) {
var signOutPath = '/security/sign_out';
function signOut() {
$http({method:'GET', url:signOutPath})
.success(Authenticator.logoutSuccess)
.error(Authenticator.logoutFailure);
}

// Navigator is the persona global object
navigator.id.watch({
loggedInUser: null,
onlogin: function(assertion) {
// A user has logged in! Here you need to:
// 1. Send the assertion to your backend for verification and to create a session.
Expand All @@ -93,43 +108,47 @@
.error(Authenticator.loginFailure);

},
onlogout: function() {
// A user has logged out! Here you need to:
// Tear down the user's session by redirecting the user or making a call to your backend.
// Also, make sure loggedInUser will get set to null on the next page load.
$http({method:'GET', url:signOutPath})
.success(Authenticator.logoutSuccess)
.error(Authenticator.logoutFailure);
}
// A user has logged out! Here you need to:
// Tear down the user's session by redirecting the user or making a call to your backend.
// Also, make sure loggedInUser will get set to null on the next page load.
onlogout: signOut
});

function openIdLogin(url) {
var popPath = "/security/auth/open_id?openid_url=" + angularCopies.fixedEncodeURIComponent(url);
popUpWindow(popPath, 700, 500, function(data) {
if (data.response === "ok") {
Authenticator.loginSuccess(data);
}
else {
Authenticator.loginFailure(data);
}
});
}

return {
"persona" : {
login: function login() { navigator.id.request(); },
logout: function logout() { navigator.id.logout(); },
requires: null
},
"google" : {
login: function login() {
popUpWindow('https://www.google.com/accounts/o8/id', 300, 200);

login: function() {
openIdLogin('https://www.google.com/accounts/o8/id');
},
logout: function logout() { },
logout: signOut,
requires: null
},
"openid" : {
login: function login(url) {
var popPath = "/security/auth/open_id?openid_url=" + angularCopies.fixedEncodeURIComponent(url);
popUpWindow(popPath, 700, 500);


// Authenticator.loginSuccess
// Authenticator.loginFailure

},
logout: function logout() {

"yahoo" : {
login: function() {
openIdLogin('https://me.yahoo.com');
},
logout: signOut,
requires: null
},
"open_id" : {
login: openIdLogin,
logout: signOut,
requires: {
text: "Enter your OpenID URL",
type: "url"
Expand Down
6 changes: 3 additions & 3 deletions app/assets/javascripts/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,13 @@ var bawApp = (function () {
// http://www.yearofmoo.com/2012/10/more-angularjs-magic-to-supercharge-your-webapp.html#apply-digest-and-phase
$rootScope.$safeApply = function ($scope, fn) {
$scope = $scope || $rootScope;
fn = fn || function () {
};
fn = fn || function () {};

if ($scope.$$phase) {
fn();
}
else {
$scope.apply(fn);
$scope.$apply(fn);
}
};

Expand Down
2 changes: 1 addition & 1 deletion app/assets/stylesheets/_annotation_viewer.css.scss
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ baw-annotation-viewer {

// general

& .tagItem {
& .boxItem {

border-style: $border-style;
border-width: $border-width;
Expand Down
4 changes: 2 additions & 2 deletions app/assets/stylesheets/_layout.css.scss
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,8 @@ header {
width: 100%;
min-width: 768px;
min-height: 100%;
// height: auto !important;
height: 100%;
height: auto !important;
//height: 100%;
position: relative;
top: -5px;
}
Expand Down
26 changes: 20 additions & 6 deletions app/controllers/api/callbacks_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,38 @@ class Api::CallbacksController < Devise::OmniauthCallbacksController
# END NOTES

# any failure

def javascript_data data
"<script type='text/javascript'>function closeWindow(){ returneddata = #{data.to_json}; window.close(); return false;};(closeWindow)()</script>"
end

def window_content display_data, data
"<!DOCTYPE html><head></head><body>#{display_data} #{javascript_data data}</body></html>"
end

def failure
#set_flash_message :alert, :failure, :kind => failed_strategy.name.to_s.humanize, :reason => failure_message
#redirect_to after_omniauth_failure_path_for(resource_name)

#render :json => {:response => 'failure', :provider_id => failed_strategy.name.to_s, :reason => failure_message}.to_json, :status => :bad_request

displayed_data = '<p>Login unsuccessful. <a href="#" onclick="javascript:closeWindow();return false;">Close this window</a>.</p>'
window_data = {:response => 'failure', :provider_id => failed_strategy.name.to_s, :reason => failure_message}
javascript_data = "<script type='text/javascript'>(function(){ returneddata = #{window_data.to_json}; window.close(); return false;})()</script>"
displayed_data = '<p>Authentication callback page. If you are seeing this page, something went wrong. <a href="/">Return to homepage</a>.</p>'
window_content = "<!DOCTYPE html><head></head><body>#{displayed_data} #{javascript_data}</body></html>"

# use this javscript to get access to the returned data
# returneddata = 0; dataitem = window.open('/security/auth/open_id/callback', 'dataitem'); dataitem.returneddata = returneddata;
# to access the object: dataitem.returneddata
render :text => window_content, :status => :bad_request

respond_to do |format|
format.json { render :json => window_data.as_json, :status => :bad_request }
format.xml { render :xml => window_data.to_xml, :status => :bad_request }
format.any { render :text => window_content(displayed_data, window_data), :status => :bad_request }
end
end

def success_complete(canonical_data)
displayed_data = '<p>Login successful. Please <a href="#" onclick="javascript:closeWindow();return false;">close</a> this window.</p>'


user = store_provider_info(canonical_data, current_user)

sign_in(user, :event => :authentication)
Expand All @@ -47,7 +61,7 @@ def success_complete(canonical_data)
respond_to do |format|
format.json { render :json => content.as_json, :status => :ok }
format.xml { render :xml => content.to_xml, :status => :ok }
format.any { render :json => content.as_json, :status => :ok }
format.any { render :text => window_content(displayed_data, content), :status => :ok }
end
end

Expand Down
19 changes: 13 additions & 6 deletions app/views/layouts/application.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -19,33 +19,40 @@

<a href="/"><h1>Bioacoustic Workbench</h1></a>
<a href ng-click="$reloadView()">refresh</a>
<div ng-controller="LoginCtrl">
<p ng-show="loggedIn">
Hello <span ng-bind="displayName" ></span>, <span ng-bind="email" ></span>.
<a href ng-click="logout()">logout</a>
</p>
<a ng-hide="loggedIn" href ng-click="login()">login</a>
</div>
</header>
<div id="page-wrapper" >

<div id="login-holder">
<div id="loginbox">
<div id="login-inner" ng-controller="LoginCtrl">

<form method="POST">
<form method="POST" autocomplete>
<h2>Login or signup with</h2>
<ul >
<li><a href="#" class="btn-auth btn-facebook">Sign in with facebook</a> </li>
<li><a href="#" class="btn-auth btn-github" >Sign in with GitHub</a> </li>
<li><a ng-click="submit('google')" class="btn-auth btn-google" >Sign in with Google</a> </li>
<li><a ng-click="submit('openid')" class="btn-auth btn-openid" >Sign in with OpenID</a> </li>
<li><a ng-click="submit('open_id')" class="btn-auth btn-openid" >Sign in with OpenID</a> </li>

<li><a ng-click="submit('persona')" class="persona-button"><span >Sign in with Persona</span></a> </li>
<li><a href="#" class="btn-auth btn-twitter" >Sign in with Twitter</a> </li>
<li><a href="#" class="btn-auth btn-windows" >Sign in with Live ID</a> </li>
<li><a href="#" class="btn-auth btn-yahoo" >Sign in with Yahoo</a> </li>
<li><a ng-click="submit('yahoo')" href="#" class="btn-auth btn-yahoo" >Sign in with Yahoo ID</a> </li>
</ul>

<div ng-show="requireMoreInformation">
<h3>Additional information is required</h3>
<label><span ng-bind="requireMoreInformation.text" ></span>
<input
name="login_url" id="login_url" placeholder="enter a valid url"
type="url"
type="url" autocomplete="on"
ng-show='requireMoreInformation.type == "url"'
ng-disabled='requireMoreInformation.type != "url"'
required="This field is required"
Expand All @@ -54,7 +61,7 @@
ng-model="additionalInformation"/>
<input
name="login_text" id="login_text" placeholder="enter required text"
type="text"
type="text" autocomplete="on"
ng-disabled='requireMoreInformation.type != "text"'
ng-show='requireMoreInformation.type == "text"'
required="This field is required"
Expand All @@ -63,7 +70,7 @@
ng-model="additionalInformation"/>
<input
name="email" id="email" placeholder="enter a valid email"
type="email"
type="email" autocomplete="on"
ng-disabled='requireMoreInformation.type != "email"'
ng-show='requireMoreInformation.type == "email"'
required="This field is required"
Expand Down
26 changes: 22 additions & 4 deletions lib/assets/javascripts/functions.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@ function fluidIf(test, truthyAction, falseyAction){
var GUID_REGEXP = /^\{?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\}?$/i;


var newwindow;
function popUpWindow(provider_url, width, height) {
function popUpWindow(provider_url, width, height, callback) {
var screenX = typeof window.screenX != 'undefined' ? window.screenX : window.screenLeft,
screenY = typeof window.screenY != 'undefined' ? window.screenY : window.screenTop,
outerWidth = typeof window.outerWidth != 'undefined' ? window.outerWidth : document.body.clientWidth,
Expand All @@ -64,10 +63,29 @@ function popUpWindow(provider_url, width, height) {
top = parseInt(screenY + ((outerHeight - height) / 2.5), 10),
features = ('width=' + width + ',height=' + height + ',left=' + left + ',top=' + top);

newwindow = window.open(provider_url, 'Login', features);
// GLOBAL WTF
returneddata = 0;
var newWindow = window.open(provider_url, 'Login', features);
newWindow.returneddata = returneddata;

function callbackOnClose() {
setTimeout(function() {
if (newWindow.closed) {
callback(newWindow.returneddata);
}
else {
callbackOnClose();
}
}, 50);
}


if (callback) {
callbackOnClose();
}

if (window.focus)
newwindow.focus();
newWindow.focus();

return false;
}
Expand Down
Loading

0 comments on commit 973df35

Please sign in to comment.