using System;
using System.Collections.Generic;
using System.Text;
using ScrewTurn.Wiki.PluginFramework;
using ScrewTurn.Wiki.AclEngine;
namespace ScrewTurn.Wiki {
///
/// Utility class for writing permissions and authorizations.
///
public static class AuthWriter {
private const string Delete = "DELETE";
private const string Set = "SET-";
private const string MessageDeleteSuccess = "Deleted ACL Entry: ";
private const string MessageDeleteFailure = "Deletion failed for ACL Entry: ";
private const string MessageSetSuccess = "Set ACL Entry: ";
private const string MessageSetFailure = "Setting failed for ACL Entry: ";
///
/// Gets the settings storage provider.
///
private static ISettingsStorageProviderV30 SettingsProvider {
get { return Collectors.SettingsProvider; }
}
///
/// Sets a permission for a global resource.
///
/// The authorization status.
/// The action of which to modify the authorization status.
/// The group subject of the authorization change.
/// true if the authorization status is changed, false otherwise.
public static bool SetPermissionForGlobals(AuthStatus status, string action, UserGroup group) {
if(group == null) throw new ArgumentNullException("group");
return SetPermissionForGlobals(status, action, AuthTools.PrepareGroup(group.Name));
}
///
/// Sets a permission for a global resource.
///
/// The authorization status.
/// The action of which to modify the authorization status.
/// The user subject of the authorization change.
/// true if the authorization status is changed, false otherwise.
public static bool SetPermissionForGlobals(AuthStatus status, string action, UserInfo user) {
if(user == null) throw new ArgumentNullException("user");
return SetPermissionForGlobals(status, action, AuthTools.PrepareUsername(user.Username));
}
///
/// Sets a permission for a global resource.
///
/// The authorization status.
/// The action of which to modify the authorization status.
/// The subject of the authorization change.
/// true if the authorization status is changed, false otherwise.
private static bool SetPermissionForGlobals(AuthStatus status, string action, string subject) {
if(action == null) throw new ArgumentNullException("action");
if(action.Length == 0) throw new ArgumentException("Action cannot be empty", "action");
if(action != Actions.FullControl && !AuthTools.IsValidAction(action, Actions.ForGlobals.All)) {
throw new ArgumentException("Invalid action", "action");
}
if(status == AuthStatus.Delete) {
bool done = SettingsProvider.AclManager.DeleteEntry(Actions.ForGlobals.ResourceMasterPrefix, action, subject);
if(done) {
Log.LogEntry(MessageDeleteSuccess + GetLogMessage(Actions.ForGlobals.ResourceMasterPrefix, "",
action, subject, Delete), EntryType.General, Log.SystemUsername);
}
else {
Log.LogEntry(MessageDeleteFailure + GetLogMessage(Actions.ForGlobals.ResourceMasterPrefix, "",
action, subject, Delete), EntryType.Error, Log.SystemUsername);
}
return done;
}
else {
bool done = SettingsProvider.AclManager.StoreEntry(Actions.ForGlobals.ResourceMasterPrefix,
action, subject, status == AuthStatus.Grant ? Value.Grant : Value.Deny);
if(done) {
Log.LogEntry(MessageSetSuccess + GetLogMessage(Actions.ForGlobals.ResourceMasterPrefix, "",
action, subject, Set + status.ToString()), EntryType.General, Log.SystemUsername);
}
else {
Log.LogEntry(MessageSetFailure + GetLogMessage(Actions.ForGlobals.ResourceMasterPrefix, "",
action, subject, Set + status.ToString()), EntryType.Error, Log.SystemUsername);
}
return done;
}
}
///
/// Sets a permission for a namespace.
///
/// The authorization status.
/// The namespace (null for the root).
/// The action of which to modify the authorization status.
/// The group subject of the authorization change.
/// true if the authorization status is changed, false otherwise.
public static bool SetPermissionForNamespace(AuthStatus status, NamespaceInfo nspace, string action, UserGroup group) {
if(group == null) throw new ArgumentNullException("group");
return SetPermissionForNamespace(status, nspace, action, AuthTools.PrepareGroup(group.Name));
}
///
/// Sets a permission for a namespace.
///
/// The authorization status.
/// The namespace (null for the root).
/// The action of which to modify the authorization status.
/// The user subject of the authorization change.
/// true if the authorization status is changed, false otherwise.
public static bool SetPermissionForNamespace(AuthStatus status, NamespaceInfo nspace, string action, UserInfo user) {
if(user == null) throw new ArgumentNullException("user");
return SetPermissionForNamespace(status, nspace, action, AuthTools.PrepareUsername(user.Username));
}
///
/// Sets a permission for a namespace.
///
/// The authorization status.
/// The namespace (null for the root).
/// The action of which to modify the authorization status.
/// The subject of the authorization change.
/// true if the authorization status is changed, false otherwise.
private static bool SetPermissionForNamespace(AuthStatus status, NamespaceInfo nspace, string action, string subject) {
if(action == null) throw new ArgumentNullException("action");
if(action.Length == 0) throw new ArgumentException("Action cannot be empty", "action");
if(action != Actions.FullControl && !AuthTools.IsValidAction(action, Actions.ForNamespaces.All)) {
throw new ArgumentException("Invalid action", "action");
}
string namespaceName = nspace != null ? nspace.Name : "";
if(status == AuthStatus.Delete) {
bool done = SettingsProvider.AclManager.DeleteEntry(Actions.ForNamespaces.ResourceMasterPrefix + namespaceName,
action, subject);
if(done) {
Log.LogEntry(MessageDeleteSuccess + GetLogMessage(Actions.ForNamespaces.ResourceMasterPrefix, namespaceName,
action, subject, Delete), EntryType.General, Log.SystemUsername);
}
else {
Log.LogEntry(MessageDeleteFailure + GetLogMessage(Actions.ForNamespaces.ResourceMasterPrefix, namespaceName,
action, subject, Delete), EntryType.Error, Log.SystemUsername);
}
return done;
}
else {
bool done = SettingsProvider.AclManager.StoreEntry(Actions.ForNamespaces.ResourceMasterPrefix + namespaceName,
action, subject, status == AuthStatus.Grant ? Value.Grant : Value.Deny);
if(done) {
Log.LogEntry(MessageSetSuccess + GetLogMessage(Actions.ForNamespaces.ResourceMasterPrefix, namespaceName,
action, subject, Set + status.ToString()), EntryType.General, Log.SystemUsername);
}
else {
Log.LogEntry(MessageSetFailure + GetLogMessage(Actions.ForNamespaces.ResourceMasterPrefix, namespaceName,
action, subject, Set + status.ToString()), EntryType.Error, Log.SystemUsername);
}
return done;
}
}
///
/// Sets a permission for a directory.
///
/// The authorization status.
/// The provider that handles the directory.
/// The directory.
/// The action of which to modify the authorization status.
/// The group subject of the authorization change.
/// true if the authorization status is changed, false otherwise.
public static bool SetPermissionForDirectory(AuthStatus status, IFilesStorageProviderV30 provider, string directory, string action, UserGroup group) {
if(group == null) throw new ArgumentNullException("group");
return SetPermissionForDirectory(status, provider, directory, action, AuthTools.PrepareGroup(group.Name));
}
///
/// Sets a permission for a directory.
///
/// The authorization status.
/// The provider that handles the directory.
/// The directory.
/// The action of which to modify the authorization status.
/// The user subject of the authorization change.
/// true if the authorization status is changed, false otherwise.
public static bool SetPermissionForDirectory(AuthStatus status, IFilesStorageProviderV30 provider, string directory, string action, UserInfo user) {
if(user == null) throw new ArgumentNullException("user");
return SetPermissionForDirectory(status, provider, directory, action, AuthTools.PrepareUsername(user.Username));
}
///
/// Sets a permission for a directory.
///
/// The authorization status.
/// The provider that handles the directory.
/// The directory.
/// The action of which to modify the authorization status.
/// The subject of the authorization change.
/// true if the authorization status is changed, false otherwise.
private static bool SetPermissionForDirectory(AuthStatus status, IFilesStorageProviderV30 provider, string directory, string action, string subject) {
if(provider == null) throw new ArgumentNullException("provider");
if(directory == null) throw new ArgumentNullException("directory");
if(directory.Length == 0) throw new ArgumentException("Directory cannot be empty", "directory");
if(action == null) throw new ArgumentNullException("action");
if(action.Length == 0) throw new ArgumentException("Action cannot be empty", "action");
if(action != Actions.FullControl && !AuthTools.IsValidAction(action, Actions.ForDirectories.All)) {
throw new ArgumentException("Invalid action", "action");
}
string directoryName = AuthTools.GetDirectoryName(provider, directory);
if(status == AuthStatus.Delete) {
bool done = SettingsProvider.AclManager.DeleteEntry(Actions.ForDirectories.ResourceMasterPrefix + directoryName,
action, subject);
if(done) {
Log.LogEntry(MessageDeleteSuccess + GetLogMessage(Actions.ForDirectories.ResourceMasterPrefix, directoryName,
action, subject, Delete), EntryType.General, Log.SystemUsername);
}
else {
Log.LogEntry(MessageDeleteFailure + GetLogMessage(Actions.ForDirectories.ResourceMasterPrefix, directoryName,
action, subject, Delete), EntryType.Error, Log.SystemUsername);
}
return done;
}
else {
bool done = SettingsProvider.AclManager.StoreEntry(Actions.ForDirectories.ResourceMasterPrefix + directoryName,
action, subject, status == AuthStatus.Grant ? Value.Grant : Value.Deny);
if(done) {
Log.LogEntry(MessageSetSuccess + GetLogMessage(Actions.ForDirectories.ResourceMasterPrefix, directoryName,
action, subject, Set + status.ToString()), EntryType.General, Log.SystemUsername);
}
else {
Log.LogEntry(MessageSetFailure + GetLogMessage(Actions.ForDirectories.ResourceMasterPrefix, directoryName,
action, subject, Set + status.ToString()), EntryType.Error, Log.SystemUsername);
}
return done;
}
}
///
/// Sets a permission for a page.
///
/// The authorization status.
/// The page.
/// The action of which to modify the authorization status.
/// The group subject of the authorization change.
/// true if the authorization status is changed, false otherwise.
public static bool SetPermissionForPage(AuthStatus status, PageInfo page, string action, UserGroup group) {
if(group == null) throw new ArgumentNullException("group");
return SetPermissionForPage(status, page, action, AuthTools.PrepareGroup(group.Name));
}
///
/// Sets a permission for a page.
///
/// The authorization status.
/// The page.
/// The action of which to modify the authorization status.
/// The user subject of the authorization change.
/// true if the authorization status is changed, false otherwise.
public static bool SetPermissionForPage(AuthStatus status, PageInfo page, string action, UserInfo user) {
if(user == null) throw new ArgumentNullException("user");
return SetPermissionForPage(status, page, action, AuthTools.PrepareUsername(user.Username));
}
///
/// Sets a permission for a page.
///
/// The authorization status.
/// The page.
/// The action of which to modify the authorization status.
/// The subject of the authorization change.
/// true if the authorization status is changed, false otherwise.
private static bool SetPermissionForPage(AuthStatus status, PageInfo page, string action, string subject) {
if(page == null) throw new ArgumentNullException("page");
if(action == null) throw new ArgumentNullException("action");
if(action.Length == 0) throw new ArgumentException("Action cannot be empty", "action");
if(action != Actions.FullControl && !AuthTools.IsValidAction(action, Actions.ForPages.All)) {
throw new ArgumentException("Invalid action", "action");
}
if(status == AuthStatus.Delete) {
bool done = SettingsProvider.AclManager.DeleteEntry(Actions.ForPages.ResourceMasterPrefix + page.FullName,
action, subject);
if(done) {
Log.LogEntry(MessageDeleteSuccess + GetLogMessage(Actions.ForPages.ResourceMasterPrefix, page.FullName,
action, subject, Delete), EntryType.General, Log.SystemUsername);
}
else {
Log.LogEntry(MessageDeleteFailure + GetLogMessage(Actions.ForPages.ResourceMasterPrefix, page.FullName,
action, subject, Delete), EntryType.Error, Log.SystemUsername);
}
return done;
}
else {
bool done = SettingsProvider.AclManager.StoreEntry(Actions.ForPages.ResourceMasterPrefix + page.FullName,
action, subject, status == AuthStatus.Grant ? Value.Grant : Value.Deny);
if(done) {
Log.LogEntry(MessageSetSuccess + GetLogMessage(Actions.ForPages.ResourceMasterPrefix, page.FullName,
action, subject, Set + status.ToString()), EntryType.General, Log.SystemUsername);
}
else {
Log.LogEntry(MessageSetFailure + GetLogMessage(Actions.ForPages.ResourceMasterPrefix, page.FullName,
action, subject, Set + status.ToString()), EntryType.Error, Log.SystemUsername);
}
return done;
}
}
///
/// Removes all the ACL Entries for global resources that are bound to a user group.
///
/// The user group.
/// true if the operation succeeded, false otherwise.
public static bool RemoveEntriesForGlobals(UserGroup group) {
if(group == null) throw new ArgumentNullException("group");
return RemoveEntriesForGlobals(AuthTools.PrepareGroup(group.Name));
}
///
/// Removes all the ACL Entries for global resources that are bound to a user.
///
/// The user.
/// true if the operation succeeded, false otherwise.
public static bool RemoveEntriesForGlobals(UserInfo user) {
if(user == null) throw new ArgumentNullException("user");
return RemoveEntriesForGlobals(AuthTools.PrepareUsername(user.Username));
}
///
/// Removes all the ACL Entries for global resources that are bound to a subject.
///
/// The subject.
/// true if the operation succeeded, false otherwise.
private static bool RemoveEntriesForGlobals(string subject) {
AclEntry[] entries = SettingsProvider.AclManager.RetrieveEntriesForSubject(subject);
foreach(AclEntry entry in entries) {
if(entry.Resource == Actions.ForGlobals.ResourceMasterPrefix) {
// This call automatically logs the operation result
bool done = SetPermissionForGlobals(AuthStatus.Delete, entry.Action, subject);
if(!done) return false;
}
}
return true;
}
///
/// Removes all the ACL Entries for a namespace that are bound to a user group.
///
/// The user group.
/// The namespace (null for the root).
/// true if the operation succeeded, false otherwise.
public static bool RemoveEntriesForNamespace(UserGroup group, NamespaceInfo nspace) {
if(group == null) throw new ArgumentNullException("group");
return RemoveEntriesForNamespace(AuthTools.PrepareGroup(group.Name), nspace);
}
///
/// Removes all the ACL Entries for a namespace that are bound to a user.
///
/// The user.
/// The namespace (null for the root).
/// true if the operation succeeded, false otherwise.
public static bool RemoveEntriesForNamespace(UserInfo user, NamespaceInfo nspace) {
if(user == null) throw new ArgumentNullException("user");
return RemoveEntriesForNamespace(AuthTools.PrepareUsername(user.Username), nspace);
}
///
/// Removes all the ACL Entries for a namespace that are bound to a subject.
///
/// The subject.
/// The namespace (null for the root).
/// true if the operation succeeded, false otherwise.
private static bool RemoveEntriesForNamespace(string subject, NamespaceInfo nspace) {
string resourceName = Actions.ForNamespaces.ResourceMasterPrefix;
if(nspace != null) resourceName += nspace.Name;
AclEntry[] entries = SettingsProvider.AclManager.RetrieveEntriesForSubject(subject);
foreach(AclEntry entry in entries) {
if(entry.Resource == resourceName) {
// This call automatically logs the operation result
bool done = SetPermissionForNamespace(AuthStatus.Delete, nspace, entry.Action, subject);
if(!done) return false;
}
}
return true;
}
///
/// Removes all the ACL Entries for a page that are bound to a user group.
///
/// The user group.
/// The page.
/// true if the operation succeeded, false otherwise.
public static bool RemoveEntriesForPage(UserGroup group, PageInfo page) {
if(group == null) throw new ArgumentNullException("group");
return RemoveEntriesForPage(AuthTools.PrepareGroup(group.Name), page);
}
///
/// Removes all the ACL Entries for a page that are bound to a user.
///
/// The user.
/// The page.
/// true if the operation succeeded, false otherwise.
public static bool RemoveEntriesForPage(UserInfo user, PageInfo page) {
if(user == null) throw new ArgumentNullException("user");
return RemoveEntriesForPage(AuthTools.PrepareUsername(user.Username), page);
}
///
/// Removes all the ACL Entries for a page that are bound to a subject.
///
/// The subject.
/// The page.
/// true if the operation succeeded, false otherwise.
private static bool RemoveEntriesForPage(string subject, PageInfo page) {
if(page == null) throw new ArgumentNullException("page");
string resourceName = Actions.ForPages.ResourceMasterPrefix + page.FullName;
AclEntry[] entries = SettingsProvider.AclManager.RetrieveEntriesForSubject(subject);
foreach(AclEntry entry in entries) {
if(entry.Resource == resourceName) {
// This call automatically logs the operation result
bool done = SetPermissionForPage(AuthStatus.Delete, page, entry.Action, subject);
if(!done) return false;
}
}
return true;
}
///
/// Removes all the ACL Entries for a directory that are bound to a user group.
///
/// The group.
/// The provider.
/// The directory.
/// true if the operation succeeded, false otherwise.
public static bool RemoveEntriesForDirectory(UserGroup group, IFilesStorageProviderV30 provider, string directory) {
if(group == null) throw new ArgumentNullException("group");
return RemoveEntriesForDirectory(AuthTools.PrepareGroup(group.Name), provider, directory);
}
///
/// Removes all the ACL Entries for a directory that are bound to a user.
///
/// The user.
/// The provider.
/// The directory.
/// true if the operation succeeded, false otherwise.
public static bool RemoveEntriesForDirectory(UserInfo user, IFilesStorageProviderV30 provider, string directory) {
if(user == null) throw new ArgumentNullException("user");
return RemoveEntriesForDirectory(AuthTools.PrepareUsername(user.Username), provider, directory);
}
///
/// Removes all the ACL Entries for a directory that are bound to a subject.
///
/// The subject.
/// The provider.
/// The directory.
/// true if the operation succeeded, false otherwise.
private static bool RemoveEntriesForDirectory(string subject, IFilesStorageProviderV30 provider, string directory) {
if(provider == null) throw new ArgumentNullException("provider");
if(directory == null) throw new ArgumentNullException("directory");
if(directory.Length == 0) throw new ArgumentException("Directory cannot be empty", "directory");
string resourceName = Actions.ForDirectories.ResourceMasterPrefix + AuthTools.GetDirectoryName(provider, directory);
AclEntry[] entries = SettingsProvider.AclManager.RetrieveEntriesForSubject(subject);
foreach(AclEntry entry in entries) {
if(entry.Resource == resourceName) {
// This call automatically logs the operation result
bool done = SetPermissionForDirectory(AuthStatus.Delete, provider, directory, entry.Action, subject);
if(!done) return false;
}
}
return true;
}
///
/// Clears all the ACL entries for a directory.
///
/// The provider.
/// The directory.
public static void ClearEntriesForDirectory(IFilesStorageProviderV30 provider, string directory) {
if(provider == null) throw new ArgumentNullException("provider");
if(directory == null) throw new ArgumentNullException("directory");
if(directory.Length == 0) throw new ArgumentException("Directory cannot be empty", "directory");
string resourceName = Actions.ForDirectories.ResourceMasterPrefix + AuthTools.GetDirectoryName(provider, directory);
SettingsProvider.AclManager.DeleteEntriesForResource(resourceName);
}
///
/// Clears all the ACL entries for a namespace.
///
/// The namespace.
/// The local names of the pages in the namespace.
public static void ClearEntriesForNamespace(string nspace, List pages) {
if(nspace == null) throw new ArgumentNullException("nspac");
if(nspace.Length == 0) throw new ArgumentException("Namespace cannot be empty", "nspace");
if(pages == null) throw new ArgumentNullException("pages");
foreach(string p in pages) {
if(p == null) throw new ArgumentNullException("pages");
if(p.Length == 0) throw new ArgumentException("Page Element cannot be empty", "pages");
}
string resourceName;
foreach(string p in pages) {
resourceName = Actions.ForPages.ResourceMasterPrefix + NameTools.GetFullName(nspace, p);
SettingsProvider.AclManager.DeleteEntriesForResource(resourceName);
}
resourceName = Actions.ForNamespaces.ResourceMasterPrefix + nspace;
SettingsProvider.AclManager.DeleteEntriesForResource(resourceName);
}
///
/// Clears all the ACL entries for a page.
///
/// The page full name.
public static void ClearEntriesForPage(string page) {
if(page == null) throw new ArgumentNullException("page");
if(page.Length == 0) throw new ArgumentException("Page cannot be empty", "page");
string resourceName = Actions.ForPages.ResourceMasterPrefix + page;
SettingsProvider.AclManager.DeleteEntriesForResource(resourceName);
}
///
/// Processes the renaming of a directory.
///
/// The provider.
/// The old directory name (full path).
/// The new directory name (full path).
/// true if the operation completed successfully, false otherwise.
/// The method does not recurse in sub-directories.
public static bool ProcessDirectoryRenaming(IFilesStorageProviderV30 provider, string oldName, string newName) {
if(provider == null) throw new ArgumentNullException("provider");
if(oldName == null) throw new ArgumentNullException("oldName");
if(oldName.Length == 0) throw new ArgumentException("Old Name cannot be empty", "oldName");
if(newName == null) throw new ArgumentNullException("newName");
if(newName.Length == 0) throw new ArgumentException("New Name cannot be empty", "newName");
return SettingsProvider.AclManager.RenameResource(
Actions.ForDirectories.ResourceMasterPrefix + AuthTools.GetDirectoryName(provider, oldName),
Actions.ForDirectories.ResourceMasterPrefix + AuthTools.GetDirectoryName(provider, newName));
}
///
/// Processes the renaming of a namespace.
///
/// The old name of the namespace.
/// The list of local names of the pages in the renamed namespace.
/// The new name of the namespace.
/// true if the operation completed successfully, false otherwise.
public static bool ProcessNamespaceRenaming(string oldName, List oldPages, string newName) {
if(oldName == null) throw new ArgumentNullException("oldName");
if(oldName.Length == 0) throw new ArgumentException("Old Name cannot be empty", "oldName");
if(oldPages == null) throw new ArgumentNullException("oldPages");
foreach(string p in oldPages) {
if(p == null) throw new ArgumentNullException("oldPages");
if(p.Length == 0) throw new ArgumentException("Page cannot be empty", "oldPages");
}
if(newName == null) throw new ArgumentNullException("newName");
if(newName.Length == 0) throw new ArgumentException("New Name cannot be empty", "newName");
foreach(string p in oldPages) {
SettingsProvider.AclManager.RenameResource(
Actions.ForPages.ResourceMasterPrefix + NameTools.GetFullName(oldName, p),
Actions.ForPages.ResourceMasterPrefix + NameTools.GetFullName(newName, p));
}
return SettingsProvider.AclManager.RenameResource(
Actions.ForNamespaces.ResourceMasterPrefix + oldName,
Actions.ForNamespaces.ResourceMasterPrefix + newName);
}
///
/// Processes the renaming of a page.
///
/// The old full page name.
/// The new full page name.
/// true if the operation completed successfully, false otherwise.
public static bool ProcessPageRenaming(string oldName, string newName) {
if(oldName == null) throw new ArgumentNullException("oldName");
if(oldName.Length == 0) throw new ArgumentException("Old Name cannot be empty", "oldName");
if(newName == null) throw new ArgumentNullException("newName");
if(newName.Length == 0) throw new ArgumentException("New Name cannot be empty", "newName");
return SettingsProvider.AclManager.RenameResource(
Actions.ForPages.ResourceMasterPrefix + oldName,
Actions.ForPages.ResourceMasterPrefix + newName);
}
///
/// Gets the log message for an ACL entry change.
///
/// The resource prefix.
/// The resource name.
/// The action.
/// The subject.
/// The status.
/// The message.
private static string GetLogMessage(string resourcePrefix, string resource, string action, string subject, string status) {
return resourcePrefix + resource + ":" + action + ":" + subject + "->" + status;
}
}
}