Piranha CMS - Control hosted database content only? - piranha-cms

I have just started using Piranha CMS with my existing MVC4 website. I have a database hosted in Azure and ideally I want Piranha to control just this i.e I don't want it to alter the pages etc.
Is this possible? I have set my databases connection string in the web.config on the Piranha key and have set passiveMode to true
So the reiterate I want Piranha to just update the data in the database, if this is possible how do I go about doing it?

Yes!
If you set passivemode to true the entire routing for pages & posts will be disabled. The basic functionality for getting uploaded media files from the CMS will still be active.
You will then have to manually get the CMS data from you controllers in you actions, for example:
public class HomeController : Controller
{
public ActionResult Index() {
//
// Let's say you have a page with the permalink 'start'
//
var cmsData = Piranha.PageModel.GetByPermalink("start");
return View(cmsData);
}
}
Regards

Related

How to Specify the "Authorize" at the Area level with Razor Pages?

I am testing the WebApp authentication using simple cookie. The app has 2 areas: Public & Internal (see Area structure at the end of this post). Users are required to login when accessing all pages under the "Internal" area.
PROGRAM DESCRIPTION
The App is implemented with .NET 6 with Razor pages (without MVC). In the program.cs file, I tried to specify the "authorize" at the "Area" level for "Internal" area (see code segment here). The HTML 404.15 error occurred when testing the app (see HTML error in attached image below).
It looks like that "AuthorizeAreaFolder" works fine with any folder name inside of Internal area. Is there a way to setup "Authorize" at an Area level?
CONFIGURE AUTHORIZE
builder.Services.AddRazorPages(options =>
{
options.Conventions.AuthorizeAreaFolder("Internal","/");
});
HTML ERROR
WEBAPP AREAS
Make sure that your signing in page is accessible to anonymous users. An easy way to accomplish this is to add the AllowAnonymous attribute to the PageModel class of the relevant page e.g (assuming the signing in page is called Signin):
[AllowAnonymous]
public class SigninModel : PageModel

Customize Identity Server 4 Login UI for Hosted Blazor WebAssembly

I have a solution based on the Visual Studio template that is successfully using IdentityServer4.
What think I understand is:
The IS4 integration implements endpoints at /authentication/{action}, e.g. authentication/login
IS4 routes that request to host/Identity/Account/Login.cshtml. I have scaffolded identity so I can see that .cshtml file in my project.
The code-behind Login.cshtml.cs takes care of speaking with SignInManager, etc.
In the client project the "LoginDisplay.razor" component redirects to /authentication/login when I click the login button. I presume that this is where step 1 above is invoked, which redirects to the location in step 2.
Fine. Now, I want to customise the whole login UI.
From instructions at: https://learn.microsoft.com/en-us/aspnet/core/blazor/security/webassembly/additional-scenarios?view=aspnetcore-5.0 I can see that:
I can configure authentication paths to be anything I want. For example:
builder.Services.AddApiAuthorization(options => {
options.AuthenticationPaths.LogInPath = "security/login";
})
So, I have created a razor component to handle security/login:
#page "/security/{action}"
#using Microsoft.AspNetCore.Components.WebAssembly.Authentication
<RemoteAuthenticatorView Action="#Action">
<LoggingIn>
This is the new login page
</LoggingIn>
</RemoteAuthenticatorView>
#code{
[Parameter] public string Action { get; set; }
}
My expectation was that after clicking "Login", I would be routed to the above and presented with a page that just said:
"This is the new login page"
and thought that from there, I would:
Customise the UI within the <LoggingIn> fragment.
Make a call to an API that would then replicate the logic in the scaffolded login.cshtml file that actually logs the user in.
That line of code from the login.cshtml.cs file looks like this:
var result = await _signInManager.PasswordSignInAsync(
Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false);
However, it seems that the razor component I created for /security/login is simply a 'transient' message that appears before being routed to the scaffolded login.csthml file.
So, to me, it seems that I am unable to actually change the physical page used to collect the user's credentials. I am only able to change the transient screen that appears before the originally scaffolded login page is shown.
Does this mean that if I want a customised UI for logging in I need to directly edit the scaffolded page as opposed to creating a whole new UI in the WebAssembly project that calls an APIController that I create to take care of using SignInManager?
It would actually be a lot less work to do that than to take the approach of creating a Client-side UI that calls an API that I create, etc. so, with hindsight, editing the scaffolded cshtml file is probably the best way to go. But am still confused as to what value is really being brought by being able to configure options.AuthenticationPaths.LogInPath.

Hook up Auth0AccountController in Umbraco 7

