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; } } }