@@ -32,26 +32,30 @@ public class ActiveDirectory
32
32
/// Active Directory Password for Querying
33
33
/// </summary>
34
34
private static string adPassword = ConfigurationManager . AppSettings [ "API_AD_PASSWORD" ] ;
35
+
36
+ /// <summary>
37
+ /// Active Directory custom properties for Querying
38
+ /// </summary>
39
+ private static List < string > adCustomProperties = ( ConfigurationManager . AppSettings [ "API_AD_CUSTOM_PROPERTIES" ] ) . Split ( ',' ) . ToList < string > ( ) ;
35
40
#endregion
36
41
37
42
#region Methods
38
43
/// <summary>
39
44
/// This method returns the entire Active Directory list for the configure Domain
40
45
/// </summary>
41
46
/// <returns></returns>
42
- private static IDictionary < string , dynamic > GetDirectory ( )
47
+ private static IDictionary < string , dynamic > GetDirectory < T > ( ) where T : UserPrincipal
43
48
{
44
49
Log . Instance . Info ( "AD Domain: " + adDomain ) ;
45
50
Log . Instance . Info ( "AD Path: " + adPath ) ;
46
51
Log . Instance . Info ( "AD Username: " + adUsername ) ;
47
52
Log . Instance . Info ( "AD Password: ********" ) ; // Hide adPassword from logs
48
53
49
- // Initilise a new dynamic object
50
- dynamic adUsers = new ExpandoObject ( ) ;
51
- // Implement the interface for handling dynamic properties
52
- var adUsers_IDictionary = adUsers as IDictionary < string , dynamic > ;
54
+ // new ExpandoObject() and implement the interface for handling dynamic properties
55
+ var adUsers_IDictionary = new ExpandoObject ( ) as IDictionary < string , dynamic > ;
53
56
54
- MemCachedD_Value adCache = MemCacheD . Get_BSO < dynamic > ( "API" , "ActiveDirectory" , "GetDirectory" , null ) ;
57
+ var inputDTO = Utility . JsonSerialize_IgnoreLoopingReference ( Activator . CreateInstance ( typeof ( T ) , new object [ ] { new PrincipalContext ( ContextType . Domain ) } ) as T ) ;
58
+ MemCachedD_Value adCache = MemCacheD . Get_BSO < dynamic > ( "API" , "ActiveDirectory" , "GetDirectory" , inputDTO ) ;
55
59
if ( adCache . hasData )
56
60
return adCache . data . ToObject < Dictionary < string , dynamic > > ( ) ;
57
61
@@ -60,11 +64,20 @@ private static IDictionary<string, dynamic> GetDirectory()
60
64
// Get to the Domain
61
65
using ( var context = new PrincipalContext ( ContextType . Domain , adDomain , String . IsNullOrEmpty ( adPath ) ? null : adPath , String . IsNullOrEmpty ( adUsername ) ? null : adUsername , String . IsNullOrEmpty ( adPassword ) ? null : adPassword ) )
62
66
{
63
- // Get to the Search, filtering by Enabled accounts, exclude accounts with blank properties
64
- using ( var searcher = new PrincipalSearcher ( new UserPrincipal ( context ) { Enabled = true , SamAccountName = "*" , EmailAddress = "*" , GivenName = "*" , Surname = "*" } ) )
67
+ // Crete the query filterusing enabled accounts and excluding those with blank basic properties
68
+ var queryFilter = Activator . CreateInstance ( typeof ( T ) , new object [ ] { context } ) as T ;
69
+ queryFilter . Enabled = true ;
70
+ queryFilter . SamAccountName = "*" ;
71
+ queryFilter . EmailAddress = "*" ;
72
+ queryFilter . GivenName = "*" ;
73
+ queryFilter . Surname = "*" ;
74
+
75
+ // Run the search
76
+ using ( var searcher = new PrincipalSearcher ( queryFilter ) )
65
77
{
66
78
// Loop trough the results and sort then by SamAccountName
67
- foreach ( var result in searcher . FindAll ( ) . Cast < UserPrincipal > ( ) . OrderBy ( x => x . SamAccountName ) )
79
+ // Cast to dynamic to get all properties including any custom one
80
+ foreach ( var result in searcher . FindAll ( ) . Cast < dynamic > ( ) . OrderBy ( x => x . SamAccountName ) )
68
81
{
69
82
// Check for duplicate accounts
70
83
if ( adUsers_IDictionary . ContainsKey ( result . SamAccountName ) )
@@ -74,23 +87,30 @@ private static IDictionary<string, dynamic> GetDirectory()
74
87
}
75
88
else
76
89
{
77
- // Create a shallow copy of the UserPrincipal with the main proprieties for caching/serialising it later on
78
- dynamic userPrincipal_ShallowCopy = new ExpandoObject ( ) ;
79
- userPrincipal_ShallowCopy . SamAccountName = result . SamAccountName ;
80
- userPrincipal_ShallowCopy . UserPrincipalName = result . UserPrincipalName ;
81
- userPrincipal_ShallowCopy . DistinguishedName = result . DistinguishedName ;
82
- userPrincipal_ShallowCopy . DisplayName = result . DisplayName ;
83
- userPrincipal_ShallowCopy . Name = result . Name ;
84
- userPrincipal_ShallowCopy . GivenName = result . GivenName ;
85
- userPrincipal_ShallowCopy . MiddleName = result . MiddleName ;
86
- userPrincipal_ShallowCopy . Surname = result . Surname ;
87
- userPrincipal_ShallowCopy . EmailAddress = result . EmailAddress ;
88
- userPrincipal_ShallowCopy . EmployeeId = result . EmployeeId ;
89
- userPrincipal_ShallowCopy . VoiceTelephoneNumber = result . VoiceTelephoneNumber ;
90
- userPrincipal_ShallowCopy . Description = result . Description ;
90
+ // Create a shallow copy of AD with the mandatory proprieties for caching/serialising it later on
91
+ var userPrincipal_ShallowCopy = new ExpandoObject ( ) as IDictionary < string , Object > ;
92
+
93
+ userPrincipal_ShallowCopy . Add ( "SamAccountName" , result . SamAccountName ) ;
94
+ userPrincipal_ShallowCopy . Add ( "UserPrincipalName" , result . UserPrincipalName ) ;
95
+ userPrincipal_ShallowCopy . Add ( "DistinguishedName" , result . DistinguishedName ) ;
96
+ userPrincipal_ShallowCopy . Add ( "DisplayName" , result . DisplayName ) ;
97
+ userPrincipal_ShallowCopy . Add ( "Name" , result . Name ) ;
98
+ userPrincipal_ShallowCopy . Add ( "GivenName" , result . GivenName ) ;
99
+ userPrincipal_ShallowCopy . Add ( "MiddleName" , result . MiddleName ) ;
100
+ userPrincipal_ShallowCopy . Add ( "Surname" , result . Surname ) ;
101
+ userPrincipal_ShallowCopy . Add ( "EmailAddress" , result . EmailAddress ) ;
102
+ userPrincipal_ShallowCopy . Add ( "EmployeeId" , result . EmployeeId ) ;
103
+ userPrincipal_ShallowCopy . Add ( "VoiceTelephoneNumber" , result . VoiceTelephoneNumber ) ;
104
+ userPrincipal_ShallowCopy . Add ( "Description" , result . Description ) ;
105
+
106
+ // Add the cusotm properties to the shallow copy if any
107
+ foreach ( string property in adCustomProperties )
108
+ {
109
+ userPrincipal_ShallowCopy . Add ( property , result . GetType ( ) . GetProperty ( property ) ? . GetValue ( result , null ) ) ;
110
+ }
91
111
92
112
// Add user to the dictionary, serialise/deserialise to avoid looping references
93
- adUsers_IDictionary . Add ( result . SamAccountName , userPrincipal_ShallowCopy ) ;
113
+ adUsers_IDictionary . Add ( result . SamAccountName , userPrincipal_ShallowCopy as ExpandoObject ) ;
94
114
}
95
115
}
96
116
}
@@ -103,7 +123,7 @@ private static IDictionary<string, dynamic> GetDirectory()
103
123
}
104
124
105
125
// Set the cache to expire at midnight
106
- MemCacheD . Store_BSO < dynamic > ( "API" , "ActiveDirectory" , "GetDirectory" , null , adUsers_IDictionary , DateTime . Today . AddDays ( 1 ) ) ;
126
+ MemCacheD . Store_BSO < dynamic > ( "API" , "ActiveDirectory" , "GetDirectory" , inputDTO , adUsers_IDictionary , DateTime . Today . AddDays ( 1 ) ) ;
107
127
108
128
return adUsers_IDictionary ;
109
129
}
@@ -115,7 +135,12 @@ private static IDictionary<string, dynamic> GetDirectory()
115
135
public static IDictionary < string , dynamic > List ( )
116
136
{
117
137
// Get the full directory
118
- return GetDirectory ( ) ;
138
+ return List < UserPrincipal > ( ) ;
139
+ }
140
+ public static IDictionary < string , dynamic > List < T > ( ) where T : UserPrincipal
141
+ {
142
+ // Get the full directory
143
+ return GetDirectory < T > ( ) ;
119
144
}
120
145
121
146
/// <summary>
@@ -124,9 +149,13 @@ public static IDictionary<string, dynamic> List()
124
149
/// <param name="username"></param>
125
150
/// <returns></returns>
126
151
public static dynamic Search ( string username )
152
+ {
153
+ return Search < UserPrincipal > ( username ) ;
154
+ }
155
+ public static dynamic Search < T > ( string username ) where T : UserPrincipal
127
156
{
128
157
// Get the full director
129
- IDictionary < string , dynamic > adDirectory = GetDirectory ( ) ;
158
+ IDictionary < string , dynamic > adDirectory = GetDirectory < T > ( ) ;
130
159
131
160
if ( adDirectory . ContainsKey ( username ) )
132
161
return adDirectory [ username ] ;
@@ -167,4 +196,30 @@ public static bool IsPasswordValid(dynamic userPrincipal, string password)
167
196
168
197
}
169
198
199
+ /// <summary>
200
+ /// Template to implement a extended UserPrincipal to retrieve custom AD properties (i.e. Sample)
201
+ /// </summary>
202
+ /*
203
+ [DirectoryRdnPrefix("CN")]
204
+ [DirectoryObjectClass("Person")]
205
+ public partial class UserPrincipalExtended : UserPrincipal
206
+ {
207
+ public UserPrincipalExtended(PrincipalContext context) : base(context) { }
208
+
209
+
210
+ // Create the "Sample" property.
211
+ [DirectoryProperty("sample")]
212
+ public string Sample
213
+ {
214
+ get
215
+ {
216
+ if (ExtensionGet("sample").Length != 1)
217
+ return string.Empty;
218
+
219
+ return (string)ExtensionGet("sample")[0];
220
+ }
221
+ set { ExtensionSet("sample", value); }
222
+ }
223
+ }
224
+ */
170
225
}
0 commit comments