diff --git a/Gruntfile.js b/Gruntfile.js index 5c9c771d..ffbd29dd 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -53,6 +53,17 @@ module.exports = function(grunt) { hostname: 'localhost', port: 3030 } + }, + auth_example:{ + options: { + hostname: 'localhost', + port: 3030, + keepalive:true, + open:{ + target:'http://localhost:3030/tests/auth-example/auth.html' + } + + } } }, @@ -162,6 +173,9 @@ module.exports = function(grunt) { // Build tasks grunt.registerTask('build', ['concat', 'jshint', 'uglify']); + // Examples + grunt.registerTask('example:auth',['concat','connect:auth_example']); + // Default task grunt.registerTask('default', ['build', 'test']); }; diff --git a/src/FirebaseAuth.js b/src/FirebaseAuth.js index 8c478e9c..f4fd962b 100644 --- a/src/FirebaseAuth.js +++ b/src/FirebaseAuth.js @@ -5,7 +5,7 @@ // Define a service which provides user authentication and management. angular.module('firebase').factory('$firebaseAuth', [ - '$q', function($q) { + '$q', '$parse', function($q, $parse) { // This factory returns an object containing the current authentication state of the client. // This service takes one argument: // @@ -14,14 +14,15 @@ // The returned object contains methods for authenticating clients, retrieving authentication // state, and managing users. return function(ref) { - var auth = new FirebaseAuth($q, ref); + var auth = new FirebaseAuth($q, $parse, ref); return auth.construct(); }; } ]); - FirebaseAuth = function($q, ref) { + FirebaseAuth = function($q, $parse, ref) { this._q = $q; + this._parse = $parse; if (typeof ref === 'string') { throw new Error('Please provide a Firebase reference instead of a URL when creating a `$firebaseAuth` object.'); @@ -46,6 +47,7 @@ $getAuth: this.getAuth.bind(this), $requireAuth: this.requireAuth.bind(this), $waitForAuth: this.waitForAuth.bind(this), + $bindTo:this.bindTo.bind(this), // User management methods $createUser: this.createUser.bind(this), @@ -189,6 +191,29 @@ return this._routerMethodOnAuthPromise(false); }, + // Bind the authentication state to a property on scope. + // Returns a deregistration function, which is called automatically when scope is destroyed. + bindTo:function(scope,propertyName){ + var ref = this._ref; + var parsed = this._parse(propertyName); + + function callback(authData){ + scope.$evalAsync(function(){ + parsed.assign(scope,authData); + }); + } + + function deregister(){ + ref.offAuth(callback); + } + + scope.$on('$destroy',deregister); + + ref.onAuth(callback); + + return deregister; + }, + /*********************/ /* User Management */ diff --git a/tests/auth-example/auth.css b/tests/auth-example/auth.css new file mode 100644 index 00000000..b88f1977 --- /dev/null +++ b/tests/auth-example/auth.css @@ -0,0 +1,79 @@ +pre { + overflow-y:scroll; + overflow-x: auto; + height: 100%; + background-color: #f0f6fa; + border: 1px solid #CCCCCC; + border-width: 1px 0; + padding: 10px; + margin: 10px 40px; + clear: both; +} + +html,body { + height: 95%; +} + +.method-container { + float: right; + margin-right: 40px; + margin-bottom: 20px; +} + +.button-container { + float: left; + margin-left: 40px; + margin-bottom: 20px; +} + +/* + Button styling is a modified copy of Tom Raspo's Simple Web Buttons. + Check it out at: http://www.lab.tommasoraspo.com/simple-web-buttoms/ +*/ + +button{ + display: inline-block; + text-decoration: none; + font: bold 12px/12px HelveticaNeue, Arial; + padding: 8px 11px; + color: #555; + border: 1px solid #dedede; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + background: #bdbdbd; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#cacaca', endColorstr='#aeaeae'); /* IE */ + background: -webkit-gradient(linear, left top, left bottom, from(#cacaca), to(#aeaeae)); /* WebKit */ + background: -moz-linear-gradient(top, #cacaca, #aeaeae); + border-color: #b5b5b5 #a1a1a1 #8f8f8f; + color: #555; + text-shadow: 0 1px 0 #d4d4d4; + -webkit-box-shadow: 0 1px 1px #c9c9c9, inset 0 1px 0 #d7d7d7; + -moz-box-shadow: 0 1px 1px #c9c9c9, inset 0 1px 0 #d7d7d7; + box-shadow: 0 1px 1px #c9c9c9, inset 0 1px 0 #d7d7d7; +} + +button:hover{ + background: #c2c2c2; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#bcbcbc', endColorstr='#c2c2c2'); /* IE */ + background: -webkit-gradient(linear, left top, left bottom, from(#bcbcbc), to(#c2c2c2)); /* WebKit */ + background: -moz-linear-gradient(top, #bcbcbc, #c2c2c2); + border-color: #989898 #8e8e8e #878787; + text-shadow: 0 1px 0 #dadada; + -webkit-box-shadow: 0 1px 1px #cdcdcd, inset 0 1px 0 #ccc; + -moz-box-shadow: 0 1px 1px #cdcdcd, inset 0 1px 0 #ccc; + box-shadow: 0 1px 1px #cdcdcd, inset 0 1px 0 #ccc; +} + +button:disabled{ + color: #888; + background: #f4f4f4; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#efefef', endColorstr='#f8f8f8'); /* IE */ + background: -webkit-gradient(linear, left top, left bottom, from(#efefef), to(#f8f8f8)); /* WebKit */ + background: -moz-linear-gradient(top, #efefef, #f8f8f8); + border-color: #c7c7c7 #c3c3c3 #bebebe; + text-shadow: 0 1px 0 #fdfdfd; + -webkit-box-shadow: 0 1px 1px #ebebeb, inset 0 1px 0 #f3f3f3; + -moz-box-shadow: 0 1px 1px #ebebeb, inset 0 1px 0 #f3f3f3; + box-shadow: 0 1px 1px #ebebeb, inset 0 1px 0 #f3f3f3; +} \ No newline at end of file diff --git a/tests/auth-example/auth.html b/tests/auth-example/auth.html new file mode 100644 index 00000000..3682d9a4 --- /dev/null +++ b/tests/auth-example/auth.html @@ -0,0 +1,42 @@ + + + + AngularFire Auth Manual Tests + + + + + + + + + + + + + + + + + + + + +
+ Popup + Redirect +
+ + +
+ + + + + + +
+ +
{{prettyData()}}
+ + \ No newline at end of file diff --git a/tests/auth-example/auth.js b/tests/auth-example/auth.js new file mode 100644 index 00000000..03e78384 --- /dev/null +++ b/tests/auth-example/auth.js @@ -0,0 +1,39 @@ +var app = angular.module('auth',['firebase']); + +app.controller('MainCtrl',function($scope,$firebaseAuth,$location){ + + var ref = new Firebase('https://jrtechnical-testing.firebaseio.com/authtesting'); + + var auth = $firebaseAuth(ref); + + $scope.data = {}; + + auth.$bindTo($scope,'data.authData'); + + $scope.prettyData = function(){ + return angular.toJson($scope.data.authData,true); + }; + + $scope.authMode=$location.search().authMode || 'popup'; + + $scope.$watch('authMode',function(newValue, oldValue){ + if(newValue !== oldValue){ + $location.search('authMode',newValue); + } + }); + + $scope.login = function (provider){ + switch ($scope.authMode) { + case 'popup' : + return auth.$authWithOAuthPopup(provider); + case 'redirect' : + return auth.$authWithOAuthRedirect(provider); + default : + throw new Error('authMode not set correctly'); + } + }; + + $scope.anonymous = auth.$authAnonymously; + $scope.logout = auth.$unauth; + +}); \ No newline at end of file