1 /**
  2  * @fileOverview Base Authentication.
  3  */
  4 
  5 (function () {
  6   // Requires.
  7   var http = require('http'),
  8     crypto = require('crypto'),
  9     parse = require('url').parse,
 10     CloudError = require("../errors").CloudError,
 11     AuthenticatedRequest = require("../request").AuthenticatedRequest,
 12     AuthenticatedXmlRequest = require("../request").AuthenticatedXmlRequest,
 13     Authentication;
 14 
 15   /**
 16    * Authentication class.
 17    *
 18    * @param  {Object}   options    Options object.
 19    * @config {string}   account    Account name.
 20    * @config {string}   secretKey  Secret key.
 21    * @config {string}   [ssl=false] Use SSL?
 22    * @config {string}   [authUrl]  Authentication URL.
 23    * @config {number}   [timeout]  HTTP timeout in seconds.
 24    * @exports Authentication as base.Authentication
 25    * @constructor
 26    */
 27   Authentication = function (options) {
 28     // Argument parsing and validation.
 29     options = options || {};
 30     if (!options.account) { throw new Error("No account name."); }
 31     if (!options.secretKey) { throw new Error("No secret key."); }
 32     if (!options.authUrl) { throw new Error("No authentication URL."); }
 33 
 34     // Member variables.
 35     this._account = options.account;
 36     this._secretKey = options.secretKey;
 37     this._ssl = options.ssl || false;
 38     this._port = options.port || (this._ssl ? 443 : 80);
 39     this._authUrl = options.authUrl;
 40     this._timeout = options.timeout || 5;
 41     this._conn = null;
 42   };
 43 
 44   Object.defineProperties(Authentication.prototype, {
 45     /**
 46      * Use SSL?
 47      *
 48      * @name Authentication#ssl
 49      * @type boolean
 50      */
 51     ssl: {
 52       get: function () {
 53         return this._ssl;
 54       }
 55     },
 56 
 57     /**
 58      * Port number.
 59      *
 60      * @name Authentication#port
 61      * @type number
 62      */
 63     port: {
 64       get: function () {
 65         return this._port;
 66       }
 67     },
 68 
 69     /**
 70      * Connection object.
 71      *
 72      * @name Authentication#connection
 73      * @type base.Connection
 74      */
 75     connection: {
 76       get: function () {
 77         var self = this;
 78 
 79         if (self._conn === null) {
 80           if (!self._CONN_CLS) {
 81             throw new Error("Subclass must define _CONN_CLS.");
 82           }
 83 
 84           self._conn = new self._CONN_CLS(self);
 85         }
 86 
 87         return self._conn;
 88       }
 89     }
 90   });
 91 
 92   /** Test provider (AWS). */
 93   Authentication.prototype.isAws = function () {
 94     return false;
 95   };
 96 
 97   /** Test provider (Google Storage). */
 98   Authentication.prototype.isGoogle = function () {
 99     return false;
100   };
101 
102   /**
103    * Return authorization url.
104    *
105    * @param {string} [name] Name to prepend to URL.
106    */
107   Authentication.prototype.authUrl = function (name) {
108     if (name) {
109       return name + "." + this._authUrl;
110     }
111     return this._authUrl;
112   };
113 
114   /**
115    * Create basic request headers.
116    * @private
117    */
118   Authentication.prototype._getHeaders = function (headers) {
119     var lowHeaders = {},
120       header;
121 
122     // Get lower-cased headers.
123     headers = headers || {};
124     for (header in headers) {
125       if (headers.hasOwnProperty(header)) {
126         lowHeaders[header.toString().toLowerCase()] = headers[header];
127       }
128     }
129 
130     // Add default parameters.
131     lowHeaders['date'] = lowHeaders['date'] || new Date().toUTCString();
132     lowHeaders['host'] = lowHeaders['host'] || this._authUrl;
133 
134     return lowHeaders;
135   };
136 
137   /**
138    * Sign request headers and return new headers.
139    *
140    * @param  {string}   [method]    HTTP method (verb).
141    * @param  {string}   [path]      HTTP path.
142    * @param  {Object}   [headers]   HTTP headers.
143    * @returns {Object}              Signed headers.
144    */
145   Authentication.prototype.sign = function (method, path, headers) {
146     // Nop.
147     return headers;
148   };
149 
150   /**
151    * Create a new signed request object.
152    *
153    * @param  {Object}   options     Options object.
154    * @config {string}   [method]    HTTP method (verb).
155    * @config {string}   [path]      HTTP path.
156    * @config {Object}   [headers]   HTTP headers.
157    * @config {Function} [resultsFn] Successful results data transform.
158    */
159   Authentication.prototype.createRequest = function (options) {
160     return new AuthenticatedRequest(this, options);
161   };
162 
163   /**
164    * Create a new signed request object with JSON results from XML.
165    *
166    * @param  {Object}   options     Options object.
167    * @config {string}   [method]    HTTP method (verb).
168    * @config {string}   [path]      HTTP path.
169    * @config {Object}   [headers]   HTTP headers.
170    * @config {Function} [resultsFn] Successful results data transform.
171    */
172   Authentication.prototype.createXmlRequest = function (options) {
173     return new AuthenticatedXmlRequest(this, options);
174   };
175 
176   module.exports.Authentication = Authentication;
177 }());
178