private void RunGovernancePolicy(SiteInformation site) { var plan = PolicyProvider.GetGovernancePlan(site); site.ComplianceState.LastCheckDate = GovernanceWorkflowHelper.GetCurrentBusinessTime(); site.ComplianceState.IsCompliant = true; var isSiteDeleted = false; try { foreach (var policy in plan.PolicyCollection) { if (isSiteDeleted) break; var isLifeCyclePolicy = policy is LifeCyclePolicy; var isCompliant = policy.IsCompliant(site); if (!isCompliant) site.ComplianceState.IsCompliant = false; if (!isCompliant || isLifeCyclePolicy) policy.Process(site); if (site.ComplianceState.DeleteDate == DateTime.MaxValue) { isSiteDeleted = true; break; } } } catch (Exception e) { Log.Error("sps", "Policy Checking Error {0}", e); } }
public virtual void Process(SiteInformation site) { var state = site.ComplianceState; var lockDate = GovernanceWorkflowHelper.GetCurrentBusinessTime() .AddDays(Convert.ToInt32(ConfigurationManager.AppSettings["DefaultFirstLockNotificationDays"])); if (state.LockedDate > lockDate || state.LockedDate == DateTime.MinValue) state.LockedDate = lockDate; }
public void Run(ClientContext tenantClientContext, SiteInformation site, bool suppressEmail) { if (site == null) throw new ArgumentNullException("site"); if (site.IsSkipGovernance) return; RunGovernancePolicy(site); var executor = new GovernanceWorkflowExecutor(tenantClientContext); executor.Enforce(site, suppressEmail); }
public override void Process(SiteInformation site) { var state = site.ComplianceState; var now = GovernanceWorkflowHelper.GetCurrentBusinessTime(); var expiredDate = GetExpiredDate(site); if (state.LockedDate > expiredDate || (DateTime.MinValue == state.LockedDate && !state.IsCompliant)) state.LockedDate = expiredDate; if (DateTime.MinValue == state.ExpireDate) state.ExpireDate = expiredDate; }
public override bool IsCompliant(SiteInformation site) { var expiredDate = GetExpiredDate(site); var now = GovernanceWorkflowHelper.GetCurrentBusinessTime(); if ((expiredDate - now).TotalDays <= GovernanceWorkflowHelper.FirstLockNotificationDays) { return false; } return true; }
/// <summary> /// Get site collection record by URL /// </summary> /// <param name="url">The site collection URL</param> /// <returns>Site information entity</returns> public SiteInformation GetSite(string url) { var tmp = new SiteInformation() { Url = url, }; var existed = Sites.FirstOrDefault(s => s.Name == tmp.Name && s.UrlDomain == tmp.UrlDomain && s.UrlPath == tmp.UrlPath); return(existed); }
public virtual int GetDefaultLifeTimeInMonth(SiteInformation site) { switch (site.AudienceScope) { case "Team": case "Project": return 6; case "Enterprise": case "Organization": return 12; } return 6; }
/// <summary> /// Insert a new site collection record in database if the URL is not existing, or otherwise update the existing site collection record with the property values of the argument /// </summary> /// <param name="site">The site information entity to be added or updated</param> public virtual void SaveSite(SiteInformation site) { var existed = GetSite(site.Url); if (existed != null) { Sites.Remove(existed); } ReplaceExistedUsers(site.Administrators); ReplaceExistedUsers(site.ExternalUsers); Sites.Add(site); SaveChanges(); }
public DateTime GetExpiredDate(SiteInformation site) { var ret = site.ComplianceState.ExpireDate; if (!ret.Equals(DateTime.MinValue)) return ret; var lease = GetDefaultLifeTimeInMonth(site); var now = GovernanceWorkflowHelper.GetCurrentBusinessTime(); ret = site.CreatedDate; while (true) { if (ret > now) break; ret = ret.AddMonths(lease); } return ret; }
public virtual void Enforce(SiteInformation site, bool supressEmail) { var state = site.ComplianceState; //If site is locked, then will not send any lock notification email, instead of sending delete email. if (site.ComplianceState.IsLocked && !site.ComplianceState.DeleteNotificationSent) SetNotifyDeleteState(site); if (GovernanceWorkflowHelper.NeedNotifyLock(state.LockedDate, state)) { ExtendOutdatedLockedDate(site); //Extend the LockedDate if it is earlier than current date } else if (GovernanceWorkflowHelper.NeedNotifyDelete(state.LockedDate, state)) { ExtendOutdatedDeleteDate(site); //Extend the DeleteDate if it is earlier than current date } if (state.IsCompliant) ChangeComplianceStateToDefault(site); var tenant = new Tenant(TenentClientContext); if (GovernanceWorkflowHelper.NeedNotifyLock(state.LockedDate, state)) { Notifiy(site, TenentClientContext, supressEmail); Log.Info(GetType().Name, "Notify Lock for site {0}", site.Url); } else if (GovernanceWorkflowHelper.NeedLock(state.LockedDate, state)) { tenant.SetSiteLockState(site.Url, SiteLockState.NoAccess, true); site.ComplianceState.IsLocked = true; Log.Info(GetType().Name, "Site {0} was locked", site.Url); } else if (GovernanceWorkflowHelper.NeedNotifyDelete(state.LockedDate, state)) { Notifiy(site, TenentClientContext, supressEmail); Log.Info(GetType().Name, "Notify Delete for site {0}", site.Url); } else if (GovernanceWorkflowHelper.NeedDelete(state.LockedDate)) { //set a flag to let us know that the site is deleted by Governance Job //site.DeletedBy = AutoSiteDeleteBy.GovernanceJob; tenant.DeleteSiteCollection(site.Url, true); //Set a value to indicate that the site was just deleted site.ComplianceState.DeleteDate = DateTime.MaxValue; Log.Info(GetType().Name, "Site {0} was deleted", site.Url); } TenentClientContext.ExecuteQueryRetry(); }
public void AddOrUpdateSiteTest() { string connetionString = ConfigurationManager.ConnectionStrings["default"].ConnectionString; var context = new GovernanceDbContext(connetionString); string url = "https://microsoftspoppe.sharepoint.com/teams/TestSite"; var existed = context.GetSite(url); int existedId = existed == null ? 0 : existed.Id; var site = new SiteInformation() { Administrators = new List<SiteUser>() { new SiteUser() { Email = "*****@*****.**", LoginName = "*****@*****.**", } }, AudienceScope = "Enterprise", BusinessImpact = "MBI", CreatedBy = "*****@*****.**", CreatedDate = DateTime.UtcNow, ComplianceState = new ComplianceState(), Description = "Test Save Site", Guid = Guid.NewGuid(), Lcid = 1099, LastBusinessImpact = "LBI", ModifiedBy = "*****@*****.**", ModifiedDate = DateTime.UtcNow, SharingStatus = 0, SiteMetadata = new SiteMetadata[] { new SiteMetadata() { MetadataKey = "TargetedAudience", MetadataValue = "PM", } }, StorageMaximumLevel = 500, StorageWarningLevel = 400, Template = "STS#0", TimeZoneId = 13, Title = "Test Save Site", Url = url, }; context.SaveSite(site); Assert.AreEqual(existedId+1, site.Id); }
//LockedDate will be displayed in first&second notification email //Extend LockedDate to no earlier than the email sent date if needed to avoid confusion private void ExtendOutdatedLockedDate(SiteInformation site) { var now = GovernanceWorkflowHelper.GetCurrentBusinessTime(); if (site.ComplianceState.LockedDate < now) { var lockDate = DateTime.MinValue; if (!site.ComplianceState.FirstLockNotificationSent) { lockDate = now.AddDays(GovernanceWorkflowHelper.FirstLockNotificationDays); } else if (!site.ComplianceState.SecondLockNotificationSent) { lockDate = now.AddDays(GovernanceWorkflowHelper.SecondLockNotificationDays); } if (lockDate == DateTime.MinValue) return; site.ComplianceState.LockedDate = lockDate; if (site.ComplianceState.ExpireDate < lockDate) site.ComplianceState.ExpireDate = lockDate; } }
public abstract IEnumerable<NoncomplianceType> GetNoncompliances(SiteInformation site);
//DeleteDate will be displayed in delete notification email //Extend DeleteDate to no earlier than the email sent date if needed to avoid confusion private void ExtendOutdatedDeleteDate(SiteInformation site) { var now = GovernanceWorkflowHelper.GetCurrentBusinessTime(); if (site.ComplianceState.LockedDate.AddDays(GovernanceWorkflowHelper.DeleteDays - 7) < now) { var lockDate = now.AddDays(-GovernanceWorkflowHelper.DeleteNotificationDays); site.ComplianceState.LockedDate = lockDate; if (site.ComplianceState.ExpireDate < lockDate) site.ComplianceState.ExpireDate = lockDate; } }
public void SetNotifyFlag(SiteInformation site) { if (site == null) throw new ArgumentNullException("site"); var now = GovernanceWorkflowHelper.GetCurrentBusinessTime(); if (!site.ComplianceState.FirstLockNotificationSent) { site.ComplianceState.FirstLockNotificationSent = true; site.ComplianceState.FirstLockNotificationSentDate = now; } else if (!site.ComplianceState.SecondLockNotificationSent) { site.ComplianceState.SecondLockNotificationSent = true; site.ComplianceState.SecondLockNotificationSentDate = now; } else if (!site.ComplianceState.DeleteNotificationSent) { site.ComplianceState.DeleteNotificationSent = true; site.ComplianceState.DeleteNotificationSentDate = now; } }
/// <summary> /// Update HasBroadAccess to 1 for both of the site collection and the current web record if any large security group permission assignment was found on the current web /// </summary> /// <param name="dbSiteRecord">The site collection record</param> /// <param name="dbWebRecord">The current web record</param> /// <param name="e">The timer job run event arguments</param> public override void Preprocess(SiteInformation dbSiteRecord, WebInformation dbWebRecord, TimerJobRunEventArgs e) { var tenant = new Tenant(e.TenantClientContext); var site = tenant.GetSiteByUrl(e.Url); var web = e.Url == dbWebRecord.SiteUrl ? site.RootWeb : site.OpenWeb(e.Url.Substring(dbWebRecord.Name.IndexOf('/') + 1)); // load additional properties could be used to optimize the permission checking process e.TenantClientContext.Load(web, w => w.HasUniqueRoleAssignments, w => w.Url, w => w.ServerRelativeUrl, w => w.ParentWeb.ServerRelativeUrl); var assignments = new List<PermissionAssignment>(); var entries = from groupLoginName in BroadAccessGroups.Keys select new PermissionAssignment { Url = e.Url, Group = groupLoginName, Permission = web.GetUserEffectivePermissions(groupLoginName) }; assignments.AddRange(entries); e.TenantClientContext.ExecuteQuery(); var incompliantAssignments = assignments.Where( p => p.Permission.Value != null && ( p.Permission.Value.Has(PermissionKind.ViewPages) || p.Permission.Value.Has(PermissionKind.ViewListItems))); dbWebRecord.HasBroadAccess = incompliantAssignments.Any(); if (dbWebRecord.HasBroadAccess) { dbWebRecord.BroadAccessGroups = string.Join(";", (from a in incompliantAssignments select a.Group).ToArray()); dbSiteRecord.HasBroadAccess = true; } }
public abstract bool IsCompliant(SiteInformation site);
protected void Notifiy(SiteInformation site, ClientContext clientContext, bool supressEmail) { if (site == null) throw new ArgumentNullException("site"); if (site.Administrators == null || site.Administrators.Count == 0) return; var mailSendTo = site.Administrators.Select(admin => admin.Email).ToList(); //Get Email Subject var subject = GetEmailSubject(site); if (string.IsNullOrEmpty(subject)) return; var body = GetEmailBody(site); //Sent Email if (mailSendTo.Count > 0 && !supressEmail) { MailUtility.SendEmail(clientContext, mailSendTo, null, subject, body); } SetNotifyFlag(site); }
/// <summary> /// All site information entities with a LastMembershipReviewDate equals to or later than the ReviewDateLimit are compliant /// </summary> /// <param name="site"></param> /// <returns></returns> public override bool IsCompliant(SiteInformation site) { return !site.IsExternalSharingEnabled || site.ComplianceState.LastMembershipReviewDate >= ReviewDateLimit; }
public override IEnumerable<NoncomplianceType> GetNoncompliances(SiteInformation site) { if (IsCompliant(site)) yield break; yield return NoncomplianceType.MembershipReviewDelay; }
private void SetNotifyDeleteState(SiteInformation site) { var now = GovernanceWorkflowHelper.GetCurrentBusinessTime(); if (site.ComplianceState.IsLocked && (!site.ComplianceState.FirstLockNotificationSent || !site.ComplianceState.SecondLockNotificationSent)) { if (!site.ComplianceState.FirstLockNotificationSent) { site.ComplianceState.FirstLockNotificationSent = true; site.ComplianceState.FirstLockNotificationSentDate = now; site.ComplianceState.SecondLockNotificationSent = true; site.ComplianceState.SecondLockNotificationSentDate = now; } else if (!site.ComplianceState.SecondLockNotificationSent) { site.ComplianceState.SecondLockNotificationSent = true; site.ComplianceState.SecondLockNotificationSentDate = now; } } ExtendOutdatedDeleteDate(site); }
public override IEnumerable<NoncomplianceType> GetNoncompliances(SiteInformation site) { if (IsCompliant(site)) yield break; yield return NoncomplianceType.NoAdditionalSiteAdmin; }
/// <summary> /// Get site collection record by URL /// </summary> /// <param name="url">The site collection URL</param> /// <returns>Site information entity</returns> public SiteInformation GetSite(string url) { var tmp = new SiteInformation() { Url = url, }; var existed = Sites.FirstOrDefault(s => s.Name == tmp.Name && s.UrlDomain == tmp.UrlDomain && s.UrlPath == tmp.UrlPath); return existed; }
/// <summary> /// All site information entity with HasBroadAccess property set to false is compliant ones /// </summary> /// <param name="site"></param> /// <returns></returns> public override bool IsCompliant(SiteInformation site) { return !site.HasBroadAccess; }
public virtual void Preprocess(SiteInformation siteCollection, WebInformation web, TimerJobRunEventArgs e) { }
public string GetEmailSubject(SiteInformation site) { if (site == null) throw new ArgumentNullException("site"); var subject = string.Empty; //If already sent delete email, then will not send any email. if (site.ComplianceState.DeleteNotificationSent) return subject; if (!site.ComplianceState.FirstLockNotificationSent) { subject = string.Format(SitePolicyResources.MailSubjectFirstLock, site.Url); } else if (!site.ComplianceState.SecondLockNotificationSent) { subject = string.Format(SitePolicyResources.MailSubjectSecondLock, site.Url); } else if (!site.ComplianceState.DeleteNotificationSent) { subject = string.Format(SitePolicyResources.MailSubjectDelete, site.Url); } return subject; }
public override IEnumerable<NoncomplianceType> GetNoncompliances(SiteInformation site) { if (IsCompliant(site)) yield break; yield return NoncomplianceType.Expiring; }
public string GetEmailBody(SiteInformation site) { if (site == null) throw new ArgumentNullException("site"); var content = string.Empty; string deadline; var specifiedZone = TimeZoneInfo.FindSystemTimeZoneById(GovernanceWorkflowHelper.TimeZoneId); var timezone = "{0} (" + specifiedZone.StandardName + ")"; //eg: (Pacific Standard Time). if (!site.ComplianceState.FirstLockNotificationSent) { deadline = string.Format(CultureInfo.CurrentCulture, timezone, site.ComplianceState.LockedDate.ToShortDateString()); content = string.Format(SitePolicyResources.MailBodyFirstLock, deadline); } else if (!site.ComplianceState.SecondLockNotificationSent) { deadline = string.Format(CultureInfo.CurrentCulture, timezone, site.ComplianceState.LockedDate.ToShortDateString()); content = string.Format(SitePolicyResources.MailBodySecondLock, deadline); } else if (!site.ComplianceState.DeleteNotificationSent) { deadline = string.Format(CultureInfo.CurrentCulture, timezone, site.ComplianceState.DeleteDate.ToShortDateString()); content = string.Format(SitePolicyResources.MailBodyDelete, deadline); } return content; }
/// <summary> /// Insert a new site collection record in database if the URL is not existing, or otherwise update the existing site collection record with the property values of the argument /// </summary> /// <param name="site">The site information entity to be added or updated</param> public virtual void SaveSite(SiteInformation site) { var existed = GetSite(site.Url); if (existed != null) Sites.Remove(existed); ReplaceExistedUsers(site.Administrators); ReplaceExistedUsers(site.ExternalUsers); Sites.Add(site); SaveChanges(); }
public virtual GovernancePlan GetGovernancePlan(SiteInformation site) { // Add GetGovernnance Plan Logic Here var plan = site.IsExternalSharingEnabled ? extSharedTeamsPlan : extSharingOffTeamsPlan; return plan; }
/// <summary> /// Site collection with 2 or more administrators will be marked as compliant /// </summary> /// <param name="site">Site information entity</param> /// <returns>Returns true if the site collection is compliant, otherwise returns false.</returns> public override bool IsCompliant(SiteInformation site) { return site.Administrators.Count() >= 2; }
public void ChangeComplianceStateToDefault(SiteInformation site) { if (site == null) throw new ArgumentNullException("site"); var status = site.ComplianceState; status.DeleteNotificationSentDate = DateTime.MinValue; status.DeleteNotificationSent = false; status.DeleteDate = DateTime.MinValue; status.LockedDate = DateTime.MinValue; status.FirstLockNotificationSentDate = DateTime.MinValue; status.FirstLockNotificationSent = false; status.IsLocked = false; status.IsReadonly = false; status.SecondLockNotificationSent = false; status.SecondLockNotificationSentDate = DateTime.MinValue; status.IsCompliant = true; }