using System;
using System.IO;
using System.Resources;
using System.Web.Configuration;
using ScrewTurn.Wiki.PluginFramework;
namespace ScrewTurn.Wiki {
///
/// Provides tools for starting and shutting down the wiki engine.
///
public static class StartupTools {
///
/// Gets the Settings Storage Provider configuration string from web.config.
///
/// The configuration string.
public static string GetSettingsStorageProviderConfiguration() {
string config = WebConfigurationManager.AppSettings["SettingsStorageProviderConfig"];
if(config != null) return config;
else return "";
}
///
/// Updates the DLLs into the settings storage provider, if appropriate.
///
/// The provider.
/// The file name of the assembly that contains the current Settings Storage Provider.
private static void UpdateDllsIntoSettingsProvider(ISettingsStorageProviderV30 provider, string settingsProviderAsmName) {
// Look into public\Plugins (hardcoded)
string fullPath = Path.Combine(Settings.PublicDirectory, "Plugins");
if(!Directory.Exists(fullPath)) return;
string[] dlls = Directory.GetFiles(fullPath, "*.dll");
string[] installedDlls = provider.ListPluginAssemblies();
foreach(string dll in dlls) {
bool found = false;
string filename = Path.GetFileName(dll);
foreach(string instDll in installedDlls) {
if(instDll.ToLowerInvariant() == filename.ToLowerInvariant()) {
found = true;
break;
}
}
if(!found && filename.ToLowerInvariant() == settingsProviderAsmName.ToLowerInvariant()) {
found = true;
}
if(found) {
// Update DLL
provider.StorePluginAssembly(filename, File.ReadAllBytes(dll));
}
}
}
///
/// Performs all needed startup operations.
///
public static void Startup() {
// Load Host
Host.Instance = new Host();
// Load config
ISettingsStorageProviderV30 ssp = ProviderLoader.LoadSettingsStorageProvider(WebConfigurationManager.AppSettings["SettingsStorageProvider"]);
ssp.Init(Host.Instance, GetSettingsStorageProviderConfiguration());
Collectors.SettingsProvider = ssp;
//Settings.Instance = new Settings(ssp);
if(!(ssp is SettingsStorageProvider)) {
// Update DLLs from public\Plugins
UpdateDllsIntoSettingsProvider(ssp, ProviderLoader.SettingsStorageProviderAssemblyName);
}
// Initialize authorization managers
//AuthReader.Instance = new AuthReader(Settings.Provider);
//AuthWriter.Instance = new AuthWriter(Settings.Provider);
//AuthChecker.Instance = new AuthChecker(Settings.Provider);
if(ssp.GetMetaDataItem(MetaDataItem.AccountActivationMessage, null) == "")
ssp.SetMetaDataItem(MetaDataItem.AccountActivationMessage, null, Defaults.AccountActivationMessageContent);
if(ssp.GetMetaDataItem(MetaDataItem.EditNotice, null) == "")
ssp.SetMetaDataItem(MetaDataItem.EditNotice, null, Defaults.EditNoticeContent);
if(ssp.GetMetaDataItem(MetaDataItem.Footer, null) == "")
ssp.SetMetaDataItem(MetaDataItem.Footer, null, Defaults.FooterContent);
if(ssp.GetMetaDataItem(MetaDataItem.Header, null) == "")
ssp.SetMetaDataItem(MetaDataItem.Header, null, Defaults.HeaderContent);
if(ssp.GetMetaDataItem(MetaDataItem.PasswordResetProcedureMessage, null) == "")
ssp.SetMetaDataItem(MetaDataItem.PasswordResetProcedureMessage, null, Defaults.PasswordResetProcedureMessageContent);
if(ssp.GetMetaDataItem(MetaDataItem.Sidebar, null) == "")
ssp.SetMetaDataItem(MetaDataItem.Sidebar, null, Defaults.SidebarContent);
if(ssp.GetMetaDataItem(MetaDataItem.PageChangeMessage, null) == "")
ssp.SetMetaDataItem(MetaDataItem.PageChangeMessage, null, Defaults.PageChangeMessage);
if(ssp.GetMetaDataItem(MetaDataItem.DiscussionChangeMessage, null) == "")
ssp.SetMetaDataItem(MetaDataItem.DiscussionChangeMessage, null, Defaults.DiscussionChangeMessage);
if(ssp.GetMetaDataItem(MetaDataItem.ApproveDraftMessage, null) == "") {
ssp.SetMetaDataItem(MetaDataItem.ApproveDraftMessage, null, Defaults.ApproveDraftMessage);
}
// Load MIME Types
MimeTypes.Init();
// Load Providers
Collectors.FileNames = new System.Collections.Generic.Dictionary(10);
Collectors.UsersProviderCollector = new ProviderCollector();
Collectors.PagesProviderCollector = new ProviderCollector();
Collectors.FilesProviderCollector = new ProviderCollector();
Collectors.FormatterProviderCollector = new ProviderCollector();
Collectors.CacheProviderCollector = new ProviderCollector();
Collectors.DisabledUsersProviderCollector = new ProviderCollector();
Collectors.DisabledPagesProviderCollector = new ProviderCollector();
Collectors.DisabledFilesProviderCollector = new ProviderCollector();
Collectors.DisabledFormatterProviderCollector = new ProviderCollector();
Collectors.DisabledCacheProviderCollector = new ProviderCollector();
// Load built-in providers
// Files storage providers have to be loaded BEFORE users storage providers in order to properly set permissions
FilesStorageProvider f = new FilesStorageProvider();
if(!ProviderLoader.IsDisabled(f.GetType().FullName)) {
f.Init(Host.Instance, "");
Collectors.FilesProviderCollector.AddProvider(f);
Log.LogEntry("Provider " + f.Information.Name + " loaded (Enabled)", EntryType.General, Log.SystemUsername);
}
else {
Collectors.DisabledFilesProviderCollector.AddProvider(f);
Log.LogEntry("Provider " + f.Information.Name + " loaded (Disabled)", EntryType.General, Log.SystemUsername);
}
UsersStorageProvider u = new UsersStorageProvider();
if(!ProviderLoader.IsDisabled(u.GetType().FullName)) {
u.Init(Host.Instance, "");
Collectors.UsersProviderCollector.AddProvider(u);
Log.LogEntry("Provider " + u.Information.Name + " loaded (Enabled)", EntryType.General, Log.SystemUsername);
}
else {
Collectors.DisabledUsersProviderCollector.AddProvider(u);
Log.LogEntry("Provider " + u.Information.Name + " loaded (Disabled)", EntryType.General, Log.SystemUsername);
}
// Load Users (pages storage providers might need access to users/groups data for upgrading from 2.0 to 3.0)
ProviderLoader.FullLoad(true, false, false, false, false);
//Users.Instance = new Users();
bool groupsCreated = VerifyAndCreateDefaultGroups();
PagesStorageProvider p = new PagesStorageProvider();
if(!ProviderLoader.IsDisabled(p.GetType().FullName)) {
p.Init(Host.Instance, "");
Collectors.PagesProviderCollector.AddProvider(p);
Log.LogEntry("Provider " + p.Information.Name + " loaded (Enabled)", EntryType.General, Log.SystemUsername);
}
else {
Collectors.DisabledPagesProviderCollector.AddProvider(p);
Log.LogEntry("Provider " + p.Information.Name + " loaded (Disabled)", EntryType.General, Log.SystemUsername);
}
CacheProvider c = new CacheProvider();
if(!ProviderLoader.IsDisabled(c.GetType().FullName)) {
c.Init(Host.Instance, "");
Collectors.CacheProviderCollector.AddProvider(c);
Log.LogEntry("Provider " + c.Information.Name + " loaded (Enabled)", EntryType.General, Log.SystemUsername);
}
else {
Collectors.DisabledCacheProviderCollector.AddProvider(c);
Log.LogEntry("Provider " + c.Information.Name + " loaded (Disabled)", EntryType.General, Log.SystemUsername);
}
// Load all other providers
ProviderLoader.FullLoad(false, true, true, true, true);
if(groupsCreated) {
// It is necessary to set default permissions for file management
UserGroup administratorsGroup = Users.FindUserGroup(Settings.AdministratorsGroup);
UserGroup anonymousGroup = Users.FindUserGroup(Settings.AnonymousGroup);
UserGroup usersGroup = Users.FindUserGroup(Settings.UsersGroup);
SetAdministratorsGroupDefaultPermissions(administratorsGroup);
SetUsersGroupDefaultPermissions(usersGroup);
SetAnonymousGroupDefaultPermissions(anonymousGroup);
}
// Init cache
//Cache.Instance = new Cache(Collectors.CacheProviderCollector.GetProvider(Settings.DefaultCacheProvider));
if(Collectors.CacheProviderCollector.GetProvider(Settings.DefaultCacheProvider) == null) {
Log.LogEntry("Default Cache Provider was not loaded, backing to integrated provider", EntryType.Error, Log.SystemUsername);
Settings.DefaultCacheProvider = typeof(CacheProvider).FullName;
Collectors.TryEnable(Settings.DefaultCacheProvider);
}
// Load Snippets and templates
//Snippets.Instance = new Snippets();
//Templates.Instance = new Templates();
// Load Pages
//Pages.Instance = new Pages();
// Load Nav. Paths
//NavigationPaths.Instance = new NavigationPaths();
// Create Collisions class
//Collisions.Instance = new Collisions();
// Create Redirections class
//Redirections.Instance = new Redirections();
// Create the Main Page, if needed
if(Pages.FindPage(Settings.DefaultPage) == null) CreateMainPage();
Log.LogEntry("ScrewTurn Wiki is ready", EntryType.General, Log.SystemUsername);
}
///
/// Verifies the existence of the default user groups and creates them if necessary.
///
/// true if the groups were created, false otherwise.
private static bool VerifyAndCreateDefaultGroups() {
UserGroup administratorsGroup = Users.FindUserGroup(Settings.AdministratorsGroup);
UserGroup anonymousGroup = Users.FindUserGroup(Settings.AnonymousGroup);
UserGroup usersGroup = Users.FindUserGroup(Settings.UsersGroup);
// Create default groups if they don't exist already, initializing permissions
bool aGroupWasCreated = false;
if(administratorsGroup == null) {
Users.AddUserGroup(Settings.AdministratorsGroup, "Built-in Administrators");
administratorsGroup = Users.FindUserGroup(Settings.AdministratorsGroup);
aGroupWasCreated = true;
}
if(usersGroup == null) {
Users.AddUserGroup(Settings.UsersGroup, "Built-in Users");
usersGroup = Users.FindUserGroup(Settings.UsersGroup);
aGroupWasCreated = true;
}
if(anonymousGroup == null) {
Users.AddUserGroup(Settings.AnonymousGroup, "Built-in Anonymous Users");
anonymousGroup = Users.FindUserGroup(Settings.AnonymousGroup);
aGroupWasCreated = true;
}
if(aGroupWasCreated) {
ImportPageDiscussionPermissions();
}
return aGroupWasCreated;
}
///
/// Creates the main page.
///
private static void CreateMainPage() {
Pages.CreatePage(null as string, Settings.DefaultPage);
Pages.ModifyPage(Pages.FindPage(Settings.DefaultPage), "Main Page", Log.SystemUsername,
DateTime.Now, "", Defaults.MainPageContent, null, null, SaveMode.Normal);
}
///
/// Performs shutdown operations, such as shutting-down Providers.
///
public static void Shutdown() {
foreach(IFormatterProviderV30 provider in Collectors.FormatterProviderCollector.AllProviders) {
provider.Shutdown();
}
foreach(IPagesStorageProviderV30 provider in Collectors.PagesProviderCollector.AllProviders) {
provider.Shutdown();
}
foreach(IUsersStorageProviderV30 provider in Collectors.UsersProviderCollector.AllProviders) {
provider.Shutdown();
}
foreach(IFilesStorageProviderV30 provider in Collectors.FilesProviderCollector.AllProviders) {
provider.Shutdown();
}
foreach(ICacheProviderV30 provider in Collectors.CacheProviderCollector.AllProviders) {
provider.Shutdown();
}
Settings.Provider.Shutdown();
}
///
/// Sets the default permissions for the administrators group, properly importing version 2.0 values.
///
/// The administrators group.
/// true if the operation succeeded, false otherwise.
public static bool SetAdministratorsGroupDefaultPermissions(UserGroup administrators) {
// Administrators can do any operation
return AuthWriter.SetPermissionForGlobals(AuthStatus.Grant, Actions.FullControl, administrators);
// Settings.ConfigVisibleToAdmins is not imported on purpose
}
///
/// Sets the default permissions for the users group, properly importing version 2.0 values.
///
/// The users group.
/// true if the operation succeeded, false otherwise.
public static bool SetUsersGroupDefaultPermissions(UserGroup users) {
bool done = true;
// Set namespace-related permissions
if(Settings.UsersCanCreateNewPages) {
done &= AuthWriter.SetPermissionForNamespace(AuthStatus.Grant, null, Actions.ForNamespaces.CreatePages, users);
}
else done &= AuthWriter.SetPermissionForNamespace(AuthStatus.Grant, null, Actions.ForNamespaces.ModifyPages, users);
done &= AuthWriter.SetPermissionForNamespace(AuthStatus.Grant, null, Actions.ForNamespaces.PostDiscussion, users);
if(Settings.UsersCanCreateNewCategories || Settings.UsersCanManagePageCategories) {
done &= AuthWriter.SetPermissionForNamespace(AuthStatus.Grant, null, Actions.ForNamespaces.ManageCategories, users);
}
done &= SetupFileManagementPermissions(users);
return done;
}
///
/// Sets the default permissions for the anonymous users group, properly importing version 2.0 values.
///
/// The anonymous users group.
/// true if the operation succeeded, false otherwise.
public static bool SetAnonymousGroupDefaultPermissions(UserGroup anonymous) {
bool done = true;
// Properly import Private/Public Mode wiki
if(Settings.PrivateAccess) {
// Nothing to do, because without any explicit grant, Anonymous users cannot do anything
}
else if(Settings.PublicAccess) {
// Public access, allow modification and propagate file management permissions if they were allowed for anonymous users
done &= AuthWriter.SetPermissionForNamespace(AuthStatus.Grant, null, Actions.ForNamespaces.ModifyPages, anonymous);
done &= AuthWriter.SetPermissionForNamespace(AuthStatus.Grant, null, Actions.ForNamespaces.DownloadAttachments, anonymous);
if(Settings.UsersCanCreateNewPages) {
done &= AuthWriter.SetPermissionForNamespace(AuthStatus.Grant, null, Actions.ForNamespaces.CreatePages, anonymous);
}
if(Settings.UsersCanCreateNewCategories || Settings.UsersCanManagePageCategories) {
done &= AuthWriter.SetPermissionForNamespace(AuthStatus.Grant, null, Actions.ForNamespaces.ManageCategories, anonymous);
}
if(Settings.FileManagementInPublicAccessAllowed) {
SetupFileManagementPermissions(anonymous);
}
}
else {
// Standard configuration, only allow read permissions
done &= AuthWriter.SetPermissionForNamespace(AuthStatus.Grant, null, Actions.ForNamespaces.ReadPages, anonymous);
done &= AuthWriter.SetPermissionForNamespace(AuthStatus.Grant, null, Actions.ForNamespaces.ReadDiscussion, anonymous);
done &= AuthWriter.SetPermissionForNamespace(AuthStatus.Grant, null, Actions.ForNamespaces.DownloadAttachments, anonymous);
foreach(IFilesStorageProviderV30 prov in Collectors.FilesProviderCollector.AllProviders) {
done &= AuthWriter.SetPermissionForDirectory(AuthStatus.Grant, prov, "/", Actions.ForDirectories.DownloadFiles, anonymous);
}
}
return done;
}
///
/// Sets file management permissions for the users or anonymous users group, importing version 2.0 values.
///
/// The group.
/// true if the operation succeeded, false otherwise.
private static bool SetupFileManagementPermissions(UserGroup group) {
bool done = true;
if(Settings.UsersCanViewFiles) {
done &= AuthWriter.SetPermissionForNamespace(AuthStatus.Grant, null, Actions.ForNamespaces.DownloadAttachments, group);
foreach(IFilesStorageProviderV30 prov in Collectors.FilesProviderCollector.AllProviders) {
done &= AuthWriter.SetPermissionForDirectory(AuthStatus.Grant, prov, "/", Actions.ForDirectories.DownloadFiles, group);
}
}
if(Settings.UsersCanUploadFiles) {
done &= AuthWriter.SetPermissionForNamespace(AuthStatus.Grant, null, Actions.ForNamespaces.UploadAttachments, group);
foreach(IFilesStorageProviderV30 prov in Collectors.FilesProviderCollector.AllProviders) {
done &= AuthWriter.SetPermissionForDirectory(AuthStatus.Grant, prov, "/", Actions.ForDirectories.UploadFiles, group);
done &= AuthWriter.SetPermissionForDirectory(AuthStatus.Grant, prov, "/", Actions.ForDirectories.CreateDirectories, group);
}
}
if(Settings.UsersCanDeleteFiles) {
done &= AuthWriter.SetPermissionForNamespace(AuthStatus.Grant, null, Actions.ForNamespaces.DeleteAttachments, group);
foreach(IFilesStorageProviderV30 prov in Collectors.FilesProviderCollector.AllProviders) {
done &= AuthWriter.SetPermissionForDirectory(AuthStatus.Grant, prov, "/", Actions.ForDirectories.DeleteFiles, group);
done &= AuthWriter.SetPermissionForDirectory(AuthStatus.Grant, prov, "/", Actions.ForDirectories.DeleteDirectories, group);
}
}
return done;
}
///
/// Imports version 2.0 page discussion settings and properly propagates them to user groups and single pages, when needed.
///
/// true if the operation succeeded, false otherwise.
private static bool ImportPageDiscussionPermissions() {
// Notes
// Who can read pages, can read discussions
// Who can modify pages, can post messages and read discussions
// Who can manage pages, can manage discussions and post messages
// Possible values: page|normal|locked|public
string value = Settings.DiscussionPermissions.ToLowerInvariant();
UserGroup usersGroup = Users.FindUserGroup(Settings.UsersGroup);
UserGroup anonymousGroup = Users.FindUserGroup(Settings.AnonymousGroup);
bool done = true;
switch(value) {
case "page":
// Nothing to do
break;
case "normal":
// Allow Users to post messages
done &= AuthWriter.SetPermissionForNamespace(AuthStatus.Grant, null, Actions.ForNamespaces.PostDiscussion, usersGroup);
break;
case "locked":
// Deny Users to post messages
done &= AuthWriter.SetPermissionForNamespace(AuthStatus.Deny, null, Actions.ForNamespaces.PostDiscussion, usersGroup);
break;
case "public":
// Allow Users and Anonymous Users to post messages
done &= AuthWriter.SetPermissionForNamespace(AuthStatus.Grant, null, Actions.ForNamespaces.PostDiscussion, usersGroup);
done &= AuthWriter.SetPermissionForNamespace(AuthStatus.Grant, null, Actions.ForNamespaces.PostDiscussion, anonymousGroup);
break;
}
return true;
}
}
}