Base solution for your next web application

Activities of "enerjisauretim"

Hi there,

We now have a couple of finished AspnetZero applications, and we started using some of their api's like login and other methods. However, the same nswag problem starts occurring: nswag generated unwrapped results.

In my opinion, you can pass such a lambda function:

Configuration.Modules.AbpAspNetCore().DefaultWrapResultAttribute.WrapOnSuccessFunc = (request) => request.Headers["x-dontwrap"] != null;

So that we can configure it per httprequest?

What we do is now create an overload for unwrapped version and use [DontWrap] Attribute, which is very weird.

@maliming you are right, however, AspnetZero does inject the response type, which is wrong, either. The service should return the same structure as it promises to.

In my opinion, instead of wrapping results, RAD tool should generate wrapped object results (such as AbpPagedResult<T> ) so that Swagger will generate related structure.

Hello,

I inspected the XmlEmbeddedFileLocalizationDictionaryProvider's source code and saw that there is no way to support case-insensitivity in terms of keys, except from rewriting the whole provider. Mistakenly in the development phase, we had this trouble a lot; for example, L("Products") and L("products") produces different results. This is very inconvenient for our projects and in my opinion, it should be enabled via configuration or replacing the provider?

Since we are calling webapi's from our other projects via server-to-server communication, this interceptor does not work for our case.

How to register a concrete class with multiple public interfaces in the IocManager

Hello there,

We extended the LdapAuthenticationSource in order to use it on linux environment via Novell library. Sometimes, Domain Controller does not respond within the predefined timeout, however, the application still logs me in although TryAuthenticateAsync method is returning false. We want users to only use their LDAP accounts, and on each login, we must precheck their existence and update their passwords accordingly in our system. However, as I have logged in before, probably, I am an already-registered user so I can log in although LDAP connection fails.

using System;
using System.Threading.Tasks;
using Abp.Configuration;
using Abp.Zero.Ldap.Authentication;
using Abp.Zero.Ldap.Configuration;
using Microsoft.Extensions.Logging;
using Novell.Directory.Ldap;
using PPM.Authorization.Users;
using PPM.MultiTenancy;

namespace PPM.Authorization.Ldap
{
    public class AppLdapAuthenticationSource : LdapAuthenticationSource<Tenant, User>
    {
        private readonly string _ldapDomain;
        private readonly string _ldapUserName;
        private readonly string _ldapPassword;
        private readonly ILogger<AppLdapAuthenticationSource> _logger;
        private readonly ILdapConnectionFactory _ldapConnectionFactory;


        public AppLdapAuthenticationSource(ILdapSettings settings, IAbpZeroLdapModuleConfig ldapModuleConfig,
            ISettingManager settingManager, ILogger<AppLdapAuthenticationSource> logger, ILdapConnectionFactory ldapConnectionFactory)
            : base(settings, ldapModuleConfig)
        {
            _logger = logger;
            _ldapConnectionFactory = ldapConnectionFactory;
            _ldapDomain = settingManager.GetSettingValueAsync(LdapSettingNames.Domain).Result;
            _ldapUserName = settingManager.GetSettingValueAsync(LdapSettingNames.UserName).Result;
            _ldapPassword = settingManager.GetSettingValueAsync(LdapSettingNames.Password).Result;
        }

        public override Task<bool> TryAuthenticateAsync(string userNameOrEmailAddress, string plainPassword,
            Tenant tenant)
        {
            var userDn = $"{userNameOrEmailAddress}@{_ldapDomain}";

            try
            {
                using (var connection = _ldapConnectionFactory.Create(10000))
                {
                    connection.Connect(_ldapDomain, LdapConnection.DefaultPort);
                    connection.Bind(userDn, plainPassword);
                    if (connection.Bound)
                    {
                        return Task.FromResult(true);
                    }
                }
            }
            catch (LdapException e)
            {
                _logger.LogInformation("Ldap Connection Error : " + e.Message);
            }

            return Task.FromResult(false);
        }

        public override async Task<User> CreateUserAsync(string userNameOrEmailAddress, Tenant tenant)
        {
            await CheckIsEnabled(tenant);
            var user = new User
            {
                UserName = userNameOrEmailAddress,
                Name = userNameOrEmailAddress,
                Surname = userNameOrEmailAddress,
                EmailAddress = userNameOrEmailAddress,
                IsEmailConfirmed = true,
                IsActive = true
            };

            var ldapUser = GetLdapUserDetail(user.UserName);
            return SetUserWithLdapDetail(user, ldapUser);
        }

        public override async Task UpdateUserAsync(User user, Tenant tenant)
        {
            await CheckIsEnabled(tenant);
            var ldapUser = GetLdapUserDetail(user.UserName);
            SetUserWithLdapDetail(user, ldapUser);
        }

        private LdapEntry GetLdapUserDetail(string userName)
        {
            var userDn = $"{_ldapUserName}@{_ldapDomain}";

            using (var connection = _ldapConnectionFactory.Create(10000))
            {
                connection.Connect(_ldapDomain, LdapConnection.DefaultPort);
                connection.Bind(userDn, _ldapPassword);
                var searchFilter = string.Format("sAMAccountName={0}", userName);
                var result = connection.Search("DC=******,DC=local",
                    LdapConnection.ScopeSub,
                    searchFilter,
                    new[]
                    {
                        "samaccountname", "givenName", "sn", "mail"
                    },
                    false
                );

                var ldapUser = result.Next();
                return ldapUser ?? null;
            }
        }

