Activities of "berkansasmaz"

Hi,

Can you try run the abp install-libs command to restore the NPM packages?

We have tested one scenario, where we will intercept the backend request and they are changing the file content from image to some other file like .aspx or any malware content. Will it still be able to block it.

Right now, the default implementation doesn't really check if the uploaded file is actually an image. So yeah, technically someone could upload something like a .jpg file that’s actually a renamed .aspx or some other non-image content.

That said, in most cases this isn't really a security issue — as long as:

  • The file isn’t executed or rendered by the server
  • It’s not served with an unsafe MIME type
  • And users can only access their own files

But, if you’d like to apply your own security rules or validation logic, you can override the SetProfilePictureAsync method in AccountAppService and handle the checks there.

Hi,

If I understood correctly, you're looking for a way to check the user's permissions (or features), and based on that, control which UI components should be visible or accessible. Is that right?

If so, here's a common and recommended approach:

For menu items:

{
  path: '/authors',
  name: '::Menu:Authors',
  parentName: '::Menu:BookStore',
  layout: eLayoutType.application,
  requiredPolicy: 'BookStore.Authors',
}

For UI components:

  <button *abpPermission="'BookStore.Authors.Create'" id="create" class="btn btn-primary" type="button" (click)="createAuthor()">
            <i class="fa fa-plus me-1"></i>
            <span>{{ '::NewAuthor' | abpLocalization }}</span>
          </button>

If you want to check whether a specific feature is enabled or disabled and render something accordingly, you can check this document.

For AppService methods:

[Authorize(BookStorePermissions.Authors.Delete)] 
public async Task DeleteAsync(Guid id)
{
    //continue to the normal flow...
}

or

public async Task CreateAsync(CreateAuthorDto input)
{
    var result = await AuthorizationService
        .AuthorizeAsync("Author_Management_Create_Books");
    if (result.Succeeded == false)
    {
        //throw exception
        throw new AbpAuthorizationException("...");
    }

    //continue to the normal flow...
}

If I misunderstood your question or you're trying to do something else, feel free to give a bit more detail.

Answer

Hi

If you're using the LeptonX SideMenu layout and want to customize things like the login page or the main layout (for example, changing the spinner), there are two main ways to do it:

1-) Override only what you need If the changes are small, you don’t need to replace the whole theme. You can just override specific layout or page files (like the login page) in your project by creating Razor files with the same path and name. ABP will use your version instead of the one from the theme or modules.

Here's how that works:

  • https://abp.io/docs/latest/framework/ui/blazor/customization-overriding-components?UI=Blazor

Note: If you need the code of a specific page, you can download the source code and look at it, or if you tell me which page you need, I can forward it to you.

2-) Customize the full theme If you plan to make bigger changes on the theme or modules, you can download the LeptonX or related modules source code and fully customize it:

  • https://abp.io/docs/latest/ui-themes/lepton-x#source-code
  • https://abp.io/docs/latest/suite/source-code

Hi,

Apologies for the earlier misunderstanding, and thank you for your patience.

If you would like to disable username character validation, you can try the following configuration:

Configure<IdentityOptions>(options =>
{
    options.User.AllowedUserNameCharacters = null;
});

This will remove the restriction on allowed characters in usernames. Let me know if you need help with anything else!

For this, you can override the Login page and remove the relevant code blocks. You can follow the steps below to override the login page.

1-) Create Account folder in Pages folder like below:

2-) Create Login.cshtml file in Account folder in your AuthServer.

3-) Update Login.cshtml file like below:

@page
@using Microsoft.AspNetCore.Mvc.Localization
@using Microsoft.Extensions.Options
@using Owl.reCAPTCHA
@using Volo.Abp.Account.Localization
@using Volo.Abp.Account.Public.Web.Pages.Account;
@using Volo.Abp.Account.Public.Web.Security.Recaptcha
@using Volo.Abp.Account.Settings
@using Volo.Abp.Identity;
@using Volo.Abp.Settings
@model Volo.Abp.Account.Public.Web.Pages.Account.LoginModel
@inject IHtmlLocalizer<AccountResource> L
@inject Volo.Abp.AspNetCore.Mvc.UI.Layout.IPageLayout PageLayout
@inject ISettingProvider SettingProvider
@{
    PageLayout.Content.Title = L["Login"].Value;
    var reCaptchaVersion = await SettingProvider.GetAsync<int>(AccountSettingNames.Captcha.Version);
    if (Model.UseCaptcha)
    {
        await Model.ReCaptchaOptions.SetAsync(reCaptchaVersion == 3 ? reCAPTCHAConsts.V3 : reCAPTCHAConsts.V2);
    }

}

@section scripts
    {
    <abp-script-bundle name="@typeof(LoginModel).FullName">
        <abp-script src="/Pages/Account/Login.js" />
    </abp-script-bundle>

    @if (Model.UseCaptcha)
    {
        if (reCaptchaVersion == 3)
        {
            <recaptcha-script-v3 />
            <recaptcha-script-v3-js action="login" execute="false" />
        }
        else
        {
            <recaptcha-script-v2 />
        }
    }
}

