17 using System.Collections.Generic;
18 using System.ComponentModel;
19 using System.DirectoryServices;
20 using System.DirectoryServices.AccountManagement;
36 [TypeDescriptionProvider(typeof(PrncplDescriptionProvider))]
37 public sealed
class AcUser : IFormattable, IEquatable<AcUser>, IComparable<AcUser>, IComparable
39 #region class variables
41 private string _givenName;
42 private string _middleName;
43 private string _surname;
44 private string _displayName;
45 private string _business;
46 private string _emailAddress;
47 private string _description;
48 private string _distinguishedName;
50 private Dictionary<string, object> _other =
new Dictionary<string, object>();
65 _principal.Name = name;
66 _principal.Status = status;
69 #region Equality comparison
81 if (ReferenceEquals(other, null))
return false;
82 if (ReferenceEquals(
this, other))
return true;
90 public override bool Equals(
object other)
92 if (ReferenceEquals(other, null))
return false;
93 if (ReferenceEquals(
this, other))
return true;
94 if (GetType() != other.GetType())
return false;
109 #region Order comparison
122 if (
AcUser.ReferenceEquals(
this, other))
141 int IComparable.CompareTo(
object other)
144 throw new ArgumentException(
"Argument is not an AcUser",
"other");
158 get {
return _principal; }
168 get {
return _givenName ?? String.Empty; }
176 get {
return _middleName ?? String.Empty; }
184 get {
return _surname ?? String.Empty; }
192 get {
return _displayName ?? String.Empty; }
200 get {
return _business ?? String.Empty; }
208 get {
return _emailAddress ?? String.Empty; }
216 get {
return _description ?? String.Empty; }
224 get {
return _distinguishedName ?? String.Empty; }
262 public IDictionary<string, object>
Other
264 get {
return _other; }
268 public string ToString(
string format, IFormatProvider provider)
291 if (provider != null)
293 ICustomFormatter fmt = provider.GetFormat(this.GetType()) as ICustomFormatter;
295 return fmt.Format(format,
this, provider);
298 if (String.IsNullOrEmpty(format))
301 switch (format.ToUpperInvariant())
306 return $
"{DisplayName} ({Principal.Name}), Business: {(String.IsNullOrEmpty(Business) ? "N/A
" : Business)}, {EmailAddress}";
330 throw new FormatException($
"The {format} format string is not supported.");
335 public string ToString(
string format)
363 return await Task.Run(() =>
368 PrincipalContext ad = null;
371 ad =
new PrincipalContext(ContextType.Domain, de.
Host.Trim(), de.
Path.Trim());
372 UserPrincipal up =
new UserPrincipal(ad);
374 using (PrincipalSearcher ps =
new PrincipalSearcher(up))
376 UserPrincipal rs = (UserPrincipal)ps.FindOne();
379 _givenName = rs.GivenName;
380 _middleName = rs.MiddleName;
381 _surname = rs.Surname;
382 _displayName = rs.DisplayName;
383 _business = rs.VoiceTelephoneNumber;
384 _emailAddress = rs.EmailAddress;
385 _description = rs.Description;
386 _distinguishedName = rs.DistinguishedName;
390 DirectoryEntry lowerLdap = (DirectoryEntry)rs.GetUnderlyingObject();
393 PropertyValueCollection pvc = lowerLdap.Properties[pe.
Field];
395 _other.Add(pe.
Title.Trim(), pvc.Value);
404 catch (Exception ecx)
407 AcDebug.
Log($
"Exception caught and logged in AcUser.initFromADAsync{Environment.NewLine}{ecx.Message}");
411 finally {
if (ad != null) ad.Dispose(); }
415 }).ConfigureAwait(
false);
441 .ConfigureAwait(
false);
442 if (r != null && r.
RetVal == 0)
444 SortedSet<string> members =
new SortedSet<string>();
445 XElement xml = XElement.Parse(r.
CmdResult);
446 foreach (XElement e
in xml.Elements(
"Element"))
448 string name = (string)e.Attribute(
"Name");
459 AcDebug.
Log($
"AcUtilsException caught and logged in AcUser.initGroupsListAsync{Environment.NewLine}{ecx.Message}");
462 catch (Exception ecx)
464 AcDebug.
Log($
"Exception caught and logged in AcUser.initGroupsListAsync{Environment.NewLine}{ecx.Message}");
499 #region class variables
502 private bool _includeGroupsList;
503 private bool _includeDeactivated;
504 [NonSerialized]
private readonly
object _locker =
new object();
505 [NonSerialized]
private int _counter;
508 #region object construction:
552 _includeGroupsList = includeGroupsList;
553 _includeDeactivated = includeDeactivated;
565 public async Task<bool>
initAsync(IProgress<int> progress = null)
571 .ConfigureAwait(
false);
572 if (r != null && r.
RetVal == 0)
574 XElement xml = XElement.Parse(r.
CmdResult);
575 IEnumerable<XElement> query =
from element in xml.Elements(
"Element") select element;
576 List<Task<bool>> tasks =
new List<Task<bool>>(query.Count());
577 Func<Task<bool>,
bool> cf = t =>
580 if (res && progress != null) progress.Report(Interlocked.Increment(ref _counter));
584 foreach (XElement e
in query)
586 string name = (string)e.Attribute(
"Name");
587 int id = (int)e.Attribute(
"Number");
591 lock (_locker) { Add(
user); }
596 bool[] arr = await Task.WhenAll(tasks).ConfigureAwait(
false);
597 ret = (arr != null && arr.All(n => n ==
true));
603 AcDebug.
Log($
"AcUtilsException caught and logged in AcUsers.initAsync{Environment.NewLine}{ecx.Message}");
606 catch (Exception ecx)
608 AcDebug.
Log($
"Exception caught and logged in AcUsers.initAsync{Environment.NewLine}{ecx.Message}");
629 if (_dc != null && _includeGroupsList)
631 Task<bool>[] tasks =
new Task<bool>[2];
636 bool[] arr = await Task.WhenAll(tasks).ConfigureAwait(
false);
637 ret = (arr != null && arr.All(n => n ==
true));
639 else if (_dc != null && !_includeGroupsList)
641 else if (_dc == null && _includeGroupsList)
647 catch (Exception ecx)
649 AcDebug.
Log($
"Exception caught and logged in AcUsers.initUserPropsAsync{Environment.NewLine}{ecx.Message}");
662 return this.SingleOrDefault(n => n.Principal.Name == name);
672 return this.SingleOrDefault(n => n.Principal.ID == ID);
682 int ii = name.LastIndexOf(
'_');
683 string prncpl = name.Substring(++ii);
string Surname
User's surname from Active Directory, e.g. Doe
AcUser getWorkspaceOwner(string name)
Get the AcUser object owner of AccuRev workspace name.
int ID
AccuRev principal ID number for the user or group.
string Business
User's business phone number from Active Directory.
AcUser getUser(int ID)
Get the AcUser object for AccuRev principal ID number.
AcPrincipal Principal
AccuRev principal attributes name, ID, and status (active or inactive), and optionally their group me...
AccuRev program return value and command result.
An Active Directory domain element host-path pair from
.exe.config.
An Active Directory user property element field-title pair from
.exe.config. These are user properties not in the regular default set.
string Description
User's description from Active Directory.
The list of Active Directory user property field-title pairs from
.exe.config. These are user properties not in the regular default set.
async Task< bool > initGroupsListAsync()
Optionally called during list construction to initialize the list of groups this user is a member of ...
string Field
The field from a field-title pair in
.exe.config.
int CompareTo(AcUser other)
Generic IComparable implementation (default) for comparing AcUser objects to sort by DisplayName from...
A user's AccuRev principal attributes name, ID, and status (active or inactive). In addition...
override int GetHashCode()
Override appropriate for type AcUser.
IDictionary< string, object > Other
Additional Active Directory user properties not in the regular default set.
bool Equals(AcUser other)
IEquatable implementation to determine the equality of instances of type AcUser. Uses the user's prin...
string ToString(string format, IFormatProvider provider)
The ToString implementation.
string Title
The title from a field-title pair in
.exe.config.
The list of Active Directory domain host-path pairs from
.exe.config.
PrinStatus
Whether the principal is active or inactive in AccuRev.
Contains the AccuRev principal attributes name, ID and status (active or inactive) for users and grou...
string EmailAddress
User's email address from Active Directory.
async Task< bool > initAsync(IProgress< int > progress=null)
Populate this container with AcUser objects as per constructor parameters.
string Host
The host from a host-path pair in
.exe.config.
string DistinguishedName
User's distinguished name from Active Directory.
string getGroups()
Get the list of groups this user is a member of as a formatted string. List optionally initialized by...
string CmdResult
The command result (usually XML) emitted by AccuRev.
int RetVal
The AccuRev program return value for the command, otherwise minus one (-1) on error.
static void Log(string message, bool formatting=true)
Write the message text to STDOUT, to weekly log files located in %LOCALAPPDATA%\AcTools\Logs, and to trigger.log in the AccuRev server's ..storage\site_slice\logs folder in the case of triggers.
async Task< bool > initUserPropsAsync(AcUser user)
Helper function for initializing user with their Active Directory properties and group memberships as...
string Name
AccuRev principal name for the user or group.
async Task< bool > initFromADAsync(DomainCollection dc, PropCollection pc=null)
Optionally called during list construction to initialize the default set of regular user properties a...
string MiddleName
User's middle name from Active Directory.
Exception thrown when an AccuRev command fails. The AccuRev program return value is zero (0) on succe...
AccuRev command processing.
static async Task< AcResult > runAsync(string command, ICmdValidate validator=null)
Run the AccuRev command asynchronously with non-blocking I/O.
Use to log and display error and general purpose text messages, and to save the XML param data sent b...
string GivenName
User's given name from Active Directory, e.g. John
A container of AcUser objects that define AccuRev users.
override bool Equals(object other)
Overridden to determine equality.
SortedSet< string > Members
The list of groups a user has membership in, or the list of principals (users and groups) in a group...
string DisplayName
User's display name from Active Directory, e.g. Doe, John
AcUser(int id, string name, PrinStatus status)
Initialize user's AccuRev principal attributes name, ID, and status (active or inactive). AcUser objects are instantiated during AcUsers list construction. This constructor is called internally and not by user code.
PrinStatus Status
Whether the principal is active or inactive in AccuRev.
AcUsers(DomainCollection dc=null, PropCollection pc=null, bool includeGroupsList=false, bool includeDeactivated=false)
A container of AcUser objects that define AccuRev users. Elements contain user principal attributes n...
AcUser getUser(string name)
Get the AcUser object for AccuRev principal name.
string Path
The path from a host-path pair in
.exe.config.