<commit_before>﻿using Signum.Engine.Authorization;
using Signum.Entities;
using Signum.Entities.Authorization;
using Signum.Services;
using Signum.Utilities;
using System;
using System.Collections.Generic;
using System.DirectoryServices.AccountManagement;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Signum.Engine.Authorization
{
    public class ActiveDirectoryAuthorizer : ICustomAuthorizer
    {
        Func<ActiveDirectoryConfigurationEmbedded> GetConfig;

        public Func<PrincipalContext, UserEntity> AutoCreateUser;  //https://stackoverflow.com/questions/14278274/how-i-get-active-directory-user-properties-with-system-directoryservices-account

        public ActiveDirectoryAuthorizer(Func<ActiveDirectoryConfigurationEmbedded> getConfig, Func<PrincipalContext, UserEntity> autoCreateUser = null)
        {
            this.GetConfig = getConfig;
            this.AutoCreateUser = autoCreateUser;
        }

        public UserEntity Login(string userName, string password)
        {
            using (AuthLogic.Disable())
            {
                var config = this.GetConfig();
                var domainName = userName.TryAfterLast('@');
                var localName = userName.TryBeforeLast('@') ?? userName;

                UserEntity user;

                if (config.DomainName.HasText() && (domainName == null || config.DomainName.ToLower() == domainName?.ToLower()))
                {
                    using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, config.DomainName))
                    {
                        if (pc.ValidateCredentials(localName + "@" + config.DomainName, password))
                        {
                            user = AuthLogic.RetrieveUser(userName);

                            if (user == null)
                            {
                                if (this.AutoCreateUser != null)
                                {
                                    user = this.AutoCreateUser(pc);
                                }
                            }

                            if (user != null)
                            {
                                AuthLogic.OnUserLogingIn(user);
                                return user;
                            }
                            else
                            {
                                throw new InvalidOperationException(ActiveDirectoryAuthorizerMessage.ActiveDirectoryUser0IsNotAssociatedWithAUserInThisApplication.NiceToString(localName));
                            }
                        }

                    }
                }

                user = AuthLogic.Login(userName, Security.EncodePassword(password));
<commit_msg>fix when domain controller is not available<commit_after>﻿using Signum.Engine.Authorization;
using Signum.Entities;
using Signum.Entities.Authorization;
using Signum.Services;
using Signum.Utilities;
using System;
using System.Collections.Generic;
using System.DirectoryServices.AccountManagement;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Signum.Engine.Authorization
{
    public class ActiveDirectoryAuthorizer : ICustomAuthorizer
    {
        Func<ActiveDirectoryConfigurationEmbedded> GetConfig;

        public Func<PrincipalContext, UserEntity> AutoCreateUser;  //https://stackoverflow.com/questions/14278274/how-i-get-active-directory-user-properties-with-system-directoryservices-account

        public ActiveDirectoryAuthorizer(Func<ActiveDirectoryConfigurationEmbedded> getConfig, Func<PrincipalContext, UserEntity> autoCreateUser = null)
        {
            this.GetConfig = getConfig;
            this.AutoCreateUser = autoCreateUser;
        }

        public UserEntity Login(string userName, string password)
        {
            using (AuthLogic.Disable())
            {
                var config = this.GetConfig();
                var domainName = userName.TryAfterLast('@');
                var localName = userName.TryBeforeLast('@') ?? userName;

                UserEntity user;

                if (config.DomainName.HasText() && (domainName == null || config.DomainName.ToLower() == domainName?.ToLower()))
                {
                    try
                    {
                        using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, config.DomainName))
                        {
                            if (pc.ValidateCredentials(localName + "@" + config.DomainName, password))
                            {
                                user = AuthLogic.RetrieveUser(userName);

                                if (user == null)
                                {
                                    if (this.AutoCreateUser != null)
                                    {
                                        user = this.AutoCreateUser(pc);
                                    }
                                }

                                if (user != null)
                                {
                                    AuthLogic.OnUserLogingIn(user);
                                    return user;
                                }
                                else
                                {
                                    throw new InvalidOperationException(ActiveDirectoryAuthorizerMessage.ActiveDirectoryUser0IsNotAssociatedWithAUserInThisApplication.NiceToString(localName));
                                }
                            }
                        }
                    }
                    catch (PrincipalServerDownException)
                    {
                        // Do nothing for this kind of Active Directory exception
                    }
                }

                user = AuthLogic.Login(userName, Security.EncodePassword(password));

{'fraction_non_alphanumeric': 0.07432662802591204, 'fraction_numerical': 0.003068530514831231, 'mean_word_length': 1.3917651854871587, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 13, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3140475', 'n_tokens_mistral': 1334, 'n_tokens_neox': 1251, 'n_words': 228}