Navigation and service panel


Content

User generated content in a security hardened environment

By Kevin Brechb├╝hl on 16. July 2015, No comments

Martina Welander talked about different methods to store user generated content at the Sitecore Usergroup Conference (SUGCON) 2015. Some of them depend on the environment and on the security harderning you have applied. In our projects, we usually configure the environments to be as secure as possible. In this blog post I want to give you an example how you can store user generated content in a second web database.

The environments of our customers are usually hardened, which means we don't have access to the master database from the delivery servers. When we want to store user generated content (such as blog comments or poll results) we have these two statements to consider:

  • All content is stored in the master database. We never ever save something directly into the web database.
  • User generated content is usually generated from the delivery system.

So this is a problem. Remember, we don't have access to the master database from the delivery system, huh? One of the solutions would be to install a second web database. This new database has the same security configurations as the web database, so we have access to it from the authoring AND delivery servers.

Configure the new database

First of all we need to install and configure the new database. We take a copy of an empty web database, attach it to our SQL Server and configure it in our App_Config\ConnectionStrings.config. Copy the line of the web database and name the connection name ugc (for user generated content).

Then we need to tell Sitecore that there is a new database available. For this, we need to copy the web.config node of the web database configuration /configuration/databases/database[@id='web'] and give it the id ugc. The other configuration you can change as well, if you like.

The last thing would be to configure a new index for the ugc database. This depends on your Sitecore version and on your needs. Basically you can also copy the index configuration from the web database. As this is not absolutely necessary, I will skip this in this blog post.

Adding a new publishing target

The ugc database is currently empty. As you know every item in Sitecore is based on a data template, so also the items we will add in the user generated content database will be based on a data template. We will add the data templates in the master database and publish them to the ugc database, exactly as we do for the web database.

To allow this, we simply need to add the new database as a new publishing target. In the Content Editor, navigate to the item /sitecore/system/Publishing targets on your master database and add a new publishing target. The field Target Database must contain the id of your database configuration (ugc).

Now you can publish all your items to the new database the same way as you publish to the web database.

Restrict publishing for content

Later on our delivery systems, we will store content in the new database. So we must not publish any content from the master database into the ugc database. There are several ways to restrict this via configuration (permissions, remove publishing target, etc.) but I like to be really sure that it's not possible. That's via code :) There is a PublishItem pipeline available, where we can intercept the publish of each item if needed. So we can create a simple processor for this pipeline which aborts the pipeline for all items under /sitecore/content and /sitecore/media library:

public class DoNotPublishContent : PublishItemProcessor
{
  public override void Process(PublishItemContext context)
  {
    Assert.ArgumentNotNull(context, "context");

    // ignore all databases expect the user generated content
    if (context.PublishOptions.TargetDatabase.Name != "ugc") return;

    // get the item
    var item = context.PublishHelper.GetSourceItem(context.ItemId);
    if (item == null) return;

    // abort pipeline for content items
    var path = item.Paths.FullPath.ToLowerInvariant();
    if (path.StartsWith("/sitecore/content") || path.StartsWith("/sitecore/media library"))
    {
      context.AbortPipeline();
    }
  }
}

And configure the pipeline processor:

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <pipelines>
      <publishItem>
        <processor
          patch:before="processor[@type='Sitecore.Publishing.Pipelines.PublishItem.PerformAction, Sitecore.Kernel']"
          type="Pipelines.PublishItem.DoNotPublishContent, MyWebsite" />
      </publishItem>
    </pipelines>
  </sitecore>
</configuration>

Now any user with publishing permission may publish to the ugc database and won't override some content, even with a full publish. Yay!

Access the database

The last thing would be to store and read content from this database. You can use the DatabaseSwitcher to switch the database and then handle everything as you would do for the master or web database.

using (new DatabaseSwitcher("ugc"))
{
  var myItem = Sitecore.Context.Database.GetItem("/sitecore/content/mycomment");
}

For more information about switchers, see this blog post.

Hope that helps you while storing user generated content the next time. Do you have any additional scenarios or approaches for this? Please feel free to add a comment to this blog post or get in touch on Twitter via @aquasonic

No comments

Add your comment

Your email address will not be published. Required fields are marked *

*