using System; using System.Collections.Generic; using System.Configuration; using System.IO; using System.Linq; using System.Threading; using System.Web; using System.Web.Script.Serialization; using System.Web.Security; using CamlexNET; using Microsoft.SharePoint; using Microsoft.SharePoint.Utilities; using Taloyhtio.CustomFBADataSource.CodeFiles; namespace Taloyhtio.CustomFBADataSource { public class sitecolls : IHttpHandler { private const string QUERY_STRING_KEY_USER_NAME = "UserName"; private const string QUERY_STRING_KEY_OP = "op"; private const string QUERY_STRING_KEY_OP_NEW = "new"; private const string QUERY_STRING_KEY_OP_OLD = "old"; public void ProcessRequest(HttpContext context) { try { var web = SPContext.Current.Web; if (web.CurrentUser == null || !web.CurrentUser.IsSiteAdmin) { throw new Exception("Current user is not site admin"); } string userName = context.Request.QueryString[QUERY_STRING_KEY_USER_NAME]; if (string.IsNullOrEmpty(userName)) { throw new Exception("User name is empty"); } userName = HttpUtility.UrlDecode(userName); string op = context.Request.QueryString[QUERY_STRING_KEY_OP]; if (string.IsNullOrEmpty(op)) { throw new Exception("Operation is empty"); } op = op.ToLower(); if (op != QUERY_STRING_KEY_OP_NEW && op != QUERY_STRING_KEY_OP_OLD) { throw new Exception("Operation is not supported"); } var siteColls = new List(); if (op == QUERY_STRING_KEY_OP_NEW) { // currently new algorithm can be used only for Taloytio if (this.isTaloyhtio()) { siteColls = this.getSiteCollectionsUsingNewMethod(userName); } } else if (op == QUERY_STRING_KEY_OP_OLD) { siteColls = this.getSiteCollectionsUsingOldMethod(userName); } this.sendResponse(context, siteColls, false, string.Empty); } catch (ThreadAbortException) { throw; } catch (Exception x) { this.sendError(context, x.Message); } } private List getSiteCollectionsUsingNewMethod(string userName) { try { var result = new List(); // run code under elevated priveleges in order to connect to db using account of application pool. In this case we need // to grant permissions to db only to single account, not to all users under which this code will be executed SPSecurity.RunWithElevatedPrivileges( () => { string url = string.Empty; using (var rootSite = new SPSite(SPContext.Current.Site.WebApplication.Sites[0].ID, SPContext.Current.Site.Zone)) { url = rootSite.Url; } if (string.IsNullOrEmpty(userName)) { return; } string connStr = this.getConnectionString(); if (string.IsNullOrEmpty(connStr)) { return; } var r = new CredentialsRepository(connStr); var userId = r.GetUserId(userName); if (userId == Guid.Empty) { return; } var condos = r.GetUserCondos(userId); if (condos.IsNullOrEmpty()) { return; } result = condos.Select(c => SPUrlUtility.CombineUrl(url, c.PmcRelativeUrl)).Distinct().ToList(); }); return result; } catch (Exception x) { this.log("Error occured in new method (user name '{0}'): {1}\n{2}", userName, x.Message, x.StackTrace); return new List(); } } private string getConnectionString() { string connStringName = this.isTaloyhtio() ? Constants.FBA_CONNECTION_STRING_TALOYHTIO : Constants.FBA_CONNECTION_STRING_TALLIER; if (ConfigurationManager.ConnectionStrings == null || ConfigurationManager.ConnectionStrings[connStringName] == null) { return string.Empty; } return ConfigurationManager.ConnectionStrings[connStringName].ConnectionString; } private bool isTaloyhtio() { string url = SPContext.Current.Site.Url.ToLower(); return url.Contains("taloyhtio"); } private List getSiteCollectionsUsingOldMethod(string userName) { var siteColls = new List(); try { SPSecurity.RunWithElevatedPrivileges( () => { string url = string.Empty; using (var rootSite = new SPSite(SPContext.Current.Site.WebApplication.Sites[0].ID, SPContext.Current.Site.Zone)) { url = rootSite.Url; } using (var elevatedSite = new SPSite(SPContext.Current.Site.ID, SPContext.Current.Site.Zone)) { var settings = Utils.GetFBAIisSettings(elevatedSite); if (settings == null) { this.log("FBA IIS settings can't be retrieved"); return; } var membershipProvider = Membership.Providers[settings.FormsClaimsAuthenticationProvider.MembershipProvider]; string prefixOld = membershipProvider.Name.ToLower() + ":"; string prefixClaims = "i:0#.f|" + membershipProvider.Name.ToLower() + "|"; var sites = elevatedSite.WebApplication.Sites; foreach (SPSite site in sites) { if (this.userBelongsToSite(prefixClaims, prefixOld, userName, site)) { siteColls.Add(SPUrlUtility.CombineUrl(url, site.ServerRelativeUrl)); } } } }); return siteColls; } catch (Exception x) { this.log("Error occured in old method (user name '{0}'): {1}\n{2}", userName, x.Message, x.StackTrace); return new List(); } } private void sendError(HttpContext context, string error) { this.sendResponse(context, new List(), true, error); } private void sendResponse(HttpContext context, List siteColls, bool isError, string error) { var response = context.Response; response.Clear(); var s = new JavaScriptSerializer(); string result = s.Serialize(new { SiteColls = siteColls, IsError = isError, ErrorMessage = error }); response.ContentType = "application/json"; response.Write(result); response.Flush(); response.End(); } private bool userBelongsToSite(string prefixClaims, string prefixOld, string userName, SPSite site) { if (string.IsNullOrEmpty(userName) || site == null) { return false; } var query = new SPQuery(); query.Query = Camlex.Query().Where(x => ((string)x["Name"] == prefixClaims + userName || (string)x["Name"] == prefixOld + userName) && (string)x["ContentType"] == "Person").ToString(); //query.ViewFields = Camlex.Query().ViewFields(x => new[] { x["Name"] }); var itemsCount = site.RootWeb.SiteUserInfoList.GetItems(query).Count; return (itemsCount > 0); } public bool IsReusable { get { return true; } } private void log(string msg, params object[] args) { try { msg = string.Format(msg, args); msg = string.Format("{0} (thread id: {1})\t{2}\n", DateTime.Now.ToString("yyyy.MM.dd HH:mm:ss"), Thread.CurrentThread.ManagedThreadId, msg); File.AppendAllText(string.Format("c://temp/_fbauserssearch_{0}.txt", isTaloyhtio() ? "taloyhtio" : "tallier"), msg); } catch { } } } }