2 // System.Web.Security.SqlRoleProvider
5 // Ben Maurer (bmaurer@users.sourceforge.net)
6 // Chris Toshok (toshok@ximian.com)
9 // Copyright (c) 2005,2006 Novell, Inc (http://www.novell.com)
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System.Collections;
34 using System.Collections.Specialized;
36 using System.Data.Common;
37 using System.Configuration;
38 using System.Configuration.Provider;
39 using System.Web.Configuration;
41 namespace System.Web.Security
44 public class SqlRoleProvider : RoleProvider
47 string applicationName;
49 ConnectionStringSettings connectionString;
50 DbProviderFactory factory;
52 DbConnection CreateConnection ()
54 DbConnection connection = factory.CreateConnection ();
55 connection.ConnectionString = connectionString.ConnectionString;
61 static void AddParameter (DbCommand command, string parameterName, object parameterValue)
63 AddParameter (command, parameterName, ParameterDirection.Input, parameterValue);
66 static DbParameter AddParameter (DbCommand command, string parameterName, ParameterDirection direction, object parameterValue)
68 DbParameter dbp = command.CreateParameter ();
69 dbp.ParameterName = parameterName;
70 dbp.Value = parameterValue;
71 dbp.Direction = direction;
72 command.Parameters.Add (dbp);
76 static DbParameter AddParameter (DbCommand command, string parameterName, ParameterDirection direction, DbType type, object parameterValue)
78 DbParameter dbp = command.CreateParameter ();
79 dbp.ParameterName = parameterName;
80 dbp.Value = parameterValue = parameterValue;
81 dbp.Direction = direction;
83 command.Parameters.Add (dbp);
87 public override void AddUsersToRoles (string [] usernames, string [] rolenames)
89 Hashtable h = new Hashtable ();
91 foreach (string u in usernames) {
93 throw new ArgumentNullException ("null element in usernames array");
94 if (h.ContainsKey (u))
95 throw new ArgumentException ("duplicate element in usernames array");
96 if (u.Length == 0 || u.Length > 256 || u.IndexOf (",") != -1)
97 throw new ArgumentException ("element in usernames array in illegal format");
101 h = new Hashtable ();
102 foreach (string r in rolenames) {
104 throw new ArgumentNullException ("null element in rolenames array");
105 if (h.ContainsKey (r))
106 throw new ArgumentException ("duplicate element in rolenames array");
107 if (r.Length == 0 || r.Length > 256 || r.IndexOf (",") != -1)
108 throw new ArgumentException ("element in rolenames array in illegal format");
112 using (DbConnection connection = CreateConnection ()) {
113 /* add the user/role combination to dbo.aspnet_UsersInRoles */
114 DbCommand command = factory.CreateCommand ();
115 command.CommandText = @"dbo.aspnet_UsersInRoles_AddUsersToRoles";
116 command.Connection = connection;
117 command.CommandType = CommandType.StoredProcedure;
119 AddParameter (command, "@RoleNames", String.Join (",", rolenames));
120 AddParameter (command, "@UserNames", String.Join (",", usernames));
121 AddParameter (command, "@ApplicationName", ApplicationName);
122 AddParameter (command, "@CurrentTimeUtc", DateTime.UtcNow);
123 DbParameter dbpr = AddParameter (command, "@ReturnVal", ParameterDirection.ReturnValue, DbType.Int32, null);
125 command.ExecuteNonQuery ();
127 int returnValue = (int) dbpr.Value;
128 if (returnValue == 0)
130 else if (returnValue == 2)
131 throw new ProviderException ("One or more of the specified user/role names was not found.");
132 else if (returnValue == 3)
133 throw new ProviderException ("One or more of the specified user names is already associated with one or more of the specified role names.");
135 throw new ProviderException ("Failed to create new user/role association.");
139 public override void CreateRole (string rolename)
141 if (rolename == null)
142 throw new ArgumentNullException ("rolename");
144 if (rolename.Length == 0 || rolename.Length > 256 || rolename.IndexOf (",") != -1)
145 throw new ArgumentException ("rolename is in invalid format");
147 using (DbConnection connection = CreateConnection ()) {
148 DbCommand command = factory.CreateCommand ();
149 command.CommandText = @"dbo.aspnet_Roles_CreateRole";
150 command.Connection = connection;
151 command.CommandType = CommandType.StoredProcedure;
153 AddParameter (command, "@ApplicationName", ApplicationName);
154 AddParameter (command, "@RoleName", rolename);
155 DbParameter dbpr = AddParameter (command, "@ReturnVal", ParameterDirection.ReturnValue, DbType.Int32, null);
157 command.ExecuteNonQuery ();
158 int returnValue = (int) dbpr.Value;
160 if (returnValue == 1)
161 throw new ProviderException (rolename + " already exists in the database");
167 public override bool DeleteRole (string rolename, bool throwOnPopulatedRole)
169 if (rolename == null)
170 throw new ArgumentNullException ("rolename");
172 if (rolename.Length == 0 || rolename.Length > 256 || rolename.IndexOf (",") != -1)
173 throw new ArgumentException ("rolename is in invalid format");
175 using (DbConnection connection = CreateConnection ()) {
177 DbCommand command = factory.CreateCommand ();
178 command.CommandText = @"dbo.aspnet_Roles_DeleteRole";
179 command.Connection = connection;
180 command.CommandType = CommandType.StoredProcedure;
181 AddParameter (command, "@ApplicationName", ApplicationName);
182 AddParameter (command, "@RoleName", rolename);
183 AddParameter (command, "@DeleteOnlyIfRoleIsEmpty", throwOnPopulatedRole);
184 DbParameter dbpr = AddParameter (command, "@ReturnVal", ParameterDirection.ReturnValue, DbType.Int32, null);
186 command.ExecuteNonQuery ();
187 int returnValue = (int)dbpr.Value;
189 if (returnValue == 0)
191 if (returnValue == 1)
192 return false; //role does not exists
193 else if (returnValue == 2 && throwOnPopulatedRole)
194 throw new ProviderException (rolename + " is not empty");
200 public override string [] FindUsersInRole (string roleName, string usernameToMatch)
202 if (roleName == null)
203 throw new ArgumentNullException ("roleName");
204 if (usernameToMatch == null)
205 throw new ArgumentNullException ("usernameToMatch");
206 if (roleName.Length == 0 || roleName.Length > 256 || roleName.IndexOf (",") != -1)
207 throw new ArgumentException ("roleName is in invalid format");
208 if (usernameToMatch.Length == 0 || usernameToMatch.Length > 256)
209 throw new ArgumentException ("usernameToMatch is in invalid format");
211 using (DbConnection connection = CreateConnection ()) {
212 DbCommand command = factory.CreateCommand ();
213 command.Connection = connection;
214 command.CommandText = @"dbo.aspnet_UsersInRoles_FindUsersInRole";
215 command.CommandType = CommandType.StoredProcedure;
217 AddParameter (command, "@ApplicationName", ApplicationName);
218 AddParameter (command, "@RoleName", roleName);
219 AddParameter (command, "@UsernameToMatch", usernameToMatch);
221 DbDataReader reader = command.ExecuteReader ();
222 ArrayList userList = new ArrayList ();
223 while (reader.Read ())
224 userList.Add (reader.GetString (0));
227 return (string []) userList.ToArray (typeof (string));
231 public override string [] GetAllRoles ()
233 using (DbConnection connection = CreateConnection ()) {
234 DbCommand command = factory.CreateCommand ();
235 command.CommandText = @"dbo.aspnet_Roles_GetAllRoles";
236 command.Connection = connection;
238 command.CommandType = CommandType.StoredProcedure;
239 AddParameter (command, "@ApplicationName", ApplicationName);
241 DbDataReader reader = command.ExecuteReader ();
242 ArrayList roleList = new ArrayList ();
243 while (reader.Read ())
244 roleList.Add (reader.GetString (0));
247 return (string []) roleList.ToArray (typeof (string));
251 public override string [] GetRolesForUser (string username)
253 using (DbConnection connection = CreateConnection ()) {
254 DbCommand command = factory.CreateCommand ();
255 command.CommandText = @"dbo.aspnet_UsersInRoles_GetRolesForUser";
256 command.Connection = connection;
258 command.CommandType = CommandType.StoredProcedure;
259 AddParameter (command, "@UserName", username);
260 AddParameter (command, "@ApplicationName", ApplicationName);
262 DbDataReader reader = command.ExecuteReader ();
263 ArrayList roleList = new ArrayList ();
264 while (reader.Read ())
265 roleList.Add (reader.GetString (0));
268 return (string []) roleList.ToArray (typeof (string));
272 public override string [] GetUsersInRole (string rolename)
274 using (DbConnection connection = CreateConnection ()) {
275 DbCommand command = factory.CreateCommand ();
276 command.CommandText = @"dbo.aspnet_UsersInRoles_GetUsersInRoles";
277 command.Connection = connection;
279 command.CommandType = CommandType.StoredProcedure;
280 AddParameter (command, "@RoleName", rolename);
281 AddParameter (command, "@ApplicationName", ApplicationName);
283 DbDataReader reader = command.ExecuteReader ();
284 ArrayList userList = new ArrayList ();
285 while (reader.Read ())
286 userList.Add (reader.GetString (0));
289 return (string []) userList.ToArray (typeof (string));
293 string GetStringConfigValue (NameValueCollection config, string name, string def)
296 string val = config [name];
302 public override void Initialize (string name, NameValueCollection config)
305 throw new ArgumentNullException ("config");
307 base.Initialize (name, config);
309 applicationName = GetStringConfigValue (config, "applicationName", "/");
310 string connectionStringName = config ["connectionStringName"];
312 if (applicationName.Length > 256)
313 throw new ProviderException ("The ApplicationName attribute must be 256 characters long or less.");
314 if (connectionStringName == null || connectionStringName.Length == 0)
315 throw new ProviderException ("The ConnectionStringName attribute must be present and non-zero length.");
317 // XXX check connectionStringName and commandTimeout
319 connectionString = WebConfigurationManager.ConnectionStrings [connectionStringName];
320 if (connectionString == null)
321 throw new ProviderException (String.Format("The connection name '{0}' was not found in the applications configuration or the connection string is empty.", connectionStringName));
322 factory = String.IsNullOrEmpty (connectionString.ProviderName) ?
323 System.Data.SqlClient.SqlClientFactory.Instance :
324 ProvidersHelper.GetDbProviderFactory (connectionString.ProviderName);
327 public override bool IsUserInRole (string username, string rolename)
329 using (DbConnection connection = CreateConnection ()) {
330 DbCommand command = factory.CreateCommand ();
331 command.CommandText = @"dbo.aspnet_UsersInRoles_IsUserInRole";
332 command.Connection = connection;
334 command.CommandType = CommandType.StoredProcedure;
335 AddParameter (command, "@RoleName", rolename);
336 AddParameter (command, "@UserName", username);
337 AddParameter (command, "@ApplicationName", ApplicationName);
338 DbParameter dbpr = AddParameter (command, "@ReturnVal", ParameterDirection.ReturnValue, DbType.Int32, null);
340 command.ExecuteNonQuery ();
341 int returnValue = (int) dbpr.Value;
343 if (returnValue == 1)
350 public override void RemoveUsersFromRoles (string [] usernames, string [] rolenames)
352 Hashtable h = new Hashtable ();
354 foreach (string u in usernames) {
356 throw new ArgumentNullException ("null element in usernames array");
357 if (h.ContainsKey (u))
358 throw new ArgumentException ("duplicate element in usernames array");
359 if (u.Length == 0 || u.Length > 256 || u.IndexOf (",") != -1)
360 throw new ArgumentException ("element in usernames array in illegal format");
364 h = new Hashtable ();
365 foreach (string r in rolenames) {
367 throw new ArgumentNullException ("null element in rolenames array");
368 if (h.ContainsKey (r))
369 throw new ArgumentException ("duplicate element in rolenames array");
370 if (r.Length == 0 || r.Length > 256 || r.IndexOf (",") != -1)
371 throw new ArgumentException ("element in rolenames array in illegal format");
375 using (DbConnection connection = CreateConnection ()) {
376 DbCommand command = factory.CreateCommand ();
377 command.CommandText = @"dbo.aspnet_UsersInRoles_RemoveUsersFromRoles";
378 command.Connection = connection;
379 command.CommandType = CommandType.StoredProcedure;
381 AddParameter (command, "@UserNames", String.Join (",", usernames));
382 AddParameter (command, "@RoleNames", String.Join (",", rolenames));
383 AddParameter (command, "@ApplicationName", ApplicationName);
384 DbParameter dbpr = AddParameter (command, "@ReturnVal", ParameterDirection.ReturnValue, DbType.Int32, null);
386 command.ExecuteNonQuery ();
387 int returnValue = (int) dbpr.Value;
389 if (returnValue == 0)
391 else if (returnValue == 1)
392 throw new ProviderException ("One or more of the specified user names was not found.");
393 else if (returnValue == 2)
394 throw new ProviderException ("One or more of the specified role names was not found.");
395 else if (returnValue == 3)
396 throw new ProviderException ("One or more of the specified user names is not associated with one or more of the specified role names.");
398 throw new ProviderException ("Failed to remove users from roles");
402 public override bool RoleExists (string rolename)
404 using (DbConnection connection = CreateConnection ()) {
406 DbCommand command = factory.CreateCommand ();
407 command.CommandText = @"dbo.aspnet_Roles_RoleExists";
408 command.Connection = connection;
409 command.CommandType = CommandType.StoredProcedure;
411 AddParameter (command, "@ApplicationName", ApplicationName);
412 AddParameter (command, "@RoleName", rolename);
413 DbParameter dbpr = AddParameter (command, "@ReturnVal", ParameterDirection.ReturnValue, DbType.Int32, null);
415 command.ExecuteNonQuery ();
416 int returnValue = (int) dbpr.Value;
418 if (returnValue == 1)
425 public override string ApplicationName
427 get { return applicationName; }
430 applicationName = value;