Integrating YetAnotherForum with SharePoint

Hi

Recently i was involved in creating forum for SharePoint 2010.

Our goals were:

  • Using existing OSS forum application, in our case we’ve chosen YetAnotherForum ver. 1.9.4 (YAF for short)
  • Installation & configuration from SharePoint (WSP)

Below is brief description of solution

1)Copying forum files.
First of all our solution copy YAF files into SharePoint layouts directory structure during installation.
Note: There is no need to create separate IIS Web Site or even Application under current SharePoint Site for hosting YAF.

Some modifications need to be done in  config file for this to work, below are some of them

  • Move provider’s declarations (membership,roleManager and profile) from web.config in {hive}\layouts\yaf to   C:\inetpub\wwwroot\wss\VirtualDirectories\{Port}
  • Set  parameters YAF.FileRoot & YAF.AppRoot to  ~/_layouts/yaf

2) For solution to be truly integrated with YAF we need  mechanism to enable auto registerstration of SharePoint users in YAF (through standard YAF membership provider)

Prerequisites:

Windows authentication is used.

<authentication mode=”Windows” />
<identity impersonate=”true” />

To enable SharePoint users to be created automatically in YAF lets create YAF module

Below is full source code for module

[YafModule(“Microsoft Sharepoint To YAF Users Synchronization Module”, “vgrem”, 1)]
public class SPS2YAFUsersSyncModule : SimpleBaseModule
{
#region Constructors and Destructors
/// <summary>
/// Initializes a new instance of the <see cref=”SPS2YAFUsersSyncModule”/> class.
/// </summary>
public SPS2YAFUsersSyncModule()
{
}
#endregion
#region Public Methods
/// <summary>
/// The init forum.
/// </summary>
public override void InitForum()
{
this.PageContext.PagePreLoad += new EventHandler<EventArgs>(this.PageContext_PagePreLoad);
}
#endregion
#region Methods
/// <summary>
/// The page context_ page pre load.
/// </summary>
/// <param name=”sender”>
/// The sender.
/// </param>
/// <param name=”e”>
/// The e.
/// </param>
private void PageContext_PagePreLoad(object sender, EventArgs e)
{
Page curPage = this.PageContext.CurrentForumPage.Page;
if (
(curPage.User.Identity.AuthenticationType == “NTLM”)
|| (curPage.User.Identity.AuthenticationType == “Negotiate”)
// || ( Context.User.Identity.AuthenticationType == “Windows” )
)
{
if (CurrentYAFUserName != curPage.User.Identity.Name)
{
ProcessYAFMembershipLogin(curPage.User);
CurrentYAFUserName = curPage.User.Identity.Name;
}
}
}
/// <summary>
///
/// </summary>
/// <param name=”p”></param>
private void ProcessYAFMembershipLogin(IPrincipal p)
{
string email = p.Identity.Name + “@company.ru”;
string userName = p.Identity.Name;
int boardID = YafContext.Current.PageBoardID;
MembershipCreateStatus status;
string question = “Company”;
string answer = “Company”;
bool approved = true;
MembershipUser user;
//if(UserMembershipHelper.GetUser(false) != null)
if (!UserMembershipHelper.UserExists(userName, email))
{
// create a new user and generate a password.
int retry = 0;
do
{
string newPassword = Membership.GeneratePassword(7 + retry, 1 + retry);
user = YafContext.Current.CurrentMembership.CreateUser(
userName, newPassword, email, question, answer, approved, null, out status);
}
while (status == MembershipCreateStatus.InvalidPassword && ++retry < 10);
if (status == MembershipCreateStatus.Success)
{
// setup inital roles (if any) for this user
RoleMembershipHelper.SetupUserRoles(boardID, userName);
// create the user in the YAF DB as well as sync roles…
int? userID = RoleMembershipHelper.CreateForumUser(user, boardID);
// create profile
YafUserProfile userProfile = YafUserProfile.GetProfile(userName);
// setup their inital profile information
userProfile.Location = string.Empty;
userProfile.Homepage = string.Empty;
userProfile.Save();
YafBuildLink.Redirect(ForumPages.forum);  //Force to reload page for new user
}
}
}
#endregion
#region Properties
private string CurrentYAFUserName
{
get
{
if (HttpContext.Current.Session[“yafUserName”] != null)
return (string)HttpContext.Current.Session[“yafUserName”];
return string.Empty;
}
set
{
HttpContext.Current.Session[“yafUserName”] = value;
}
}
#endregion
}
You may create separate assembly for this module, but you must meet  some requirements for YAF engine to load your module:
  • your assembly name need start with YAF and  SPS2YAFUsersSyncModule
  • class need to be located in YAF.Modules namespace.

Now you should be able to use YAF from SharePoint

That’s all for now.
In next post we’ll take a look at some ways to improve our solution such as
  • implement Forum scopes between SharePoint sites (isolation forums for different sites)
  • create Site Definitions for forum
  • web part for using in Site page