Skip to content

Instantly share code, notes, and snippets.

@f1code
Created August 30, 2013 14:35
Show Gist options
  • Select an option

  • Save f1code/6390503 to your computer and use it in GitHub Desktop.

Select an option

Save f1code/6390503 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Text;
using Sage.Platform.Application;
using Sage.Platform.Application.UI;
using Sage.Platform.Security;
using Sage.SalesLogix.Web;
using Sage.SalesLogix.Security;
using System.Reflection;
using Sage.Entity.Interfaces;
using System.Security;
using Sage.Platform.ComponentModel;
using log4net;
using Sage.SalesLogix.Client.GroupBuilder;
using System.Xml;
using SSSWorld.Common;
using System.Diagnostics;
namespace SSSWorld.Slx75.Web.Security
{
/// <summary>
/// Decorate groups retrieved on the Customer Portal to apply the user's security.
/// To use this module you actually need to load it via the CustomerPortalGroupSecurityModuleLoader.
/// It does not need to be registered in the application's modules.
///
/// In the properties for the module, add an app setting named "PortalSecurityCondition_TABLE"
/// containing the condition to add (replace table with name of table, eg
/// PortalSecurityCondition_RMA)
/// :CUSACCID and :CUSCONID will be replaced with the customer's account and contact id.
/// For example, use A1.ACCOUNTID=:CUSACCID on ticket.
/// Joined table can be used only if they already exist in the group, and the proper alias (A1, A2 etc) must be used.
/// </summary>
/// <see cref="CustomerPortalGroupSecurityModuleLoader"/>
public class CustomerPortalGroupSecurityModule : IModule, IModuleConfiguration
{
private static readonly ILog LOG = LogManager.GetLogger(typeof(CustomerPortalGroupSecurityModule));
#region Service Dependencies
private WebPortalUserService _userService;
private IGroupContextService _groupContextService;
[ServiceDependency(Type = typeof(IUserService))]
public WebPortalUserService UserService
{
get { return _userService; }
set { _userService = value; }
}
[ServiceDependency(Type = typeof(IGroupContextService))]
public IGroupContextService GroupContextService
{
get { return _groupContextService; }
set { _groupContextService = value; }
}
#endregion
#region IModule Members
/// <summary>
/// When the module loads, it will pull the current group's XML, and adjust it if needed.
/// </summary>
public void Load()
{
GroupContext ctx = GroupContextService.GetGroupContext();
/*
ModuleConfiguration config = (ModuleConfiguration)_parentWorkItem.Modules.Get(typeof(CustomerPortalGroupSecurityModule));
if (config == null)
{
throw new Slx72Exception("Missing configuration for module CustomerPortalGroupSecurity");
}
*/
if (ctx == null || ctx.CurrentGroupInfo == null)
{
LOG.Debug("NULL group context");
}
else
{
Debug.Assert(ctx != null, "ctx != null");
Debug.Assert(ctx.CurrentGroupInfo != null, "ctx.CurrentGroupInfo != null");
Debug.Assert(ctx.CurrentGroupInfo.CurrentGroup != null, "ctx.CurrentGroupInfo.CurrentGroup != null");
GroupInfo groupInfo = ctx.CurrentGroupInfo.CurrentGroup.GroupInformation;
AddGroupSecurity(groupInfo);
}
}
public WorkItem ModuleWorkItem
{
get { return null; }
}
#endregion
#region IModuleConfiguration Members
public void Configure(XmlElement xmlConfig)
{
LOG.Debug(xmlConfig.OuterXml);
throw new Exception("Testing, testing.");
}
#endregion
/// <summary>
/// If the group's XML has not yet been decorated, add the parameter to restrict it by the user's account.
/// This can also be called externally to decorate an arbitrary GroupInfo object.
/// </summary>
/// <param name="groupInfo"></param>
public void AddGroupSecurity(GroupInfo groupInfo)
{
String xml = groupInfo.GroupXML;
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xml);
if (!WasGroupDecorated(xmlDoc))
{
PortalUser user = this.UserService.GetPortalUser();
String condition = GetGroupCondition(user);
if(condition != null)
AddGroupWhere(xmlDoc, condition);
SetGroupParameterValue(xmlDoc, "CUSACCID", (String)user.Contact.Account.Id);
SetGroupParameterValue(xmlDoc, "CUSCONID", (String)user.Contact.Id);
SetGroupDecorated(xmlDoc);
groupInfo.GroupXML = xmlDoc.OuterXml;
LOG.Debug("Group XML: " + xmlDoc.OuterXml);
groupInfo.GroupXML = xmlDoc.OuterXml;
}
}
/// <summary>
/// Retrieve condition template from the configuration
/// </summary>
/// <returns></returns>
protected virtual String GetGroupCondition(PortalUser user)
{
String c = MyConfiguration.Instance.GetAppSetting("PortalSecurityCondition_" + _groupContextService.GetGroupContext().CurrentTable);
if (c == null)
return null;
return "(" + c + ")";
}
/// <summary>
/// Set the value of the specified parameter in the XML.
/// If the parameter does not already exist under the parameters node, it will be created.
/// </summary>
/// <param name="xmlDoc"></param>
/// <param name="paramName"></param>
/// <param name="paramValue"></param>
private void SetGroupParameterValue(XmlDocument xmlDoc, string paramName, string paramValue)
{
XmlElement groupNode = (XmlElement)xmlDoc.SelectSingleNode("SLXGroup");
if (groupNode == null)
throw new InvalidOperationException("SLXGroup node not found in xml");
XmlElement paramsNode = (XmlElement) groupNode.SelectSingleNode("parameters");
XmlElement paramNode = null;
if (paramsNode == null)
{
XmlElement selectNode = (XmlElement)groupNode.SelectSingleNode("selectsql");
if (selectNode == null)
throw new InvalidOperationException("selectsql node not found in xml");
paramsNode = xmlDoc.CreateElement("parameters");
groupNode.InsertBefore(paramsNode, selectNode);
}
else
{
paramNode = (XmlElement)paramsNode.SelectSingleNode("parameter[name/text()='" + paramName + "']/value");
}
if (paramNode != null)
{
XmlCDataSection data = (XmlCDataSection)paramNode.FirstChild;
data.Data = paramValue;
}
else
{
paramNode = xmlDoc.CreateElement("parameter");
paramNode.InnerXml = "<name><![CDATA[" + paramName + "]]></name><datatype>string</datatype><value><![CDATA[" +
paramValue + "]]></value>";
paramsNode.AppendChild(paramNode);
}
}
/// <summary>
/// Add a condition to the wheresql node in the group XML.
/// Note: this does not add the condition to the conditions section (which is used to edit the group)
/// </summary>
/// <param name="xmlDoc">Root of group xml</param>
/// <param name="condition">condition to add</param>
private void AddGroupWhere(XmlDocument xmlDoc, String condition)
{
XmlElement whereNode = (XmlElement)xmlDoc.SelectSingleNode("SLXGroup/wheresql");
if (whereNode == null)
{
// add wheresql after selectsql
XmlElement selectNode = (XmlElement)xmlDoc.SelectSingleNode("SLXGroup/selectsql");
if (selectNode == null)
throw new SlxGobiException("Group error - Can't locate selectsql node in group");
whereNode = xmlDoc.CreateElement("wheresql");
XmlCDataSection whereData = xmlDoc.CreateCDataSection(condition);
whereNode.AppendChild(whereData);
xmlDoc.InsertAfter(whereNode, selectNode);
}
else
{
if (whereNode.ChildNodes.Count == 0)
whereNode.AppendChild(xmlDoc.CreateCDataSection(""));
else if (whereNode.FirstChild.NodeType != XmlNodeType.CDATA)
throw new SlxGobiException("Group error - First child to a wheresql node should be CDATA");
XmlCDataSection whereData = (XmlCDataSection)whereNode.FirstChild;
if(!whereData.Data.Contains(condition))
whereData.Data = AddSqlCondition(whereData.Data, condition);
}
}
/// <summary>
/// Add a condition to the given SQL and return the modified string.
/// </summary>
/// <param name="sql"></param>
/// <param name="condition"></param>
/// <returns></returns>
String AddSqlCondition(String sql, String condition)
{
if (sql != "")
sql = "(" + sql + ") AND ";
return sql + condition;
}
/// <summary>
/// Check whether the group was marked decorated for security.
/// </summary>
/// <param name="xml"></param>
/// <returns></returns>
private bool WasGroupDecorated(XmlDocument xmlDoc){
return xmlDoc.DocumentElement.HasAttribute("decorated");
}
/// <summary>
/// Mark group as decorated for security.
/// </summary>
/// <param name="xml"></param>
private void SetGroupDecorated(XmlDocument xmlDoc){
XmlElement groupNode = xmlDoc.DocumentElement;
XmlAttribute decAttr = xmlDoc.CreateAttribute("decorated");
decAttr.Value = "true";
groupNode.Attributes.Append(decAttr);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment