How can I make N2CMS show edit page in admin interface by default? - n2cms

When I am in the N2 management / admin interface, if I click on a node in the tree, by default it shows the output of that page. I can show the edit screen for that node by right clicking the node and clicking 'Edit'. Can I get it to show the edit screen for that node by just clicking the node? Is there some setting I can change in web.config?

So the comment that I left on the question above doesn't really answer the question (it works only for the root node). However, pretty much everything in N2 is pluggable, so you can use the dependency injection framework to replace the code that generates URLs in the edit interface with your own code as follows:
using N2.Configuration;
using N2.Edit;
using N2.Engine;
using N2.Web;
namespace MyWebsite
{
[Service(typeof(IEditUrlManager), Replaces = typeof(EditUrlManager))]
public class MyEditUrlManager : EditUrlManager
{
public MyEditUrlManager(IUrlParser parser, EditSection config)
: base(parser, config)
{
}
public override string GetPreviewUrl(N2.ContentItem selectedItem)
{
return GetEditExistingItemUrl(selectedItem);
}
}
}

Related

Switching a DbContext to using Ninject Dependency injection per user session

I have an application that is used in 2 different sites. Each site has it's own Database.
There are 2 DbContexts, 1 for each site. When the user opens my application there is a splash page where they choose their site. After choosing the site the kernel is rebound to use the DbContext for the selected site.
private void RebindDbContext(string site)
{
switch (site)
{
case "Site1":
_kernel.Rebind<DbContext>().To<DbContext1>().InRequestScope();
break;
case "Site2":
_kernel.Rebind<DbContext>().To<DbContext2>().InRequestScope();
break;
}
}
Now for the Bob & Mary explanation:
This works fine when Bob selects site 1. But when Mary selects a site 2. The dbContext for Bob is re-bound to site 2. What I want is for Bob and Mary to be able to use the application at the same time without affecting each other.
I have tried using TransientScope, ThreadScope and InRequest Scope but none of these have worked.
The application is being run on an IIS server
Thanks for any help
Bindings are intended to be done once per application, not dependent upon state. In this instance, you have a couple options:
1) A Ninject.Activation.IProvider
public class DbContextProvider : Ninject.Activation.IProvider
{
public Type Type
{
get { return typeof(DbContext); }
}
public object Create(IContext context)
{
var siteProvider = context.Kernel.Get<ISiteProvider>(); // use a provider to find which site is being used
switch (siteProvider.Current)
{
case "Site1":
return new DbContext1(); // or use a factory to create
case "Site2":
return new DbContext2();
}
}
}
then:
Bind<DbContext>().ToProvider<DbContextProvider>().InRequestScope();
2) Conditional Binding
The When() modifier has a bunch of overloads for different states, or you could create an extension method if you have one type you use a lot.
Bind<DbContext>().To<DbContext1>()
.When(request => request.ParentContext.Kernel.Get<ISiteProvider>().Current == "Site1")
.InRequestScope();
Bind<DbContext>().To<DbContext2>()
.When(request => request.ParentContext.Kernel.Get<ISiteProvider>().Current == "Site2")
.InRequestScope();
This is a good option if you only have a few conditions that this binding may be applied. If your logic gets ANY more complex than this, go for the provider. Also note that Conditional Bindings incur a performance penalty.
3) A ToMethod() Binding
For the simplest binding logic, you can have Ninject run some code each time the binding is resolved:
Bind<DbContext>().ToMethod(context =>
context.Kernel.Get<ISiteProvider>().GetSite());
Basically, which option you select depends on how much logic is involved in deciding which instance to activate. In each instance, you can either new() up an instance, or you have access to the IKernel in which you can resolve an instance:
context.Kernel.Get<DbContext2>();
here's some official documentation of the activation process:
https://github.com/ninject/Ninject/wiki/Providers%2C-Factory-Methods-and-the-Activation-Context

plugin for adding issues referring to manual rules into sonar

import org.sonar.api.component.ResourcePerspectives;
public class MySensor extends Sensor {
private final ResourcePerspectives perspectives;
public MySensor(ResourcePerspectives p) {
this.perspectives = p;
}
public void analyse(Project project, SensorContext context) {
Resource myResource; // to be set
Issuable issuable = perspectives.as(Issuable.class, myResource);
if (issuable != null) {
// can be used
Issue issue = issuable.newIssueBuilder()
//repository : pmd, key : AvoidArrayLoops
.setRuleKey(RuleKey.of("pmd", "AvoidArrayLoops"))
.setLine(10)
.build();
//works
issuable.addIssue(issue);
Issue issue2 = issuable.newIssueBuilder()
//repository : manual, key : performance
.setRuleKey(RuleKey.of("manual", "performance"))
.setLine(10)
.build();
// doesn't work
issuable.addIssue(issue2);
}
}
}
When I try to add the issue "issue" referring to the pmd rule AvoidArrayLoops it works. More generally, when I try to add issues referring to pmd or checkstyle rules it works.
However, when I try to add issues referring to manual rules such as the issue "issue2", it doesn't work. I have created manually the rule "performance" so the rule performance exists in the list of manual rules in sonar.
I would like to know if it is impossible to add issues referring to manual rules or if I am not using the right parameters for the method RuleKey.of.
Thanks
One reason why your custom issue is not shown in Sonar may be that you haven't enabled it the rule.
Select settings - Quality Profiles, click on your quality profile, select the tab "Coding rules", set Activation to "any", click search and check whether your rule is being displayed here.
If so, check the checkbox next to it and select the severity. Now, the rule violations will be displayed in Sonar.

In N2CMS, can you disable the prompt to 'Update links leading to' the item you just edited?

I am using N2CMS to manage the content of my site without using the page routing from N2. Hence when I edit a piece of content, it's quite useless when N2 asks me: "Update links leading to..." "Add permanent redirect at previous URL?". Can I disable this behaviour?
Converting Page into Part is inherently bad idea. It may be temporary fix for the problem you have, but it will bounce back at you in a bad way.
Instead, you can do this
Turn LinkTracker off in web.config
linkTracker enabled="false" permanentRedirectEnabled="false"
Copy CommandFactory.cs from N2 Source into your solution, and rename it to MyCommandFactory.cs.
Add Service replacement attribute
[Service(typeof(ICommandFactory), Replaces = typeof(CommandFactory))]
In a constructor, change this line
updateReferences = new MyUpdateReferencesCommand();
Write your own empty Update reference command class
public class MyUpdateReferencesCommand : UpdateReferencesCommand
{
public override void Process(CommandContext state)
{
}
}
As far as I can see from the source code, N2 expects always to show you the "Update links leading to..." page if the ContentItem is a Page (i.e. [PageDefinition] attribute or .IsPage = true) and the address has been updated. The solution in our case was to make the 'page' in question into a 'part' using [PartDefinition].

authorization on wicket component using wicket auth-role

I am using wicket 1.4.9 and implemented spring + wicket auth-role and using #AuthorizeInstantiation based on roles on pages. I have multiple custom roles.
I have followed this link to implement the basics:
https://cwiki.apache.org/WICKET/spring-security-and-wicket-auth-roles.html
After that I have implemented my own UserDetailsService to have my own roles/users from database.
Now, How can I impose controls on roles with components eg, Links,Buttons ? like
link A can be accessed only by SUPER_USER, DR_MANAGER. (roles comes from database).
I have done like this and it seems to work, but is that the good way to do this? OrbitWebSession is of type AuthenticatedWebSession.
#Override
public boolean isVisible() {
if(OrbitWebSession.get().getRoles().hasRole("SUPER_USER")){
return true;
}
return false;
}
thanks.
Overriding isVisible all the time is a major pain. Take a look at MetaDataRoleAuthorizationStrategy instead. You call authorize(Component component, Action action, String roles) with Action RENDER, and the roles you want to allow. This way the component, whatever it is, is automatically hidden for other roles provided that the authorization strategy is registered in your webapplication. Basically it does the same thing as Holms answer, except you don't have to subclass anything.
You are in the right track, the only change I would do is:
#Override
public boolean isVisible() {
return super.isVisible() && OrbitWebSession.get().getRoles().hasRole("SUPER_USER");
}
That way you don't accidentally override its default visible behavior for example if the parent component is not visible.
Using the #AuthorizeAction annotation you can control wether the component is rendered or not based on roles. It's quite easy to use, but you have to subclass the component that you want to authorize.
#AuthorizeAction(action = Action.RENDER, roles = { "SUPER_USER", "DR_MANAGER" })
class UserAdminPageLink extends BookmarkablePageLink<String> {
//Implementation…
}
add(new UserAdminPageLink("UserAdminPageLink", UserAdminPage.class));
Check out Wicket Examples - Authorization for some working code.

MVC 2.0 - different view based on URL with shared controls

I have 2 master pages. One is intended to be shown in a normal standalone website. The other is to be used in external sites as an Iframe.
I want to be able to show the normal page at http://example.com/home/index and the iframed version at http://example.com/framed/home/index
I want to have controls that will postback to one controller so I don't have to duplicate logic, so they must be available in both the normal and iframed versions.
My problem is that when I try and use areas, I just can't get them to work right with the default url. Also, I have the added complication of structuremap. When I try and hit /area/controller/action, I get
The IControllerFactory
'MySite.Web.Code.IoC.StructureMapControllerFactory'
did not return a controller for the
name 'MyArea'.
Does anyone know how to make this kind of setup work? Really all I'm doing is trying to show one set of views if it has /Framed/controller/action and another set if it does not have /framed. I thought areas were the way to go, but maybe not.
All of our controllers implement the same base class, and we use the following override to do what you're describing:
protected override ViewResult View(string viewName, string masterName, object model)
{
if (masterName == null)
{
var options = PortalRequestManager.CurrentPortalRouteOptions;
masterName = options.MvcMasterPath;
}
return base.View(viewName, masterName, model);
}
All of our AreaRegistrations use the following method to register their areas:
public static void RegisterMvcAreaRoutes(AreaRegistrationContext context, string name, string url,
object defaults)
{
context.MapRoute(name + "Portal",
"P/Channel/" + url,
defaults);
context.MapRoute(name + "FramePortal",
"F/Channel/" + url,
defaults);
}
And then the PortalRequestManager that you saw in the first code block parses the URL to see if it uses "/P" or "/F" to determine which MvcMasterPath to use.
We use Ninject's controller factory, which has no problem with this setup, so I can't really speak to your problems with StructureMap.