mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2026-02-09 09:16:41 +08:00
Implemented tenant reset action.
This commit is contained in:
@@ -30,32 +30,34 @@ namespace Orchard.MultiTenancy.Controllers {
|
|||||||
public ILogger Logger { get; set; }
|
public ILogger Logger { get; set; }
|
||||||
|
|
||||||
public ActionResult Index() {
|
public ActionResult Index() {
|
||||||
return View(new TenantsIndexViewModel { TenantSettings = _tenantService.GetTenants() });
|
return View(new TenantsIndexViewModel {
|
||||||
|
TenantSettings = _tenantService.GetTenants()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActionResult Add() {
|
public ActionResult Add() {
|
||||||
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Cannot create tenant")))
|
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("You don't have permission to create tenants.")))
|
||||||
return new HttpUnauthorizedResult();
|
return new HttpUnauthorizedResult();
|
||||||
|
|
||||||
if ( !EnsureDefaultTenant() )
|
if (!IsExecutingInDefaultTenant())
|
||||||
return new HttpUnauthorizedResult();
|
return new HttpUnauthorizedResult();
|
||||||
|
|
||||||
var model = new TenantAddViewModel();
|
var viewModel = new TenantAddViewModel();
|
||||||
|
|
||||||
// fetches all available themes and modules
|
// Fetches all available themes and modules.
|
||||||
model.Themes = _tenantService.GetInstalledThemes().Select(x => new ThemeEntry { ThemeId = x.Id, ThemeName = x.Name }).ToList();
|
viewModel.Themes = _tenantService.GetInstalledThemes().Select(x => new ThemeEntry { ThemeId = x.Id, ThemeName = x.Name }).ToList();
|
||||||
model.Modules = _tenantService.GetInstalledModules().Select(x => new ModuleEntry { ModuleId = x.Id, ModuleName = x.Name }).ToList();
|
viewModel.Modules = _tenantService.GetInstalledModules().Select(x => new ModuleEntry { ModuleId = x.Id, ModuleName = x.Name }).ToList();
|
||||||
|
|
||||||
return View(model);
|
return View(viewModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost, ActionName("Add")]
|
[HttpPost, ActionName("Add")]
|
||||||
public ActionResult AddPOST(TenantAddViewModel viewModel) {
|
public ActionResult AddPost(TenantAddViewModel viewModel) {
|
||||||
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Couldn't create tenant"))) {
|
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("You don't have permission to create tenants."))) {
|
||||||
return new HttpUnauthorizedResult();
|
return new HttpUnauthorizedResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EnsureDefaultTenant()) {
|
if (!IsExecutingInDefaultTenant()) {
|
||||||
return new HttpUnauthorizedResult();
|
return new HttpUnauthorizedResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +65,7 @@ namespace Orchard.MultiTenancy.Controllers {
|
|||||||
ModelState.AddModelError("Name", T("A tenant with the same name already exists.", viewModel.Name).Text);
|
ModelState.AddModelError("Name", T("A tenant with the same name already exists.", viewModel.Name).Text);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure tenants name are valid
|
// Ensure tenants name are valid.
|
||||||
if (!String.IsNullOrEmpty(viewModel.Name) && !Regex.IsMatch(viewModel.Name, @"^\w+$")) {
|
if (!String.IsNullOrEmpty(viewModel.Name) && !Regex.IsMatch(viewModel.Name, @"^\w+$")) {
|
||||||
ModelState.AddModelError("Name", T("Invalid tenant name. Must contain characters only and no spaces.").Text);
|
ModelState.AddModelError("Name", T("Invalid tenant name. Must contain characters only and no spaces.").Text);
|
||||||
}
|
}
|
||||||
@@ -88,56 +90,58 @@ namespace Orchard.MultiTenancy.Controllers {
|
|||||||
|
|
||||||
return RedirectToAction("Index");
|
return RedirectToAction("Index");
|
||||||
}
|
}
|
||||||
catch (ArgumentException exception) {
|
catch (ArgumentException ex) {
|
||||||
Services.Notifier.Error(T("Creating Tenant failed: {0}", exception.Message));
|
Logger.Error(ex, "Error while creating tenant.");
|
||||||
|
Services.Notifier.Error(T("Tenant creation failed with error: {0}", ex.Message));
|
||||||
return View(viewModel);
|
return View(viewModel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActionResult Edit(string name) {
|
public ActionResult Edit(string name) {
|
||||||
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Cannot edit tenant")))
|
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("You don't have permission to edit tenants.")))
|
||||||
return new HttpUnauthorizedResult();
|
return new HttpUnauthorizedResult();
|
||||||
|
|
||||||
if ( !EnsureDefaultTenant() )
|
if (!IsExecutingInDefaultTenant())
|
||||||
return new HttpUnauthorizedResult();
|
return new HttpUnauthorizedResult();
|
||||||
|
|
||||||
var tenant = _tenantService.GetTenants().FirstOrDefault(ss => ss.Name == name);
|
var tenant = _tenantService.GetTenants().FirstOrDefault(ss => ss.Name == name);
|
||||||
|
|
||||||
if (tenant == null)
|
if (tenant == null)
|
||||||
return HttpNotFound();
|
return HttpNotFound();
|
||||||
|
|
||||||
return View(new TenantEditViewModel {
|
return View(new TenantEditViewModel {
|
||||||
Name = tenant.Name,
|
Name = tenant.Name,
|
||||||
RequestUrlHost = tenant.RequestUrlHost,
|
RequestUrlHost = tenant.RequestUrlHost,
|
||||||
RequestUrlPrefix = tenant.RequestUrlPrefix,
|
RequestUrlPrefix = tenant.RequestUrlPrefix,
|
||||||
DataProvider = tenant.DataProvider,
|
DataProvider = tenant.DataProvider,
|
||||||
DatabaseConnectionString = tenant.DataConnectionString,
|
DatabaseConnectionString = tenant.DataConnectionString,
|
||||||
DatabaseTablePrefix = tenant.DataTablePrefix,
|
DatabaseTablePrefix = tenant.DataTablePrefix,
|
||||||
State = tenant.State,
|
State = tenant.State,
|
||||||
Themes = _tenantService.GetInstalledThemes().Select(x => new ThemeEntry {
|
Themes = _tenantService.GetInstalledThemes().Select(x => new ThemeEntry {
|
||||||
ThemeId = x.Id,
|
ThemeId = x.Id,
|
||||||
ThemeName = x.Name,
|
ThemeName = x.Name,
|
||||||
Checked = tenant.Themes.Contains(x.Id)
|
Checked = tenant.Themes.Contains(x.Id)
|
||||||
}).ToList(),
|
}).ToList(),
|
||||||
Modules = _tenantService.GetInstalledModules().Select(x => new ModuleEntry {
|
Modules = _tenantService.GetInstalledModules().Select(x => new ModuleEntry {
|
||||||
ModuleId = x.Id,
|
ModuleId = x.Id,
|
||||||
ModuleName = x.Name,
|
ModuleName = x.Name,
|
||||||
Checked = tenant.Modules.Contains(x.Id)
|
Checked = tenant.Modules.Contains(x.Id)
|
||||||
}).ToList()
|
}).ToList()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost, ActionName("Edit")]
|
[HttpPost, ActionName("Edit")]
|
||||||
public ActionResult EditPost(TenantEditViewModel viewModel) {
|
public ActionResult EditPost(TenantEditViewModel viewModel) {
|
||||||
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Couldn't edit tenant")))
|
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("You don't have permission to edit tenants.")))
|
||||||
return new HttpUnauthorizedResult();
|
return new HttpUnauthorizedResult();
|
||||||
|
|
||||||
if ( !EnsureDefaultTenant() )
|
if (!IsExecutingInDefaultTenant())
|
||||||
return new HttpUnauthorizedResult();
|
return new HttpUnauthorizedResult();
|
||||||
|
|
||||||
var tenant = _tenantService.GetTenants().FirstOrDefault(ss => ss.Name == viewModel.Name);
|
var tenant = _tenantService.GetTenants().FirstOrDefault(ss => ss.Name == viewModel.Name);
|
||||||
if (tenant == null)
|
if (tenant == null)
|
||||||
return HttpNotFound();
|
return HttpNotFound();
|
||||||
|
else if (tenant.Name == _thisShellSettings.Name)
|
||||||
|
return new HttpUnauthorizedResult();
|
||||||
|
|
||||||
if (!ModelState.IsValid) {
|
if (!ModelState.IsValid) {
|
||||||
return View(viewModel);
|
return View(viewModel);
|
||||||
@@ -163,18 +167,19 @@ namespace Orchard.MultiTenancy.Controllers {
|
|||||||
|
|
||||||
return RedirectToAction("Index");
|
return RedirectToAction("Index");
|
||||||
}
|
}
|
||||||
catch (Exception exception) {
|
catch (Exception ex) {
|
||||||
Services.Notifier.Error(T("Failed to edit tenant: {0} ", exception.Message));
|
Logger.Error(ex, "Error while editing tenant.");
|
||||||
|
Services.Notifier.Error(T("Failed to edit tenant: {0} ", ex.Message));
|
||||||
return View(viewModel);
|
return View(viewModel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public ActionResult Disable(string name) {
|
public ActionResult Disable(string name) {
|
||||||
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Couldn't disable tenant")))
|
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("You don't have permission to disable tenants.")))
|
||||||
return new HttpUnauthorizedResult();
|
return new HttpUnauthorizedResult();
|
||||||
|
|
||||||
if ( !EnsureDefaultTenant() )
|
if (!IsExecutingInDefaultTenant())
|
||||||
return new HttpUnauthorizedResult();
|
return new HttpUnauthorizedResult();
|
||||||
|
|
||||||
var tenant = _tenantService.GetTenants().FirstOrDefault(ss => ss.Name == name);
|
var tenant = _tenantService.GetTenants().FirstOrDefault(ss => ss.Name == name);
|
||||||
@@ -189,10 +194,10 @@ namespace Orchard.MultiTenancy.Controllers {
|
|||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public ActionResult Enable(string name) {
|
public ActionResult Enable(string name) {
|
||||||
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Couldn't enable tenant")))
|
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("You don't have permission to enable tenants.")))
|
||||||
return new HttpUnauthorizedResult();
|
return new HttpUnauthorizedResult();
|
||||||
|
|
||||||
if ( !EnsureDefaultTenant() )
|
if (!IsExecutingInDefaultTenant())
|
||||||
return new HttpUnauthorizedResult();
|
return new HttpUnauthorizedResult();
|
||||||
|
|
||||||
var tenant = _tenantService.GetTenants().FirstOrDefault(ss => ss.Name == name);
|
var tenant = _tenantService.GetTenants().FirstOrDefault(ss => ss.Name == name);
|
||||||
@@ -205,7 +210,55 @@ namespace Orchard.MultiTenancy.Controllers {
|
|||||||
return RedirectToAction("Index");
|
return RedirectToAction("Index");
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool EnsureDefaultTenant() {
|
public ActionResult Reset(string name) {
|
||||||
|
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("You don't have permission to reset tenants.")))
|
||||||
|
return new HttpUnauthorizedResult();
|
||||||
|
|
||||||
|
if (!IsExecutingInDefaultTenant())
|
||||||
|
return new HttpUnauthorizedResult();
|
||||||
|
|
||||||
|
var tenant = _tenantService.GetTenants().FirstOrDefault(ss => ss.Name == name);
|
||||||
|
if (tenant == null)
|
||||||
|
return HttpNotFound();
|
||||||
|
|
||||||
|
return View(new TenantResetViewModel() {
|
||||||
|
Name = name,
|
||||||
|
DatabaseTableNames = _tenantService.GetTenantDatabaseTableNames(tenant)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost, ActionName("Reset")]
|
||||||
|
public ActionResult ResetPost(TenantResetViewModel viewModel) {
|
||||||
|
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("You don't have permission to reset tenants.")))
|
||||||
|
return new HttpUnauthorizedResult();
|
||||||
|
|
||||||
|
if (!IsExecutingInDefaultTenant())
|
||||||
|
return new HttpUnauthorizedResult();
|
||||||
|
|
||||||
|
var tenant = _tenantService.GetTenants().FirstOrDefault(ss => ss.Name == viewModel.Name);
|
||||||
|
if (tenant == null)
|
||||||
|
return HttpNotFound();
|
||||||
|
else if (tenant.Name == _thisShellSettings.Name)
|
||||||
|
return new HttpUnauthorizedResult();
|
||||||
|
|
||||||
|
if (!ModelState.IsValid) {
|
||||||
|
viewModel.DatabaseTableNames = _tenantService.GetTenantDatabaseTableNames(tenant);
|
||||||
|
return View(viewModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
_tenantService.ResetTenant(tenant, viewModel.DropDatabaseTables);
|
||||||
|
return RedirectToAction("Index");
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
Logger.Error(ex, "Error while resetting tenant.");
|
||||||
|
Services.Notifier.Error(T("Failed to reset tenant: {0} ", ex.Message));
|
||||||
|
viewModel.DatabaseTableNames = _tenantService.GetTenantDatabaseTableNames(tenant);
|
||||||
|
return View(viewModel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsExecutingInDefaultTenant() {
|
||||||
return _thisShellSettings.Name == ShellSettings.DefaultName;
|
return _thisShellSettings.Name == ShellSettings.DefaultName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
<IISExpressAnonymousAuthentication />
|
<IISExpressAnonymousAuthentication />
|
||||||
<IISExpressWindowsAuthentication />
|
<IISExpressWindowsAuthentication />
|
||||||
<IISExpressUseClassicPipelineMode />
|
<IISExpressUseClassicPipelineMode />
|
||||||
|
<UseGlobalApplicationHostFile />
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
@@ -48,6 +49,12 @@
|
|||||||
<Prefer32Bit>false</Prefer32Bit>
|
<Prefer32Bit>false</Prefer32Bit>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Reference Include="Autofac">
|
||||||
|
<HintPath>..\..\..\..\lib\autofac\Autofac.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="NHibernate">
|
||||||
|
<HintPath>..\..\..\..\lib\nhibernate\NHibernate.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.ComponentModel.DataAnnotations">
|
<Reference Include="System.ComponentModel.DataAnnotations">
|
||||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||||
@@ -73,9 +80,11 @@
|
|||||||
<Compile Include="Controllers\AdminController.cs" />
|
<Compile Include="Controllers\AdminController.cs" />
|
||||||
<Compile Include="Extensions\UrlHelperExtensions.cs" />
|
<Compile Include="Extensions\UrlHelperExtensions.cs" />
|
||||||
<Compile Include="Routes.cs" />
|
<Compile Include="Routes.cs" />
|
||||||
|
<Compile Include="Services\ITenantResetEventHandler.cs" />
|
||||||
<Compile Include="Services\ITenantService.cs" />
|
<Compile Include="Services\ITenantService.cs" />
|
||||||
<Compile Include="Services\TenantService.cs" />
|
<Compile Include="Services\TenantService.cs" />
|
||||||
<Compile Include="ViewModels\ModuleEntry.cs" />
|
<Compile Include="ViewModels\ModuleEntry.cs" />
|
||||||
|
<Compile Include="ViewModels\TenantResetViewModel.cs" />
|
||||||
<Compile Include="ViewModels\TenantEditViewModel.cs" />
|
<Compile Include="ViewModels\TenantEditViewModel.cs" />
|
||||||
<Compile Include="ViewModels\TenantAddViewModel.cs" />
|
<Compile Include="ViewModels\TenantAddViewModel.cs" />
|
||||||
<Compile Include="ViewModels\TenantsIndexViewModel.cs" />
|
<Compile Include="ViewModels\TenantsIndexViewModel.cs" />
|
||||||
@@ -123,6 +132,9 @@
|
|||||||
</SubType>
|
</SubType>
|
||||||
</Content>
|
</Content>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="Views\Admin\Reset.cshtml" />
|
||||||
|
</ItemGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
using Orchard.Events;
|
||||||
|
|
||||||
|
namespace Orchard.MultiTenancy.Services {
|
||||||
|
/// <summary>
|
||||||
|
/// An event handler interface that allows implementers to execute code when a tenant is being reset.
|
||||||
|
/// </summary>
|
||||||
|
public interface ITenantResetEventHandler : IEventHandler {
|
||||||
|
void Resetting();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,23 +5,35 @@ using Orchard.Environment.Extensions.Models;
|
|||||||
namespace Orchard.MultiTenancy.Services {
|
namespace Orchard.MultiTenancy.Services {
|
||||||
public interface ITenantService : IDependency {
|
public interface ITenantService : IDependency {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves all tenants' shell settings.
|
/// Retrieves ShellSettings objects for all tenants.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>All tenants' shell settings.</returns>
|
|
||||||
IEnumerable<ShellSettings> GetTenants();
|
IEnumerable<ShellSettings> GetTenants();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new tenant.
|
/// Creates a new tenant.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="settings">Shell settings of the tenant.</param>
|
/// <param name="settings">A ShellSettings object specifying the settings for the new tenant.</param>
|
||||||
void CreateTenant(ShellSettings settings);
|
void CreateTenant(ShellSettings settings);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates the shell settings of a tenant.
|
/// Updates the settings of a tenant.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="settings">Shell settings of the tenant.</param>
|
/// <param name="settings">The new ShellSettings object for the tenant.</param>
|
||||||
void UpdateTenant(ShellSettings settings);
|
void UpdateTenant(ShellSettings settings);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Resets a tenant to its uninitialized state.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tenantName">A ShellSettings object for the tenant to reset.</param>
|
||||||
|
/// <param name="dropDatabaseTables">A boolean indicated whether tenant database tables should be dropped also.</param>
|
||||||
|
void ResetTenant(ShellSettings settings, bool dropDatabaseTables);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a list of all known database tables in a tenant.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A ShellSettings object for the tenant.</returns>
|
||||||
|
IEnumerable<string> GetTenantDatabaseTableNames(ShellSettings settings);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a list of all installed themes.
|
/// Returns a list of all installed themes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,21 +1,36 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Orchard.Environment.Configuration;
|
using Orchard.Environment.Configuration;
|
||||||
using Orchard.Environment.Extensions.Models;
|
using Orchard.Environment.Extensions.Models;
|
||||||
using Orchard.Environment.Extensions;
|
using Orchard.Environment.Extensions;
|
||||||
|
using Orchard.Environment.ShellBuilders;
|
||||||
|
using Orchard.Data.Migration.Interpreters;
|
||||||
|
using Orchard.Data.Migration.Schema;
|
||||||
|
using Orchard.Data;
|
||||||
|
using Orchard.Logging;
|
||||||
|
|
||||||
namespace Orchard.MultiTenancy.Services {
|
namespace Orchard.MultiTenancy.Services {
|
||||||
public class TenantService : ITenantService {
|
public class TenantService : ITenantService {
|
||||||
private readonly IShellSettingsManager _shellSettingsManager;
|
private readonly IShellSettingsManager _shellSettingsManager;
|
||||||
private readonly IExtensionManager _extensionManager;
|
private readonly IExtensionManager _extensionManager;
|
||||||
|
private readonly IShellContextFactory _shellContextFactory;
|
||||||
|
private readonly IShellContainerFactory _shellContainerFactory;
|
||||||
|
|
||||||
public TenantService(
|
public TenantService(
|
||||||
IShellSettingsManager shellSettingsManager,
|
IShellSettingsManager shellSettingsManager,
|
||||||
IExtensionManager extensionManager) {
|
IExtensionManager extensionManager,
|
||||||
|
IShellContextFactory shellContextFactory,
|
||||||
|
IShellContainerFactory shellContainerFactory) {
|
||||||
_shellSettingsManager = shellSettingsManager;
|
_shellSettingsManager = shellSettingsManager;
|
||||||
_extensionManager = extensionManager;
|
_extensionManager = extensionManager;
|
||||||
|
_shellContextFactory = shellContextFactory;
|
||||||
|
_shellContainerFactory = shellContainerFactory;
|
||||||
|
Logger = NullLogger.Instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ILogger Logger { get; set; }
|
||||||
|
|
||||||
public IEnumerable<ShellSettings> GetTenants() {
|
public IEnumerable<ShellSettings> GetTenants() {
|
||||||
return _shellSettingsManager.LoadSettings();
|
return _shellSettingsManager.LoadSettings();
|
||||||
}
|
}
|
||||||
@@ -28,16 +43,32 @@ namespace Orchard.MultiTenancy.Services {
|
|||||||
_shellSettingsManager.SaveSettings(settings);
|
_shellSettingsManager.SaveSettings(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public void ResetTenant(ShellSettings settings, bool dropDatabaseTables) {
|
||||||
/// Loads only installed themes
|
if (settings.State != TenantState.Disabled)
|
||||||
/// </summary>
|
throw new InvalidOperationException(String.Format("Tenant state is '{0}'; must be '{1}' to perform reset action.", settings.State, TenantState.Disabled));
|
||||||
|
|
||||||
|
ExecuteOnTenantScope(settings, environment => {
|
||||||
|
ExecuteResetEventHandlers(environment);
|
||||||
|
if (dropDatabaseTables)
|
||||||
|
DropTenantDatabaseTables(environment);
|
||||||
|
});
|
||||||
|
|
||||||
|
settings.State = TenantState.Uninitialized;
|
||||||
|
_shellSettingsManager.SaveSettings(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<string> GetTenantDatabaseTableNames(ShellSettings settings) {
|
||||||
|
IEnumerable<string> result = null;
|
||||||
|
ExecuteOnTenantScope(settings, environment => {
|
||||||
|
result = GetTenantDatabaseTableNames(environment);
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public IEnumerable<ExtensionDescriptor> GetInstalledThemes() {
|
public IEnumerable<ExtensionDescriptor> GetInstalledThemes() {
|
||||||
return GetThemes(_extensionManager.AvailableExtensions());
|
return GetThemes(_extensionManager.AvailableExtensions());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Loads only installed modules
|
|
||||||
/// </summary>
|
|
||||||
public IEnumerable<ExtensionDescriptor> GetInstalledModules() {
|
public IEnumerable<ExtensionDescriptor> GetInstalledModules() {
|
||||||
return _extensionManager.AvailableExtensions().Where(descriptor => DefaultExtensionTypes.IsModule(descriptor.ExtensionType));
|
return _extensionManager.AvailableExtensions().Where(descriptor => DefaultExtensionTypes.IsModule(descriptor.ExtensionType));
|
||||||
}
|
}
|
||||||
@@ -58,5 +89,45 @@ namespace Orchard.MultiTenancy.Services {
|
|||||||
}
|
}
|
||||||
return themes;
|
return themes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ExecuteOnTenantScope(ShellSettings settings, Action<IWorkContextScope> action) {
|
||||||
|
var shellContext = _shellContextFactory.CreateShellContext(settings);
|
||||||
|
using (var container = _shellContainerFactory.CreateContainer(shellContext.Settings, shellContext.Blueprint)) {
|
||||||
|
using (var environment = container.CreateWorkContextScope()) {
|
||||||
|
action(environment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<string> GetTenantDatabaseTableNames(IWorkContextScope environment) {
|
||||||
|
var sessionFactoryHolder = environment.Resolve<ISessionFactoryHolder>();
|
||||||
|
var schemaBuilder = new SchemaBuilder(environment.Resolve<IDataMigrationInterpreter>());
|
||||||
|
var configuration = sessionFactoryHolder.GetConfiguration();
|
||||||
|
|
||||||
|
var result =
|
||||||
|
from mapping in configuration.ClassMappings
|
||||||
|
select mapping.Table.Name;
|
||||||
|
|
||||||
|
return result.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DropTenantDatabaseTables(IWorkContextScope environment) {
|
||||||
|
var sessionFactoryHolder = environment.Resolve<ISessionFactoryHolder>();
|
||||||
|
var schemaBuilder = new SchemaBuilder(environment.Resolve<IDataMigrationInterpreter>());
|
||||||
|
var configuration = sessionFactoryHolder.GetConfiguration();
|
||||||
|
foreach (var mapping in configuration.ClassMappings) {
|
||||||
|
try {
|
||||||
|
schemaBuilder.DropTable(mapping.Table.Name);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
Logger.Warning(ex, "Failed to drop table '{0}'.", mapping.Table.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ExecuteResetEventHandlers(IWorkContextScope environment) {
|
||||||
|
var handler = environment.Resolve<ITenantResetEventHandler>();
|
||||||
|
handler.Resetting();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Orchard.MultiTenancy.ViewModels {
|
||||||
|
public class TenantResetViewModel {
|
||||||
|
public TenantResetViewModel() {
|
||||||
|
DatabaseTableNames = Enumerable.Empty<string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string Name { get; set; }
|
||||||
|
public bool DropDatabaseTables { get; set; }
|
||||||
|
public IEnumerable<string> DatabaseTableNames { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
@model Orchard.Environment.Configuration.ShellSettings
|
@model Orchard.Environment.Configuration.ShellSettings
|
||||||
@using Orchard.MultiTenancy.Extensions;
|
@using Orchard.MultiTenancy.Extensions;
|
||||||
|
|
||||||
@using(Html.BeginFormAntiForgeryPost(Url.Action("enable", new {area = "Orchard.MultiTenancy"}), FormMethod.Post, new {@class = "inline link"})) {
|
@using(Html.BeginFormAntiForgeryPost(Url.Action("Enable", new {area = "Orchard.MultiTenancy"}), FormMethod.Post, new {@class = "inline link"})) {
|
||||||
@Html.HiddenFor(ss => ss.Name)
|
@Html.HiddenFor(ss => ss.Name)
|
||||||
<button type="submit">@T("Resume")</button>
|
<button type="submit">@T("Resume")</button>
|
||||||
}
|
} @T(" | ")
|
||||||
|
@Html.ActionLink(T("Reset").ToString(), "Reset", new { name = Model.Name, area = "Orchard.MultiTenancy" })
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
@model Orchard.Environment.Configuration.ShellSettings
|
@model Orchard.Environment.Configuration.ShellSettings
|
||||||
@using Orchard.MultiTenancy.Extensions;
|
@using Orchard.MultiTenancy.Extensions;
|
||||||
|
|
||||||
@using(Html.BeginFormAntiForgeryPost(Url.Action("disable", new {area = "Orchard.MultiTenancy"}), FormMethod.Post, new {@class = "inline link"})) {
|
@using(Html.BeginFormAntiForgeryPost(Url.Action("Disable", new {area = "Orchard.MultiTenancy"}), FormMethod.Post, new {@class = "inline link"})) {
|
||||||
@Html.HiddenFor(ss => ss.Name)
|
@Html.HiddenFor(ss => ss.Name)
|
||||||
<button type="submit">@T("Suspend")</button>
|
<button type="submit">@T("Suspend")</button>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,30 +7,31 @@
|
|||||||
Layout.Title = T("List of Site's Tenants").ToString();
|
Layout.Title = T("List of Site's Tenants").ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
<div class="manage">@Html.ActionLink(T("Add a Tenant").ToString(), "Add", new {area = "Orchard.MultiTenancy"}, new { @class = "button primaryAction" })</div>
|
<div class="manage">@Html.ActionLink(T("Add a Tenant").ToString(), "Add", new { area = "Orchard.MultiTenancy" }, new { @class = "button primaryAction" })</div>
|
||||||
<ul class="contentItems tenants">
|
<ul class="contentItems tenants">
|
||||||
@foreach (var tenant in Model.TenantSettings) {
|
@foreach (var tenant in Model.TenantSettings) {
|
||||||
<li class="tenant @tenant.State">
|
<li class="tenant @tenant.State">
|
||||||
<div class="summary">
|
<div class="summary">
|
||||||
<div class="properties">
|
<div class="properties">
|
||||||
<h3>@tenant.Name @if (!string.IsNullOrEmpty(tenant.RequestUrlHost)) {
|
<h3>
|
||||||
var tenantClone = new ShellSettings(tenant);
|
@tenant.Name @if (!string.IsNullOrEmpty(tenant.RequestUrlHost)) {
|
||||||
foreach (var t in tenant.RequestUrlHost.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) {
|
var tenantClone = new ShellSettings(tenant);
|
||||||
tenantClone.RequestUrlHost = t;
|
foreach (var t in tenant.RequestUrlHost.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) {
|
||||||
var url = Url.Tenant(tenantClone);
|
tenantClone.RequestUrlHost = t;
|
||||||
<span class="tenantHost"> - @Html.Link(url, url)</span>
|
var url = Url.Tenant(tenantClone);
|
||||||
}
|
<span class="tenantHost"> - @Html.Link(url, url)</span>
|
||||||
}
|
}
|
||||||
</h3>
|
}
|
||||||
</div>
|
</h3>
|
||||||
<div class="related">
|
</div>
|
||||||
@if (!string.Equals(tenant.Name, "default", StringComparison.OrdinalIgnoreCase)) { //todo: (heskew) base this off the view model so logic on what can be removed and have its state changed stays in the controller
|
<div class="related">
|
||||||
|
@if (!String.Equals(tenant.Name, "default", StringComparison.OrdinalIgnoreCase)) { //todo: (heskew) base this off the view model so logic on what can be removed and have its state changed stays in the controller
|
||||||
var t = tenant;
|
var t = tenant;
|
||||||
@Html.DisplayFor(m => t, string.Format("ActionsFor{0}", tenant.State.ToString()), "") @T(" | ")
|
@Html.DisplayFor(m => t, String.Format("ActionsFor{0}", tenant.State.ToString()), "") @T(" | ")
|
||||||
}
|
}
|
||||||
@Html.ActionLink(T("Edit").ToString(), "Edit", new {name = tenant.Name, area = "Orchard.MultiTenancy"})
|
@Html.ActionLink(T("Edit").ToString(), "Edit", new { name = tenant.Name, area = "Orchard.MultiTenancy" })
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</li>
|
||||||
</li>
|
|
||||||
}
|
}
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
@model Orchard.MultiTenancy.ViewModels.TenantResetViewModel
|
||||||
|
|
||||||
|
@{
|
||||||
|
Layout.Title = T("Reset Tenant").ToString();
|
||||||
|
|
||||||
|
Script.Require("jQuery");
|
||||||
|
Script.Include(Url.Content("~/Themes/TheAdmin/Scripts/admin.js")).AtFoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
@using (Html.BeginFormAntiForgeryPost()) {
|
||||||
|
@Html.ValidationSummary()
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<p>@T("This will reset the tenant <strong>{0}</strong> to its uninitialized state, allowing you to set it up again.", Model.Name)</p>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
@Html.CheckBoxFor(m => Model.DropDatabaseTables)
|
||||||
|
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.DropDatabaseTables)">@("Also delete tenant database tables:")</label>
|
||||||
|
<ul style="margin-left: 4em; margin-top: 1em; -webkit-column-width: 24em; -moz-column-width: 24em; column-width: 24em;">
|
||||||
|
@foreach (var tableName in Model.DatabaseTableNames) {
|
||||||
|
<li><span class="hint">@tableName</span></li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<button class="primaryAction" type="submit">@T("Reset")</button>
|
||||||
|
</fieldset>
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user