1 /**
  2  * @fileOverview This file provides classes related to authentication and role based permissions.
  3  * @author <a href="mailto:paul.bottin+creds@gmail.com">Paul Bottin</a>
  4  * @version 1.0.0
  5  */
  6 
  7 /**
  8  * provides two classes, {@link creds.users} and {@link creds.roles}<br/>
  9  * @example
 10  *	var creds = require('creds');
 11  *	
 12  *	var u = creds.users({
 13  *		
 14  *		// passwords
 15  *		'admin': 'nimda',
 16  *		'user':	'resu'
 17  *		
 18  *	});
 19  *	
 20  *	var r = creds.roles({
 21  *		
 22  *		// users
 23  *		'anonymous': [],
 24  *		'admin': ['admins'],
 25  *		'user': ['users'],
 26  *		
 27  *		// groups
 28  *		'admins': ['users'],
 29  *		'users': ['registered'],
 30  *		'registered': []
 31  *		
 32  *	});
 33  *   
 34  *	u('admin', 'nimda');		// => true
 35  *	r('admin', 'registered');	// => true
 36  *
 37  * @name creds
 38  * @namespace
 39  */
 40 
 41 /**
 42  * stores user names and their passwords
 43  * @name creds.users
 44  * @constructor
 45  * @param {Object} data
 46  * @returns {creds.users}
 47  */
 48 function users (data) {
 49 
 50 	/**
 51 	 * checks if the given password matches that of the given user
 52 	 * @name creds.users#checkUser
 53 	 * @function
 54 	 * @param {String} username
 55 	 * @param {String} password
 56 	 * @returns {Boolean}
 57 	 */
 58 	function checkUser (username, password) {
 59 		return	(username			!==	undefined)		// no user name given
 60 		&&		(username.length	 >	0)				// empty user name given
 61 		&&		(data[username]		!==	undefined)		// unknown user name
 62 		&&		(password			!==	undefined)		// no password given
 63 		&&		(password.length	 >	0)				// empty password given
 64 		&&		(data[username]		 ==	password)		// password mismatch
 65 		;
 66 	};
 67 	checkUser.checkUser = checkUser;
 68 	
 69 	/**
 70 	 * gets a list of known user names
 71 	 * @name creds.users#usernames
 72 	 * @property
 73 	 * @constant
 74 	 * @type Array
 75 	 */
 76 	checkUser.__defineGetter__('usernames', function () {
 77 		return Object.keys(data);
 78 	});
 79 	
 80 	Object.freeze(checkUser);
 81 	Object.seal(checkUser);
 82 	return checkUser;
 83 }
 84 exports.users = users;
 85 Object.freeze(users);
 86 Object.seal(users);
 87 
 88 /**
 89  * stores role assignments
 90  * @name creds.roles
 91  * @constructor
 92  * @param {Object} data
 93  * @returns {creds.roles}
 94  */
 95 function roles (data) {
 96 	
 97 	/**
 98 	 * checks if the role is membership or owns inherited membership
 99 	 * @name creds.roles#checkRole
100 	 * @function
101 	 * @param {String} role
102 	 * @param {String} membership
103 	 * @returns {Boolean}
104 	 */
105 	function checkRole (role, membership) {
106 		var result = false;
107 		if ( 	(role				!==	undefined)		// no role given
108 		&&		(role.length		 >	0)				// empty role given
109 		&&		(data[role]			!==	undefined)		// unknown role
110 		&&		(membership			!==	undefined)		// no membership given
111 		&&		(membership.length	 >	0)				// empty membership given
112 		) {
113 			if (role == membership)
114 				result = true;
115 			data[role].forEach(function (m) {
116 				if (membership == m)
117 					result = true;
118 				else
119 					result = result || checkRole(m, membership);
120 			});
121 			
122 		}
123 		return result;
124 	}
125 	checkRole.checkRole = checkRole;
126 	
127 	/**
128 	 * gets a list of known roles
129 	 * @name creds.roles#roles
130 	 * @property
131 	 * @constant
132 	 * @type Array
133 	 */
134 	checkRole.__defineGetter__('roles', function () {
135 		return Object.keys(data);
136 	});
137 	
138 	/**
139 	 * gets all inherited roles of a role
140 	 * @name creds.roles#activeRoles
141 	 * @function
142 	 * @param {String} role
143 	 * @returns {Array}
144 	 */
145 	function activeRoles (role) {
146 		return Object.keys(data).filter(function (r) {
147 			return checkRole(role, r);
148 		});;
149 	}
150 	checkRole.activeRoles = activeRoles;
151 
152 	Object.freeze(checkRole);
153 	Object.seal(checkRole);
154 	return checkRole;
155 }
156 exports.roles = roles;
157 
158 Object.freeze(roles);
159 Object.seal(roles);
160 
161 Object.freeze(exports);
162 Object.seal(exports);
163