@if (Model.IsLinkLogin)
{
    <abp-alert alert-type="Warning">
        @L["LinkAccountWarning", Url.PageLink()]
    </abp-alert>
}

@if (Model.BackToExternalLogins)
{
    <div class="d-grid gap-2">
        <a class="mb-3 btn btn-primary btn-block" href="@Url.Page("./ExternalLogins")">@L["Back"]</a>
    </div>
}

@if (Model.ShowRequireMigrateSeedMessage)
{
    <div class="alert alert-danger">
        <h4 class="alert-heading">@L["RequireMigrateSeedTitle"]</h4>
        <p>@L["RequireMigrateSeedMessage"]</p>
    </div>
}

<div class="account-module-form">

    @if (Model.IsSelfRegistrationEnabled)
    {
        <h5 class="mb-2">@L["NotAMemberYet"] <a class="text-decoration-none" href="@Url.Page("./Register", new {returnUrl = Model.ReturnUrl, returnUrlHash = Model.ReturnUrlHash})">@L["Register"]</a></h5>
    }

    @if (Model.EnableLocalLogin)
    {
        <form method="post" id="loginForm">
            @if (Model.UseCaptcha)
            {
                <input class="mb-3" data-captcha="true" type="hidden" name="@RecaptchaValidatorBase.RecaptchaResponseKey" id="@RecaptchaValidatorBase.RecaptchaResponseKey"/>
            }
            <div>
                <div class="form-floating mb-2">
                    <input asp-for="LoginInput.UserNameOrEmailAddress" type="text" class="form-control" placeholder="name@example.com">
                    @Html.LabelFor(m => m.LoginInput.UserNameOrEmailAddress)
                    <span asp-validation-for="LoginInput.UserNameOrEmailAddress"/>
                </div>

                <div class="form-floating mb-2">
                    <input asp-for="LoginInput.Password" id="password-input" type="password" class="form-control" placeholder="Password">
                    @Html.LabelFor(m => m.LoginInput.Password)
                    <i id="PasswordVisibilityButton" class="bi bi-eye-slash show-pass-icon" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-html="true" aria-label="@L["ShowPassword"]" data-bs-original-title="@L["ShowPassword"]"></i>
                    <i id="capslockicon" class="bi bi-capslock caps-lock-icon" style="display: none;" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-html="true" aria-label="<i class='bi bi-exclamation-circle'></i> @L["CapsLockOn"]!" data-bs-original-title="<i class='bi bi-exclamation-circle'></i> @L["CapsLockOn"]!"></i>
                    <span asp-validation-for="LoginInput.Password"/>
                </div>
            </div>
            <abp-row>
                <abp-column>
                    <div class="form-switch ps-2">
                        <abp-input asp-for="LoginInput.RememberMe" class="mb-4"/>
                    </div>
                </abp-column>
                <abp-column class="text-end">
                    <a href="@Url.Page("./ForgotPassword", new {returnUrl = Model.ReturnUrl, returnUrlHash = Model.ReturnUrlHash})">@L["ForgotPassword"]</a>
                </abp-column>
            </abp-row>

            @if (reCaptchaVersion == 2)
            {
                <script>
                    recaptchaCallback = function (token) {
                        $('form button[type=submit]').removeAttr("disabled");
                        $('#@RecaptchaValidatorBase.RecaptchaResponseKey').val(token)
                    };
                </script>
                <div class="mb-3">
                    <recaptcha-div-v2 callback="recaptchaCallback"/>
                </div>
            }

            <div class="d-grid gap-2">
                <abp-button button-type="Primary" type="submit" class="mb-3" name="Action" value="Login" disabled="true">
                    <i class="bi bi-box-arrow-in-right me-1"></i>
                    @L["Login"]
                </abp-button>
            </div>

            @if (Model.ShowCancelButton)
            {
                <div class="d-grid gap-2">
                    <abp-button button-type="Secondary" type="submit" formnovalidate="formnovalidate" class="mb-3" name="Action" value="Cancel">@L["Cancel"]</abp-button>
                </div>
            }
        </form>
    }

    @if (Model.VisibleExternalProviders.Any())
    {
        if(Model.EnableLocalLogin)
        {
            <hr/>
            @L["OrSignInWith"]
            <br/>
        }
        else
        {
            @L["SignInWithOneOfTheFollowingProviders"]
        }

        <form asp-page="./Login" asp-page-handler="ExternalLogin"
              asp-route-returnUrl="@Model.ReturnUrl"
              asp-route-returnUrlHash="@Model.ReturnUrlHash"
              asp-route-linkTenantId="@Model.LinkTenantId"
              asp-route-linkUserId="@Model.LinkUserId"
              asp-route-linkToken="@Model.LinkToken"
              method="post">
            @foreach (var provider in Model.VisibleExternalProviders)
            {
                <button type="submit"
                        class="mt-2 me-2 btn btn-outline-primary btn-sm"
                        name="provider"
                        value="@provider.AuthenticationScheme"
                        data-busy-text="@L["ProcessingWithThreeDot"]">
                    @if (provider.Icon != null)
                    {
                        <i class="@provider.Icon"></i>
                    }
                    <span>@provider.DisplayName</span>
                </button>
            }
        </form>
    }