Has anyone successfully integrated Auth0 with Umbraco 7 for member (front-end public users, not CMS back-end users) authentication?
I've successfully integrated with owin startup and dealing with signin-auth0 response. However I'm stuck on hooking up the Auth0AccountController to work with Umbraco (I'm getting a 404). Any suggestions?
I've tried adding ~/Auth0Account to the "umbracoReservedPaths" appSetting, but I just get a slightly different looking 404 (not controlled by Umbraco by looks of it).
I've also tried mapping the route in Startup.cs using
RouteTable.Routes.MapRoute(
"Auth0Account",
"Auth0Account/{action}",
new
{
controller = "Auth0Account"
}
);
but that results in a "No route in the route table matches the supplied values" error.
Any ideas?
Mapping the Auth0Account route in Startup.cs was correct:
RouteTable.Routes.MapRoute(
"Auth0Account",
"Auth0Account/{action}",
new
{
controller = "Auth0Account"
}
);
Turns out my problem was with the default redirect RedirectToLocal method in the Auth0AccountController controller. It was doing a
return RedirectToAction("Index", "Home");
which I didn't have a controller hooked up for. I replaced this with an Umbraco compatible redirect instead.
Also, instead of Auth0AccountController inheriting from Controller it might be useful to inherit from Umbraco.Web.Mvc.SurfaceController or Umbraco.Web.Mvc.RenderMvcController to expose useful Umbraco methods to the code.

Piranha showing my current webpages in the CMS

I have a project I have attached Piranha CMS too. That bit worked fine.... However the pages I have already created and the template are not displaying in the CMS edit.
Steps I have done.
imported Piranha from guget.
Altered webconfig to passive.
removed piranha connection section.
changed connection to forms.
Alter connection string to match sql-server DB.
altered the global.config
built DB in sql server
Built project setup admin and the DB structure built followed.
Like I said it has built ok... But only the standard template. I'm guessing I've ether missed a step or there are steps to go. Can you advise me were to go next?
The webpage site currently just a home page.. The remaining pages are not completed. But if I don't crack this point there is little point continuing.
I think you have to add the pages into Piranha through the manager interface, then use the Permalink as the argument to fetch the Piranha managed content from Piranha. I don't think Piranha will parse your view/controller/routes and automatically import them into the site definition.
I use Piranha in my views like this;
#Html.ActionLink((string)Model.CMSData.Properties.WebSiteTitle, "Index", "Home", new { area = "" }, new { #class = "navbar-brand" })
I embed the CMS data into my model based on the examples in the Getting Started section;
public object CMSData = Piranha.Models.PageModel.GetByPermalink("my-permalink") ;
This enables me to weave in CMS content to my Model and then use it inside my View.

injecting changing view engine list

I'm trying to develop a multi-tenancy project wherein each client can have their own specific view engines.
Specifically I'd like to compile the views to a DLL (using RazorEngine) and have an individual RazorViewEngine for each client but also provide a fallback to the standard RazorViewEngine if no matching views are found, just as the MVC framework does if you have multiple view engines specified.
I have found I can inject view engines using autofac in the Global.asax of my MVC 4 project using:
ViewEngines.Engines.Clear();
var builder = new ContainerBuilder();
builder.RegisterType<WebFormViewEngine>().As<IViewEngine>();
Now I also want to provide tenant specific overrides as mentioned above which I can do with the following code:
var mtc = new MultitenantContainer(tenantIdStrategy, builder.Build());
mtc.ConfigureTenant("Client1", b => b.RegisterType<RazorViewEngine>().As<IViewEngine>());
DependencyResolver.SetResolver(new AutofacDependencyResolver(mtc));
In this example code I just wanted to see if I could set the WebFormsViewEngine as a fallback and then enable the RazorViewEngine for a specific tenant.
Upon loading and browsing to a non-tenant url, mvc will resolve just the WebFormsViewEngine as expected (through calling the DependencyResolver and in turn Autofac), this works as expected however when I then visit a url that would also include the RazorViewEngine no views are found, even though a valid razor view exists.
Conversely if I stop IISExpress or do something to generate an app pool recycle and visit a tenantable url first both view engines are registered.
From what I can tell MVC caches the list of view engines retrieved after the first call to the MultiServiceResolver.
internal IViewEngine[] CombinedItems
{
get
{
IViewEngine[] combinedItems = _combinedItems;
if (combinedItems == null)
{
combinedItems = MultiServiceResolver.GetCombined<IViewEngine>(Items, _dependencyResolver);
_combinedItems = combinedItems;
}
return combinedItems;
}
}
Is there a way to override this caching or another better way to achieve what I'm trying to get here?