bolcom / libunftp

Extensible, async, cloud orientated FTP(S) server library and the core of unFTP: https://github.com/bolcom/unFTP. Follow up and talk to us on https://t.me/unftp
Apache License 2.0
187 stars 35 forks source link

Root directory for each user #389

Closed fatmatto closed 2 years ago

fatmatto commented 3 years ago

Hello,

Is it possible to have each client confined in a different directory?

My use case would be to use the rest authenticator and the filesystem storage to authenticate each client trying to connect to the server, then ,given the credentials they provided, assign the correct root directory.

I was only able to provide a global root directory for every client, but maybe I'm missing something since I'm new to Rust

use std::sync::Arc;
use unftp_auth_rest::{Builder, RestAuthenticator};
use unftp_sbe_fs::ServerExt;

#[tokio::main]
pub async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let authenticator: RestAuthenticator = Builder::new()
        .with_username_placeholder("{USER}".to_string())
        .with_password_placeholder("{PASS}".to_string())
        .with_url("http://localhost:3000/login".to_string())
        .with_method(hyper::Method::POST)
        .with_body(r#"{"user":"{USER}","pass":"{PASS}"}"#.to_string())
        .with_selector("/status".to_string())
        .with_regex("true".to_string())
        .build()?;

    // let ftp_home = std::env::temp_dir();
    let server = libunftp::Server::with_fs("/path/to/main/dir")
        .authenticator(Arc::new(authenticator))
        .passive_ports(50000..65535)
        .passive_host(libunftp::options::PassiveHost::FromConnection)
        .metrics();
    let addr = "127.0.0.1:2121";
    server.listen(addr).await;
    Ok(())
}
hannesdejager commented 3 years ago

Hi @fatmatto, no you're not missing something. It's something we would like to add to libunftp so its not there at the moment. At the moment we've added it to unFTP server here. I thought of making a crate out of this but perhaps you can copy it and adapt it for your needs until we release that as a crate.

You will need something like that and to also define your own UserDetail implementation that will hold the root directory of each user. In unFTP its here.

Please let us know how the Rest Authenticator works for you and where we can improve.

fatmatto commented 3 years ago

Hi @fatmatto, no you're not missing something. It's something we would like to add to libunftp so its not there at the moment. At the moment we've added it to unFTP server here. I thought of making a crate out of this but perhaps you can copy it and adapt it for your needs until we release that as a crate.

You will need something like that and to also define your own UserDetail implementation that will hold the root directory of each user. In unFTP its here.

Please let us know how the Rest Authenticator works for you and where we can improve.

Thank you for your reply @hannesdejager , it seems to be exatcly what I'm trying to achieve, thanks for the "pointer", I will look into it.

Regarding the rest authenticator, it was very easy to use for me, the only thing i had to do to make it work is to add an endpoint on the upstream auth service to accept credentials via request body, it was looking for credentials in http headers and the authenticator does not support custom headers.

For more context, I'm migrating an existing FTP service written in NodeJS to Rust (evaluating Rust as Node replacement for core services)

hannesdejager commented 3 years ago

Very nice to hear and super about the use case here. Go go Rust!