mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2024-12-04 15:24:23 +01:00
419 lines
13 KiB
Markdown
419 lines
13 KiB
Markdown
AngularDevise [![Build Status](https://travis-ci.org/cloudspace/angular_devise.png)](http://travis-ci.org/cloudspace/angular_devise)
|
|
=============
|
|
|
|
A small AngularJS Service to interact with Devise Authentication.
|
|
|
|
|
|
Requirements
|
|
------------
|
|
|
|
This service requires Devise to respond to JSON. To do that, simply add
|
|
|
|
```ruby
|
|
# app/controllers/application_controller.rb
|
|
class ApplicationController < ActionController::Base
|
|
respond_to :html, :json
|
|
# ...
|
|
end
|
|
```
|
|
|
|
Aditionally, if you have [CSRF Forgery
|
|
Protection](http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection/ClassMethods.html)
|
|
enabled for your controller actions, you will also need to include the
|
|
`X-CSRF-TOKEN` header with the token provided by rails. The easiest way
|
|
to include this is to use the
|
|
[angular_rails_csrf gem](https://github.com/jsanders/angular_rails_csrf).
|
|
|
|
Downloading
|
|
-----------
|
|
|
|
AngularDevise is registered as `angular-devise` in
|
|
[bower](http://sindresorhus.com/bower-components/#!/search/angular-devise).
|
|
|
|
```bash
|
|
bower install --save angular-devise
|
|
```
|
|
|
|
You can then use the main file at `angular-devise/lib/devise-min.js`.
|
|
|
|
|
|
Usage
|
|
-----
|
|
|
|
Just register `Devise` as a dependency for your module. Then, the `Auth`
|
|
service will be available for use.
|
|
|
|
```javascript
|
|
angular.module('myModule', ['Devise']).
|
|
config(function(AuthProvider) {
|
|
// Configure Auth service with AuthProvider
|
|
}).
|
|
controller('myCtrl', function(Auth) {
|
|
// Use your configured Auth service.
|
|
});
|
|
```
|
|
|
|
### Auth.currentUser()
|
|
|
|
`Auth.currentUser()` returns a promise that will be resolved into the
|
|
currentUser. There are three possible outcomes:
|
|
|
|
1. Auth has authenticated a user, and will resolve with that user.
|
|
2. Auth has not authenticated a user but the server has a previously
|
|
authenticated session, Auth will attempt to retrieve that session
|
|
and resolve with its user. Then, a `devise:new-session` event will
|
|
be broadcast with the current user as the argument.
|
|
3. Neither Auth nor the server has an authenticated session, and a
|
|
rejected promise will be returned. (see [Interceptor](#interceptor)
|
|
for for custom handling.)
|
|
|
|
```javascript
|
|
angular.module('myModule', ['Devise']).
|
|
controller('myCtrl', function(Auth) {
|
|
Auth.currentUser().then(function(user) {
|
|
// User was logged in, or Devise returned
|
|
// previously authenticated session.
|
|
console.log(user); // => {id: 1, ect: '...'}
|
|
}, function(error) {
|
|
// unauthenticated error
|
|
});
|
|
});
|
|
```
|
|
|
|
#### Auth._currentUser
|
|
|
|
`Auth._currentUser` will be either `null` or the currentUser's object
|
|
representation. It is not recommended to directly access
|
|
`Auth._currentUser`, but instead use
|
|
[Auth.currentUser()](#authcurrentuser).
|
|
|
|
```javascript
|
|
angular.module('myModule', ['Devise']).
|
|
controller('myCtrl', function(Auth) {
|
|
console.log(Auth._currentUser); // => null
|
|
|
|
// Log in user...
|
|
|
|
console.log(Auth._currentUser); // => {id: 1, ect: '...'}
|
|
});
|
|
```
|
|
|
|
|
|
### Auth.isAuthenticated()
|
|
|
|
`Auth.isAuthenticated()` is a helper method to determine if a
|
|
currentUser is logged in with Auth.
|
|
|
|
```javascript
|
|
angular.module('myModule', ['Devise']).
|
|
controller('myCtrl', function(Auth) {
|
|
console.log(Auth.isAuthenticated()); // => false
|
|
|
|
// Log in user...
|
|
|
|
console.log(Auth.isAuthenticated()); // => true
|
|
});
|
|
```
|
|
|
|
### Auth.login(creds)
|
|
|
|
Use `Auth.login()` to authenticate with the server. Keep in mind,
|
|
credentials are sent in plaintext; use a SSL connection to secure them.
|
|
`creds` is an object which should contain any credentials needed to
|
|
authenticate with the server. `Auth.login()` will return a promise that
|
|
will resolve to the logged-in user. See
|
|
[Auth.parse(response)](#authparseresponse) to customize how the response
|
|
is parsed into a user.
|
|
|
|
Upon a successful login, two events will be broadcast, `devise:login` and
|
|
`devise:new-session`, both with the currentUser as the argument. New-Session will only
|
|
be broadcast if the user was logged in by `Auth.login({...})`. If the server
|
|
has a previously authenticated session, only the login event will be broadcast.
|
|
|
|
```javascript
|
|
angular.module('myModule', ['Devise']).
|
|
controller('myCtrl', function(Auth) {
|
|
var credentials = {
|
|
email: 'user@domain.com',
|
|
password: 'password1'
|
|
};
|
|
|
|
Auth.login(credentials).then(function(user) {
|
|
console.log(user); // => {id: 1, ect: '...'}
|
|
}, function(error) {
|
|
// Authentication failed...
|
|
});
|
|
|
|
$scope.$on('devise:login', function(event, currentUser) {
|
|
// after a login, a hard refresh, a new tab
|
|
});
|
|
|
|
$scope.$on('devise:new-session', function(event, currentUser) {
|
|
// user logged in by Auth.login({...})
|
|
});
|
|
});
|
|
```
|
|
|
|
By default, `login` will POST to '/users/sign_in.json' using the
|
|
resource name `user`. The path, HTTP method, and resource name used to
|
|
login are configurable using:
|
|
|
|
```javascript
|
|
angular.module('myModule', ['Devise']).
|
|
config(function(AuthProvider) {
|
|
AuthProvider.loginPath('path/on/server.json');
|
|
AuthProvider.loginMethod('GET');
|
|
AuthProvider.resourceName('customer');
|
|
});
|
|
```
|
|
|
|
### Auth.logout()
|
|
|
|
Use `Auth.logout()` to de-authenticate from the server. `Auth.logout()`
|
|
returns a promise that will be resolved to the old currentUser. Then a
|
|
`devise:logout` event will be broadcast with the old currentUser as the argument.
|
|
|
|
```javascript
|
|
angular.module('myModule', ['Devise']).
|
|
controller('myCtrl', function(Auth) {
|
|
// Log in user...
|
|
// ...
|
|
Auth.logout().then(function(oldUser) {
|
|
// alert(oldUser.name + "you're signed out now.");
|
|
}, function(error) {
|
|
// An error occurred logging out.
|
|
});
|
|
|
|
$scope.$on('devise:logout', function(event, oldCurrentUser) {
|
|
// ...
|
|
});
|
|
});
|
|
```
|
|
|
|
By default, `logout` will DELETE to '/users/sign_out.json'. The path and
|
|
HTTP method used to logout are configurable using:
|
|
|
|
```javascript
|
|
angular.module('myModule', ['Devise']).
|
|
config(function(AuthProvider) {
|
|
AuthProvider.logoutPath('path/on/server.json');
|
|
AuthProvider.logoutMethod('GET');
|
|
});
|
|
```
|
|
|
|
### Auth.parse(response)
|
|
|
|
This is the method used to parse the `$http` response into the appropriate
|
|
user object. By default, it simply returns `response.data`. This can be
|
|
customized either by specifying a parse function during configuration:
|
|
|
|
```javascript
|
|
angular.module('myModule', ['Devise']).
|
|
config(function(AuthProvider) {
|
|
// Customize user parsing
|
|
// NOTE: **MUST** return a truth-y expression
|
|
AuthProvider.parse(function(response) {
|
|
return response.data.user;
|
|
});
|
|
});
|
|
```
|
|
|
|
or by directly overwriting it, perhaps when writing a custom version of
|
|
the Auth service which depends on another service:
|
|
|
|
```javascript
|
|
angular.module('myModule', ['Devise']).
|
|
factory('User', function() {
|
|
// Custom user factory
|
|
}).
|
|
factory('CustomAuth', function(Auth, User) {
|
|
Auth['parse'] = function(response) {
|
|
return new User(response.data);
|
|
};
|
|
return Auth;
|
|
});
|
|
```
|
|
|
|
### Auth.register(creds)
|
|
|
|
Use `Auth.register()` to register and authenticate with the server. Keep
|
|
in mind, credentials are sent in plaintext; use a SSL connection to
|
|
secure them. `creds` is an object that should contain any credentials
|
|
needed to register with the server. `Auth.register()` will return a
|
|
promise that will resolve to the registered user. See
|
|
[Auth.parse(response)](#authparseresponse) to customize how the response
|
|
is parsed into a user. Then a `devise:new-registration` event will be
|
|
broadcast with the user object as the argument.
|
|
|
|
```javascript
|
|
angular.module('myModule', ['Devise']).
|
|
controller('myCtrl', function(Auth) {
|
|
var credentials = {
|
|
email: 'user@domain.com',
|
|
password: 'password1',
|
|
password_confirmation: 'password1'
|
|
};
|
|
|
|
Auth.register(credentials).then(function(registeredUser) {
|
|
console.log(registeredUser); // => {id: 1, ect: '...'}
|
|
}, function(error) {
|
|
// Registration failed...
|
|
});
|
|
|
|
$scope.$on('devise:new-registration', function(event, user) {
|
|
// ...
|
|
});
|
|
});
|
|
```
|
|
|
|
By default, `register` will POST to '/users.json' using the resource
|
|
name `user`. The path, HTTP method, and resource name used to register
|
|
are configurable using:
|
|
|
|
```javascript
|
|
angular.module('myModule', ['Devise']).
|
|
config(function(AuthProvider) {
|
|
AuthProvider.registerPath('path/on/server.json');
|
|
AuthProvider.registerMethod('GET');
|
|
AuthProvider.resourceName('customer');
|
|
});
|
|
```
|
|
|
|
|
|
Interceptor
|
|
-----------
|
|
|
|
AngularDevise comes with a [$http
|
|
Interceptor](http://docs.angularjs.org/api/ng.$http#description_interceptors)
|
|
that may be enabled using the `interceptAuth` config. Its purpose is to
|
|
listen for `401 Unauthorized` responses and give you the ability to
|
|
seamlessly recover. When it catches a 401, it will:
|
|
1. create a deferred
|
|
2. broadcast a `devise:unauthorized` event passing:
|
|
- the ajax response
|
|
- the deferred
|
|
3. return the deferred's promise
|
|
|
|
Since the deferred is passed to the `devise:unauthorized` event, you are
|
|
free to resolve it (and the request) inside of the event listener. For
|
|
instance:
|
|
|
|
```javascript
|
|
angular.module('myModule', []).
|
|
controller('myCtrl', function($scope, Auth, $http) {
|
|
// Guest user
|
|
|
|
// Catch unauthorized requests and recover.
|
|
$scope.$on('devise:unauthorized', function(event, xhr, deferred) {
|
|
// Ask user for login credentials
|
|
|
|
Auth.login(credentials).then(function() {
|
|
// Successfully logged in.
|
|
// Redo the original request.
|
|
return $http(xhr.config);
|
|
}).then(function(response) {
|
|
// Successfully recovered from unauthorized error.
|
|
// Resolve the original request's promise.
|
|
deferred.resolve(response);
|
|
}, function(error) {
|
|
// There was an error logging in.
|
|
// Reject the original request's promise.
|
|
deferred.reject(error);
|
|
});
|
|
});
|
|
|
|
// Request requires authorization
|
|
// Will cause a `401 Unauthorized` response,
|
|
// that will be recovered by our listener above.
|
|
$http.delete('/users/1', {
|
|
interceptAuth: true
|
|
}).then(function(response) {
|
|
// Deleted user 1
|
|
}, function(error) {
|
|
// Something went wrong.
|
|
});
|
|
});
|
|
```
|
|
|
|
The Interceptor can be enabled globally or on a per-request basis using the
|
|
`interceptAuth` setting on the AuthIntercept provider.
|
|
|
|
```javascript
|
|
angular.module('myModule', ['Devise']).
|
|
config(function(AuthInterceptProvider) {
|
|
// Intercept 401 Unauthorized everywhere
|
|
AuthInterceptProvider.interceptAuth(true);
|
|
}).
|
|
controller('myCtrl', function($http) {
|
|
// Disable per-request
|
|
$http({
|
|
url: '/',
|
|
interceptAuth: false,
|
|
// ...
|
|
});
|
|
});
|
|
```
|
|
|
|
|
|
AuthProvider
|
|
------------
|
|
|
|
By default, AngularDevise uses the following HTTP methods/paths:
|
|
|
|
| Method | HTTP Method | HTTP Path |
|
|
| -------- | ----------- | -------------------- |
|
|
| login | POST | /users/sign_in.json |
|
|
| logout | DELETE | /users/sign_out.json |
|
|
| register | POST | /users.json |
|
|
|
|
All credentials will be under the `users` namespace, and the following
|
|
parse function will be used to parse the response:
|
|
|
|
```javascript
|
|
function(response) {
|
|
return response.data;
|
|
};
|
|
```
|
|
|
|
All of these can be configured using a `.config` block in your module.
|
|
|
|
```javascript
|
|
angular.module('myModule', ['Devise']).
|
|
config(function(AuthProvider, AuthInterceptProvider) {
|
|
// Customize login
|
|
AuthProvider.loginMethod('GET');
|
|
AuthProvider.loginPath('/admins/login.json');
|
|
|
|
// Customize logout
|
|
AuthProvider.logoutMethod('POST');
|
|
AuthProvider.logoutPath('/user/logout.json');
|
|
|
|
// Customize register
|
|
AuthProvider.registerMethod('PATCH');
|
|
AuthProvider.registerPath('/user/sign_up.json');
|
|
|
|
// Customize the resource name data use namespaced under
|
|
// Pass false to disable the namespace altogether.
|
|
AuthProvider.resourceName('customer');
|
|
|
|
// Customize user parsing
|
|
// NOTE: **MUST** return a truth-y expression
|
|
AuthProvider.parse(function(response) {
|
|
return response.data.user;
|
|
});
|
|
|
|
// Intercept 401 Unauthorized everywhere
|
|
// Enables `devise:unauthorized` interceptor
|
|
AuthInterceptProvider.interceptAuth(true);
|
|
});
|
|
```
|
|
|
|
|
|
Credits
|
|
-------
|
|
|
|
[![Cloudspace](http://cloudspace.com/assets/images/logo.png)](http://cloudspace.com/)
|
|
|
|
AngularDevise is maintained by [Cloudspace](http://cloudspace.com/), and
|
|
is distributed under the [MIT License](/LICENSE.md).
|