New test.
[mono.git] / mcs / class / System.Web / System.Web.Security / SqlRoleProvider.cs
1 //
2 // System.Web.Security.SqlRoleProvider
3 //
4 // Authors:
5 //      Ben Maurer (bmaurer@users.sourceforge.net)
6 //      Chris Toshok (toshok@ximian.com)
7 //
8 // (C) 2003 Ben Maurer
9 // Copyright (c) 2005,2006 Novell, Inc (http://www.novell.com)
10 //
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:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
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.
29 //
30
31 #if NET_2_0
32
33 using System.Collections;
34 using System.Collections.Specialized;
35 using System.Data;
36 using System.Data.Common;
37 using System.Configuration;
38 using System.Configuration.Provider;
39 using System.Web.Configuration;
40
41 namespace System.Web.Security
42 {
43
44         public class SqlRoleProvider : RoleProvider
45         {
46
47                 string applicationName;
48
49                 ConnectionStringSettings connectionString;
50                 DbProviderFactory factory;
51
52                 DbConnection CreateConnection ()
53                 {
54                         DbConnection connection = factory.CreateConnection ();
55                         connection.ConnectionString = connectionString.ConnectionString;
56
57                         connection.Open ();
58                         return connection;
59                 }
60
61                 static void AddParameter (DbCommand command, string parameterName, object parameterValue)
62                 {
63                         AddParameter (command, parameterName, ParameterDirection.Input, parameterValue);
64                 }
65
66                 static DbParameter AddParameter (DbCommand command, string parameterName, ParameterDirection direction, object parameterValue)
67                 {
68                         DbParameter dbp = command.CreateParameter ();
69                         dbp.ParameterName = parameterName;
70                         dbp.Value = parameterValue;
71                         dbp.Direction = direction;
72                         command.Parameters.Add (dbp);
73                         return dbp;
74                 }
75
76                 public override void AddUsersToRoles (string [] usernames, string [] rolenames)
77                 {
78                         Hashtable h = new Hashtable ();
79
80                         foreach (string u in usernames) {
81                                 if (u == null)
82                                         throw new ArgumentNullException ("null element in usernames array");
83                                 if (h.ContainsKey (u))
84                                         throw new ArgumentException ("duplicate element in usernames array");
85                                 if (u.Length == 0 || u.Length > 256 || u.IndexOf (",") != -1)
86                                         throw new ArgumentException ("element in usernames array in illegal format");
87                                 h.Add (u, u);
88                         }
89
90                         h = new Hashtable ();
91                         foreach (string r in rolenames) {
92                                 if (r == null)
93                                         throw new ArgumentNullException ("null element in rolenames array");
94                                 if (h.ContainsKey (r))
95                                         throw new ArgumentException ("duplicate element in rolenames array");
96                                 if (r.Length == 0 || r.Length > 256 || r.IndexOf (",") != -1)
97                                         throw new ArgumentException ("element in rolenames array in illegal format");
98                                 h.Add (r, r);
99                         } 
100                         
101                         using (DbConnection connection = CreateConnection ()) {
102                                 /* add the user/role combination to dbo.aspnet_UsersInRoles */
103                                 DbCommand command = factory.CreateCommand ();
104                                 command.CommandText = @"dbo.aspnet_UsersInRoles_AddUsersToRoles";
105                                 command.Connection = connection;
106                                 command.CommandType = CommandType.StoredProcedure;
107
108                                 AddParameter (command, "RoleNames", String.Join (",", rolenames));
109                                 AddParameter (command, "UserNames", String.Join (",", usernames));
110                                 AddParameter (command, "ApplicationName", ApplicationName);
111                                 AddParameter (command, "CurrentTimeUtc", DateTime.UtcNow);
112                                 DbParameter dbpr = AddParameter (command, null, ParameterDirection.ReturnValue, null);
113
114                                 command.ExecuteNonQuery ();
115
116                                 int returnValue = (int) dbpr.Value;
117                                 if (returnValue == 0)
118                                         return;
119                                 else if (returnValue == 2)
120                                         throw new ProviderException ("One or more of the specified user/role names was not found.");
121                                 else if (returnValue == 3)
122                                         throw new ProviderException ("One or more of the specified user names is already associated with one or more of the specified role names.");
123                                 else
124                                         throw new ProviderException ("Failed to create new user/role association.");
125                         }
126                 }
127
128                 public override void CreateRole (string rolename)
129                 {
130                         if (rolename == null)
131                                 throw new ArgumentNullException ("rolename");
132
133                         if (rolename.Length == 0 || rolename.Length > 256 || rolename.IndexOf (",") != -1)
134                                 throw new ArgumentException ("rolename is in invalid format");
135
136                         using (DbConnection connection = CreateConnection ()) {
137                                 DbCommand command = factory.CreateCommand ();
138                                 command.CommandText = @"dbo.aspnet_Roles_CreateRole";
139                                 command.Connection = connection;
140                                 command.CommandType = CommandType.StoredProcedure;
141                                 
142                                 AddParameter (command, "ApplicationName", ApplicationName);
143                                 AddParameter (command, "RoleName", rolename);
144                                 DbParameter dbpr = AddParameter (command, null, ParameterDirection.ReturnValue, null);
145
146                                 command.ExecuteNonQuery ();
147                                 int returnValue = (int) dbpr.Value;
148
149                                 if (returnValue == 1)
150                                         throw new ProviderException (rolename + " already exists in the database");
151                                 else
152                                         return;
153                         }
154                 }
155
156                 public override bool DeleteRole (string rolename, bool throwOnPopulatedRole)
157                 {
158                         if (rolename == null)
159                                 throw new ArgumentNullException ("rolename");
160
161                         if (rolename.Length == 0 || rolename.Length > 256 || rolename.IndexOf (",") != -1)
162                                 throw new ArgumentException ("rolename is in invalid format");
163
164                         using (DbConnection connection = CreateConnection ()) {
165
166                                 DbCommand command = factory.CreateCommand ();
167                                 command.CommandText = @"dbo.aspnet_Roles_DeleteRole";
168                                 command.Connection = connection;
169                                 command.CommandType = CommandType.StoredProcedure;
170                                 AddParameter (command, "ApplicationName", ApplicationName);
171                                 AddParameter (command, "RoleName", rolename);
172                                 AddParameter (command, "DeleteOnlyIfRoleIsEmpty", throwOnPopulatedRole);
173                                 DbParameter dbpr = AddParameter (command, null, ParameterDirection.ReturnValue, null);
174
175                                 command.ExecuteNonQuery ();
176                                 int returnValue = (int)dbpr.Value;
177
178                                 if (returnValue == 0)
179                                         return true;
180                                 if (returnValue == 1)
181                                         return false; //role does not exists
182                                 else if (returnValue == 2 && throwOnPopulatedRole)
183                                         throw new ProviderException (rolename + " is not empty");
184                                 else
185                                         return false;
186                         }
187                 }
188
189                 public override string [] FindUsersInRole (string roleName, string usernameToMatch)
190                 {
191                         if (roleName == null)
192                                 throw new ArgumentNullException ("roleName");
193                         if (usernameToMatch == null)
194                                 throw new ArgumentNullException ("usernameToMatch");
195                         if (roleName.Length == 0 || roleName.Length > 256 || roleName.IndexOf (",") != -1)
196                                 throw new ArgumentException ("roleName is in invalid format");
197                         if (usernameToMatch.Length == 0 || usernameToMatch.Length > 256)
198                                 throw new ArgumentException ("usernameToMatch is in invalid format");
199
200                         using (DbConnection connection = CreateConnection ()) {
201                                 DbCommand command = factory.CreateCommand ();
202                                 command.Connection = connection;
203                                 command.CommandText = @"dbo.aspnet_UsersInRoles_FindUsersInRole";
204                                 command.CommandType = CommandType.StoredProcedure;
205
206                                 AddParameter (command, "ApplicationName", ApplicationName);
207                                 AddParameter (command, "RoleName", roleName);
208                                 AddParameter (command, "UsernameToMatch", usernameToMatch);
209
210                                 DbDataReader reader = command.ExecuteReader ();
211                                 ArrayList userList = new ArrayList ();
212                                 while (reader.Read ())
213                                         userList.Add (reader.GetString (0));
214                                 reader.Close ();
215
216                                 return (string []) userList.ToArray (typeof (string));
217                         }
218                 }
219
220                 public override string [] GetAllRoles ()
221                 {
222                         using (DbConnection connection = CreateConnection ()) {
223                                 DbCommand command = factory.CreateCommand ();
224                                 command.CommandText = @"dbo.aspnet_Roles_GetAllRoles";
225                                 command.Connection = connection;
226
227                                 command.CommandType = CommandType.StoredProcedure;
228                                 AddParameter (command, "ApplicationName", ApplicationName);
229
230                                 DbDataReader reader = command.ExecuteReader ();
231                                 ArrayList roleList = new ArrayList ();
232                                 while (reader.Read ())
233                                         roleList.Add (reader.GetString (0));
234                                 reader.Close ();
235
236                                 return (string []) roleList.ToArray (typeof (string));
237                         }
238                 }
239
240                 public override string [] GetRolesForUser (string username)
241                 {
242                         using (DbConnection connection = CreateConnection ()) {
243                                 DbCommand command = factory.CreateCommand ();
244                                 command.CommandText = @"dbo.aspnet_UsersInRoles_GetRolesForUser";
245                                 command.Connection = connection;
246
247                                 command.CommandType = CommandType.StoredProcedure;
248                                 AddParameter (command, "UserName", username);
249                                 AddParameter (command, "ApplicationName", ApplicationName);
250
251                                 DbDataReader reader = command.ExecuteReader ();
252                                 ArrayList roleList = new ArrayList ();
253                                 while (reader.Read ())
254                                         roleList.Add (reader.GetString (0));
255                                 reader.Close ();
256
257                                 return (string []) roleList.ToArray (typeof (string));
258                         }
259                 }
260
261                 public override string [] GetUsersInRole (string rolename)
262                 {
263                         using (DbConnection connection = CreateConnection ()) {
264                                 DbCommand command = factory.CreateCommand ();
265                                 command.CommandText = @"dbo.aspnet_UsersInRoles_GetUsersInRoles";
266                                 command.Connection = connection;
267
268                                 command.CommandType = CommandType.StoredProcedure;
269                                 AddParameter (command, "RoleName", rolename);
270                                 AddParameter (command, "ApplicationName", ApplicationName);
271
272                                 DbDataReader reader = command.ExecuteReader ();
273                                 ArrayList userList = new ArrayList ();
274                                 while (reader.Read ())
275                                         userList.Add (reader.GetString (0));
276                                 reader.Close ();
277
278                                 return (string []) userList.ToArray (typeof (string));
279                         }
280                 }
281
282                 string GetStringConfigValue (NameValueCollection config, string name, string def)
283                 {
284                         string rv = def;
285                         string val = config [name];
286                         if (val != null)
287                                 rv = val;
288                         return rv;
289                 }
290
291                 public override void Initialize (string name, NameValueCollection config)
292                 {
293                         if (config == null)
294                                 throw new ArgumentNullException ("config");
295
296                         base.Initialize (name, config);
297
298                         applicationName = config ["applicationName"];
299                         string connectionStringName = config ["connectionStringName"];
300
301                         if (applicationName.Length > 256)
302                                 throw new ProviderException ("The ApplicationName attribute must be 256 characters long or less.");
303                         if (connectionStringName == null || connectionStringName.Length == 0)
304                                 throw new ProviderException ("The ConnectionStringName attribute must be present and non-zero length.");
305
306                         // XXX check connectionStringName and commandTimeout
307
308                         connectionString = WebConfigurationManager.ConnectionStrings [connectionStringName];
309                         if (connectionString == null)
310                                 throw new ProviderException (String.Format("The connection name '{0}' was not found in the applications configuration or the connection string is empty.", connectionStringName));
311                         factory = String.IsNullOrEmpty (connectionString.ProviderName) ?
312                                 System.Data.SqlClient.SqlClientFactory.Instance :
313                                 ProvidersHelper.GetDbProviderFactory (connectionString.ProviderName);
314                 }
315
316                 public override bool IsUserInRole (string username, string rolename)
317                 {
318                         using (DbConnection connection = CreateConnection ()) {
319                                 DbCommand command = factory.CreateCommand ();
320                                 command.CommandText = @"dbo.aspnet_UsersInRoles_IsUserInRole";
321                                 command.Connection = connection;
322
323                                 command.CommandType = CommandType.StoredProcedure;
324                                 AddParameter (command, "RoleName", rolename);
325                                 AddParameter (command, "UserName", username);
326                                 AddParameter (command, "ApplicationName", ApplicationName);
327                                 DbParameter dbpr = AddParameter (command, null, ParameterDirection.ReturnValue, null);
328
329                                 command.ExecuteNonQuery ();
330                                 int returnValue = (int) dbpr.Value;
331
332                                 if (returnValue == 1)
333                                         return true;
334
335                                 return false;
336                         }
337                 }
338
339                 public override void RemoveUsersFromRoles (string [] usernames, string [] rolenames)
340                 {
341                         Hashtable h = new Hashtable ();
342
343                         foreach (string u in usernames) {
344                                 if (u == null)
345                                         throw new ArgumentNullException ("null element in usernames array");
346                                 if (h.ContainsKey (u))
347                                         throw new ArgumentException ("duplicate element in usernames array");
348                                 if (u.Length == 0 || u.Length > 256 || u.IndexOf (",") != -1)
349                                         throw new ArgumentException ("element in usernames array in illegal format");
350                                 h.Add (u, u);
351                         }
352
353                         h = new Hashtable ();
354                         foreach (string r in rolenames) {
355                                 if (r == null)
356                                         throw new ArgumentNullException ("null element in rolenames array");
357                                 if (h.ContainsKey (r))
358                                         throw new ArgumentException ("duplicate element in rolenames array");
359                                 if (r.Length == 0 || r.Length > 256 || r.IndexOf (",") != -1)
360                                         throw new ArgumentException ("element in rolenames array in illegal format");
361                                 h.Add (r, r);
362                         } 
363
364                         using (DbConnection connection = CreateConnection ()) {
365                                 DbCommand command = factory.CreateCommand ();
366                                 command.CommandText = @"dbo.aspnet_UsersInRoles_RemoveUsersFromRoles";
367                                 command.Connection = connection;
368                                 command.CommandType = CommandType.StoredProcedure;
369
370                                 AddParameter (command, "UserNames", String.Join (",", usernames));
371                                 AddParameter (command, "RoleNames", String.Join (",", rolenames));
372                                 AddParameter (command, "ApplicationName", ApplicationName);
373                                 DbParameter dbpr = AddParameter (command, null, ParameterDirection.ReturnValue, null);
374
375                                 command.ExecuteNonQuery ();
376                                 int returnValue = (int) dbpr.Value;
377
378                                 if (returnValue == 0)
379                                         return;
380                                 else if (returnValue == 1)
381                                         throw new ProviderException ("One or more of the specified user names was not found.");
382                                 else if (returnValue == 2)
383                                         throw new ProviderException ("One or more of the specified role names was not found.");
384                                 else if (returnValue == 3)
385                                         throw new ProviderException ("One or more of the specified user names is not associated with one or more of the specified role names.");
386                                 else
387                                         throw new ProviderException ("Failed to remove users from roles");
388                         }
389                 }
390
391                 public override bool RoleExists (string rolename)
392                 {
393                         using (DbConnection connection = CreateConnection ()) {
394
395                                 DbCommand command = factory.CreateCommand ();
396                                 command.CommandText = @"dbo.aspnet_Roles_RoleExists";
397                                 command.Connection = connection;
398                                 command.CommandType = CommandType.StoredProcedure;
399
400                                 AddParameter (command, "ApplicationName", ApplicationName);
401                                 AddParameter (command, "RoleName", rolename);
402                                 DbParameter dbpr = AddParameter (command, null, ParameterDirection.ReturnValue, null);
403
404                                 command.ExecuteNonQuery ();
405                                 int returnValue = (int) dbpr.Value;
406
407                                 if (returnValue == 1)
408                                         return true;
409
410                                 return false;
411                         }
412                 }
413
414                 public override string ApplicationName
415                 {
416                         get { return applicationName; }
417                         set
418                         {
419                                 applicationName = value;
420                         }
421                 }
422         }
423 }
424 #endif
425