using System;
using System.Collections.Generic;
using System.Text;
using ScrewTurn.Wiki.PluginFramework;
using System.Data.Common;
namespace ScrewTurn.Wiki.Plugins.SqlCommon {
///
/// Implements a base class for a SQL users storage provider.
///
public abstract class SqlUsersStorageProviderBase : SqlStorageProviderBase, IUsersStorageProviderV30 {
#region IUsersStorageProvider Members
///
/// Tests a Password for a User account.
///
/// The User account.
/// The Password to test.
/// True if the Password is correct.
/// If or are null.
public bool TestAccount(UserInfo user, string password) {
if(user == null) throw new ArgumentNullException("user");
if(password == null) throw new ArgumentNullException("password");
return TryManualLogin(user.Username, password) != null;
}
///
/// Gets the complete list of Users.
///
/// All the Users, sorted by username.
public UserInfo[] GetUsers() {
ICommandBuilder builder = GetCommandBuilder();
string query = QueryBuilder.NewQuery(builder).SelectFrom(
"User", "UserGroupMembership", "Username", "User", Join.LeftJoin,
new string[] { "Username", "DisplayName", "Email", "Active", "DateTime" },
new string[] { "UserGroup" });
DbCommand command = builder.GetCommand(connString, query, new List());
DbDataReader reader = ExecuteReader(command);
if(reader != null) {
List result = new List(100);
string prevUsername = "|||";
string username = null;
string displayName;
string email;
bool active;
DateTime dateTime;
List groups = new List(5);
while(reader.Read()) {
username = reader["User_Username"] as string;
if(username != prevUsername) {
// Set previous user's groups
if(prevUsername != "|||") {
result[result.Count - 1].Groups = groups.ToArray();
groups.Clear();
}
// Read new data
displayName = GetNullableColumn(reader, "User_DisplayName", null);
email = reader["User_Email"] as string;
active = (bool)reader["User_Active"];
dateTime = (DateTime)reader["User_DateTime"];
// Append new user
result.Add(new UserInfo(username, displayName, email, active, dateTime, this));
}
// Keep reading groups
prevUsername = username;
if(!IsDBNull(reader, "UserGroupMembership_UserGroup")) {
groups.Add(reader["UserGroupMembership_UserGroup"] as string);
}
}
if(result.Count > 0) {
result[result.Count - 1].Groups = groups.ToArray();
}
CloseReader(command, reader);
return result.ToArray();
}
else return null;
}
///
/// Adds a new User.
///
/// The Username.
/// The display name (can be null).
/// The Password.
/// The Email address.
/// A value indicating whether the account is active.
/// The Account creation Date/Time.
/// The correct object or null.
/// If , or are null.
/// If , or are empty.
public UserInfo AddUser(string username, string displayName, string password, string email, bool active, DateTime dateTime) {
if(username == null) throw new ArgumentNullException("username");
if(username.Length == 0) throw new ArgumentException("Username cannot be empty", "username");
if(password == null) throw new ArgumentNullException("password");
if(password.Length == 0) throw new ArgumentException("Password cannot be empty", "password");
if(email == null) throw new ArgumentNullException("email");
if(email.Length == 0) throw new ArgumentException("Email cannot be empty", "email");
ICommandBuilder builder = GetCommandBuilder();
string query = QueryBuilder.NewQuery(builder).InsertInto("User",
new string[] { "Username", "PasswordHash", "DisplayName", "Email", "Active", "DateTime" },
new string[] { "Username", "PasswordHash", "DisplayName", "Email", "Active", "DateTime" });
List parameters = new List(6);
parameters.Add(new Parameter(ParameterType.String, "Username", username));
parameters.Add(new Parameter(ParameterType.String, "PasswordHash", Hash.Compute(password)));
if(string.IsNullOrEmpty(displayName)) parameters.Add(new Parameter(ParameterType.String, "DisplayName", DBNull.Value));
else parameters.Add(new Parameter(ParameterType.String, "DisplayName", displayName));
parameters.Add(new Parameter(ParameterType.String, "Email", email));
parameters.Add(new Parameter(ParameterType.Boolean, "Active", active));
parameters.Add(new Parameter(ParameterType.DateTime, "DateTime", dateTime));
DbCommand command = builder.GetCommand(connString, query, parameters);
int rows = ExecuteNonQuery(command);
if(rows == 1) {
return new UserInfo(username, displayName, email, active, dateTime, this);
}
else return null;
}
///
/// Gets the user groups of a user.
///
/// A database transaction.
/// The username.
/// The groups.
private string[] GetUserGroups(DbTransaction transaction, string username) {
ICommandBuilder builder = GetCommandBuilder();
QueryBuilder queryBuilder = new QueryBuilder(builder);
string query = queryBuilder.SelectFrom("UserGroupMembership", new string[] { "UserGroup" });
query = queryBuilder.Where(query, "User", WhereOperator.Equals, "Username");
List parameters = new List(1);
parameters.Add(new Parameter(ParameterType.String, "Username", username));
DbCommand command = builder.GetCommand(transaction, query, parameters);
DbDataReader reader = ExecuteReader(command);
if(reader != null) {
List result = new List(5);
while(reader.Read()) {
result.Add(reader["UserGroup"] as string);
}
CloseReader(reader);
return result.ToArray();
}
else return null;
}
///
/// Gets the user groups of a user.
///
/// A database connection.
/// The username.
/// The groups.
private string[] GetUserGroups(DbConnection connection, string username) {
ICommandBuilder builder = GetCommandBuilder();
QueryBuilder queryBuilder = new QueryBuilder(builder);
string query = queryBuilder.SelectFrom("UserGroupMembership", new string[] { "UserGroup" });
query = queryBuilder.Where(query, "User", WhereOperator.Equals, "Username");
List parameters = new List(1);
parameters.Add(new Parameter(ParameterType.String, "Username", username));
DbCommand command = builder.GetCommand(connection, query, parameters);
DbDataReader reader = ExecuteReader(command);
if(reader != null) {
List result = new List(5);
while(reader.Read()) {
result.Add(reader["UserGroup"] as string);
}
CloseReader(reader);
return result.ToArray();
}
else return null;
}
///
/// Modifies a User.
///
/// The Username of the user to modify.
/// The new display name (can be null).
/// The new Password (null or blank to keep the current password).
/// The new Email address.
/// A value indicating whether the account is active.
/// The correct object or null.
/// If user or newEmail are null.
/// If newEmail is empty.
public UserInfo ModifyUser(UserInfo user, string newDisplayName, string newPassword, string newEmail, bool newActive) {
if(user == null) throw new ArgumentNullException("user");
if(newEmail == null) throw new ArgumentNullException("newEmail");
if(newEmail.Length == 0) throw new ArgumentException("New Email cannot be empty", "newEmail");
ICommandBuilder builder = GetCommandBuilder();
DbConnection connection = builder.GetConnection(connString);
DbTransaction transaction = BeginTransaction(connection);
QueryBuilder queryBuilder = new QueryBuilder(builder);
string query = "";
if(string.IsNullOrEmpty(newPassword)) {
query = queryBuilder.Update("User",
new string[] { "DisplayName", "Email", "Active", },
new string[] { "DisplayName", "Email", "Active", });
}
else {
query = queryBuilder.Update("User",
new string[] { "PasswordHash", "DisplayName", "Email", "Active", },
new string[] { "PasswordHash", "DisplayName", "Email", "Active", });
}
query = queryBuilder.Where(query, "Username", WhereOperator.Equals, "Username");
List parameters = new List(5);
if(!string.IsNullOrEmpty(newPassword)) {
parameters.Add(new Parameter(ParameterType.String, "PasswordHash", Hash.Compute(newPassword)));
}
if(string.IsNullOrEmpty(newDisplayName)) parameters.Add(new Parameter(ParameterType.String, "DisplayName", DBNull.Value));
else parameters.Add(new Parameter(ParameterType.String, "DisplayName", newDisplayName));
parameters.Add(new Parameter(ParameterType.String, "Email", newEmail));
parameters.Add(new Parameter(ParameterType.Boolean, "Active", newActive));
parameters.Add(new Parameter(ParameterType.String, "Username", user.Username));
DbCommand command = builder.GetCommand(transaction, query, parameters);
int rows = ExecuteNonQuery(command, false);
if(rows == 1) {
UserInfo result = new UserInfo(user.Username, newDisplayName, newEmail, newActive, user.DateTime, this);
result.Groups = GetUserGroups(transaction, user.Username);
CommitTransaction(transaction);
return result;
}
else {
RollbackTransaction(transaction);
return null;
}
}
///
/// Removes a User.
///
/// The User to remove.
/// True if the User has been removed successfully.
/// If user is null.
public bool RemoveUser(UserInfo user) {
if(user == null) throw new ArgumentNullException("user");
ICommandBuilder builder = GetCommandBuilder();
QueryBuilder queryBuilder = new QueryBuilder(builder);
string query = queryBuilder.DeleteFrom("User");
query = queryBuilder.Where(query, "Username", WhereOperator.Equals, "Username");
List parameters = new List(1);
parameters.Add(new Parameter(ParameterType.String, "Username", user.Username));
DbCommand command = builder.GetCommand(connString, query, parameters);
int rows = ExecuteNonQuery(command);
return rows == 1;
}
///
/// Gets all the user groups.
///
/// All the groups, sorted by name.
public UserGroup[] GetUserGroups() {
ICommandBuilder builder = GetCommandBuilder();
string query = QueryBuilder.NewQuery(builder).SelectFrom(
"UserGroup", "UserGroupMembership", "Name", "UserGroup", Join.LeftJoin,
new string[] { "Name", "Description" }, new string[] { "User" });
DbCommand command = builder.GetCommand(connString, query, new List());
DbDataReader reader = ExecuteReader(command);
string previousName = "|||";
string name = null;
string description;
List users = new List(50);
if(reader != null) {
List result = new List(5);
while(reader.Read()) {
name = reader["UserGroup_Name"] as string;
if(name != previousName) {
// Set previous group's users
if(previousName != "|||") {
result[result.Count - 1].Users = users.ToArray();
users.Clear();
}
// Read new data
description = reader["UserGroup_Description"] as string;
// Append new group
result.Add(new UserGroup(name, description, this));
}
// Keep reading users
previousName = name;
if(!IsDBNull(reader, "UserGroupMembership_User")) {
users.Add(reader["UserGroupMembership_User"] as string);
}
}
if(result.Count > 0) {
result[result.Count - 1].Users = users.ToArray();
}
CloseReader(command, reader);
return result.ToArray();
}
else return null;
}
///
/// Adds a new user group.
///
/// The name of the group.
/// The description of the group.
/// The correct object or null.
/// If name or description are null.
/// If name is empty.
public UserGroup AddUserGroup(string name, string description) {
if(name == null) throw new ArgumentNullException("name");
if(name.Length == 0) throw new ArgumentException("Name cannot be empty", "name");
if(description == null) throw new ArgumentNullException("description");
ICommandBuilder builder = GetCommandBuilder();
string query = QueryBuilder.NewQuery(builder).InsertInto("UserGroup",
new string[] { "Name", "Description" }, new string[] { "Name", "Description" });
List parameters = new List(2);
parameters.Add(new Parameter(ParameterType.String, "Name", name));
parameters.Add(new Parameter(ParameterType.String, "Description", description));
DbCommand command = builder.GetCommand(connString, query, parameters);
int rows = ExecuteNonQuery(command);
if(rows == 1) {
return new UserGroup(name, description, this);
}
else return null;
}
///
/// Gets the users of a group.
///
/// A database transaction.
/// The group.
/// The users.
private string[] GetUserGroupUsers(DbTransaction transaction, string group) {
ICommandBuilder builder = GetCommandBuilder();
QueryBuilder queryBuilder = new QueryBuilder(builder);
string query = queryBuilder.SelectFrom("UserGroupMembership", new string[] { "User" });
query = queryBuilder.Where(query, "UserGroup", WhereOperator.Equals, "UserGroup");
List parameters = new List(1);
parameters.Add(new Parameter(ParameterType.String, "UserGroup", group));
DbCommand command = builder.GetCommand(transaction, query, parameters);
DbDataReader reader = ExecuteReader(command);
if(reader != null) {
List result = new List(100);
while(reader.Read()) {
result.Add(reader["User"] as string);
}
CloseReader(reader);
return result.ToArray();
}
else return null;
}
///
/// Gets the users of a group.
///
/// A database connection.
/// The group.
/// The users.
private string[] GetUserGroupUsers(DbConnection connection, string group) {
ICommandBuilder builder = GetCommandBuilder();
QueryBuilder queryBuilder = new QueryBuilder(builder);
string query = queryBuilder.SelectFrom("UserGroupMembership", new string[] { "User" });
query = queryBuilder.Where(query, "UserGroup", WhereOperator.Equals, "UserGroup");
List parameters = new List(1);
parameters.Add(new Parameter(ParameterType.String, "UserGroup", group));
DbCommand command = builder.GetCommand(connection, query, parameters);
DbDataReader reader = ExecuteReader(command);
if(reader != null) {
List result = new List(100);
while(reader.Read()) {
result.Add(reader["User"] as string);
}
CloseReader(reader);
return result.ToArray();
}
else return null;
}
///
/// Modifies a user group.
///
/// The group to modify.
/// The new description of the group.
/// The correct object or null.
/// If group or description are null.
public UserGroup ModifyUserGroup(UserGroup group, string description) {
if(group == null) throw new ArgumentNullException("group");
if(description == null) throw new ArgumentNullException("description");
ICommandBuilder builder = GetCommandBuilder();
DbConnection connection = builder.GetConnection(connString);
DbTransaction transaction = BeginTransaction(connection);
QueryBuilder queryBuilder = new QueryBuilder(builder);
string query = queryBuilder.Update("UserGroup",
new string[] { "Description" }, new string[] { "Description" });
query = queryBuilder.Where(query, "Name", WhereOperator.Equals, "Name");
List parameters = new List(2);
parameters.Add(new Parameter(ParameterType.String, "Description", description));
parameters.Add(new Parameter(ParameterType.String, "Name", group.Name));
DbCommand command = builder.GetCommand(transaction, query, parameters);
int rows = ExecuteNonQuery(command, false);
if(rows == 1) {
UserGroup result = new UserGroup(group.Name, description, this);
result.Users = GetUserGroupUsers(transaction, group.Name);
CommitTransaction(transaction);
return result;
}
else {
RollbackTransaction(transaction);
return null;
}
}
///
/// Removes a user group.
///
/// The group to remove.
/// true if the group is removed, false otherwise.
/// If group is null.
public bool RemoveUserGroup(UserGroup group) {
if(group == null) throw new ArgumentNullException("group");
ICommandBuilder builder = GetCommandBuilder();
QueryBuilder queryBuilder = new QueryBuilder(builder);
string query = queryBuilder.DeleteFrom("UserGroup");
query = queryBuilder.Where(query, "Name", WhereOperator.Equals, "Name");
List parameters = new List(1);
parameters.Add(new Parameter(ParameterType.String, "Name", group.Name));
DbCommand command = builder.GetCommand(connString, query, parameters);
int rows = ExecuteNonQuery(command);
return rows == 1;
}
///
/// Verifies that a user exists.
///
/// A database transaction.
/// The username.
/// true if the user exists, false otherwise.
private bool UserExists(DbTransaction transaction, string username) {
ICommandBuilder builder = GetCommandBuilder();
QueryBuilder queryBuilder = new QueryBuilder(builder);
string query = queryBuilder.SelectCountFrom("User");
query = queryBuilder.Where(query, "Username", WhereOperator.Equals, "Username");
List parameters = new List(1);
parameters.Add(new Parameter(ParameterType.String, "Username", username));
DbCommand command = builder.GetCommand(transaction, query, parameters);
int count = ExecuteScalar(command, -1, false);
return count == 1;
}
///
/// Verifies that a user exists.
///
/// A database connection.
/// The username.
/// true if the user exists, false otherwise.
private bool UserExists(DbConnection connection, string username) {
ICommandBuilder builder = GetCommandBuilder();
QueryBuilder queryBuilder = new QueryBuilder(builder);
string query = queryBuilder.SelectCountFrom("User");
query = queryBuilder.Where(query, "Username", WhereOperator.Equals, "Username");
List parameters = new List(1);
parameters.Add(new Parameter(ParameterType.String, "Username", username));
DbCommand command = builder.GetCommand(connection, query, parameters);
int count = ExecuteScalar(command, -1, false);
return count == 1;
}
///
/// Removes the user group membership for a user.
///
/// A database transaction.
/// The username.
private void RemoveUserGroupMembership(DbTransaction transaction, string username) {
ICommandBuilder builder = GetCommandBuilder();
QueryBuilder queryBuilder = new QueryBuilder(builder);
string query = queryBuilder.DeleteFrom("UserGroupMembership");
query = queryBuilder.Where(query, "User", WhereOperator.Equals, "Username");
List parameters = new List(1);
parameters.Add(new Parameter(ParameterType.String, "Username", username));
DbCommand command = builder.GetCommand(transaction, query, parameters);
ExecuteNonQuery(command, false);
}
///
/// Sets the group memberships of a user account.
///
/// The user account.
/// The groups the user account is member of.
/// The correct object or null.
/// If user or groups are null.
public UserInfo SetUserMembership(UserInfo user, string[] groups) {
if(user == null) throw new ArgumentNullException("user");
if(groups == null) throw new ArgumentNullException("groups");
// 1. Remove old user group membership
// 2. Add new memberships, one by one
ICommandBuilder builder = GetCommandBuilder();
DbConnection connection = builder.GetConnection(connString);
DbTransaction transaction = BeginTransaction(connection);
if(!UserExists(transaction, user.Username)) {
RollbackTransaction(transaction);
return null;
}
RemoveUserGroupMembership(transaction, user.Username);
string query = QueryBuilder.NewQuery(builder).InsertInto("UserGroupMembership",
new string[] { "User", "UserGroup" }, new string[] { "User", "UserGroup" });
foreach(string group in groups) {
List parameters = new List(2);
parameters.Add(new Parameter(ParameterType.String, "User", user.Username));
parameters.Add(new Parameter(ParameterType.String, "UserGroup", group));
DbCommand command = builder.GetCommand(transaction, query, parameters);
int rows = ExecuteNonQuery(command, false);
if(rows != 1) {
RollbackTransaction(transaction);
return null;
}
}
UserInfo result = new UserInfo(user.Username, user.DisplayName, user.Email, user.Active, user.DateTime, this);
result.Groups = groups;
CommitTransaction(transaction);
return result;
}
///
/// Tries to login a user directly through the provider.
///
/// The username.
/// The password.
/// The correct UserInfo object, or null.
/// If username or password are null.
public UserInfo TryManualLogin(string username, string password) {
if(username == null) throw new ArgumentNullException("username");
if(password == null) throw new ArgumentNullException("password");
// Shortcut
if(username.Length == 0) return null;
if(password.Length == 0) return null;
ICommandBuilder builder = GetCommandBuilder();
QueryBuilder queryBuilder = new QueryBuilder(builder);
string query = queryBuilder.SelectFrom(
"User", "UserGroupMembership", "Username", "User", Join.LeftJoin,
new string[] { "Username", "PasswordHash", "DisplayName", "Email", "Active", "DateTime" },
new string[] { "UserGroup" });
query = queryBuilder.Where(query, "User", "Username", WhereOperator.Equals, "Username");
query = queryBuilder.AndWhere(query, "User", "PasswordHash", WhereOperator.Equals, "PasswordHash");
string providedPasswordHash = Hash.Compute(password);
List parameters = new List(2);
parameters.Add(new Parameter(ParameterType.String, "Username", username));
parameters.Add(new Parameter(ParameterType.String, "PasswordHash", providedPasswordHash));
DbCommand command = builder.GetCommand(connString, query, parameters);
DbDataReader reader = ExecuteReader(command);
if(reader != null) {
UserInfo result = null;
string realUsername = null;
string passwordHash = null;
string displayName;
string email;
bool active;
DateTime dateTime;
List groups = new List(5);
while(reader.Read()) {
if(result == null) {
// Read data
realUsername = reader["User_Username"] as string;
passwordHash = reader["User_PasswordHash"] as string;
displayName = GetNullableColumn(reader, "User_DisplayName", null);
email = reader["User_Email"] as string;
active = (bool)reader["User_Active"];
dateTime = (DateTime)reader["User_DateTime"];
// Create user
result = new UserInfo(realUsername, displayName, email, active, dateTime, this);
}
// Keep reading groups
if(!IsDBNull(reader, "UserGroupMembership_UserGroup")) {
groups.Add(reader["UserGroupMembership_UserGroup"] as string);
}
}
if(result != null) {
result.Groups = groups.ToArray();
}
CloseReader(command, reader);
if(result != null) {
if(result.Active &&
string.CompareOrdinal(result.Username, username) == 0 &&
string.CompareOrdinal(passwordHash, providedPasswordHash) == 0) {
return result;
}
else return null;
}
else return null;
}
else return null;
}
///
/// Tries to login a user directly through the provider using
/// the current HttpContext and without username/password.
///
/// The current HttpContext.
/// The correct UserInfo object, or null.
/// If context is null.
public UserInfo TryAutoLogin(System.Web.HttpContext context) {
if(context == null) throw new ArgumentNullException("context");
return null;
}
///
/// Gets a user account.
///
/// The username.
/// The , or null.
/// If username is null.
/// If username is empty.
public UserInfo GetUser(string username) {
if(username == null) throw new ArgumentNullException("username");
if(username.Length == 0) throw new ArgumentException("Username cannot be empty", "username");
ICommandBuilder builder = GetCommandBuilder();
QueryBuilder queryBuilder = new QueryBuilder(builder);
string query = queryBuilder.SelectFrom(
"User", "UserGroupMembership", "Username", "User", Join.LeftJoin,
new string[] { "Username", "DisplayName", "Email", "Active", "DateTime" },
new string[] { "UserGroup" });
query = queryBuilder.Where(query, "User", "Username", WhereOperator.Equals, "Username");
List parameters = new List(2);
parameters.Add(new Parameter(ParameterType.String, "Username", username));
DbCommand command = builder.GetCommand(connString, query, parameters);
DbDataReader reader = ExecuteReader(command);
if(reader != null) {
UserInfo result = null;
string realUsername = null;
string displayName;
string email;
bool active;
DateTime dateTime;
List groups = new List(5);
while(reader.Read()) {
if(result == null) {
// Read data
realUsername = reader["User_Username"] as string;
displayName = GetNullableColumn(reader, "User_DisplayName", null);
email = reader["User_Email"] as string;
active = (bool)reader["User_Active"];
dateTime = (DateTime)reader["User_DateTime"];
// Create user
result = new UserInfo(realUsername, displayName, email, active, dateTime, this);
}
// Keep reading groups
if(!IsDBNull(reader, "UserGroupMembership_UserGroup")) {
groups.Add(reader["UserGroupMembership_UserGroup"] as string);
}
}
if(result != null) {
result.Groups = groups.ToArray();
}
CloseReader(command, reader);
return result;
}
else return null;
}
///
/// Gets a user account.
///
/// The email address.
/// The first user found with the specified email address, or null.
/// If email is null.
/// If email is empty.
public UserInfo GetUserByEmail(string email) {
if(email == null) throw new ArgumentNullException("email");
if(email.Length == 0) throw new ArgumentException("Email cannot be empty", "email");
ICommandBuilder builder = GetCommandBuilder();
QueryBuilder queryBuilder = new QueryBuilder(builder);
string query = queryBuilder.SelectFrom(
"User", "UserGroupMembership", "Username", "User", Join.LeftJoin,
new string[] { "Username", "DisplayName", "Email", "Active", "DateTime" },
new string[] { "UserGroup" });
query = queryBuilder.Where(query, "User", "Email", WhereOperator.Equals, "Email");
List parameters = new List(2);
parameters.Add(new Parameter(ParameterType.String, "Email", email));
DbCommand command = builder.GetCommand(connString, query, parameters);
DbDataReader reader = ExecuteReader(command);
if(reader != null) {
UserInfo result = null;
string username = null;
string displayName;
string realEmail = null;
bool active;
DateTime dateTime;
List groups = new List(5);
while(reader.Read()) {
if(result == null) {
// Read data
username = reader["User_Username"] as string;
displayName = GetNullableColumn(reader, "User_DisplayName", null);
realEmail = reader["User_Email"] as string;
active = (bool)reader["User_Active"];
dateTime = (DateTime)reader["User_DateTime"];
// Create user
result = new UserInfo(username, displayName, realEmail, active, dateTime, this);
}
// Keep reading groups
if(!IsDBNull(reader, "UserGroupMembership_UserGroup")) {
groups.Add(reader["UserGroupMembership_UserGroup"] as string);
}
}
if(result != null) {
result.Groups = groups.ToArray();
}
CloseReader(command, reader);
return result;
}
else return null;
}
///
/// Notifies the provider that a user has logged in through the authentication cookie.
///
/// The user who has logged in.
/// If user is null.
public void NotifyCookieLogin(UserInfo user) {
if(user == null) throw new ArgumentNullException("user");
// Nothing to do
}
///
/// Notifies the provider that a user has logged out.
///
/// The user who has logged out.
/// If user is null.
public void NotifyLogout(UserInfo user) {
if(user == null) throw new ArgumentNullException("user");
// Nothing to do
}
///
/// Removes a user data element.
///
/// A database transaction.
/// The username.
/// The key.
/// true if the data element is removed, false otherwise.
private bool RemoveUserData(DbTransaction transaction, string username, string key) {
ICommandBuilder builder = GetCommandBuilder();
QueryBuilder queryBuilder = new QueryBuilder(builder);
string query = queryBuilder.DeleteFrom("UserData");
query = queryBuilder.Where(query, "User", WhereOperator.Equals, "Username");
query = queryBuilder.AndWhere(query, "Key", WhereOperator.Equals, "Key");
List parameters = new List(2);
parameters.Add(new Parameter(ParameterType.String, "Username", username));
parameters.Add(new Parameter(ParameterType.String, "Key", key));
DbCommand command = builder.GetCommand(transaction, query, parameters);
int rows = ExecuteNonQuery(command, false);
return rows != -1; // Success also if no elements are removed
}
///
/// Stores a user data element, overwriting the previous one if present.
///
/// The user the data belongs to.
/// The key of the data element (case insensitive).
/// The value of the data element, null for deleting the data.
/// true if the data element is stored, false otherwise.
/// If user or key are null.
/// If key is empty.
public bool StoreUserData(UserInfo user, string key, string value) {
if(user == null) throw new ArgumentNullException("user");
if(key == null) throw new ArgumentNullException("key");
if(key.Length == 0) throw new ArgumentException("Key cannot be empty", "key");
// 1. Remove previous key, if present
// 2. Add new key, if value != null
ICommandBuilder builder = GetCommandBuilder();
DbConnection connection = builder.GetConnection(connString);
DbTransaction transaction = BeginTransaction(connection);
bool done = RemoveUserData(transaction, user.Username, key);
if(done) {
if(value != null) {
string query = QueryBuilder.NewQuery(builder).InsertInto("UserData",
new string[] { "User", "Key", "Data" }, new string[] { "Username", "Key", "Data" });
List parameters = new List(3);
parameters.Add(new Parameter(ParameterType.String, "Username", user.Username));
parameters.Add(new Parameter(ParameterType.String, "Key", key));
parameters.Add(new Parameter(ParameterType.String, "Data", value));
DbCommand command = builder.GetCommand(transaction, query, parameters);
int rows = ExecuteNonQuery(command, false);
if(rows == 1) CommitTransaction(transaction);
else RollbackTransaction(transaction);
return rows == 1;
}
else {
CommitTransaction(transaction);
return true;
}
}
else {
RollbackTransaction(transaction);
return false;
}
}
///
/// Gets a user data element, if any.
///
/// The user the data belongs to.
/// The key of the data element.
/// The value of the data element, or null if the element is not found.
/// If user or key are null.
/// If key is empty.
public string RetrieveUserData(UserInfo user, string key) {
if(user == null) throw new ArgumentNullException("user");
if(key == null) throw new ArgumentNullException("key");
if(key.Length == 0) throw new ArgumentException("Key cannot be empty", "key");
ICommandBuilder builder = GetCommandBuilder();
QueryBuilder queryBuilder = new QueryBuilder(builder);
string query = queryBuilder.SelectFrom("UserData", new string[] { "Data" });
query = queryBuilder.Where(query, "User", WhereOperator.Equals, "Username");
query = queryBuilder.AndWhere(query, "Key", WhereOperator.Equals, "Key");
List parameters = new List(2);
parameters.Add(new Parameter(ParameterType.String, "Username", user.Username));
parameters.Add(new Parameter(ParameterType.String, "Key", key));
DbCommand command = builder.GetCommand(connString, query, parameters);
DbDataReader reader = ExecuteReader(command);
if(reader != null) {
string data = null;
if(reader.Read()) {
data = reader["Data"] as string;
}
CloseReader(command, reader);
return data;
}
else return null;
}
///
/// Retrieves all the user data elements for a user.
///
/// The user.
/// The user data elements (key->value).
/// If user is null.
public IDictionary RetrieveAllUserData(UserInfo user) {
if(user == null) throw new ArgumentNullException("user");
ICommandBuilder builder = GetCommandBuilder();
QueryBuilder queryBuilder = new QueryBuilder(builder);
string query = queryBuilder.SelectFrom("UserData", new string[] { "Key", "Data" });
query = queryBuilder.Where(query, "User", WhereOperator.Equals, "Username");
List parameters = new List(1);
parameters.Add(new Parameter(ParameterType.String, "Username", user.Username));
DbCommand command = builder.GetCommand(connString, query, parameters);
DbDataReader reader = ExecuteReader(command);
if(reader != null) {
Dictionary result = new Dictionary(10);
while(reader.Read()) {
result.Add(reader["Key"] as string, reader["Data"] as string);
}
CloseReader(command, reader);
return result;
}
else return null;
}
///
/// Gets all the users that have the specified element in their data.
///
/// The key of the data.
/// The users and the data.
/// If key is null.
/// If key is empty.
public IDictionary GetUsersWithData(string key) {
if(key == null) throw new ArgumentNullException("key");
if(key.Length == 0) throw new ArgumentException("Key cannot be empty", "key");
ICommandBuilder builder = GetCommandBuilder();
QueryBuilder queryBuilder = new QueryBuilder(builder);
string query = queryBuilder.SelectFrom("User", "UserData", "Username", "User", Join.RightJoin,
new string[] { "Username", "DisplayName", "Email", "Active", "DateTime" }, new string[] { "Data" },
"UserGroupMembership", "User", Join.LeftJoin, new string[] { "UserGroup" });
query = queryBuilder.Where(query, "UserData", "Key", WhereOperator.Equals, "Key");
List parameters = new List(1);
parameters.Add(new Parameter(ParameterType.String, "Key", key));
DbCommand command = builder.GetCommand(connString, query, parameters);
DbDataReader reader = ExecuteReader(command);
if(reader != null) {
Dictionary result = new Dictionary(100);
string prevUsername = "|||";
UserInfo prevUser = null;
string username = null;
string displayName;
string email;
bool active;
DateTime dateTime;
string data;
List groups = new List(5);
while(reader.Read()) {
username = reader["User_Username"] as string;
if(username != prevUsername) {
// Set previous user's groups
if(prevUsername != "|||") {
prevUser.Groups = groups.ToArray();
groups.Clear();
}
// Read new data
displayName = GetNullableColumn(reader, "User_DisplayName", null);
email = reader["User_Email"] as string;
active = (bool)reader["User_Active"];
dateTime = (DateTime)reader["User_DateTime"];
data = reader["UserData_Data"] as string;
// Append new user
prevUser = new UserInfo(username, displayName, email, active, dateTime, this);
result.Add(prevUser, data);
}
// Keep reading groups
prevUsername = username;
if(!IsDBNull(reader, "UserGroupMembership_UserGroup")) {
groups.Add(reader["UserGroupMembership_UserGroup"] as string);
}
}
if(prevUser != null) {
prevUser.Groups = groups.ToArray();
}
CloseReader(command, reader);
return result;
}
else return null;
}
#endregion
///
/// Gets a value indicating whether user accounts are read-only.
///
public bool UserAccountsReadOnly {
get { return false; }
}
///
/// Gets a value indicating whether user groups are read-only. If so, the provider
/// should support default user groups as defined in the wiki configuration.
///
public bool UserGroupsReadOnly {
get { return false; }
}
///
/// Gets a value indicating whether group membership is read-only (if
/// is false, then this property must be false). If this property is true, the provider
/// should return membership data compatible with default user groups.
///
public bool GroupMembershipReadOnly {
get { return false; }
}
///
/// Gets a value indicating whether users' data is read-only.
///
public bool UsersDataReadOnly {
get { return false; }
}
}
}