</div>

You can then customize it any way you want. If you have a specific question in the implementation, you can ask.

Hi,

It’s possible that a rule in your CSS is overriding the branding logo. Could you please check your CSS files for any definitions that might affect the logo?

For example, in a Blazor WebAssembly project that uses the LeptonX theme, the logo is defined via CSS variables like this:

:root .lpx-theme-dim,
:root .lpx-theme-dark {
    --lpx-logo: url('/images/logo/leptonx/icon.svg');
    --lpx-logo-icon: url('/images/logo/leptonx/icon.svg');
}

:root .lpx-theme-light {
    --lpx-logo: url('/images/logo/leptonx/icon.svg');
    --lpx-logo-icon: url('/images/logo/leptonx/icon.svg');
}

You can try updating these CSS variables to point to your own logo file to see if it solves the issue.

If this does not resolve the issue, please send your application with the ticket number in an email to support@abp.io so that I can fix it in your code and inform you about the issue later.

Hi,

It seems like the issue is caused by jQuery not being loaded before your Login.js file is executed.

Since we cannot see the bundle configuration for the CustomLoginModel, we cannot confirm exactly what is included. However, you can try updating the script bundle reference from:

<abp-script-bundle name="@typeof(CustomLoginModel).FullName">

to:

<abp-script-bundle name="@typeof(LoginModel).FullName">

This change will load the default login model’s script bundle, which includes jQuery by default. If this resolves the issue, it confirms that your custom login model bundle is missing jQuery.

If the issue still persists after this change, could you please share the contents of your host module class? Additionally, let us know if this issue occurs only on the login page or on other pages as well. This information will help us further investigate.

Hi,

If you have configured AbpDistributedEntityEventOptions as follows, this may be the problem:

Configure<AbpDistributedEntityEventOptions>(options =>
{
    options.AutoEventSelectors.AddAll();
});

Because the line options.AutoEventSelectors.AddAll(); causes an issue. I tested the following code instead, and it works as expected:

Configure<AbpDistributedEntityEventOptions>(options =>
{
    // options.AutoEventSelectors.AddAll(); // do not use this method until next version of ABP
    
    // Use following codes for your entities
    options.AutoEventSelectors.Add<MyEntity1>();
    options.AutoEventSelectors.Add<MyEntity2>();
});

We will address the AddAll issue in this PR: 🔧 https://github.com/abpframework/abp/pull/22471

Are the abp doing any kind of validation, like only specific format are allowed to upload the image

There is no format validation in the API endpoint, but only certain types of files are allowed to be selected from the UI.

also do abp check the file is valid/secured to proceed to store in the blob.

There is no such validation, I am not sure if it is necessary. Because, for example, if a user uploads an invalid image, it only affects them. We know that this does not affect other users or cause any securrity vulnerability.

Here are the impelemtation of SetProfilePictureAsync:

   [Authorize]
    public virtual async Task SetProfilePictureAsync(ProfilePictureInput input)
    {
        await SettingManager.SetForUserAsync(CurrentUser.GetId(), AccountSettingNames.ProfilePictureSource, input.Type.ToString());

        var userIdText = CurrentUser.GetId().ToString();

        if (input.Type != ProfilePictureType.Image)
        {
            if (await AccountProfilePictureContainer.ExistsAsync(userIdText))
            {
                await AccountProfilePictureContainer.DeleteAsync(userIdText);
            }
        }
        else
        {
            if (input.ImageContent == null)
            {
                throw new NoImageProvidedException();
            }

            var imageStream = input.ImageContent.GetStream();

            if (ProfilePictureOptions.Value.EnableImageCompression)
            {
                try
                {
                    var compressResult = await ImageCompressor.CompressAsync(imageStream);

                    if (compressResult.Result is not null && imageStream != compressResult.Result && compressResult.Result.CanRead)
                    {
                        await imageStream.DisposeAsync();
                        imageStream = compressResult.Result;
                    }
                }
                catch (Exception e)
                {
                    Logger.LogWarning(e, "Profile picture compression failed! User ID:" + CurrentUser.GetId());
                }
            }

            await AccountProfilePictureContainer.SaveAsync(userIdText, imageStream, true);
        }
    }
Showing 111 to 120 of 737 entries
Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.1.0-preview. Updated on December 17, 2025, 07:08
1
ABP Assistant
🔐 You need to be logged in to use the chatbot. Please log in first.