Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom root folders for users #74

Closed
aavanesov opened this issue Jul 16, 2019 · 8 comments
Closed

Custom root folders for users #74

aavanesov opened this issue Jul 16, 2019 · 8 comments
Assignees
Labels

Comments

@aavanesov
Copy link

Is there a way to define flexible root folders on the level of users?
I found a way to use root folder per user with UseRootPerUser() but is is not providing enough flexiibilty for my case.

@fubar-coder fubar-coder self-assigned this Jul 16, 2019
@fubar-coder
Copy link
Contributor

Implement IAccountDirectoryQuery and add it as "singleton" service.

@aavanesov
Copy link
Author

Thank you for your clarifications. But unfortunatelly, it looks like GetDirectories of IAccountDirectoryQuery is setting the relative path starting from the root path. Is there a way to override the root path completly for the user? For example, map users to folders on different drives.

@fubar-coder
Copy link
Contributor

The root path returned by IAccountDirectoryQuery might be relative to the file system root, but it might also be an absolute path, due to the way Path.Combine works.

@aavanesov
Copy link
Author

aavanesov commented Jul 16, 2019

For example, this set up will not change the drive to "C:" for the user, but will create a sub folders in D:\ drive like "d:\Temp\ftpserver\Temp\ftpserver":

services.Configure<DotNetFileSystemOptions>(opt =>  opt.RootPath = @"d:\Temp\ftpserver\");

// ...

public class FtpAccountDirectoryQuery : IAccountDirectoryQuery
{
    public IAccountDirectories GetDirectories(IAccountInformation accountInformation)
    {
        return new GenericAccountDirectories(@"c:\Temp\ftpserver\" + accountInformation.User.Name);
    }
}

@fubar-coder
Copy link
Contributor

Umm, no. The Users root directory will be c:\Temp\ftpserver\<username> and all directories he will create are in (or below) this directory, regardless of the DotNetFileSystemOptions configuration. BTW: You can differentiate between "normal" and "anonymous" FTP users by testing if accountInformation.User is of type IAnonymousFtpUser.

So, if your code returns new GenericAccountDirectories(null) for anonymous user, then those users will use d:\Temp\ftpserver, while authenticated users might be using c:\Temp\ftpserver\<username> as root directory.

@Maciejszuchta
Copy link

I am wondering if this is correct configuration to use IAccountDirectoryQuery

 public class AccountDirectoryQuery : IAccountDirectoryQuery
    {
        private readonly IProjectsQueryHub _projectsQueryHub;
        private readonly IConfiguration _configuration;

        public AccountDirectoryQuery(IProjectsQueryHub projectsHub, IConfiguration configuration)
        {
            _projectsQueryHub = projectsHub;
            _configuration = configuration;
        }

        public IAccountDirectories GetDirectories(IAccountInformation accountInformation)
        {
            var adminUser = _configuration.GetSection("Settings")["FtpLogin"];
            var login = accountInformation.User.Name;
            var rootPath = _configuration.GetSection("Settings")["DataPath"];

            if (accountInformation.User.Name != adminUser)
            {
                var project = _projectsQueryHub.GetSingle(login).WaitResult();
                if (project != null)
                {

                    return new GenericAccountDirectories(Path.Combine("Upload", login));
                }
            }
            return new GenericAccountDirectories(rootPath);
        }
    }

and in startup:

services.Configure<DotNetFileSystemOptions>(opt =>
            {
                opt.RootPath = DataFolderPath;
            });

 services.AddFtpServer(builder => builder
                .UseDotNetFileSystem()
                .UseRootPerUser(opt => { opt.UserRootDirectory = "Upload"; })
            );

services.AddSingleton<IAccountDirectoryQuery, AccountDirectoryQuery>();

However, if I set a breakpoint in GetDirectories method it never hits. Also connecting with custom user name doesn't correctly set the root folder for this user.

I am really confused about how to configure the option so when the user is connecting its root directory is set to "Upload/userName" and when the Administrator connects root is set to a directory above Upload.

@fubar-coder
Copy link
Contributor

That the breakpoint doesn't get called means that services.AddSingleton<IAccountDirectoryQuery, AccountDirectoryQuery>(); gets executed before the services.AddFtpServer line. The UseRootPerUser adds its own IAccountDirectoryQuery implementation to the service collection.

@Maciejszuchta
Copy link

@fubar-coder Thank you,
After changing the order and some fixes here and there it started working as expected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants