using System;
using System.Collections.Generic;
using System.Text;
using ScrewTurn.Wiki.PluginFramework;
using System.Web;
namespace ScrewTurn.Wiki {
///
/// Manages all the User Accounts data.
///
public static class Users {
private static UserInfo adminAccount = null;
private static UserInfo anonAccount = null;
///
/// Gets the built-in administrator account.
///
/// The account.
public static UserInfo GetAdministratorAccount() {
if(adminAccount == null) {
adminAccount = new UserInfo("admin", "Administrator", Settings.ContactEmail, true, DateTime.MinValue, null);
adminAccount.Groups = new[] { Settings.AdministratorsGroup };
}
return adminAccount;
}
///
/// Gets the fake anonymous account.
///
/// The account.
public static UserInfo GetAnonymousAccount() {
if(anonAccount == null) {
anonAccount = new UserInfo(SessionFacade.AnonymousUsername, null, null, false, DateTime.MinValue, null);
anonAccount.Groups = new[] { Settings.AnonymousGroup };
}
return anonAccount;
}
///
/// The user data key pointing to page changes notification entries.
///
private const string PageChangesKey = "PageChanges";
///
/// The user data key pointing to discussion messages notification entries.
///
private const string DiscussionMessagesKey = "DiscussionMessages";
///
/// The user data key pointing to page changes notification entries for whole namespace.
///
private const string NamespacePageChangesKey = "NamespacePageChanges";
///
/// The user data key pointing to discussion messages notification entries for whole namespaces.
///
private const string NamespaceDiscussionMessagesKey = "NamespaceDiscussionMessages";
///
/// Gets all the Users that the providers declare to manage.
///
/// The users, sorted by username.
public static List GetUsers() {
List allUsers = new List(1000);
// Retrieve all the users from the Users Providers
int count = 0;
foreach(IUsersStorageProviderV30 provider in Collectors.UsersProviderCollector.AllProviders) {
count++;
allUsers.AddRange(provider.GetUsers());
}
if(count > 1) {
allUsers.Sort(new UsernameComparer());
}
return allUsers;
}
///
/// Finds a user.
///
/// The username.
/// The user, or null.
public static UserInfo FindUser(string username) {
if(username == "admin") return GetAdministratorAccount();
// Try default provider first
IUsersStorageProviderV30 defaultProvider = Collectors.UsersProviderCollector.GetProvider(Settings.DefaultUsersProvider);
UserInfo temp = defaultProvider.GetUser(username);
if(temp != null) return temp;
// The try other providers
temp = null;
IUsersStorageProviderV30[] providers = Collectors.UsersProviderCollector.AllProviders;
foreach(IUsersStorageProviderV30 p in providers) {
IUsersStorageProviderV30 extProv = p as IUsersStorageProviderV30;
if(extProv != null && extProv != defaultProvider) {
temp = extProv.GetUser(username);
if(temp != null) return temp;
}
}
return null;
}
///
/// Finds a user by email.
///
/// The email address.
/// The user, or null.
public static UserInfo FindUserByEmail(string email) {
// Try default provider first
IUsersStorageProviderV30 defaultProvider = Collectors.UsersProviderCollector.GetProvider(Settings.DefaultUsersProvider);
UserInfo temp = defaultProvider.GetUserByEmail(email);
if(temp != null) return temp;
// The try other providers
temp = null;
IUsersStorageProviderV30[] providers = Collectors.UsersProviderCollector.AllProviders;
foreach(IUsersStorageProviderV30 p in providers) {
IUsersStorageProviderV30 extProv = p as IUsersStorageProviderV30;
if(extProv != null && extProv != defaultProvider) {
temp = extProv.GetUserByEmail(email);
if(temp != null) return temp;
}
}
return null;
}
///
/// Gets user data.
///
/// The user.
/// The data key.
/// The data, or null if either the user or the key is not found.
public static string GetUserData(UserInfo user, string key) {
if(user == null) return null;
if(string.IsNullOrEmpty(key)) return null;
if(user.Username == "admin") return null;
return user.Provider.RetrieveUserData(user, key);
}
///
/// Sets user data.
///
/// The user.
/// The data key.
/// The data value.
/// true if the data is stored, false otherwise.
public static bool SetUserData(UserInfo user, string key, string data) {
if(user == null) return false;
if(string.IsNullOrEmpty(key)) return false;
if(user.Username == "admin") return false;
if(user.Provider.UsersDataReadOnly) return false;
bool done = user.Provider.StoreUserData(user, key, data);
if(done) Log.LogEntry("User data stored for " + user.Username, EntryType.General, Log.SystemUsername);
else Log.LogEntry("Could not store user data for " + user.Username, EntryType.Error, Log.SystemUsername);
return done;
}
///
/// Adds a new User.
///
/// The Username.
/// The display name.
/// The Password (plain text).
/// The Email address.
/// A value specifying whether or not the account is active.
/// The Provider. If null, the default provider is used.
/// True if the User has been created successfully.
public static bool AddUser(string username, string displayName, string password, string email, bool active, IUsersStorageProviderV30 provider) {
if(FindUser(username) != null) return false;
if(provider == null) provider = Collectors.UsersProviderCollector.GetProvider(Settings.DefaultUsersProvider);
if(provider.UserAccountsReadOnly) return false;
UserInfo u = provider.AddUser(username, displayName, password, email, active, DateTime.Now);
if(u == null) {
Log.LogEntry("User creation failed for " + username, EntryType.Error, Log.SystemUsername);
return false;
}
else {
Log.LogEntry("User " + username + " created", EntryType.General, Log.SystemUsername);
Host.Instance.OnUserAccountActivity(u, UserAccountActivity.AccountAdded);
return true;
}
}
///
/// Updates a new User.
///
/// The user to modify.
/// The display name.
/// The Password (plain text, null or empty for no change).
/// The Email address.
/// A value specifying whether or not the account is active.
/// True if the User has been created successfully.
public static bool ModifyUser(UserInfo user, string displayName, string password, string email, bool active) {
if(user.Provider.UserAccountsReadOnly) return false;
bool done = user.Provider.ModifyUser(user, displayName, password, email, active) != null;
if(done) {
Log.LogEntry("User " + user.Username + " updated", EntryType.General, Log.SystemUsername);
Host.Instance.OnUserAccountActivity(user, UserAccountActivity.AccountModified);
return true;
}
else {
Log.LogEntry("User update failed for " + user.Username, EntryType.Error, Log.SystemUsername);
return false;
}
}
///
/// Removes a User.
///
/// The User to remove.
/// True if the User has been removed successfully.
public static bool RemoveUser(UserInfo user) {
if(user.Provider.UserAccountsReadOnly) return false;
bool done = user.Provider.RemoveUser(user);
if(done) {
Log.LogEntry("User " + user.Username + " removed", EntryType.General, Log.SystemUsername);
Host.Instance.OnUserAccountActivity(user, UserAccountActivity.AccountRemoved);
return true;
}
else {
Log.LogEntry("User deletion failed for " + user.Username, EntryType.Error, Log.SystemUsername);
return false;
}
}
///
/// Changes the Password of a User.
///
/// The User to change the password of.
/// The new Password (plain text).
/// true if the Password has been changed successfully, false otherwise.
public static bool ChangePassword(UserInfo user, string newPassword) {
return ModifyUser(user, user.DisplayName, newPassword, user.Email, user.Active);
}
///
/// Sends the password reset message to a user.
///
/// The username.
/// The email.
/// The user registration date/time.
public static void SendPasswordResetMessage(string username, string email, DateTime dateTime) {
string mainLink = Settings.MainUrl + "Login.aspx?ResetCode=" + Tools.ComputeSecurityHash(username, email, dateTime) + "&Username=" + Tools.UrlEncode(username);
string body = Settings.Provider.GetMetaDataItem(MetaDataItem.PasswordResetProcedureMessage, null).Replace("##USERNAME##",
username).Replace("##LINK##", mainLink).Replace("##WIKITITLE##",
Settings.WikiTitle).Replace("##EMAILADDRESS##", Settings.ContactEmail);
EmailTools.AsyncSendEmail(email, Settings.SenderEmail,
Settings.WikiTitle + " - " + Exchanger.ResourceExchanger.GetResource("ResetPassword"), body, false);
}
///
/// Changes the Email address of a User.
///
/// The User to change the Email address of.
/// The new Email address.
/// true if the Email address has been changed successfully, false otherwise.
public static bool ChangeEmail(UserInfo user, string newEmail) {
return ModifyUser(user, user.DisplayName, null, newEmail, user.Active);
}
///
/// Sets the Active/Inactive status of a User.
///
/// The User.
/// The status.
/// True if the User's status has been changed successfully.
public static bool SetActivationStatus(UserInfo user, bool active) {
return ModifyUser(user, user.DisplayName, null, user.Email, active);
}
///
/// Gets all the user groups.
///
/// All the user groups, sorted by name.
public static List GetUserGroups() {
List result = new List(50);
int count = 0;
foreach(IUsersStorageProviderV30 prov in Collectors.UsersProviderCollector.AllProviders) {
count++;
result.AddRange(prov.GetUserGroups());
}
if(count > 1) {
result.Sort(new UserGroupComparer());
}
return result;
}
///
/// Gets all the user groups in a provider.
///
/// The provider.
/// The user groups, sorted by name.
public static List GetUserGroups(IUsersStorageProviderV30 provider) {
return new List(provider.GetUserGroups());
}
///
/// Gets all the user groups a user is member of.
///
/// The user.
/// All the user groups the user is member of, sorted by name.
public static List GetUserGroupsForUser(UserInfo user) {
UserGroup[] allGroups = user.Provider.GetUserGroups();
List result = new List(allGroups.Length);
StringComparer comp = StringComparer.OrdinalIgnoreCase;
foreach(UserGroup group in allGroups) {
if(Array.Find(user.Groups, delegate(string g) {
return comp.Compare(g, group.Name) == 0;
}) != null) {
result.Add(group);
}
}
return result;
}
///
/// Finds a user group.
///
/// The name of the user group to find.
/// The object or null if no data is found.
public static UserGroup FindUserGroup(string name) {
List allGroups = GetUserGroups();
int index = allGroups.BinarySearch(new UserGroup(name, "", null), new UserGroupComparer());
if(index < 0) return null;
else return allGroups[index];
}
///
/// Adds a new user group to a specific provider.
///
/// The name of the group.
/// The description of the group.
/// The target provider.
/// true if the groups is added, false otherwise.
public static bool AddUserGroup(string name, string description, IUsersStorageProviderV30 provider) {
if(provider == null) provider = Collectors.UsersProviderCollector.GetProvider(Settings.DefaultUsersProvider);
if(provider.UserGroupsReadOnly) return false;
if(FindUserGroup(name) != null) return false;
UserGroup result = provider.AddUserGroup(name, description);
if(result != null) {
Host.Instance.OnUserGroupActivity(result, UserGroupActivity.GroupAdded);
Log.LogEntry("User Group " + name + " created", EntryType.General, Log.SystemUsername);
}
else Log.LogEntry("Creation failed for User Group " + name, EntryType.Error, Log.SystemUsername);
return result != null;
}
///
/// Adds a new user group to the default provider.
///
/// The name of the group.
/// The description of the group.
/// true if the groups is added, false otherwise.
public static bool AddUserGroup(string name, string description) {
return AddUserGroup(name, description,
Collectors.UsersProviderCollector.GetProvider(Settings.DefaultUsersProvider));
}
///
/// Modifies a user group.
///
/// The user group to modify.
/// The new description.
/// true if the user group is modified, false otherwise.
public static bool ModifyUserGroup(UserGroup group, string description) {
if(group.Provider.UserGroupsReadOnly) return false;
UserGroup result = group.Provider.ModifyUserGroup(group, description);
if(result != null) {
Host.Instance.OnUserGroupActivity(result, UserGroupActivity.GroupModified);
Log.LogEntry("User Group " + group.Name + " updated", EntryType.General, Log.SystemUsername);
}
else Log.LogEntry("Update failed for User Group " + result.Name, EntryType.Error, Log.SystemUsername);
return result != null;
}
///
/// Removes a user group.
///
/// The user group to remove.
/// true if the user group is removed, false otherwise.
public static bool RemoveUserGroup(UserGroup group) {
if(group.Provider.UserGroupsReadOnly) return false;
bool done = group.Provider.RemoveUserGroup(group);
if(done) {
Host.Instance.OnUserGroupActivity(group, UserGroupActivity.GroupRemoved);
Log.LogEntry("User Group " + group.Name + " deleted", EntryType.General, Log.SystemUsername);
}
else Log.LogEntry("Deletion failed for User Group " + group.Name, EntryType.Error, Log.SystemUsername);
return done;
}
///
/// Sets the group memberships of a user account.
///
/// The user account.
/// The groups the user account is member of.
/// true if the membership is set, false otherwise.
public static bool SetUserMembership(UserInfo user, string[] groups) {
if(user.Provider.GroupMembershipReadOnly) return false;
UserInfo result = user.Provider.SetUserMembership(user, groups);
if(result != null) {
Host.Instance.OnUserAccountActivity(result, UserAccountActivity.AccountMembershipChanged);
Log.LogEntry("Group membership set for User " + user.Username, EntryType.General, Log.SystemUsername);
}
else Log.LogEntry("Could not set group membership for User " + user.Username, EntryType.Error, Log.SystemUsername);
return result != null;
}
///
/// Creates the correct link of a User.
///
/// The Username.
/// The User link.
public static string UserLink(string username) {
return UserLink(username, false);
}
///
/// Creates the correct link of a User.
///
/// The Username.
/// A value indicating whether to open the link in a new window.
/// The User link.
public static string UserLink(string username, bool newWindow) {
if(username != null && (username.EndsWith("+" + Log.SystemUsername) || username == Log.SystemUsername)) return username;
UserInfo u = FindUser(username);
if(u == null && username.Equals("admin")) u = new UserInfo("admin", null, Settings.ContactEmail, true, DateTime.Now, null);
if(u != null) {
return @"" +
GetDisplayName(u) + "";
}
else return username;
}
///
/// Gets the display name of a user.
///
/// The user.
/// The display name.
public static string GetDisplayName(UserInfo user) {
if(string.IsNullOrEmpty(user.DisplayName)) return user.Username;
else return user.DisplayName;
}
///
/// Tries to automatically login a user using the current HttpContext,
/// through any provider that supports the operation.
///
/// The current HttpContext.
/// The correct UserInfo, or null.
public static UserInfo TryAutoLogin(HttpContext context) {
// Try default provider first
IUsersStorageProviderV30 defaultProvider =
Collectors.UsersProviderCollector.GetProvider(Settings.DefaultUsersProvider) as IUsersStorageProviderV30;
if(defaultProvider != null) {
UserInfo temp = defaultProvider.TryAutoLogin(context);
if(temp != null) return temp;
}
// Then try all other providers
IUsersStorageProviderV30[] providers = Collectors.UsersProviderCollector.AllProviders;
foreach(IUsersStorageProviderV30 p in providers) {
IUsersStorageProviderV30 extProv = p as IUsersStorageProviderV30;
if(extProv != null && extProv != defaultProvider) {
UserInfo temp = extProv.TryAutoLogin(context);
if(temp != null) return temp;
}
}
return null;
}
///
/// Tries to manually login a user using all the available methods.
///
/// The username.
/// The password.
/// The correct UserInfo, or null.
public static UserInfo TryLogin(string username, string password) {
if(username == "admin" && password == Settings.MasterPassword) {
return GetAdministratorAccount();
}
// Try default provider first
IUsersStorageProviderV30 defaultProvider =
Collectors.UsersProviderCollector.GetProvider(Settings.DefaultUsersProvider) as IUsersStorageProviderV30;
if(defaultProvider != null) {
UserInfo temp = defaultProvider.TryManualLogin(username, password);
if(temp != null) return temp;
}
// Then try all other providers
IUsersStorageProviderV30[] providers = Collectors.UsersProviderCollector.AllProviders;
foreach(IUsersStorageProviderV30 p in providers) {
IUsersStorageProviderV30 extProv = p as IUsersStorageProviderV30;
if(extProv != null && extProv != defaultProvider) {
UserInfo temp = extProv.TryManualLogin(username, password);
if(temp != null) return temp;
}
}
return null;
}
///
/// Tries to login a user through the cookie-stored authentication data.
///
/// The username.
/// The login key.
/// The correct UserInfo object, or null.
public static UserInfo TryCookieLogin(string username, string loginKey) {
if(username == "admin" && loginKey == ComputeLoginKey(username, Settings.ContactEmail, DateTime.MinValue)) {
// Just return, no notification to providers because the "admin" account is fictitious
return GetAdministratorAccount();
}
UserInfo user = FindUser(username);
if(user != null && user.Active) {
if(loginKey == ComputeLoginKey(user.Username, user.Email, user.DateTime)) {
// Notify provider
user.Provider.NotifyCookieLogin(user);
return user;
}
}
return null;
}
///
/// Notifies to the proper provider that a user has logged out.
///
/// The username.
public static void NotifyLogout(string username) {
UserInfo user = FindUser(username);
if(user != null) {
IUsersStorageProviderV30 prov = user.Provider as IUsersStorageProviderV30;
if(prov != null) prov.NotifyLogout(user);
}
}
///
/// Copmputes the login key.
///
/// The username.
/// The email.
/// The registration date/time.
/// The login key.
public static string ComputeLoginKey(string username, string email, DateTime dateTime) {
if(username == null) throw new ArgumentNullException("username");
if(email == null) throw new ArgumentNullException("email");
return Tools.ComputeSecurityHash(username, email, dateTime);
}
///
/// Sets the email notification status for a page.
///
/// The user for which to set the notification status.
/// The page subject of the notification.
/// A value indicating whether page changes should be notified.
/// A value indicating whether discussion messages should be notified.
/// true if the notification is set, false otherwise.
public static bool SetEmailNotification(UserInfo user, PageInfo page, bool pageChanges, bool discussionMessages) {
if(user == null || page == null) return false;
// Get user's data
// Depending on the status of pageChanges and discussionMessages,
// either remove existing entries (if any) or add new entries
// In the process, remove entries that refer to inexistent pages
// Format
// Page1:Page2:Page3
string pageChangeData = user.Provider.RetrieveUserData(user, PageChangesKey);
string discussionMessagesData = user.Provider.RetrieveUserData(user, DiscussionMessagesKey);
if(pageChangeData == null) pageChangeData = "";
if(discussionMessagesData == null) discussionMessagesData = "";
string[] pageChangesEntries = pageChangeData.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
string[] discussionMessagesEntries = discussionMessagesData.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
List pageChangesResult = new List(pageChangesEntries.Length + 1);
List discussionMessagesResult = new List(discussionMessagesEntries.Length + 1);
string lowercasePage = page.FullName.ToLowerInvariant();
bool added = false;
foreach(string entry in pageChangesEntries) {
if(entry.ToLowerInvariant() == lowercasePage) {
if(pageChanges) {
pageChangesResult.Add(entry);
added = true;
}
}
else if(Pages.FindPage(entry) != null) pageChangesResult.Add(entry);
}
if(!added && pageChanges) pageChangesResult.Add(page.FullName);
added = false;
foreach(string entry in discussionMessagesEntries) {
if(entry.ToLowerInvariant() == lowercasePage) {
if(discussionMessages) {
discussionMessagesResult.Add(entry);
added = true;
}
}
else if(Pages.FindPage(entry) != null) discussionMessagesResult.Add(entry);
}
if(!added && discussionMessages) discussionMessagesResult.Add(page.FullName);
string newPageChangesData = string.Join(":", pageChangesResult.ToArray());
string newDiscussionMessagesData = string.Join(":", discussionMessagesResult.ToArray());
bool done = user.Provider.StoreUserData(user, PageChangesKey, newPageChangesData) &
user.Provider.StoreUserData(user, DiscussionMessagesKey, newDiscussionMessagesData);
return done;
}
///
/// Sets the email notification status for a namespace.
///
/// The user for which to set the notification status.
/// The namespace subject of the notification.
/// A value indicating whether page changes should be notified.
/// A value indicating whether discussion messages should be notified.
/// true if the notification is set, false otherwise.
public static bool SetEmailNotification(UserInfo user, NamespaceInfo nspace, bool pageChanges, bool discussionMessages) {
if(user == null) return false;
// Get user's data
// Depending on the status of pageChanges and discussionMessages,
// either remove existing entries (if any) or add new entries
// In the process, remove entries that refer to inexistent pages
// Format
// Namespace1:Namespace2:Namespace3
string pageChangeData = user.Provider.RetrieveUserData(user, NamespacePageChangesKey);
string discussionMessagesData = user.Provider.RetrieveUserData(user, NamespaceDiscussionMessagesKey);
if(pageChangeData == null) pageChangeData = "";
if(discussionMessagesData == null) discussionMessagesData = "";
string[] pageChangesEntries = pageChangeData.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
string[] discussionMessagesEntries = discussionMessagesData.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
List pageChangesResult = new List(pageChangesEntries.Length + 1);
List discussionMessagesResult = new List(discussionMessagesEntries.Length + 1);
string namespaceName = nspace != null ? nspace.Name : "";
string lowercaseNamespace = nspace != null ? nspace.Name.ToLowerInvariant() : "";
bool added = false;
foreach(string entry in pageChangesEntries) {
if(entry.ToLowerInvariant() == lowercaseNamespace) {
if(pageChanges) {
pageChangesResult.Add(entry);
added = true;
}
}
else {
if(entry == "") pageChangesResult.Add("");
else if(Pages.FindNamespace(entry) != null) pageChangesResult.Add(entry);
}
}
if(!added && pageChanges) pageChangesResult.Add(namespaceName);
added = false;
foreach(string entry in discussionMessagesEntries) {
if(entry.ToLowerInvariant() == lowercaseNamespace) {
if(discussionMessages) {
discussionMessagesResult.Add(entry);
added = true;
}
}
else {
if(entry == "") discussionMessagesResult.Add("");
else if(Pages.FindNamespace(entry) != null) discussionMessagesResult.Add(entry);
}
}
if(!added && discussionMessages) discussionMessagesResult.Add(namespaceName);
string newPageChangesData = string.Join(":", pageChangesResult.ToArray());
string newDiscussionMessagesData = string.Join(":", discussionMessagesResult.ToArray());
bool done = user.Provider.StoreUserData(user, NamespacePageChangesKey, newPageChangesData) &
user.Provider.StoreUserData(user, NamespaceDiscussionMessagesKey, newDiscussionMessagesData);
return done;
}
///
/// Gets the email notification status for a page.
///
/// The user for which to get the notification status.
/// The page subject of the notification.
/// A value indicating whether page changes should be notified.
/// A value indicating whether discussion messages should be notified.
public static void GetEmailNotification(UserInfo user, PageInfo page, out bool pageChanges, out bool discussionMessages) {
pageChanges = false;
discussionMessages = false;
if(user == null || page == null) return;
string pageChangeData = user.Provider.RetrieveUserData(user, PageChangesKey);
string discussionMessagesData = user.Provider.RetrieveUserData(user, DiscussionMessagesKey);
if(pageChangeData == null) pageChangeData = "";
if(discussionMessagesData == null) discussionMessagesData = "";
pageChangeData = pageChangeData.ToLowerInvariant();
discussionMessagesData = discussionMessagesData.ToLowerInvariant();
string[] pageChangeEntries = pageChangeData.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
string[] discussionMessagesEntries = discussionMessagesData.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
string lowercasePage = page.FullName.ToLowerInvariant();
// Elements in the array are already lowercase
pageChanges = Array.Find(pageChangeEntries, delegate(string elem) { return elem == lowercasePage; }) != null;
discussionMessages = Array.Find(discussionMessagesEntries, delegate(string elem) { return elem == lowercasePage; }) != null;
}
///
/// Gets the email notification status for a namespace.
///
/// The user for which to get the notification status.
/// The namespace subject of the notification (null for the root).
/// A value indicating whether page changes should be notified.
/// A value indicating whether discussion messages should be notified.
public static void GetEmailNotification(UserInfo user, NamespaceInfo nspace, out bool pageChanges, out bool discussionMessages) {
pageChanges = false;
discussionMessages = false;
if(user == null) return;
string lowercaseNamespaces = nspace != null ? nspace.Name.ToLowerInvariant() : "";
string pageChangesData = user.Provider.RetrieveUserData(user, NamespacePageChangesKey);
string discussionMessagesData = user.Provider.RetrieveUserData(user, NamespaceDiscussionMessagesKey);
if(pageChangesData == null) pageChangesData = "";
if(discussionMessagesData == null) discussionMessagesData = "";
pageChangesData = pageChangesData.ToLowerInvariant();
discussionMessagesData = discussionMessagesData.ToLowerInvariant();
string[] pageChangeEntries = pageChangesData.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
string[] discussionMessagesEntries = discussionMessagesData.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
// Elements in the array are already lowercase
pageChanges = Array.Find(pageChangeEntries, delegate(string elem) { return elem == lowercaseNamespaces; }) != null;
discussionMessages = Array.Find(discussionMessagesEntries, delegate(string elem) { return elem == lowercaseNamespaces; }) != null;
}
///
/// Gets all the users that must be notified of a page change.
///
/// The page.
/// The users to be notified.
public static UserInfo[] GetUsersToNotifyForPageChange(PageInfo page) {
if(page == null) return new UserInfo[0];
UserInfo[] specific = GetUsersToNotify(page, PageChangesKey);
UserInfo[] nspace = GetUsersToNotify(Pages.FindNamespace(NameTools.GetNamespace(page.FullName)),
NamespacePageChangesKey);
UserInfo[] temp = MergeArrays(specific, nspace);
List result = new List(temp.Length);
// Verify read permissions
foreach(UserInfo user in temp) {
if(AuthChecker.CheckActionForPage(page, Actions.ForPages.ReadPage, user.Username, user.Groups)) {
result.Add(user);
}
}
return result.ToArray();
}
///
/// Gets all the users that must be notified of a discussion message.
///
/// The page.
/// The users to be notified.
public static UserInfo[] GetUsersToNotifyForDiscussionMessages(PageInfo page) {
if(page == null) return new UserInfo[0];
UserInfo[] specific = GetUsersToNotify(page, DiscussionMessagesKey);
UserInfo[] nspace = GetUsersToNotify(Pages.FindNamespace(NameTools.GetNamespace(page.FullName)),
NamespaceDiscussionMessagesKey);
UserInfo[] temp = MergeArrays(specific, nspace);
List result = new List(temp.Length);
// Verify read permissions
foreach(UserInfo user in temp) {
if(AuthChecker.CheckActionForPage(page, Actions.ForPages.ReadDiscussion, user.Username, user.Groups)) {
result.Add(user);
}
}
return result.ToArray();
}
///
/// Merges two arrays of users, removing duplicates.
///
/// The first array.
/// The second array.
/// The merged users.
private static UserInfo[] MergeArrays(UserInfo[] array1, UserInfo[] array2) {
List result = new List(array1.Length + array2.Length);
result.AddRange(array1);
UsernameComparer comp = new UsernameComparer();
foreach(UserInfo user in array2) {
bool found = false;
foreach(UserInfo present in result) {
if(comp.Compare(present, user) == 0) {
found = true;
break;
}
}
if(!found) {
result.Add(user);
}
}
return result.ToArray();
}
///
/// Gets the users to notify for either a page change or a discussion message.
///
/// The page.
/// The key to look for in the user's data.
/// The users to be notified.
private static UserInfo[] GetUsersToNotify(PageInfo page, string key) {
List result = new List(200);
string lowercasePage = page.FullName.ToLowerInvariant();
foreach(IUsersStorageProviderV30 prov in Collectors.UsersProviderCollector.AllProviders) {
IDictionary users = prov.GetUsersWithData(key);
string[] fields;
foreach(KeyValuePair pair in users) {
fields = pair.Value.ToLowerInvariant().Split(':');
if(Array.Find(fields, delegate(string elem) { return elem == lowercasePage; }) != null) {
result.Add(pair.Key);
}
}
}
return result.ToArray();
}
///
/// Gets the users to notify for either a page change or a discussion message in a namespace.
///
/// The namespace (null for the root).
/// The key to look for in the user's data.
/// The users to be notified.
private static UserInfo[] GetUsersToNotify(NamespaceInfo nspace, string key) {
List result = new List(200);
string lowercaseNamespace = nspace != null ? nspace.Name.ToLowerInvariant() : "";
foreach(IUsersStorageProviderV30 prov in Collectors.UsersProviderCollector.AllProviders) {
IDictionary users = prov.GetUsersWithData(key);
string[] fields;
foreach(KeyValuePair pair in users) {
fields = pair.Value.ToLowerInvariant().Split(':');
if(Array.Find(fields, delegate(string elem) { return elem == lowercaseNamespace; }) != null) {
result.Add(pair.Key);
}
}
}
return result.ToArray();
}
}
}