maintenance: AD integration refactoring
This commit is contained in:
@@ -270,6 +270,17 @@ namespace Disco.Services.Interop.ActiveDirectory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IADObject RetrieveADObjectByDistinguishedName(string distinguishedName, bool quick, string[] additionalProperties = null)
|
||||||
|
{
|
||||||
|
using (var entry = RetrieveDirectoryEntry(distinguishedName, additionalProperties))
|
||||||
|
{
|
||||||
|
if (entry == null)
|
||||||
|
return null;
|
||||||
|
else
|
||||||
|
return entry.AsADObject(quick, additionalProperties);
|
||||||
|
}
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Organisational Units
|
#region Organisational Units
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace Disco.Services.Interop.ActiveDirectory
|
|||||||
{
|
{
|
||||||
public class ADGroup : IADObject
|
public class ADGroup : IADObject
|
||||||
{
|
{
|
||||||
internal static readonly string[] LoadProperties = { "name", "distinguishedName", "sAMAccountName", "objectSid", "memberOf" };
|
internal static readonly string[] LoadProperties = { "name", "distinguishedName", "sAMAccountName", "objectSid", "memberOf", "member" };
|
||||||
internal static string LdapSearchFilterTemplate = "(&(objectCategory=Group)(|(sAMAccountName={0}*)(name={0}*)(cn={0}*)))";
|
internal static string LdapSearchFilterTemplate = "(&(objectCategory=Group)(|(sAMAccountName={0}*)(name={0}*)(cn={0}*)))";
|
||||||
internal const string LdapSamAccountNameFilterTemplate = "(&(objectCategory=Group)(sAMAccountName={0}))";
|
internal const string LdapSamAccountNameFilterTemplate = "(&(objectCategory=Group)(sAMAccountName={0}))";
|
||||||
internal const string LdapSecurityIdentifierFilterTemplate = "(&(objectCategory=Group)(objectSid={0}))";
|
internal const string LdapSecurityIdentifierFilterTemplate = "(&(objectCategory=Group)(objectSid={0}))";
|
||||||
@@ -23,11 +23,13 @@ namespace Disco.Services.Interop.ActiveDirectory
|
|||||||
public string Name { get; private set; }
|
public string Name { get; private set; }
|
||||||
public string DisplayName { get { return Name; } }
|
public string DisplayName { get { return Name; } }
|
||||||
|
|
||||||
public List<string> MemberOf { get; private set; }
|
public List<string> MemberOf { get; }
|
||||||
|
|
||||||
|
public List<string> Members { get; }
|
||||||
|
|
||||||
public Dictionary<string, object[]> LoadedProperties { get; private set; }
|
public Dictionary<string, object[]> LoadedProperties { get; private set; }
|
||||||
|
|
||||||
private ADGroup(ADDomain Domain, string DistinguishedName, SecurityIdentifier SecurityIdentifier, string SamAccountName, string Name, List<string> MemberOf, Dictionary<string, object[]> LoadedProperties)
|
private ADGroup(ADDomain Domain, string DistinguishedName, SecurityIdentifier SecurityIdentifier, string SamAccountName, string Name, List<string> MemberOf, List<string> Members, Dictionary<string, object[]> LoadedProperties)
|
||||||
{
|
{
|
||||||
this.Domain = Domain;
|
this.Domain = Domain;
|
||||||
this.DistinguishedName = DistinguishedName;
|
this.DistinguishedName = DistinguishedName;
|
||||||
@@ -35,6 +37,7 @@ namespace Disco.Services.Interop.ActiveDirectory
|
|||||||
this.SamAccountName = SamAccountName;
|
this.SamAccountName = SamAccountName;
|
||||||
this.Name = Name;
|
this.Name = Name;
|
||||||
this.MemberOf = MemberOf;
|
this.MemberOf = MemberOf;
|
||||||
|
this.Members = Members;
|
||||||
this.LoadedProperties = LoadedProperties;
|
this.LoadedProperties = LoadedProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,6 +51,7 @@ namespace Disco.Services.Interop.ActiveDirectory
|
|||||||
var sAMAccountName = SearchResult.Value<string>("sAMAccountName");
|
var sAMAccountName = SearchResult.Value<string>("sAMAccountName");
|
||||||
var objectSid = new SecurityIdentifier(SearchResult.Value<byte[]>("objectSid"), 0);
|
var objectSid = new SecurityIdentifier(SearchResult.Value<byte[]>("objectSid"), 0);
|
||||||
var memberOf = SearchResult.Values<string>("memberOf").ToList();
|
var memberOf = SearchResult.Values<string>("memberOf").ToList();
|
||||||
|
var members = SearchResult.Values<string>("member").ToList();
|
||||||
|
|
||||||
// Additional Properties
|
// Additional Properties
|
||||||
Dictionary<string, object[]> additionalProperties;
|
Dictionary<string, object[]> additionalProperties;
|
||||||
@@ -60,7 +64,7 @@ namespace Disco.Services.Interop.ActiveDirectory
|
|||||||
additionalProperties = new Dictionary<string, object[]>();
|
additionalProperties = new Dictionary<string, object[]>();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ADGroup(SearchResult.Domain, distinguishedName, objectSid, sAMAccountName, name, memberOf, additionalProperties);
|
return new ADGroup(SearchResult.Domain, distinguishedName, objectSid, sAMAccountName, name, memberOf, members, additionalProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ADGroup FromDirectoryEntry(ADDirectoryEntry DirectoryEntry, string[] AdditionalProperties)
|
public static ADGroup FromDirectoryEntry(ADDirectoryEntry DirectoryEntry, string[] AdditionalProperties)
|
||||||
@@ -75,6 +79,7 @@ namespace Disco.Services.Interop.ActiveDirectory
|
|||||||
var sAMAccountName = properties.Value<string>("sAMAccountName");
|
var sAMAccountName = properties.Value<string>("sAMAccountName");
|
||||||
var objectSid = new SecurityIdentifier(properties.Value<byte[]>("objectSid"), 0);
|
var objectSid = new SecurityIdentifier(properties.Value<byte[]>("objectSid"), 0);
|
||||||
var memberOf = properties.Values<string>("memberOf").ToList();
|
var memberOf = properties.Values<string>("memberOf").ToList();
|
||||||
|
var members = properties.Values<string>("member").ToList();
|
||||||
|
|
||||||
Dictionary<string, object[]> additionalProperties;
|
Dictionary<string, object[]> additionalProperties;
|
||||||
if (AdditionalProperties != null)
|
if (AdditionalProperties != null)
|
||||||
@@ -86,7 +91,7 @@ namespace Disco.Services.Interop.ActiveDirectory
|
|||||||
additionalProperties = new Dictionary<string, object[]>();
|
additionalProperties = new Dictionary<string, object[]>();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ADGroup(DirectoryEntry.Domain, distinguishedName, objectSid, sAMAccountName, name, memberOf, additionalProperties);
|
return new ADGroup(DirectoryEntry.Domain, distinguishedName, objectSid, sAMAccountName, name, memberOf, members, additionalProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete("Use generic equivalents: GetPropertyValue<T>(string PropertyName)")]
|
[Obsolete("Use generic equivalents: GetPropertyValue<T>(string PropertyName)")]
|
||||||
@@ -113,6 +118,8 @@ namespace Disco.Services.Interop.ActiveDirectory
|
|||||||
return new SecurityIdentifier[] { SecurityIdentifier }.OfType<T>();
|
return new SecurityIdentifier[] { SecurityIdentifier }.OfType<T>();
|
||||||
case "memberof":
|
case "memberof":
|
||||||
return MemberOf.OfType<T>();
|
return MemberOf.OfType<T>();
|
||||||
|
case "member":
|
||||||
|
return Members.OfType<T>();
|
||||||
default:
|
default:
|
||||||
object[] adProperty;
|
object[] adProperty;
|
||||||
if (LoadedProperties.TryGetValue(PropertyName, out adProperty))
|
if (LoadedProperties.TryGetValue(PropertyName, out adProperty))
|
||||||
@@ -122,6 +129,42 @@ namespace Disco.Services.Interop.ActiveDirectory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerable<ADUserAccount> GetUserMembersRecursive()
|
||||||
|
{
|
||||||
|
var foundGroups = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
return GetUserMembersRecursive(foundGroups);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<ADUserAccount> GetUserMembersRecursive(HashSet<string> foundGroups)
|
||||||
|
{
|
||||||
|
if (!foundGroups.Add(DistinguishedName))
|
||||||
|
yield break;
|
||||||
|
|
||||||
|
var memberGroups = new List<ADGroup>();
|
||||||
|
foreach (var memberDn in Members)
|
||||||
|
{
|
||||||
|
if (foundGroups.Contains(memberDn))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var adObject = ActiveDirectory.RetrieveADObjectByDistinguishedName(memberDn, true);
|
||||||
|
|
||||||
|
if (adObject == null)
|
||||||
|
continue;
|
||||||
|
else if (adObject is ADGroup group)
|
||||||
|
memberGroups.Add(group);
|
||||||
|
else if (adObject is ADUserAccount adUser)
|
||||||
|
yield return adUser;
|
||||||
|
}
|
||||||
|
foreach (var group in memberGroups)
|
||||||
|
{
|
||||||
|
if (foundGroups.Contains(group.DistinguishedName))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
foreach (var adUser in group.GetUserMembersRecursive(foundGroups))
|
||||||
|
yield return adUser;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return Id;
|
return Id;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.DirectoryServices;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Security.Principal;
|
using System.Security.Principal;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -108,6 +109,56 @@ namespace Disco.Services.Interop.ActiveDirectory
|
|||||||
additionalProperties);
|
additionalProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ADMachineAccount FromDirectoryEntry(ADDirectoryEntry directoryEntry, string[] additionalProperties)
|
||||||
|
{
|
||||||
|
if (directoryEntry == null)
|
||||||
|
throw new ArgumentNullException(nameof(directoryEntry));
|
||||||
|
|
||||||
|
var properties = directoryEntry.Entry.Properties;
|
||||||
|
|
||||||
|
var name = properties.Value<string>("name");
|
||||||
|
var description = properties.Value<string>("description");
|
||||||
|
var sAMAccountName = properties.Value<string>("sAMAccountName");
|
||||||
|
var distinguishedName = properties.Value<string>("distinguishedName");
|
||||||
|
var objectSid = new SecurityIdentifier(properties.Value<byte[]>("objectSid"), 0);
|
||||||
|
|
||||||
|
var dNSName = properties.Value<string>("dNSHostName");
|
||||||
|
if (dNSName == null)
|
||||||
|
dNSName = string.Format("{0}.{1}", sAMAccountName.TrimEnd('$'), directoryEntry.Domain.Name);
|
||||||
|
|
||||||
|
var userAccountControl = (ADUserAccountControlFlags)properties.Value<int>("userAccountControl");
|
||||||
|
var isCriticalSystemObject = properties.Value<bool>("isCriticalSystemObject");
|
||||||
|
|
||||||
|
var netbootGUID = default(Guid);
|
||||||
|
var netbootGuidBytes = properties.Value<byte[]>("netbootGUID");
|
||||||
|
if (netbootGuidBytes != null)
|
||||||
|
netbootGUID = new Guid(netbootGuidBytes);
|
||||||
|
|
||||||
|
// Additional Properties
|
||||||
|
Dictionary<string, object[]> additionalProps;
|
||||||
|
if (additionalProperties != null)
|
||||||
|
additionalProps = additionalProperties
|
||||||
|
.Select(p => Tuple.Create(p, properties.Values<object>(p).ToArray()))
|
||||||
|
.ToDictionary(t => t.Item1, t => t.Item2);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
additionalProps = new Dictionary<string, object[]>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ADMachineAccount(
|
||||||
|
directoryEntry.Domain,
|
||||||
|
distinguishedName,
|
||||||
|
objectSid,
|
||||||
|
sAMAccountName,
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
dNSName,
|
||||||
|
netbootGUID,
|
||||||
|
userAccountControl,
|
||||||
|
isCriticalSystemObject,
|
||||||
|
additionalProps);
|
||||||
|
}
|
||||||
|
|
||||||
public User ToRepositoryUser()
|
public User ToRepositoryUser()
|
||||||
{
|
{
|
||||||
return new User
|
return new User
|
||||||
|
|||||||
@@ -126,6 +126,72 @@ namespace Disco.Services.Interop.ActiveDirectory
|
|||||||
additionalProperties);
|
additionalProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ADUserAccount FromDirectoryEntry(ADDirectoryEntry directoryEntry, bool quick, string[] additionalProperties)
|
||||||
|
{
|
||||||
|
if (directoryEntry == null)
|
||||||
|
throw new ArgumentNullException(nameof(directoryEntry));
|
||||||
|
|
||||||
|
var properties = directoryEntry.Entry.Properties;
|
||||||
|
|
||||||
|
var name = properties.Value<string>("name");
|
||||||
|
var sAMAccountName = properties.Value<string>("sAMAccountName");
|
||||||
|
var distinguishedName = properties.Value<string>("distinguishedName");
|
||||||
|
var objectSid = new SecurityIdentifier(properties.Value<byte[]>("objectSid"), 0);
|
||||||
|
|
||||||
|
var displayName = properties.Value<string>("displayName") ?? sAMAccountName;
|
||||||
|
var surname = properties.Value<string>("sn");
|
||||||
|
var givenName = properties.Value<string>("givenName");
|
||||||
|
var email = properties.Value<string>("mail");
|
||||||
|
var phone = properties.Value<string>("telephoneNumber");
|
||||||
|
|
||||||
|
var userAccountControl = (ADUserAccountControlFlags)properties.Value<int>("userAccountControl");
|
||||||
|
var isCriticalSystemObject = properties.Value<bool>("isCriticalSystemObject");
|
||||||
|
|
||||||
|
List<ADGroup> groups = null;
|
||||||
|
// Don't load Groups when doing a quick search
|
||||||
|
if (!quick)
|
||||||
|
{
|
||||||
|
var primaryGroupID = properties.Value<int>("primaryGroupID");
|
||||||
|
var primaryGroupSid = ADHelpers.BuildPrimaryGroupSid(objectSid, primaryGroupID);
|
||||||
|
var memberGroups = properties.Values<string>("memberOf");
|
||||||
|
|
||||||
|
var primaryGroup = ActiveDirectory.GroupCache.GetGroup(primaryGroupSid);
|
||||||
|
|
||||||
|
var groupDistinguishedNames =
|
||||||
|
new string[] { primaryGroup.DistinguishedName }
|
||||||
|
.Concat(memberGroups);
|
||||||
|
|
||||||
|
groups = ActiveDirectory.GroupCache.GetRecursiveGroups(groupDistinguishedNames).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Additional Properties
|
||||||
|
Dictionary<string, object[]> additionalProps;
|
||||||
|
if (additionalProperties != null)
|
||||||
|
additionalProps = additionalProperties
|
||||||
|
.Select(p => Tuple.Create(p, properties.Values<object>(p).ToArray()))
|
||||||
|
.ToDictionary(t => t.Item1, t => t.Item2);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
additionalProps = new Dictionary<string, object[]>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ADUserAccount(
|
||||||
|
directoryEntry.Domain,
|
||||||
|
distinguishedName,
|
||||||
|
objectSid,
|
||||||
|
sAMAccountName,
|
||||||
|
name,
|
||||||
|
displayName,
|
||||||
|
surname,
|
||||||
|
givenName,
|
||||||
|
email,
|
||||||
|
phone,
|
||||||
|
userAccountControl,
|
||||||
|
isCriticalSystemObject,
|
||||||
|
groups,
|
||||||
|
additionalProps);
|
||||||
|
}
|
||||||
|
|
||||||
[Obsolete("Use generic equivalents: GetPropertyValue<T>(string PropertyName)")]
|
[Obsolete("Use generic equivalents: GetPropertyValue<T>(string PropertyName)")]
|
||||||
public object GetPropertyValue(string PropertyName, int Index = 0)
|
public object GetPropertyValue(string PropertyName, int Index = 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -173,6 +173,11 @@ namespace Disco.Services.Interop.ActiveDirectory
|
|||||||
var domain = Context.GetDomainFromId(Id);
|
var domain = Context.GetDomainFromId(Id);
|
||||||
return domain.GetAvailableDomainController().RetrieveADObject(Id, Quick);
|
return domain.GetAvailableDomainController().RetrieveADObject(Id, Quick);
|
||||||
}
|
}
|
||||||
|
public static IADObject RetrieveADObjectByDistinguishedName(string distinguishedName, bool quick)
|
||||||
|
{
|
||||||
|
var domain = Context.GetDomainFromDistinguishedName(distinguishedName);
|
||||||
|
return domain.GetAvailableDomainController().RetrieveADObjectByDistinguishedName(distinguishedName, quick);
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Actions
|
#region Actions
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
using Disco.Models.Repository;
|
using Disco.Models.Repository;
|
||||||
using Disco.Services.Interop.ActiveDirectory;
|
using Disco.Services.Interop.ActiveDirectory;
|
||||||
|
using DocumentFormat.OpenXml.Vml.Office;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.DirectoryServices;
|
using System.DirectoryServices;
|
||||||
using System.DirectoryServices.ActiveDirectory;
|
using System.DirectoryServices.ActiveDirectory;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.NetworkInformation;
|
using System.Net.NetworkInformation;
|
||||||
|
using ZXing;
|
||||||
|
|
||||||
namespace Disco.Services
|
namespace Disco.Services
|
||||||
{
|
{
|
||||||
@@ -95,6 +99,24 @@ namespace Disco.Services
|
|||||||
return SearchResults.Select(sr => ADOrganisationalUnit.FromSearchResult(sr));
|
return SearchResults.Select(sr => ADOrganisationalUnit.FromSearchResult(sr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IADObject AsADObject(this ADDirectoryEntry directoryEntry, bool quick, string[] additionalProperties)
|
||||||
|
{
|
||||||
|
var properties = directoryEntry.Entry.Properties;
|
||||||
|
var objectCategory = properties.Value<string>("objectCategory");
|
||||||
|
objectCategory = objectCategory.Substring(0, objectCategory.IndexOf(',')).ToLower();
|
||||||
|
switch (objectCategory)
|
||||||
|
{
|
||||||
|
case "cn=person":
|
||||||
|
return ADUserAccount.FromDirectoryEntry(directoryEntry, quick, additionalProperties);
|
||||||
|
case "cn=computer":
|
||||||
|
return ADMachineAccount.FromDirectoryEntry(directoryEntry, additionalProperties);
|
||||||
|
case "cn=group":
|
||||||
|
return ADGroup.FromDirectoryEntry(directoryEntry, additionalProperties);
|
||||||
|
default:
|
||||||
|
throw new InvalidOperationException("Unexpected objectCategory");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public static ADUserAccount ActiveDirectoryAccount(this User User, params string[] AdditionalProperties)
|
public static ADUserAccount ActiveDirectoryAccount(this User User, params string[] AdditionalProperties)
|
||||||
|
|||||||
@@ -39,6 +39,11 @@ namespace Disco.Services.Users
|
|||||||
return GetAuthorization(UserId, false);
|
return GetAuthorization(UserId, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static bool TryGetUser(string UserId, DiscoDataContext Database, bool ForceRefresh, out User User)
|
||||||
|
{
|
||||||
|
return TryGet(UserId, Database, ForceRefresh, out User, out _, out _);
|
||||||
|
}
|
||||||
|
|
||||||
internal static User GetUser(string UserId, DiscoDataContext Database, bool ForceRefresh)
|
internal static User GetUser(string UserId, DiscoDataContext Database, bool ForceRefresh)
|
||||||
{
|
{
|
||||||
Tuple<User, AuthorizationToken, DateTime> record = Get(UserId, Database, ForceRefresh);
|
Tuple<User, AuthorizationToken, DateTime> record = Get(UserId, Database, ForceRefresh);
|
||||||
@@ -66,6 +71,31 @@ namespace Disco.Services.Users
|
|||||||
return GetUser(UserId, false);
|
return GetUser(UserId, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static bool TryGet(string UserId, DiscoDataContext Database, bool ForceRefresh, out User User, out AuthorizationToken AuthToken, out DateTime CacheExpirationTimestamp)
|
||||||
|
{
|
||||||
|
Tuple<User, AuthorizationToken, DateTime> record = null;
|
||||||
|
|
||||||
|
// Check Cache
|
||||||
|
if (!ForceRefresh)
|
||||||
|
record = TryUserCache(UserId);
|
||||||
|
|
||||||
|
if (record == null && UserService.TryImportUser(Database, UserId, out var user, out var authorizationToken))
|
||||||
|
record = SetValue(UserId, Tuple.Create(user, authorizationToken));
|
||||||
|
|
||||||
|
if (record != null)
|
||||||
|
{
|
||||||
|
User = record.Item1;
|
||||||
|
AuthToken = record.Item2;
|
||||||
|
CacheExpirationTimestamp = record.Item3;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
User = default;
|
||||||
|
AuthToken = default;
|
||||||
|
CacheExpirationTimestamp = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
internal static Tuple<User, AuthorizationToken, DateTime> Get(string UserId, DiscoDataContext Database, bool ForceRefresh)
|
internal static Tuple<User, AuthorizationToken, DateTime> Get(string UserId, DiscoDataContext Database, bool ForceRefresh)
|
||||||
{
|
{
|
||||||
Tuple<User, AuthorizationToken, DateTime> record = null;
|
Tuple<User, AuthorizationToken, DateTime> record = null;
|
||||||
|
|||||||
@@ -115,6 +115,11 @@ namespace Disco.Services.Users
|
|||||||
return Cache.GetUser(UserId, Database, ForceRefresh);
|
return Cache.GetUser(UserId, Database, ForceRefresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool TryGetUser(string UserId, DiscoDataContext Database, bool ForceRefresh, out User User)
|
||||||
|
{
|
||||||
|
return Cache.TryGetUser(UserId, Database, ForceRefresh, out User);
|
||||||
|
}
|
||||||
|
|
||||||
public static AuthorizationToken GetAuthorization(string UserId)
|
public static AuthorizationToken GetAuthorization(string UserId)
|
||||||
{
|
{
|
||||||
return Cache.GetAuthorization(UserId);
|
return Cache.GetAuthorization(UserId);
|
||||||
@@ -223,10 +228,13 @@ namespace Disco.Services.Users
|
|||||||
return adImportedUsers;
|
return adImportedUsers;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static Tuple<User, AuthorizationToken> ImportUser(DiscoDataContext Database, string UserId)
|
internal static bool TryImportUser(DiscoDataContext Database, string UserId, out User User, out AuthorizationToken AuthorizationToken)
|
||||||
{
|
{
|
||||||
|
User = null;
|
||||||
|
AuthorizationToken = null;
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(UserId))
|
if (string.IsNullOrEmpty(UserId))
|
||||||
throw new ArgumentNullException("UserId is required", "UserId");
|
return false;
|
||||||
|
|
||||||
if (UserId.EndsWith("$"))
|
if (UserId.EndsWith("$"))
|
||||||
{
|
{
|
||||||
@@ -234,12 +242,12 @@ namespace Disco.Services.Users
|
|||||||
var adAccount = ActiveDirectory.RetrieveADMachineAccount(UserId);
|
var adAccount = ActiveDirectory.RetrieveADMachineAccount(UserId);
|
||||||
|
|
||||||
if (adAccount == null)
|
if (adAccount == null)
|
||||||
return null;
|
return false;
|
||||||
|
|
||||||
var user = adAccount.ToRepositoryUser();
|
User = adAccount.ToRepositoryUser();
|
||||||
var token = AuthorizationToken.BuildComputerAccountToken(user);
|
AuthorizationToken = AuthorizationToken.BuildComputerAccountToken(User);
|
||||||
|
|
||||||
return new Tuple<User, AuthorizationToken>(user, token);
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -251,7 +259,7 @@ namespace Disco.Services.Users
|
|||||||
adAccount = ActiveDirectory.RetrieveADUserAccount(UserId);
|
adAccount = ActiveDirectory.RetrieveADUserAccount(UserId);
|
||||||
|
|
||||||
if (adAccount == null)
|
if (adAccount == null)
|
||||||
throw new ArgumentException(string.Format("Invalid Username: '{0}'; User not found in Active Directory", UserId), "Username");
|
return false;
|
||||||
}
|
}
|
||||||
catch (COMException ex)
|
catch (COMException ex)
|
||||||
{
|
{
|
||||||
@@ -259,36 +267,51 @@ namespace Disco.Services.Users
|
|||||||
if (ex.ErrorCode == -2147016646)
|
if (ex.ErrorCode == -2147016646)
|
||||||
SystemLog.LogException("Server is not operational; Primary Domain Controller Down?", ex);
|
SystemLog.LogException("Server is not operational; Primary Domain Controller Down?", ex);
|
||||||
|
|
||||||
throw ex;
|
return false;
|
||||||
}
|
}
|
||||||
catch (ActiveDirectoryOperationException ex)
|
catch (ActiveDirectoryOperationException ex)
|
||||||
{
|
{
|
||||||
// Try From Cache...
|
// Try From Cache...
|
||||||
SystemLog.LogException("Primary Domain Controller Down?", ex);
|
SystemLog.LogException("Primary Domain Controller Down?", ex);
|
||||||
throw ex;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var user = adAccount.ToRepositoryUser();
|
User = adAccount.ToRepositoryUser();
|
||||||
|
|
||||||
// Update Repository
|
// Update Repository
|
||||||
User existingUser = Database.Users.Find(user.UserId);
|
User existingUser = Database.Users.Find(User.UserId);
|
||||||
if (existingUser == null)
|
if (existingUser == null)
|
||||||
{
|
{
|
||||||
Database.Users.Add(user);
|
Database.Users.Add(User);
|
||||||
Database.SaveChanges();
|
Database.SaveChanges();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (existingUser.UpdateSelf(user))
|
if (existingUser.UpdateSelf(User))
|
||||||
{
|
{
|
||||||
Database.SaveChanges();
|
Database.SaveChanges();
|
||||||
}
|
}
|
||||||
user = existingUser;
|
User = existingUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
var token = AuthorizationToken.BuildToken(user, adAccount.Groups.Select(g => g.Id));
|
AuthorizationToken = AuthorizationToken.BuildToken(User, adAccount.Groups.Select(g => g.Id));
|
||||||
|
|
||||||
return new Tuple<User, AuthorizationToken>(user, token);
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static Tuple<User, AuthorizationToken> ImportUser(DiscoDataContext Database, string UserId)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(UserId))
|
||||||
|
throw new ArgumentNullException(nameof(UserId));
|
||||||
|
|
||||||
|
if (TryImportUser(Database, UserId, out var user, out var authorization))
|
||||||
|
{
|
||||||
|
return Tuple.Create(user, authorization);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"Unable to import Active Directory user '{UserId}'", nameof(UserId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user