Permalink
Browse files

feat($cookiesProvider): provide path, domain, expires and secure options

This change provides properties on `$cookiesProvider` so that you can set the application
level default options for cookies that are set using the `$cookies` service
  • Loading branch information...
shahata authored and petebacondarwin committed Mar 2, 2015
1 parent 92c366d commit 53c663699126815eabc2a3bc1e3bafc8b3874268
Showing with 125 additions and 40 deletions.
  1. +69 −40 src/ngCookies/cookies.js
  2. +56 −0 test/ngCookies/cookiesSpec.js
View
@@ -19,31 +19,66 @@
angular.module('ngCookies', ['ng']).
/**
* @ngdoc service
* @name $cookies
*
* @ngdoc provider
* @name $cookiesProvider
* @description
* Provides read/write access to browser's cookies.
*
* BREAKING CHANGE: `$cookies` no longer exposes properties that represent the
* current browser cookie values. Now you must use the get/put/remove/etc. methods
* as described below.
*
* Requires the {@link ngCookies `ngCookies`} module to be installed.
*
* @example
*
* ```js
* angular.module('cookiesExample', ['ngCookies'])
* .controller('ExampleController', ['$cookies', function($cookies) {
* // Retrieving a cookie
* var favoriteCookie = $cookies.get('myFavorite');
* // Setting a cookie
* $cookies.put('myFavorite', 'oatmeal');
* }]);
* ```
*/
factory('$cookies', ['$$cookieReader', '$$cookieWriter', function($$cookieReader, $$cookieWriter) {
* Use `$cookiesProvider` to change the default behavior of the {@link ngCookies.$cookies $cookies} service.
* */
provider('$cookies', [function $CookiesProvider() {
/**
* @ngdoc property
* @name $cookiesProvider#defaults
* @description
*
* Object containing default options to pass when setting cookies.
*
* The object may have following properties:
*
* - **path** - `{string}` - The cookie will be available only for this path and its
* sub-paths. By default, this would be the URL that appears in your base tag.
* - **domain** - `{string}` - The cookie will be available only for this domain and
* its sub-domains. For obvious security reasons the user agent will not accept the
* cookie if the current domain is not a sub domain or equals to the requested domain.
* - **expires** - `{string|Date}` - String of the form "Wdy, DD Mon YYYY HH:MM:SS GMT"
* or a Date object indicating the exact date/time this cookie will expire.
* - **secure** - `{boolean}` - The cookie will be available only in secured connection.
*
* Note: by default the address that appears in your <base> tag will be used as path.
* This is import so that cookies will be visible for all routes in case html5mode is enabled
*
**/
var defaults = this.defaults = {};
function calcOptions(options) {
return options ? angular.extend({}, defaults, options) : defaults;
}
/**
* @ngdoc service
* @name $cookies
*
* @description
* Provides read/write access to browser's cookies.
*
* BREAKING CHANGE: `$cookies` no longer exposes properties that represent the
* current browser cookie values. Now you must use the get/put/remove/etc. methods
* as described below.
*
* Requires the {@link ngCookies `ngCookies`} module to be installed.
*
* @example
*
* ```js
* angular.module('cookiesExample', ['ngCookies'])
* .controller('ExampleController', ['$cookies', function($cookies) {
* // Retrieving a cookie
* var favoriteCookie = $cookies.get('myFavorite');
* // Setting a cookie
* $cookies.put('myFavorite', 'oatmeal');
* }]);
* ```
*/
this.$get = ['$$cookieReader', '$$cookieWriter', function($$cookieReader, $$cookieWriter) {
return {
/**
* @ngdoc method
@@ -70,7 +105,7 @@ angular.module('ngCookies', ['ng']).
* @returns {Object} Deserialized cookie value.
*/
getObject: function(key) {
var value = $$cookieReader()[key];
var value = this.get(key);
return value ? angular.fromJson(value) : value;
},
@@ -96,20 +131,11 @@ angular.module('ngCookies', ['ng']).
*
* @param {string} key Id for the `value`.
* @param {string} value Raw value to be stored.
* @param {Object=} options Object with options that need to be stored for the cookie.
* The object may have following properties:
*
* - **path** - `{string}` - The cookie will be available only for this path and its
* sub-paths. By default, this would be the URL that appears in your base tag.
* - **domain** - `{string}` - The cookie will be available only for this domain and
* its sub-domains. For obvious security reasons the user agent will not accept the
* cookie if the current domain is not a sub domain or equals to the requested domain.
* - **expires** - `{string|Date}` - String of the form "Wdy, DD Mon YYYY HH:MM:SS GMT"
* or a Date object indicating the exact date/time this cookie will expire.
* - **secure** - `{boolean}` - The cookie will be available only in secured connection.
* @param {Object=} options Options object.
* See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults}
*/
put: function(key, value, options) {
$$cookieWriter(key, value, options);
$$cookieWriter(key, value, calcOptions(options));
},
/**
@@ -122,9 +148,10 @@ angular.module('ngCookies', ['ng']).
* @param {string} key Id for the `value`.
* @param {Object} value Value to be stored.
* @param {Object=} options Options object.
* See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults}
*/
putObject: function(key, value, options) {
$$cookieWriter(key, angular.toJson(value), options);
this.put(key, angular.toJson(value), options);
},
/**
@@ -136,9 +163,11 @@ angular.module('ngCookies', ['ng']).
*
* @param {string} key Id of the key-value pair to delete.
* @param {Object=} options Options object.
* See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults}
*/
remove: function(key, options) {
$$cookieWriter(key, undefined, options);
$$cookieWriter(key, undefined, calcOptions(options));
}
};
}]);
}];
}]);
@@ -83,4 +83,60 @@ describe('$cookies', function() {
$cookies.remove('name', {path: '/a/b'});
expect($$cookieWriter).toHaveBeenCalledWith('name', undefined, {path: '/a/b'});
}));
it('should pass default options on put', function() {
module(function($cookiesProvider) {
$cookiesProvider.defaults.secure = true;
});
inject(function($cookies, $$cookieWriter) {
$cookies.put('name', 'value', {path: '/a/b'});
expect($$cookieWriter).toHaveBeenCalledWith('name', 'value', {path: '/a/b', secure: true});
});
});
it('should pass default options on putObject', function() {
module(function($cookiesProvider) {
$cookiesProvider.defaults.secure = true;
});
inject(function($cookies, $$cookieWriter) {
$cookies.putObject('name', 'value', {path: '/a/b'});
expect($$cookieWriter).toHaveBeenCalledWith('name', '"value"', {path: '/a/b', secure: true});
});
});
it('should pass default options on remove', function() {
module(function($cookiesProvider) {
$cookiesProvider.defaults.secure = true;
});
inject(function($cookies, $$cookieWriter) {
$cookies.remove('name', {path: '/a/b'});
expect($$cookieWriter).toHaveBeenCalledWith('name', undefined, {path: '/a/b', secure: true});
});
});
it('should let passed options override default options', function() {
module(function($cookiesProvider) {
$cookiesProvider.defaults.secure = true;
});
inject(function($cookies, $$cookieWriter) {
$cookies.put('name', 'value', {secure: false});
expect($$cookieWriter).toHaveBeenCalledWith('name', 'value', {secure: false});
});
});
it('should pass default options if no options are passed', function() {
module(function($cookiesProvider) {
$cookiesProvider.defaults.secure = true;
});
inject(function($cookies, $$cookieWriter) {
$cookies.put('name', 'value');
expect($$cookieWriter).toHaveBeenCalledWith('name', 'value', {secure: true});
});
});
});

0 comments on commit 53c6636

Please sign in to comment.