FubarDevelopment / FtpServer

Portable FTP server written in .NET
http://fubardevelopment.github.io/FtpServer/
MIT License
473 stars 161 forks source link

How to create readonly users? #104

Open TheTrigger opened 4 years ago

TheTrigger commented 4 years ago

How could I make a user be read-only on the filesystem? Working on aspnetcore 3.1

I have te code from the example:

/// <summary>
/// Custom membership provider
/// </summary>
public class CustomMembershipProvider : IMembershipProvider
{
    /// <inheritdoc />
    public Task<MemberValidationResult> ValidateUserAsync(string username, string password)
    {
        if (username != "tester" || password != "testing")
        {
            return Task.FromResult(new MemberValidationResult(MemberValidationStatus.InvalidLogin));
        }

        var user = new ClaimsPrincipal(
            new ClaimsIdentity(
                new[]
                {
                    new Claim(ClaimsIdentity.DefaultNameClaimType, username),
                    new Claim(ClaimsIdentity.DefaultRoleClaimType, username),
                    new Claim(ClaimsIdentity.DefaultRoleClaimType, "user"),
                },
                "custom"));

        return Task.FromResult(
            new MemberValidationResult(
                MemberValidationStatus.AuthenticatedUser,
                user));
    }
}
public static class FtpExtension
{
    public static void UseFtpServer(this IServiceCollection services)
    {
        services.AddFtpServer(builder => builder
            .UseDotNetFileSystem() // Use the .NET file system functionality
        );

        services.Configure<FtpServerOptions>(opt => opt.ServerAddress = "*");
        services.Configure<DotNetFileSystemOptions>(opt => opt.RootPath = Path.Combine("FtpServer"));
        services.AddHostedService<HostedFtpService>();

        services.AddSingleton<IMembershipProvider, CustomMembershipProvider>();
    }
}

thanks

mo3head commented 4 years ago

What I did is the following:

Added this to ValidateUserAsync claimList.AddRange(user.Roles.Select(x => new Claim(ClaimTypes.Role, x.ToString())).ToList());

And then added Custom Command Handler with this at the start:

        if (!this.Data.FtpUser.Claims.Any(x => x.Value == User.Roles.role_one.ToString().ToLower()) &&
           !this.Data.FtpUser.Claims.Any(x => x.Value == User.Roles.role_two.ToString().ToLower())
       )
        {
            throw new Exception("Not Allowed...");
        }
TheTrigger commented 4 years ago

Sorry, I don't mean how to authorize a user, but how to setup witch commands that user could call. I would like to have two users, one read-write, and another read-only, any ideas? ty

mo3head commented 4 years ago

That is exactly what I explained. Add specific role and check for it in a custom Controller ( i.e. CustomSTORController for disallowing write permission ).

TheTrigger commented 4 years ago

Sorry, I don't get it, I should be able to do this from CustomMembershipProvider so set the rights claims for MemberValidationResult...(?) I'm lost

Jinngoo commented 3 years ago

Same issue

MarcoParreira commented 1 year ago

You can override the commands you want to control by creating and registering your own. Your commands take precedence. The samples show how to do this command registration.

In my case, i'm checking roles to create folders:

[FtpCommandHandler("MKD")]
public class MkdCommandHandler : FtpCommandHandler
{
    public override Task<IFtpResponse> Process(FtpCommand command, CancellationToken cancellationToken)
    {
        var user = CommandContext.FtpContext.Connection.Features.Get<IAuthorizationInformationFeature>().FtpUser;
        var roles = Startup.Settings.Roles;

        foreach (var claim in user.Claims)
        {
            var role = roles.FirstOrDefault(r => r.Name == claim.Value);
            if(role?.CanCreateFolder == true)
            {
                FubarDev.FtpServer.CommandHandlers.MkdCommandHandler mkdCommandHandler = new()
                {
                    CommandContext = this.CommandContext
                };

                return mkdCommandHandler.Process(command, cancellationToken);
            }
        }

        return Task.FromResult<IFtpResponse>(new FtpResponse(502, $"Not allowed!"));
    }
}