From 65cdc289b9cd15ee61bb53ea75b7aaabbfa1e463 Mon Sep 17 00:00:00 2001 From: Yvan Duhamel Date: Thu, 29 Feb 2024 09:56:20 +0100 Subject: [PATCH 01/15] Update AssemblyInfo.cs --- Yvand.LDAPCPSE/Properties/AssemblyInfo.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Yvand.LDAPCPSE/Properties/AssemblyInfo.cs b/Yvand.LDAPCPSE/Properties/AssemblyInfo.cs index be1e2a0..fa75685 100644 --- a/Yvand.LDAPCPSE/Properties/AssemblyInfo.cs +++ b/Yvand.LDAPCPSE/Properties/AssemblyInfo.cs @@ -7,11 +7,11 @@ // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("LDAPCP")] -[assembly: AssemblyDescription("")] +[assembly: AssemblyDescription("A claims provider to connect SharePoint Subscription / 2019 / 2016 with Active Directory and LDAP directories in federated authentication")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("GitHub.com/Yvand - Yvan Duhamel")] +[assembly: AssemblyCompany("Yvan Duhamel - GitHub.com/Yvand")] [assembly: AssemblyProduct("LDAPCP")] -[assembly: AssemblyCopyright("Copyright © 2019, Yvan Duhamel, All rights reserved")] +[assembly: AssemblyCopyright("Copyright © 2024, Yvan Duhamel, All rights reserved")] [assembly: AssemblyTrademark("LDAPCP")] [assembly: AssemblyCulture("")] From bdf6846409692859a2736621486f36ee9980e6b1 Mon Sep 17 00:00:00 2001 From: Yvan Duhamel Date: Tue, 19 Mar 2024 17:58:36 +0100 Subject: [PATCH 02/15] Update GlobalSettings.ascx --- .../ADMIN/LDAPCPSE/GlobalSettings.ascx | 111 +++++++++--------- 1 file changed, 56 insertions(+), 55 deletions(-) diff --git a/Yvand.LDAPCPSE/TEMPLATE/ADMIN/LDAPCPSE/GlobalSettings.ascx b/Yvand.LDAPCPSE/TEMPLATE/ADMIN/LDAPCPSE/GlobalSettings.ascx index 6449b96..cbcadd5 100644 --- a/Yvand.LDAPCPSE/TEMPLATE/ADMIN/LDAPCPSE/GlobalSettings.ascx +++ b/Yvand.LDAPCPSE/TEMPLATE/ADMIN/LDAPCPSE/GlobalSettings.ascx @@ -249,17 +249,17 @@ - - + + - - + + - + - - + + - + - + - - + + From ce3ae0564075d76504a48de22c62f4f30520722f Mon Sep 17 00:00:00 2001 From: Yvan Duhamel Date: Mon, 15 Apr 2024 09:44:22 +0200 Subject: [PATCH 04/15] Fix error if group claim type does not exist in the trust (#207) * fix https://github.com/Yvand/LDAPCP/issues/203 * Update CHANGELOG.md * update test in GroupIdentifierEncodedValuePrefix * delete group claim type if None is selected --- CHANGELOG.md | 4 ++ .../ADMIN/LDAPCPSE/GlobalSettings.ascx.cs | 39 ++++++++++++------- .../Administration/LDAPCPSEUserControl.cs | 10 +++-- .../Configuration/ClaimTypeConfig.cs | 13 ++++--- 4 files changed, 44 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ef6d10..c137bbb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Change log for LDAPCP +## Unreleased + +* Fix the error when loading the global configuration page, if the group claim type set in the LDAPCP configuration does not exist in the trust. https://github.com/Yvand/LDAPCP/issues/203 + ## LDAPCP Second Edition v17.0.20240226.2 - Published in February 26, 2024 * Initial release of LDAPCP Second Edition, a complete rewrite of current project diff --git a/Yvand.LDAPCPSE/TEMPLATE/ADMIN/LDAPCPSE/GlobalSettings.ascx.cs b/Yvand.LDAPCPSE/TEMPLATE/ADMIN/LDAPCPSE/GlobalSettings.ascx.cs index 25c16b1..5c768e6 100644 --- a/Yvand.LDAPCPSE/TEMPLATE/ADMIN/LDAPCPSE/GlobalSettings.ascx.cs +++ b/Yvand.LDAPCPSE/TEMPLATE/ADMIN/LDAPCPSE/GlobalSettings.ascx.cs @@ -229,23 +229,34 @@ protected bool UpdateConfiguration(bool commitChanges) Settings.ClaimTypes.SetAdditionalLdapFilterForEntity(this.TxtUserIdAdditionalLdapFilter.Text, DirectoryObjectType.User); // Group identifier settings - ClaimTypeConfig groupIdConfig = Settings.ClaimTypes.GroupIdentifierConfig; - bool newGroupConfigObject = false; - if (groupIdConfig == null) + if (!String.Equals(this.DdlGroupClaimType.SelectedValue, "None", StringComparison.OrdinalIgnoreCase)) { - groupIdConfig = new ClaimTypeConfig { DirectoryObjectType = DirectoryObjectType.Group }; - newGroupConfigObject = true; + ClaimTypeConfig groupIdConfig = Settings.ClaimTypes.GroupIdentifierConfig; + bool newGroupConfigObject = false; + if (groupIdConfig == null) + { + groupIdConfig = new ClaimTypeConfig { DirectoryObjectType = DirectoryObjectType.Group }; + newGroupConfigObject = true; + } + groupIdConfig.ClaimType = this.DdlGroupClaimType.SelectedValue; + groupIdConfig.DirectoryObjectClass = this.TxtGroupLdapClass.Text; + groupIdConfig.DirectoryObjectAttribute = this.TxtGroupLdapAttribute.Text; + groupIdConfig.DirectoryObjectAttributeForDisplayText = this.TxtGroupDisplayTextAttribute.Text; + groupIdConfig.ClaimValueLeadingToken = this.TxtGroupLeadingToken.Text; + Settings.ClaimTypes.SetSearchAttributesForEntity(this.TxtGroupAdditionalLdapAttributes.Text, groupIdConfig.DirectoryObjectClass, DirectoryObjectType.Group); + Settings.ClaimTypes.SetAdditionalLdapFilterForEntity(this.TxtGroupAdditionalLdapFilter.Text, DirectoryObjectType.Group); + if (newGroupConfigObject) + { + Settings.ClaimTypes.Add(groupIdConfig); + } } - groupIdConfig.ClaimType = this.DdlGroupClaimType.SelectedValue; - groupIdConfig.DirectoryObjectClass = this.TxtGroupLdapClass.Text; - groupIdConfig.DirectoryObjectAttribute = this.TxtGroupLdapAttribute.Text; - groupIdConfig.DirectoryObjectAttributeForDisplayText = this.TxtGroupDisplayTextAttribute.Text; - groupIdConfig.ClaimValueLeadingToken = this.TxtGroupLeadingToken.Text; - Settings.ClaimTypes.SetSearchAttributesForEntity(this.TxtGroupAdditionalLdapAttributes.Text, groupIdConfig.DirectoryObjectClass, DirectoryObjectType.Group); - Settings.ClaimTypes.SetAdditionalLdapFilterForEntity(this.TxtGroupAdditionalLdapFilter.Text, DirectoryObjectType.Group); - if (newGroupConfigObject) + else { - Settings.ClaimTypes.Add(groupIdConfig); + ClaimTypeConfig groupIdConfig = Settings.ClaimTypes.GroupIdentifierConfig; + if (groupIdConfig != null) + { + Settings.ClaimTypes.Remove(groupIdConfig); + } } // Augmentation settings diff --git a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Administration/LDAPCPSEUserControl.cs b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Administration/LDAPCPSEUserControl.cs index 65c3b05..5df1147 100644 --- a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Administration/LDAPCPSEUserControl.cs +++ b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Administration/LDAPCPSEUserControl.cs @@ -3,6 +3,7 @@ using Microsoft.SharePoint.Administration.Claims; using Microsoft.SharePoint.Utilities; using System; +using System.Linq; using System.Security.Claims; using System.Web.UI; using Yvand.LdapClaimsProvider.Configuration; @@ -107,11 +108,14 @@ protected string GroupIdentifierEncodedValuePrefix { SPClaimProviderManager claimMgr = SPClaimProviderManager.Local; ClaimTypeConfig idConfig = Settings.ClaimTypes.GroupIdentifierConfig; - if (idConfig == null) + string accountPrefix = String.Empty; + // https://github.com/Yvand/LDAPCP/issues/203 group claim type may not exist in the trust + if (!String.IsNullOrWhiteSpace(idConfig?.ClaimType) && + SPTrust.ClaimTypeInformation.Count(x => String.Equals(x.MappedClaimType, idConfig.ClaimType, StringComparison.OrdinalIgnoreCase)) > 0) { - return String.Empty; + accountPrefix = claimMgr.EncodeClaim(new SPClaim(idConfig.ClaimType, String.Empty, ClaimValueTypes.String, SPOriginalIssuers.Format(SPOriginalIssuerType.TrustedProvider, SPTrust.Name))); } - return claimMgr.EncodeClaim(new SPClaim(idConfig.ClaimType, String.Empty, ClaimValueTypes.String, SPOriginalIssuers.Format(SPOriginalIssuerType.TrustedProvider, SPTrust.Name))); + return accountPrefix; } } diff --git a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/ClaimTypeConfig.cs b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/ClaimTypeConfig.cs index 2353e75..01f3ec2 100644 --- a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/ClaimTypeConfig.cs +++ b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/ClaimTypeConfig.cs @@ -745,7 +745,7 @@ public void SetSearchAttributesForEntity(string newSearchAttributesCsv, string l { Add(newSearchAttributeConfig); } - catch (InvalidOperationException ex) + catch (InvalidOperationException ex) { // A InvalidOperationException is thrown if the LDAP attribute already exists as metadata Logger.LogException(String.Empty, $"while trying to set the LDAP attribute {newAttribute} for entity type {entityType} as a search attribute", TraceCategory.Core, ex); @@ -770,11 +770,14 @@ public void SetSearchAttributesForEntity(string newSearchAttributesCsv, string l public void SetAdditionalLdapFilterForEntity(string newAdditionalLdapFilter, DirectoryObjectType entityType) { ClaimTypeConfig mainConfig = GetIdentifierConfiguration(entityType); - mainConfig.DirectoryObjectAdditionalFilter = newAdditionalLdapFilter; - IEnumerable additionalConfigurations = GetAdditionalConfigurationsForEntity(entityType); - foreach (ClaimTypeConfig additionalConfiguration in additionalConfigurations) + if (mainConfig != null) { - additionalConfiguration.DirectoryObjectAdditionalFilter = newAdditionalLdapFilter; + mainConfig.DirectoryObjectAdditionalFilter = newAdditionalLdapFilter; + IEnumerable additionalConfigurations = GetAdditionalConfigurationsForEntity(entityType); + foreach (ClaimTypeConfig additionalConfiguration in additionalConfigurations) + { + additionalConfiguration.DirectoryObjectAdditionalFilter = newAdditionalLdapFilter; + } } } } From 4e2896b03f32ca15bc1472ee98f2b9d7a8ccdc83 Mon Sep 17 00:00:00 2001 From: Yvan Duhamel Date: Mon, 15 Apr 2024 09:53:43 +0200 Subject: [PATCH 05/15] Ignore case when comparing claim types (#205) * ignore case when comparing claim types * Update CHANGELOG.md * Update CHANGELOG.md --- CHANGELOG.md | 3 ++- .../Configuration/LDAPProviderConfiguration.cs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c137bbb..334e73d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,12 @@ ## Unreleased +* Fix error when creating the configuration, due to case-sensitive test in the claim types - https://github.com/Yvand/LDAPCP/issues/204 * Fix the error when loading the global configuration page, if the group claim type set in the LDAPCP configuration does not exist in the trust. https://github.com/Yvand/LDAPCP/issues/203 ## LDAPCP Second Edition v17.0.20240226.2 - Published in February 26, 2024 -* Initial release of LDAPCP Second Edition, a complete rewrite of current project +* Ignore case when comparing claim types, to avoid errors when creating the configuration - https://github.com/Yvand/LDAPCP/pull/205 ## LDAPCP v16.0.20230824.1 enhancements & bug-fixes - Published in August 24, 2023 diff --git a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/LDAPProviderConfiguration.cs b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/LDAPProviderConfiguration.cs index 9c80646..3eaa8e0 100644 --- a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/LDAPProviderConfiguration.cs +++ b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/LDAPProviderConfiguration.cs @@ -141,7 +141,7 @@ public static ClaimTypeConfigCollection ReturnDefaultClaimTypesConfig(string cla //// Not adding those as additional attributes to avoid having too many LDAP attributes to search users in the LDAP filter - var nonIdentityClaimTypes = ClaimsProviderConstants.GetDefaultSettingsPerUserClaimType().Where(x => x.Key != spTrust.IdentityClaimTypeInformation.MappedClaimType); + var nonIdentityClaimTypes = ClaimsProviderConstants.GetDefaultSettingsPerUserClaimType().Where(x => !String.Equals(x.Key, spTrust.IdentityClaimTypeInformation.MappedClaimType, StringComparison.OrdinalIgnoreCase)); foreach (var nonIdentityClaimType in nonIdentityClaimTypes) { ctConfig = nonIdentityClaimType.Value; From 33451864dd5fe7a7697eb4ce34371867e18bcbfa Mon Sep 17 00:00:00 2001 From: Yvan Duhamel Date: Mon, 15 Apr 2024 10:20:31 +0200 Subject: [PATCH 06/15] add server-side member NoValueSelected to test "None" --- Yvand.LDAPCPSE/TEMPLATE/ADMIN/LDAPCPSE/GlobalSettings.ascx | 4 +--- .../TEMPLATE/ADMIN/LDAPCPSE/GlobalSettings.ascx.cs | 5 ++++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Yvand.LDAPCPSE/TEMPLATE/ADMIN/LDAPCPSE/GlobalSettings.ascx b/Yvand.LDAPCPSE/TEMPLATE/ADMIN/LDAPCPSE/GlobalSettings.ascx index ff42204..180d0df 100644 --- a/Yvand.LDAPCPSE/TEMPLATE/ADMIN/LDAPCPSE/GlobalSettings.ascx +++ b/Yvand.LDAPCPSE/TEMPLATE/ADMIN/LDAPCPSE/GlobalSettings.ascx @@ -453,9 +453,7 @@
  • - - - +
  • diff --git a/Yvand.LDAPCPSE/TEMPLATE/ADMIN/LDAPCPSE/GlobalSettings.ascx.cs b/Yvand.LDAPCPSE/TEMPLATE/ADMIN/LDAPCPSE/GlobalSettings.ascx.cs index 5c768e6..bb517c9 100644 --- a/Yvand.LDAPCPSE/TEMPLATE/ADMIN/LDAPCPSE/GlobalSettings.ascx.cs +++ b/Yvand.LDAPCPSE/TEMPLATE/ADMIN/LDAPCPSE/GlobalSettings.ascx.cs @@ -18,6 +18,7 @@ public partial class GlobalSettingsUserControl : LDAPCPSEUserControl public new string UserIdentifierEncodedValuePrefix = String.Empty; // This must be a member to be accessible from marup code, it cannot be a property public new string GroupIdentifierEncodedValuePrefix = String.Empty; // This must be a member to be accessible from marup code, it cannot be a property + readonly string NoValueSelected = "None"; readonly string TextConnectionSuccessful = "Connection successful."; readonly string TextSummaryPersistedObjectInformation = "Found configuration '{0}' v{1} (Persisted Object ID: '{2}')"; readonly string TextSharePointDomain = "Connect to SharePoint domain"; @@ -149,6 +150,8 @@ private void PopulateFields() this.TxtUserIdAdditionalLdapFilter.Text = Settings.ClaimTypes.UserIdentifierConfig.DirectoryObjectAdditionalFilter; // Group identifier settings + this.DdlGroupClaimType.Items.Add(NoValueSelected); + this.DdlGroupClaimType.Items[0].Selected = true; var possibleGroupClaimTypes = Utils.GetNonWellKnownUserClaimTypesFromTrust(base.ClaimsProviderName); foreach (string possibleGroupClaimType in possibleGroupClaimTypes) { @@ -229,7 +232,7 @@ protected bool UpdateConfiguration(bool commitChanges) Settings.ClaimTypes.SetAdditionalLdapFilterForEntity(this.TxtUserIdAdditionalLdapFilter.Text, DirectoryObjectType.User); // Group identifier settings - if (!String.Equals(this.DdlGroupClaimType.SelectedValue, "None", StringComparison.OrdinalIgnoreCase)) + if (!String.Equals(this.DdlGroupClaimType.SelectedValue, NoValueSelected, StringComparison.OrdinalIgnoreCase)) { ClaimTypeConfig groupIdConfig = Settings.ClaimTypes.GroupIdentifierConfig; bool newGroupConfigObject = false; From 14f973faf8d1ff33dbc7131b82e33c95c87e3815 Mon Sep 17 00:00:00 2001 From: Yvan Duhamel Date: Mon, 6 May 2024 10:21:16 +0200 Subject: [PATCH 07/15] Add property max search results count (#211) * initial work * work --- CHANGELOG.md | 3 ++- .../Configuration/ClaimsProviderConstants.cs | 3 ++- .../LDAPProviderConfiguration.cs | 25 +++++++++++++++++++ .../LdapEntityProvider.cs | 2 +- 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 334e73d..d04b811 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,8 @@ ## Unreleased * Fix error when creating the configuration, due to case-sensitive test in the claim types - https://github.com/Yvand/LDAPCP/issues/204 -* Fix the error when loading the global configuration page, if the group claim type set in the LDAPCP configuration does not exist in the trust. https://github.com/Yvand/LDAPCP/issues/203 +* Fix the error when loading the global configuration page, if the group claim type set in the LDAPCP configuration does not exist in the trust - https://github.com/Yvand/LDAPCP/issues/203 +* Add the property MaxSearchResultsCount, to override the SharePoint limit of the maximum number of objects that the LDAP server returns - https://github.com/Yvand/LDAPCP/issues/209 ## LDAPCP Second Edition v17.0.20240226.2 - Published in February 26, 2024 diff --git a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/ClaimsProviderConstants.cs b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/ClaimsProviderConstants.cs index 7eeb25b..37971f6 100644 --- a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/ClaimsProviderConstants.cs +++ b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/ClaimsProviderConstants.cs @@ -321,7 +321,8 @@ public OperationContext(ClaimsProviderSettings settings, OperationType currentRe this.IncomingEntity = incomingEntity; this.UriContext = context; this.HierarchyNodeID = hierarchyNodeID; - this.MaxCount = maxCount; + this.MaxCount = settings.MaxSearchResultsCount == -1 || currentRequestType != OperationType.Search ? maxCount : settings.MaxSearchResultsCount; + // settings.LdapConnections must be cloned locally to ensure its properties ($select / $filter) won't be updated by multiple threads this.LdapConnections = new List(settings.LdapConnections.Count); diff --git a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/LDAPProviderConfiguration.cs b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/LDAPProviderConfiguration.cs index 3eaa8e0..2c21fda 100644 --- a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/LDAPProviderConfiguration.cs +++ b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/LDAPProviderConfiguration.cs @@ -52,6 +52,11 @@ public interface ILdapProviderSettings /// This property is not used by LDAPCP and is available to developers for their own needs /// string CustomData { get; } + + /// + /// Gets how many results maximum can be returned to the people picker during a search operation + /// + int MaxSearchResultsCount { get; } #endregion #region LDAP specific settings @@ -76,6 +81,7 @@ public class LdapProviderSettings : ILdapProviderSettings public string EntityDisplayTextPrefix { get; set; } public int Timeout { get; set; } = ClaimsProviderConstants.DEFAULT_TIMEOUT; public string CustomData { get; set; } + public int MaxSearchResultsCount { get; set; } = -1; #endregion #region LDAP specific settings @@ -265,6 +271,17 @@ public string CustomData } [Persisted] private string _CustomData; + + public int MaxSearchResultsCount + { + get + { + return _MaxSearchResultsCount; + } + private set => _MaxSearchResultsCount = value; + } + [Persisted] + private int _MaxSearchResultsCount = -1; #endregion @@ -364,6 +381,8 @@ protected virtual ILdapProviderSettings GenerateSettingsFromCurrentConfiguration EntityDisplayTextPrefix = this.EntityDisplayTextPrefix, FilterExactMatchOnly = this.FilterExactMatchOnly, Timeout = this.Timeout, + MaxSearchResultsCount = this.MaxSearchResultsCount, + Version = this.Version, // Properties specific to type IEntraSettings @@ -449,6 +468,11 @@ public virtual void ValidateConfiguration() } } } + + if (MaxSearchResultsCount < -1) + { + throw new InvalidOperationException($"The configuration is invalid because the value of property {nameof(MaxSearchResultsCount)} is < -1"); + } } /// @@ -498,6 +522,7 @@ public virtual void ApplySettings(ILdapProviderSettings settings, bool commitIfV this.EntityDisplayTextPrefix = settings.EntityDisplayTextPrefix; this.Timeout = settings.Timeout; this.CustomData = settings.CustomData; + this.MaxSearchResultsCount = settings.MaxSearchResultsCount; this.LdapConnections = settings.LdapConnections; diff --git a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/LdapEntityProvider.cs b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/LdapEntityProvider.cs index 64b1d58..2cda0bf 100644 --- a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/LdapEntityProvider.cs +++ b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/LdapEntityProvider.cs @@ -502,7 +502,7 @@ protected List QueryLDAPServers(OperationContext curre using (DirectorySearcher ds = new DirectorySearcher(ldapFilter)) { ds.SearchRoot = directory; - ds.SizeLimit = currentContext.MaxCount; + ds.SizeLimit = currentContext.MaxCount; // Property SizeLimit is ignored if it is set to 0 (tested), and ArgumentException an exception is < 0 - https://learn.microsoft.com/en-us/dotnet/api/system.directoryservices.directorysearcher.sizelimit?view=netframework-4.8.1 ds.ClientTimeout = new TimeSpan(0, 0, this.Settings.Timeout); // Set the timeout in seconds ds.PropertiesToLoad.Add("objectclass"); ds.PropertiesToLoad.Add("nETBIOSName"); From c2008061d8d596e13378e192d3f18e565f7d040f Mon Sep 17 00:00:00 2001 From: Yvan Duhamel Date: Mon, 6 May 2024 10:57:34 +0200 Subject: [PATCH 08/15] Fix uninitialized properties (#212) --- CHANGELOG.md | 1 + .../Configuration/LDAPProviderConfiguration.cs | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d04b811..934e029 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Fix error when creating the configuration, due to case-sensitive test in the claim types - https://github.com/Yvand/LDAPCP/issues/204 * Fix the error when loading the global configuration page, if the group claim type set in the LDAPCP configuration does not exist in the trust - https://github.com/Yvand/LDAPCP/issues/203 * Add the property MaxSearchResultsCount, to override the SharePoint limit of the maximum number of objects that the LDAP server returns - https://github.com/Yvand/LDAPCP/issues/209 +* Correctly initialize LDAP-specific properties with their actual value, instead of the default value of the type - https://github.com/Yvand/LDAPCP/pull/212 ## LDAPCP Second Edition v17.0.20240226.2 - Published in February 26, 2024 diff --git a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/LDAPProviderConfiguration.cs b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/LDAPProviderConfiguration.cs index 2c21fda..c835ee5 100644 --- a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/LDAPProviderConfiguration.cs +++ b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/LDAPProviderConfiguration.cs @@ -227,7 +227,7 @@ public bool AlwaysResolveUserInput private set => _AlwaysResolveUserInput = value; } [Persisted] - private bool _AlwaysResolveUserInput; + private bool _AlwaysResolveUserInput = false; public bool FilterExactMatchOnly { @@ -235,7 +235,7 @@ public bool FilterExactMatchOnly private set => _FilterExactMatchOnly = value; } [Persisted] - private bool _FilterExactMatchOnly; + private bool _FilterExactMatchOnly = false; public bool EnableAugmentation { @@ -300,7 +300,7 @@ public bool FilterEnabledUsersOnly private set => _FilterEnabledUsersOnly = value; } [Persisted] - private bool _FilterEnabledUsersOnly; + private bool _FilterEnabledUsersOnly = true; public bool FilterSecurityGroupsOnly { @@ -308,7 +308,7 @@ public bool FilterSecurityGroupsOnly private set => _FilterSecurityGroupsOnly = value; } [Persisted] - private bool _FilterSecurityGroupsOnly; + private bool _FilterSecurityGroupsOnly = true; public bool AddWildcardAsPrefixOfInput { @@ -316,7 +316,7 @@ public bool AddWildcardAsPrefixOfInput private set => _AddWildcardAsPrefixOfInput = value; } [Persisted] - private bool _AddWildcardAsPrefixOfInput; + private bool _AddWildcardAsPrefixOfInput = false; #endregion #region "Other properties" @@ -382,11 +382,14 @@ protected virtual ILdapProviderSettings GenerateSettingsFromCurrentConfiguration FilterExactMatchOnly = this.FilterExactMatchOnly, Timeout = this.Timeout, MaxSearchResultsCount = this.MaxSearchResultsCount, - + Version = this.Version, // Properties specific to type IEntraSettings LdapConnections = this.LdapConnections, + FilterEnabledUsersOnly = this.FilterEnabledUsersOnly, + FilterSecurityGroupsOnly = this.FilterSecurityGroupsOnly, + AddWildcardAsPrefixOfInput = this.AddWildcardAsPrefixOfInput, }; return (ILdapProviderSettings)entityProviderSettings; } @@ -525,6 +528,9 @@ public virtual void ApplySettings(ILdapProviderSettings settings, bool commitIfV this.MaxSearchResultsCount = settings.MaxSearchResultsCount; this.LdapConnections = settings.LdapConnections; + this.FilterEnabledUsersOnly = settings.FilterEnabledUsersOnly; + this.FilterSecurityGroupsOnly = settings.FilterSecurityGroupsOnly; + this.AddWildcardAsPrefixOfInput = settings.AddWildcardAsPrefixOfInput; if (commitIfValid) { From bc2c30a6e0b19dcc98750d0fa815a377c983cc22 Mon Sep 17 00:00:00 2001 From: Yvan Duhamel Date: Mon, 6 May 2024 11:04:36 +0200 Subject: [PATCH 09/15] Update LDAPProviderConfiguration.cs --- .../LDAPProviderConfiguration.cs | 49 +++++++++++++++---- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/LDAPProviderConfiguration.cs b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/LDAPProviderConfiguration.cs index c835ee5..08c33fc 100644 --- a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/LDAPProviderConfiguration.cs +++ b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/LDAPProviderConfiguration.cs @@ -23,33 +23,33 @@ public interface ILdapProviderSettings ClaimTypeConfigCollection ClaimTypes { get; } /// - /// Gets or sets whether to skip the requests to LDAP and consider any input as valid. + /// Gets whether to skip the requests to LDAP and consider any input as valid. /// This can be useful to keep people picker working even if connectivity with the directory is lost. /// bool AlwaysResolveUserInput { get; } /// - /// Gets or sets whether to return only results that match exactly the user input (case-insensitive). + /// Gets whether to return only results that match exactly the user input (case-insensitive). /// bool FilterExactMatchOnly { get; } /// - /// Gets or sets whether to return the trusted groups that the user is a member of. + /// Gets whether to return the groups the user is a member of. /// bool EnableAugmentation { get; } /// - /// Gets or sets a string that will appear as a prefix of the text of each result, in the people picker. + /// Gets the string that will appear as a prefix of the text of each result, in the people picker. /// string EntityDisplayTextPrefix { get; } /// - /// Gets or sets the timeout in seconds before an operation to LDAP directory is canceled. + /// Gets the timeout in seconds, before an operation to LDAP directory is canceled. /// int Timeout { get; } /// - /// This property is not used by LDAPCP and is available to developers for their own needs + /// Gets this property, not used by LDAPCP and available to developers for their own needs /// string CustomData { get; } @@ -59,9 +59,9 @@ public interface ILdapProviderSettings int MaxSearchResultsCount { get; } #endregion - #region LDAP specific settings + #region LDAP-specific settings /// - /// Gets the list of Azure tenants to use to get entities + /// Gets the list of LDAP directories /// List LdapConnections { get; } bool FilterEnabledUsersOnly { get; } @@ -183,8 +183,9 @@ public static ClaimTypeConfigCollection ReturnDefaultClaimTypesConfig(string cla public class LdapProviderConfiguration : SPPersistedObject, ILdapProviderSettings { public string LocalAssemblyVersion => ClaimsProviderConstants.ClaimsProviderVersion; + /// - /// Gets the settings, based on the configuration stored in this persisted object + /// Gets or sets the version of the settings /// public ILdapProviderSettings Settings { @@ -201,6 +202,9 @@ public ILdapProviderSettings Settings #region "Base settings implemented from IEntraIDEntityProviderSettings" + /// + /// Gets or sets the claim types and their mapping with a DirectoryObject property + /// public ClaimTypeConfigCollection ClaimTypes { get @@ -221,6 +225,10 @@ private set private Collection _ClaimTypesCollection; private ClaimTypeConfigCollection _ClaimTypes; + /// + /// Gets or sets whether to skip the requests to LDAP and consider any input as valid. + /// This can be useful to keep people picker working even if connectivity with the directory is lost. + /// public bool AlwaysResolveUserInput { get => _AlwaysResolveUserInput; @@ -229,6 +237,9 @@ public bool AlwaysResolveUserInput [Persisted] private bool _AlwaysResolveUserInput = false; + /// + /// Gets or sets whether to return only results that match exactly the user input (case-insensitive). + /// public bool FilterExactMatchOnly { get => _FilterExactMatchOnly; @@ -237,6 +248,9 @@ public bool FilterExactMatchOnly [Persisted] private bool _FilterExactMatchOnly = false; + /// + /// Gets or sets whether to return the groups the user is a member of. + /// public bool EnableAugmentation { get => _EnableAugmentation; @@ -245,6 +259,9 @@ public bool EnableAugmentation [Persisted] private bool _EnableAugmentation = true; + /// + /// Gets or sets the string that will appear as a prefix of the text of each result, in the people picker. + /// public string EntityDisplayTextPrefix { get => _EntityDisplayTextPrefix; @@ -253,6 +270,9 @@ public string EntityDisplayTextPrefix [Persisted] private string _EntityDisplayTextPrefix; + /// + /// Gets or sets the timeout in seconds, before an operation to LDAP directory is canceled. + /// public int Timeout { get @@ -264,6 +284,9 @@ public int Timeout [Persisted] private int _Timeout = ClaimsProviderConstants.DEFAULT_TIMEOUT; + /// + /// Gets or sets this property, not used by LDAPCP and available to developers for their own needs + /// public string CustomData { get => _CustomData; @@ -272,6 +295,9 @@ public string CustomData [Persisted] private string _CustomData; + /// + /// Gets or sets how many results maximum can be returned to the people picker during a search operation + /// public int MaxSearchResultsCount { get @@ -285,7 +311,10 @@ public int MaxSearchResultsCount #endregion - #region "EntraID settings implemented from IEntraIDEntityProviderSettings" + #region "LDAP-specific settings implemented from IEntraIDEntityProviderSettings" + /// + /// Gets or sets the list of LDAP directories + /// public List LdapConnections { get => _LdapServers; From 83fd6f8accf97f29c63e89ab9a9c7d1ec3dde635 Mon Sep 17 00:00:00 2001 From: Yvan Duhamel Date: Mon, 6 May 2024 14:34:41 +0200 Subject: [PATCH 10/15] remove deprecated pipelines --- azure-pipelines/ci-apply-dtl-artifacts.yml | 131 ------------------ azure-pipelines/ci-compile.yml | 121 ---------------- azure-pipelines/ci-create-dtl-environment.yml | 21 --- 3 files changed, 273 deletions(-) delete mode 100644 azure-pipelines/ci-apply-dtl-artifacts.yml delete mode 100644 azure-pipelines/ci-compile.yml delete mode 100644 azure-pipelines/ci-create-dtl-environment.yml diff --git a/azure-pipelines/ci-apply-dtl-artifacts.yml b/azure-pipelines/ci-apply-dtl-artifacts.yml deleted file mode 100644 index bbfb89e..0000000 --- a/azure-pipelines/ci-apply-dtl-artifacts.yml +++ /dev/null @@ -1,131 +0,0 @@ -resources: -- repo: self - -jobs: -- job: ApplyArtifactsSP2013 - condition: eq(variables['Deployment.ProvisionSharePoint2013'], true) - displayName: Apply artifacts on SP2013 - timeoutInMinutes: 30 - variables: - jobSharePointVersion: 2013 - pool: - vmImage: 'windows-2019' - steps: - - checkout: none #skip checking out the default repository resource - - task: automagically.DownloadFile.DownloadFile.DownloadFile@1 - displayName: 'Download apply-dtl-artifact.ps1' - inputs: - FileUrl: 'https://raw.githubusercontent.com/Yvand/AzureRM-Templates/master/DevTestLabs-Artifacts/manage-artifacts/apply-dtl-artifact.ps1' - DestinationFolder: '$(System.DefaultWorkingDirectory)\scripts' - - - task: AzurePowerShell@3 - displayName: 'Create and register a VSTS agent in DevOps agent pools by applying artifact "Azure Pipelines Agent"' - inputs: - azureSubscription: '$(DevTestLabs.AzureConnectionName)' - ScriptPath: '$(System.DefaultWorkingDirectory)\scripts\apply-dtl-artifact.ps1' - ScriptArguments: '-DevTestLabName "$(DevTestLabs.LabName)" -VirtualMachineName "SP$(jobSharePointVersion)" -RepositoryName "Yvand/AzureRM-Templates" -ArtifactName "windows-vsts-build-agent" -param_vstsAccount "$(DevOps.OrganizationName)" -param_vstsPassword "$(DevOps.AccessToken)" -param_poolName "$(system.teamProject)-Tests-$(jobSharePointVersion)" -param_windowsLogonAccount "$(Deployment.DomainName)\$(Deployment.AdminUserName)" -param_windowsLogonPassword "$(Deployment.AdminPassword)" -param_agentName "SP$(jobSharePointVersion)" -param_agentNameSuffix "-$(Build.BuildNumber)" -param_RunAsAutoLogon false -param_driveLetter C -param_workDirectory ""' - preferredAzurePowerShellVersion: 5.1.1 - - - task: AzurePowerShell@3 - displayName: 'Apply artifact "Download Azure Pipelines Artifact and Run Script"' - inputs: - azureSubscription: '$(DevTestLabs.AzureConnectionName)' - ScriptPath: '$(System.DefaultWorkingDirectory)\scripts\apply-dtl-artifact.ps1' - ScriptArguments: -DevTestLabName '$(DevTestLabs.LabName)' -VirtualMachineName 'SP$(jobSharePointVersion)' -RepositoryName 'Yvand/AzureRM-Templates' -ArtifactName 'windows-vsts-download-and-run-script' -param_vstsProjectUri 'https://dev.azure.com/$(DevOps.OrganizationName)/$(system.teamProject)' -param_buildDefinitionName '$(DevOps.BuildArtifactsPipelineName)' -param_personalAccessToken $(DevOps.AccessToken) -param_pathToScript 'drop_$(Tests.BuildConfiguration)\$(Deployment.ConfigureServerFolderName)\ConfigureLab.ps1' -param_scriptArguments "-pathToPackage '..\$(system.teamProject)\bin\$(Tests.BuildConfiguration)\$(system.teamProject).wsp' -claimsProviderName '$(system.teamProject)' -spTrustName '$(Deployment.DomainFQDN)' -adminUserName '$(Deployment.DomainName)\$(Deployment.AdminUserName)' -adminPassword '$(Deployment.AdminPassword)'" - preferredAzurePowerShellVersion: 5.1.1 - -- job: ApplyArtifactsSP2016 - condition: eq(variables['Deployment.ProvisionSharePoint2016'], true) - displayName: Apply artifacts on SP2016 - timeoutInMinutes: 30 - variables: - jobSharePointVersion: 2016 - pool: - vmImage: 'windows-2019' - steps: - - checkout: none #skip checking out the default repository resource - - task: automagically.DownloadFile.DownloadFile.DownloadFile@1 - displayName: 'Download apply-dtl-artifact.ps1' - inputs: - FileUrl: 'https://raw.githubusercontent.com/Yvand/AzureRM-Templates/master/DevTestLabs-Artifacts/manage-artifacts/apply-dtl-artifact.ps1' - DestinationFolder: '$(System.DefaultWorkingDirectory)\scripts' - - - task: AzurePowerShell@3 - displayName: 'Create and register a VSTS agent in DevOps agent pools by applying artifact "Azure Pipelines Agent"' - inputs: - azureSubscription: '$(DevTestLabs.AzureConnectionName)' - ScriptPath: '$(System.DefaultWorkingDirectory)\scripts\apply-dtl-artifact.ps1' - ScriptArguments: '-DevTestLabName "$(DevTestLabs.LabName)" -VirtualMachineName "SP$(jobSharePointVersion)" -RepositoryName "Yvand/AzureRM-Templates" -ArtifactName "windows-vsts-build-agent" -param_vstsAccount "$(DevOps.OrganizationName)" -param_vstsPassword "$(DevOps.AccessToken)" -param_poolName "$(system.teamProject)-Tests-$(jobSharePointVersion)" -param_windowsLogonAccount "$(Deployment.DomainName)\$(Deployment.AdminUserName)" -param_windowsLogonPassword "$(Deployment.AdminPassword)" -param_agentName "SP$(jobSharePointVersion)" -param_agentNameSuffix "-$(Build.BuildNumber)" -param_RunAsAutoLogon false -param_driveLetter C -param_workDirectory ""' - preferredAzurePowerShellVersion: 5.1.1 - - - task: AzurePowerShell@3 - displayName: 'Apply artifact "Download Azure Pipelines Artifact and Run Script"' - inputs: - azureSubscription: '$(DevTestLabs.AzureConnectionName)' - ScriptPath: '$(System.DefaultWorkingDirectory)\scripts\apply-dtl-artifact.ps1' - ScriptArguments: -DevTestLabName '$(DevTestLabs.LabName)' -VirtualMachineName 'SP$(jobSharePointVersion)' -RepositoryName 'Yvand/AzureRM-Templates' -ArtifactName 'windows-vsts-download-and-run-script' -param_vstsProjectUri 'https://dev.azure.com/$(DevOps.OrganizationName)/$(system.teamProject)' -param_buildDefinitionName '$(DevOps.BuildArtifactsPipelineName)' -param_personalAccessToken $(DevOps.AccessToken) -param_pathToScript 'drop_$(Tests.BuildConfiguration)\$(Deployment.ConfigureServerFolderName)\ConfigureLab.ps1' -param_scriptArguments "-pathToPackage '..\$(system.teamProject)\bin\$(Tests.BuildConfiguration)\$(system.teamProject).wsp' -claimsProviderName '$(system.teamProject)' -spTrustName '$(Deployment.DomainFQDN)' -adminUserName '$(Deployment.DomainName)\$(Deployment.AdminUserName)' -adminPassword '$(Deployment.AdminPassword)'" - preferredAzurePowerShellVersion: 5.1.1 - -- job: ApplyArtifactsSP2019 - condition: eq(variables['Deployment.ProvisionSharePoint2019'], true) - displayName: Apply artifacts on SP2019 - timeoutInMinutes: 30 - variables: - jobSharePointVersion: 2019 - pool: - vmImage: 'windows-2019' - steps: - - checkout: none #skip checking out the default repository resource - - task: automagically.DownloadFile.DownloadFile.DownloadFile@1 - displayName: 'Download apply-dtl-artifact.ps1' - inputs: - FileUrl: 'https://raw.githubusercontent.com/Yvand/AzureRM-Templates/master/DevTestLabs-Artifacts/manage-artifacts/apply-dtl-artifact.ps1' - DestinationFolder: '$(System.DefaultWorkingDirectory)\scripts' - - - task: AzurePowerShell@3 - displayName: 'Create and register a VSTS agent in DevOps agent pools by applying artifact "Azure Pipelines Agent"' - inputs: - azureSubscription: '$(DevTestLabs.AzureConnectionName)' - ScriptPath: '$(System.DefaultWorkingDirectory)\scripts\apply-dtl-artifact.ps1' - ScriptArguments: '-DevTestLabName "$(DevTestLabs.LabName)" -VirtualMachineName "SP$(jobSharePointVersion)" -RepositoryName "Yvand/AzureRM-Templates" -ArtifactName "windows-vsts-build-agent" -param_vstsAccount "$(DevOps.OrganizationName)" -param_vstsPassword "$(DevOps.AccessToken)" -param_poolName "$(system.teamProject)-Tests-$(jobSharePointVersion)" -param_windowsLogonAccount "$(Deployment.DomainName)\$(Deployment.AdminUserName)" -param_windowsLogonPassword "$(Deployment.AdminPassword)" -param_agentName "SP$(jobSharePointVersion)" -param_agentNameSuffix "-$(Build.BuildNumber)" -param_RunAsAutoLogon false -param_driveLetter C -param_workDirectory ""' - preferredAzurePowerShellVersion: 5.1.1 - - - task: AzurePowerShell@3 - displayName: 'Apply artifact "Download Azure Pipelines Artifact and Run Script"' - inputs: - azureSubscription: '$(DevTestLabs.AzureConnectionName)' - ScriptPath: '$(System.DefaultWorkingDirectory)\scripts\apply-dtl-artifact.ps1' - ScriptArguments: -DevTestLabName '$(DevTestLabs.LabName)' -VirtualMachineName 'SP$(jobSharePointVersion)' -RepositoryName 'Yvand/AzureRM-Templates' -ArtifactName 'windows-vsts-download-and-run-script' -param_vstsProjectUri 'https://dev.azure.com/$(DevOps.OrganizationName)/$(system.teamProject)' -param_buildDefinitionName '$(DevOps.BuildArtifactsPipelineName)' -param_personalAccessToken $(DevOps.AccessToken) -param_pathToScript 'drop_$(Tests.BuildConfiguration)\$(Deployment.ConfigureServerFolderName)\ConfigureLab.ps1' -param_scriptArguments "-pathToPackage '..\$(system.teamProject)\bin\$(Tests.BuildConfiguration)\$(system.teamProject).wsp' -claimsProviderName '$(system.teamProject)' -spTrustName '$(Deployment.DomainFQDN)' -adminUserName '$(Deployment.DomainName)\$(Deployment.AdminUserName)' -adminPassword '$(Deployment.AdminPassword)'" - preferredAzurePowerShellVersion: 5.1.1 - -- job: ApplyArtifactsSPSubscription - condition: eq(variables['Deployment.ProvisionSharePointSubscription'], true) - displayName: Apply artifacts on SPSubscription - timeoutInMinutes: 30 - variables: - jobSharePointVersion: Subscription - pool: - vmImage: 'windows-latest' - steps: - - checkout: none #skip checking out the default repository resource - - task: automagically.DownloadFile.DownloadFile.DownloadFile@1 - displayName: 'Download apply-dtl-artifact.ps1' - inputs: - FileUrl: 'https://raw.githubusercontent.com/Yvand/AzureRM-Templates/master/DevTestLabs-Artifacts/manage-artifacts/apply-dtl-artifact.ps1' - DestinationFolder: '$(System.DefaultWorkingDirectory)\scripts' - - - task: AzurePowerShell@3 - displayName: 'Create and register a VSTS agent in DevOps agent pools by applying artifact "Azure Pipelines Agent"' - inputs: - azureSubscription: '$(DevTestLabs.AzureConnectionName)' - ScriptPath: '$(System.DefaultWorkingDirectory)\scripts\apply-dtl-artifact.ps1' - ScriptArguments: '-DevTestLabName "$(DevTestLabs.LabName)" -VirtualMachineName "SP$(jobSharePointVersion)" -RepositoryName "Yvand/AzureRM-Templates" -ArtifactName "windows-vsts-build-agent" -param_vstsAccount "$(DevOps.OrganizationName)" -param_vstsPassword "$(DevOps.AccessToken)" -param_poolName "$(system.teamProject)-Tests-$(jobSharePointVersion)" -param_windowsLogonAccount "$(Deployment.DomainName)\$(Deployment.AdminUserName)" -param_windowsLogonPassword "$(Deployment.AdminPassword)" -param_agentName "SP$(jobSharePointVersion)" -param_agentNameSuffix "-$(Build.BuildNumber)" -param_RunAsAutoLogon false -param_driveLetter C -param_workDirectory ""' - preferredAzurePowerShellVersion: 5.1.1 - - - task: AzurePowerShell@3 - displayName: 'Apply artifact "Download Azure Pipelines Artifact and Run Script"' - inputs: - azureSubscription: '$(DevTestLabs.AzureConnectionName)' - ScriptPath: '$(System.DefaultWorkingDirectory)\scripts\apply-dtl-artifact.ps1' - ScriptArguments: -DevTestLabName '$(DevTestLabs.LabName)' -VirtualMachineName 'SP$(jobSharePointVersion)' -RepositoryName 'Yvand/AzureRM-Templates' -ArtifactName 'windows-vsts-download-and-run-script' -param_vstsProjectUri 'https://dev.azure.com/$(DevOps.OrganizationName)/$(system.teamProject)' -param_buildDefinitionName '$(DevOps.BuildArtifactsPipelineName)' -param_personalAccessToken $(DevOps.AccessToken) -param_pathToScript 'drop_$(Tests.BuildConfiguration)\$(Deployment.ConfigureServerFolderName)\ConfigureLab.ps1' -param_scriptArguments "-pathToPackage '..\$(system.teamProject)\bin\$(Tests.BuildConfiguration)\$(system.teamProject).wsp' -claimsProviderName '$(system.teamProject)' -spTrustName '$(Deployment.DomainFQDN)' -adminUserName '$(Deployment.DomainName)\$(Deployment.AdminUserName)' -adminPassword '$(Deployment.AdminPassword)'" - preferredAzurePowerShellVersion: 5.1.1 \ No newline at end of file diff --git a/azure-pipelines/ci-compile.yml b/azure-pipelines/ci-compile.yml deleted file mode 100644 index 9b5ffd9..0000000 --- a/azure-pipelines/ci-compile.yml +++ /dev/null @@ -1,121 +0,0 @@ -name: $(BuildVersion).$(date:yyyyMMdd).$(Build.BuildId) -resources: -- repo: self - -variables: - SolutionFileName: '$(system.teamProject).sln' - -jobs: -- job: Compile - strategy: - maxParallel: 2 - matrix: - debugJob: - configuration: debug - releaseJob: - configuration: release - displayName: Compile - pool: - vmImage: 'windows-2019' - demands: - - msbuild - - visualstudio - - azureps - steps: - - task: DownloadSecureFile@1 - displayName: 'Download signing key' - inputs: - secureFile: '$(SigningKeySecureFileID)' - - - powershell: | - # Set variables - $azureStorageBaseDirectory = "Resources\$(system.teamProject)" - $projectLocalPath = "$(System.DefaultWorkingDirectory)\$(system.teamProject)" - $devTestLabsLocalPath = "$(Build.ArtifactStagingDirectory)\$(Tests.DataFolderName)" - - # Create now folder that will contain later scripts to configure local test server - #if ((Test-Path -Path "$(Build.ArtifactStagingDirectory)\$(Deployment.ConfigureServerFolderName)" -PathType Container) -eq $false) { - #New-Item -ItemType Directory -Path "$(Build.ArtifactStagingDirectory)\$(Deployment.ConfigureServerFolderName)" - #} - - Write-Output ("Copy signing key from $(DownloadSecureFile.secureFilePath) to $projectLocalPath") - Copy-Item "$(DownloadSecureFile.secureFilePath)" -Destination "$projectLocalPath" - - Write-Output ("Copy Microsoft.SharePoint.dll from Azure storage account") - $azureContext = New-AzureStorageContext $(AzureStorageAccountName) $(AzureStorageAccountKey) - $azureShare = Get-AzureStorageShare $(AzureStorageShareName) -Context $azureContext - Get-AzureStorageFileContent -Share $azureShare -Path "$azureStorageBaseDirectory\SharePoint 2013\Microsoft.SharePoint.dll" "$projectLocalPath\Microsoft.SharePoint.dll" - Write-Output ("Add Microsoft.SharePoint.dll to the GAC") - [System.Reflection.Assembly]::Load("System.EnterpriseServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a") - $publish = New-Object System.EnterpriseServices.Internal.Publish - $publish.GacInstall("$projectLocalPath\Microsoft.SharePoint.dll") - - Write-Output ("Copy integration tests data from the Azure storage account") - # Create the destination directory - if ((Test-Path -Path $devTestLabsLocalPath -PathType Container) -eq $false) { - New-Item -ItemType Directory -Path $devTestLabsLocalPath - } - $azurePath = Join-Path -Path $azureStorageBaseDirectory -ChildPath "$(Tests.DataFolderName)" - Get-AzureStorageFile -ShareName $(AzureStorageShareName) -Context $azureContext -Path $azurePath | Get-AzureStorageFile | ?{$_.GetType().Name -eq "CloudFile"} | Get-AzureStorageFileContent -Destination $devTestLabsLocalPath - - displayName: 'Import resources' - - - task: automagically.DownloadFile.DownloadFile.DownloadFile@1 - displayName: 'Download ConfigureLab.ps1' - inputs: - FileUrl: 'https://raw.githubusercontent.com/Yvand/AzureRM-Templates/master/DevTestLabs-Artifacts/manage-artifacts/ConfigureLab.ps1' - DestinationFolder: '$(Build.ArtifactStagingDirectory)\$(Deployment.ConfigureServerFolderName)' - - - task: automagically.DownloadFile.DownloadFile.DownloadFile@1 - displayName: 'Download ConfigureLab.psm1' - inputs: - FileUrl: 'https://raw.githubusercontent.com/Yvand/AzureRM-Templates/master/DevTestLabs-Artifacts/manage-artifacts/ConfigureLab.psm1' - DestinationFolder: '$(Build.ArtifactStagingDirectory)\$(Deployment.ConfigureServerFolderName)' - - - task: NuGetToolInstaller@0 - displayName: 'Use NuGet 4.4.1' - inputs: - versionSpec: 4.4.1 - - - task: NuGetCommand@2 - displayName: 'NuGet restore' - inputs: - restoreSolution: '$(SolutionFileName)' - - - task: bleddynrichards.Assembly-Info-Task.Assembly-Info-Task.Assembly-Info-NetFramework@2 - displayName: 'Set $(system.teamProject) assemblies manifest' - inputs: - FileNames: '**\AssemblyInfo.cs' - Title: $(system.teamProject) - Product: $(system.teamProject) - Description: '$(ProductDescription)' - Company: GitHub.com/Yvand - Copyright: 'Copyright © $(date:YYYY) Yvan Duhamel, All rights reserved' - Trademark: '$(system.teamProject)' - VersionNumber: 1.0.0.0 - FileVersionNumber: '$(Build.BuildNumber)' - InformationalVersion: '$(Build.BuildNumber)' - - - task: VSBuild@1 - displayName: 'Build $(system.teamProject) solution' - inputs: - solution: '$(SolutionFileName)' - msbuildArgs: '/p:IsPackaging=true' - platform: '$(BuildPlatform)' - configuration: '$(configuration)' - msbuildArchitecture: x64 - - - task: CopyFiles@2 - displayName: 'Copy binaries to artifacts' - inputs: - SourceFolder: '$(Build.SourcesDirectory)' - Contents: | - $(system.teamProject)/bin/$(configuration)/?($(system.teamProject).*) - $(system.teamProject).Tests/bin/$(configuration)/?(*.dll) - TargetFolder: '$(Build.ArtifactStagingDirectory)' - - - task: PublishBuildArtifacts@1 - displayName: 'Publish Artifact: drop' - inputs: - pathtoPublish: '$(Build.ArtifactStagingDirectory)' - artifactName: 'drop_$(configuration)' diff --git a/azure-pipelines/ci-create-dtl-environment.yml b/azure-pipelines/ci-create-dtl-environment.yml deleted file mode 100644 index 658ef1e..0000000 --- a/azure-pipelines/ci-create-dtl-environment.yml +++ /dev/null @@ -1,21 +0,0 @@ -resources: -- repo: self - -jobs: -- job: CreateTestEnvironment - displayName: Create test environment - timeoutInMinutes: 90 - pool: - vmImage: 'windows-latest' - steps: - - checkout: none #skip checking out the default repository resource - - task: ms-azuredevtestlabs.tasks.azure-dtl-task-createEnvironment.AzureDevTestLabsCreateEnvironment@3 - displayName: 'Create Azure DevTest Labs Environment' - inputs: - azureSubscription: '$(DevTestLabs.AzureConnectionName)' - LabId: '/subscriptions/$(DevTestLabs.AzureSubscriptionId)/resourceGroups/$(DevTestLabs.LabName)/providers/Microsoft.DevTestLab/labs/$(DevTestLabs.LabName)' - RepositoryId: '/subscriptions/$(DevTestLabs.AzureSubscriptionId)/resourcegroups/$(DevTestLabs.LabName)/providers/microsoft.devtestlab/labs/$(DevTestLabs.LabName)/artifactsources/$(DevTestLabs.RepoID)' - TemplateId: '/subscriptions/$(DevTestLabs.AzureSubscriptionId)/resourceGroups/$(DevTestLabs.LabName)/providers/Microsoft.DevTestLab/labs/$(DevTestLabs.LabName)/artifactSources/$(DevTestLabs.RepoID)/armTemplates/$(DevTestLabs.ARMTemplateName)' - EnvironmentName: 'Tests-$(system.teamProject)' - ParameterOverrides: "-provisionSharePoint2013 $(Deployment.ProvisionSharePoint2013) -provisionSharePoint2016 $(Deployment.ProvisionSharePoint2016) -provisionSharePoint2019 $(Deployment.ProvisionSharePoint2019) -provisionSharePointSubscription $(Deployment.ProvisionSharePointSubscription) -adminUserName '$(Deployment.AdminUserName)' -adminPassword '$(Deployment.AdminPassword)' -serviceAccountsPassword '$(Deployment.ServiceAccountsPassword)' -addPublicIPAddressToEachVM true -configureADFS true -addAzureBastion true -enableHybridBenefitServerLicenses true -enableAutomaticUpdates false" - timeoutInMinutes: 90 From d57f979676cae6b6e47e1ed9e018b0e6dd3bc270 Mon Sep 17 00:00:00 2001 From: Yvan Duhamel Date: Tue, 7 May 2024 08:35:44 +0200 Subject: [PATCH 11/15] test if ClaimsPrincipal.Identity is null --- CHANGELOG.md | 1 + .../Configuration/ClaimsProviderConstants.cs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 934e029..03c3226 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * Fix the error when loading the global configuration page, if the group claim type set in the LDAPCP configuration does not exist in the trust - https://github.com/Yvand/LDAPCP/issues/203 * Add the property MaxSearchResultsCount, to override the SharePoint limit of the maximum number of objects that the LDAP server returns - https://github.com/Yvand/LDAPCP/issues/209 * Correctly initialize LDAP-specific properties with their actual value, instead of the default value of the type - https://github.com/Yvand/LDAPCP/pull/212 +* Fix an NullReferenceException in a very rare scenario where ClaimsPrincipal.Identity is null ## LDAPCP Second Edition v17.0.20240226.2 - Published in February 26, 2024 diff --git a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/ClaimsProviderConstants.cs b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/ClaimsProviderConstants.cs index 37971f6..060b0af 100644 --- a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/ClaimsProviderConstants.cs +++ b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/ClaimsProviderConstants.cs @@ -351,7 +351,7 @@ public OperationContext(ClaimsProviderSettings settings, OperationType currentRe if (httpctx != null) { WIF4_5.ClaimsPrincipal cp = httpctx.User as WIF4_5.ClaimsPrincipal; - if (cp != null) + if (cp != null && cp.Identity != null) { if (SPClaimProviderManager.IsEncodedClaim(cp.Identity.Name)) { From ab6b8a63fb49a3b57bac2fe7d1dd682a2109aac8 Mon Sep 17 00:00:00 2001 From: Yvan Duhamel Date: Tue, 7 May 2024 10:38:01 +0200 Subject: [PATCH 12/15] Add helper methods to get/delete a directory connection in the configuration --- CHANGELOG.md | 1 + .../LDAPProviderConfiguration.cs | 34 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 03c3226..d59ffcf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * Add the property MaxSearchResultsCount, to override the SharePoint limit of the maximum number of objects that the LDAP server returns - https://github.com/Yvand/LDAPCP/issues/209 * Correctly initialize LDAP-specific properties with their actual value, instead of the default value of the type - https://github.com/Yvand/LDAPCP/pull/212 * Fix an NullReferenceException in a very rare scenario where ClaimsPrincipal.Identity is null +* Add helper methods to get/delete a directory connection in the configuration ## LDAPCP Second Edition v17.0.20240226.2 - Published in February 26, 2024 diff --git a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/LDAPProviderConfiguration.cs b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/LDAPProviderConfiguration.cs index 08c33fc..eaeb353 100644 --- a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/LDAPProviderConfiguration.cs +++ b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/LDAPProviderConfiguration.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.DirectoryServices.Protocols; using System.Linq; using Yvand.LdapClaimsProvider.Logging; @@ -423,6 +424,39 @@ protected virtual ILdapProviderSettings GenerateSettingsFromCurrentConfiguration return (ILdapProviderSettings)entityProviderSettings; } + /// + /// Gets the directory configuration + /// + /// Directory path + /// + /// + public DirectoryConnection GetLdapConnection(string directoryConnectionPath) + { + if (String.IsNullOrWhiteSpace(directoryConnectionPath)) + { + throw new ArgumentNullException(nameof(directoryConnectionPath)); + } + return this.LdapConnections.FirstOrDefault(x => x.LdapPath.Equals(directoryConnectionPath, StringComparison.OrdinalIgnoreCase)); + } + + /// + /// Deletes the directory configuration + /// + /// Directory path + /// + /// + public bool DeleteLdapConnection(string directoryConnectionPath) + { + if (String.IsNullOrWhiteSpace(directoryConnectionPath)) + { + throw new ArgumentNullException(nameof(directoryConnectionPath)); + } + + DirectoryConnection directory = GetLdapConnection(directoryConnectionPath); + if (directory == null) { return false; } + return this.LdapConnections.Remove(directory); + } + /// /// If it is valid, commits the current settings to the SharePoint settings database /// From e0dbbad86a472699e63df497a0eafdd16adb485b Mon Sep 17 00:00:00 2001 From: Yvan Duhamel Date: Tue, 7 May 2024 10:58:28 +0200 Subject: [PATCH 13/15] ask for confirmation before deleting connection --- .../TEMPLATE/ADMIN/LDAPCPSE/GlobalSettings.ascx | 4 ++-- .../ADMIN/LDAPCPSE/GlobalSettings.ascx.cs | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Yvand.LDAPCPSE/TEMPLATE/ADMIN/LDAPCPSE/GlobalSettings.ascx b/Yvand.LDAPCPSE/TEMPLATE/ADMIN/LDAPCPSE/GlobalSettings.ascx index 180d0df..3cc9e74 100644 --- a/Yvand.LDAPCPSE/TEMPLATE/ADMIN/LDAPCPSE/GlobalSettings.ascx +++ b/Yvand.LDAPCPSE/TEMPLATE/ADMIN/LDAPCPSE/GlobalSettings.ascx @@ -262,12 +262,12 @@
  • diff --git a/Yvand.LDAPCPSE/TEMPLATE/ADMIN/LDAPCPSE/GlobalSettings.ascx.cs b/Yvand.LDAPCPSE/TEMPLATE/ADMIN/LDAPCPSE/GlobalSettings.ascx.cs index bb517c9..132e35d 100644 --- a/Yvand.LDAPCPSE/TEMPLATE/ADMIN/LDAPCPSE/GlobalSettings.ascx.cs +++ b/Yvand.LDAPCPSE/TEMPLATE/ADMIN/LDAPCPSE/GlobalSettings.ascx.cs @@ -51,9 +51,9 @@ protected void Initialize() LabelMessage.Text = String.Format(TextSummaryPersistedObjectInformation, Configuration.Name, Configuration.Version, Configuration.Id); UserIdentifierEncodedValuePrefix = base.UserIdentifierEncodedValuePrefix; GroupIdentifierEncodedValuePrefix = base.GroupIdentifierEncodedValuePrefix; - PopulateConnectionsGrid(); if (!this.IsPostBack) { + PopulateConnectionsGrid(); PopulateCblAuthenticationTypes(); PopulateFields(); InitializeAugmentation(); @@ -401,6 +401,19 @@ void AddTenantConnection() this.TxtLdapUsername.Text = String.Empty; this.TxtLdapPassword.Text = String.Empty; } + + protected void grdLDAPConnections_RowDataBound(object sender, GridViewRowEventArgs e) + { + // Ask user for confirmation when cliking on button Delete - https://stackoverflow.com/questions/9026884/asp-net-gridview-delete-row-only-on-confirmation + if (e.Row.RowType == DataControlRowType.DataRow) + { + Button deleteButton = (Button)e.Row.Cells[3].Controls[0]; + if (deleteButton != null && String.Equals(deleteButton.Text, "Delete", StringComparison.OrdinalIgnoreCase)) + { + deleteButton.OnClientClick = "if(!confirm('Are you sure you want to delete this directory?')) return;"; + } + } + } } public class PropertyCollectionBinder From d46d04496b014bff94341998c7293903a233eb84 Mon Sep 17 00:00:00 2001 From: Yvan Duhamel Date: Tue, 7 May 2024 12:00:32 +0200 Subject: [PATCH 14/15] fix repository name hosting the reusable workflows --- .github/workflows/publish-production-release.yml | 2 +- .github/workflows/run-tests.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish-production-release.yml b/.github/workflows/publish-production-release.yml index ad6e85c..b3b9914 100644 --- a/.github/workflows/publish-production-release.yml +++ b/.github/workflows/publish-production-release.yml @@ -2,7 +2,7 @@ name: Publish production release on: workflow_dispatch jobs: call-workflow-publish-nightly-release: - uses: Yvand/AzureCP/.github/workflows/reusable-build-publish-release.yml@master + uses: Yvand/EntraCP/.github/workflows/reusable-build-publish-release.yml@master with: project-name: ${{ vars.PROJECT_NAME }} version-major-minor: ${{ vars.VERSION_MAJOR_MINOR }} diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 4d3225d..ac71b5e 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -16,7 +16,7 @@ on: jobs: call-workflow-prepare-dtl-env: - uses: Yvand/AzureCP/.github/workflows/reusable-prepare-dtl-env.yml@master + uses: Yvand/EntraCP/.github/workflows/reusable-prepare-dtl-env.yml@master with: project-name: ${{ vars.PROJECT_NAME }} sharepoint-versions: ${{ inputs.sharepoint_versions }} From 680609ccafe489f75588837fc7d271c90de2ee0e Mon Sep 17 00:00:00 2001 From: Yvan Duhamel Date: Tue, 7 May 2024 16:14:14 +0200 Subject: [PATCH 15/15] update build workflow --- .../workflows/{verify-prs-and-commits.yml => build.yml} | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) rename .github/workflows/{verify-prs-and-commits.yml => build.yml} (77%) diff --git a/.github/workflows/verify-prs-and-commits.yml b/.github/workflows/build.yml similarity index 77% rename from .github/workflows/verify-prs-and-commits.yml rename to .github/workflows/build.yml index 6a223cd..65c9365 100644 --- a/.github/workflows/verify-prs-and-commits.yml +++ b/.github/workflows/build.yml @@ -1,11 +1,13 @@ -name: Verify PRs and commits +name: Build code on: workflow_dispatch: push: - branches: [ "master", "dev" ] + branches: + - master + - 'releases/**' pull_request: - branches: [ "master", "dev" ] + branches: [ "master", "releases/**" ] jobs: call-build:
    @@ -272,14 +272,14 @@
    @@ -337,11 +337,11 @@

    - + - - + +

    @@ -354,8 +354,8 @@

    -
    - +
    +
    - - + + - - + +

    @@ -438,8 +438,8 @@

    -
    - +
    +

    @@ -492,18 +492,16 @@ -
    -
    + + - - - -
    + +
    - -
    - + +
    +
    - + - +

    -
    +
    - + - + - - - + + +
    - +
    - +
    -
    - +
    +
    + +
    + - +
    - + - - + + - + - - + + - + - - + + - - + +
    @@ -421,11 +421,11 @@
    @@ -525,58 +523,61 @@
    From 57c31183b3e2a922853a0b8e45381974eb16faa5 Mon Sep 17 00:00:00 2001 From: Yvan Duhamel Date: Wed, 20 Mar 2024 17:54:22 +0100 Subject: [PATCH 03/15] Update GlobalSettings.ascx --- Yvand.LDAPCPSE/TEMPLATE/ADMIN/LDAPCPSE/GlobalSettings.ascx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Yvand.LDAPCPSE/TEMPLATE/ADMIN/LDAPCPSE/GlobalSettings.ascx b/Yvand.LDAPCPSE/TEMPLATE/ADMIN/LDAPCPSE/GlobalSettings.ascx index cbcadd5..ff42204 100644 --- a/Yvand.LDAPCPSE/TEMPLATE/ADMIN/LDAPCPSE/GlobalSettings.ascx +++ b/Yvand.LDAPCPSE/TEMPLATE/ADMIN/LDAPCPSE/GlobalSettings.ascx @@ -499,7 +499,7 @@
    - +
    - + - +