        private User SetUserWithLdapDetail(User user, LdapEntry ldapUser)
        {
            var samAccountName = ldapUser.GetAttribute("samaccountname").StringValue;
            var givenName = ldapUser.GetAttribute("givenName").StringValue;
            var surName = "";
            try
            {
                surName = ldapUser.GetAttribute("sn").StringValue;
            }
            catch
            {
                // ignored
            }

            var mail = ldapUser.GetAttribute("mail").StringValue;

            if (!string.IsNullOrEmpty(samAccountName))
            {
                user.UserName = samAccountName;
            }

            user.Name = givenName;
            user.Surname = surName;
            user.EmailAddress = mail;
            user.IsActive = true;

            return user;
        }
    }
}

I found out that default implementation of AbpLoginManager does that, if an external login provider fails, it checks the user along with his password in our database. And if the password seems okay, it lets the user in: (which is an undesired behaviour for our case, we will probably throw an UserFriendlyException to prevent his login attempt on LDAP failure cases)

 protected virtual async Task<AbpLoginResult<TTenant, TUser>> LoginAsyncInternal(string userNameOrEmailAddress, string plainPassword, string tenancyName, bool shouldLockout)
        {
            if (userNameOrEmailAddress.IsNullOrEmpty())
            {
                throw new ArgumentNullException(nameof(userNameOrEmailAddress));
            }

            if (plainPassword.IsNullOrEmpty())
            {
                throw new ArgumentNullException(nameof(plainPassword));
            }

            //Get and check tenant
            TTenant tenant = null;
            using (UnitOfWorkManager.Current.SetTenantId(null))
            {
                if (!MultiTenancyConfig.IsEnabled)
                {
                    tenant = await GetDefaultTenantAsync();
                }
                else if (!string.IsNullOrWhiteSpace(tenancyName))
                {
                    tenant = await TenantRepository.FirstOrDefaultAsync(t => t.TenancyName == tenancyName);
                    if (tenant == null)
                    {
                        return new AbpLoginResult<TTenant, TUser>(AbpLoginResultType.InvalidTenancyName);
                    }

                    if (!tenant.IsActive)
                    {
                        return new AbpLoginResult<TTenant, TUser>(AbpLoginResultType.TenantIsNotActive, tenant);
                    }
                }
            }

            var tenantId = tenant == null ? (int?)null : tenant.Id;
            using (UnitOfWorkManager.Current.SetTenantId(tenantId))
            {
                await UserManager.InitializeOptionsAsync(tenantId);

                //TryLoginFromExternalAuthenticationSources method may create the user, that's why we are calling it before AbpUserStore.FindByNameOrEmailAsync
                var loggedInFromExternalSource = await TryLoginFromExternalAuthenticationSourcesAsync(userNameOrEmailAddress, plainPassword, tenant);

                var user = await UserManager.FindByNameOrEmailAsync(tenantId, userNameOrEmailAddress);
                if (user == null)
                {
                    return new AbpLoginResult<TTenant, TUser>(AbpLoginResultType.InvalidUserNameOrEmailAddress, tenant);
                }

                if (await UserManager.IsLockedOutAsync(user))
                {
                    return new AbpLoginResult<TTenant, TUser>(AbpLoginResultType.LockedOut, tenant, user);
                }

                if (!loggedInFromExternalSource)
                {
                    if (!await UserManager.CheckPasswordAsync(user, plainPassword))
                    {
                        if (shouldLockout)
                        {
                            if (await TryLockOutAsync(tenantId, user.Id))
                            {
                                return new AbpLoginResult<TTenant, TUser>(AbpLoginResultType.LockedOut, tenant, user);
                            }
                        }

                        return new AbpLoginResult<TTenant, TUser>(AbpLoginResultType.InvalidPassword, tenant, user);
                    }

                    await UserManager.ResetAccessFailedCountAsync(user);
                }

                return await CreateLoginResultAsync(user, tenant);
            }
        }

Hello there,

We almost edited all of your templates that are being used by RAD extension. However, there is no documentation about it. Is there a source code or any kind of documentation about the properties,conditions and everyting helpful that we can learn about the extension?

Hello,

I can list our needs:

  1. AppPermissions: related lines gets duplicated on each regeneration of the entity. It must be prevented and also, I want to change the generated code, however, its template is probably hidden in the application
  2. CustomDtoMapper: requirement is the same with the first line
  3. I want to prevent overriding some files when a regeneration occurs. for example, we created a validator template and within the templateinfo.txt file, i want to prevent duplicate generation/overriding if the specified already exists.

These are the ones that I remember for the moment.

Can you provide an example for this scenario?

I've tried many ways to either remove AbpResultFilter and add my extended Filter class, or make this filter class working conditionally.

In startup.cs file, services.Configure<MvcOptions> and PostConfigure methods not working, so that i was not be able to modify filters accordingly.

Showing 11 to 20 of 36 entries