Oh, sorry about that. I've coded for both Mina SFTP and Mina FTP, and the
concepts are very similar (so similar, in fact, that it's a shame the two
projects don't share a Filesystem API). You should be able to adapt the
concept -- and possibly the code directly -- to Mina FTP.


On 18 October 2013 19:54, Gentian Hila <gh...@commercehub.com> wrote:

> Taking a closer look at the example - it seems to be more geared toward
> the SFTP (SSH) rather than FTP.
>
>
> Genti
>
> -----Original Message-----
> From: Gentian Hila [mailto:gh...@commercehub.com]
> Sent: Wednesday, October 16, 2013 10:44 AM
> To: ftpserver-users@mina.apache.org
> Subject: RE: directory structure permissions & account locking
>
> That's great. All I was looking for was  a way to approach the problem .
> You've provided even more
>
> Thank you very much,
>
> Genti
>
> -----Original Message-----
> From: John Hartnup [mailto:john.hart...@gmail.com]
> Sent: Wednesday, October 16, 2013 10:28 AM
> To: ftpserver-users@mina.apache.org
> Subject: Re: directory structure permissions & account locking
>
> It looks like the mailing list strips attachments. Here's the source,
> pasted in:
>
> Unfortunately there are some imports that I can't provide you, but you
> should be able to knock up a substitute.
>
> -------------------------------------
>
> package com.example.apachesftp.filesystem.delegating;
>
> import java.io.IOException;
> import java.util.*;
> import java.util.Map.Entry;
>
> import org.apache.sshd.common.Session;
> import org.apache.sshd.server.FileSystemFactory;
> import org.apache.sshd.server.FileSystemView;
>
> public class DelegatingFilesystemFactory implements FileSystemFactory {
>
>    Map<String, FileSystemFactory> delegateFactories = new TreeMap<String,
> FileSystemFactory>();
>
>    @Override
>    public FileSystemView createFileSystemView(final Session session)
>          throws IOException {
>       Map<String, FileSystemView> delegates = new TreeMap<String,
> FileSystemView>();
>
>       for (Entry<String, FileSystemFactory> entry : delegateFactories
>             .entrySet()) {
>          delegates.put(entry.getKey(),
>                entry.getValue().createFileSystemView(session));
>       }
>
>       return new DelegatingFilesystemView(session, delegates);
>    }
>
>    /**
>     * Provides a set of FileSystemFactories from which delegate
> FileSystemViews
>     * are created.
>     *
>     * @param delegateFactories
>     *           A map. The keys are the names of the "directories" used for
>     *           these delegates; the values are the FileSystemFactories.
>     */
>    public void setDelegateFactories(
>          final Map<String, FileSystemFactory> delegateFactories) {
>       this.delegateFactories = delegateFactories;
>    }
>
> }
>
> ---------------------------------------
>
> package com.example.apachesftp.filesystem.delegating;
>
> import java.io.*;
> import java.util.*;
>
> import org.apache.sshd.server.FileSystemView;
> import org.apache.sshd.server.SshFile;
>
> import com.example.apachesftp.filesystem.*;
>
> public class DelegatingSshFile implements DelegatableSshDirectory {
>
>    public enum Disposition {
>       ROOT_OF_EVERYTHING, ROOT_OF_DELEGATE, IN_DELEGATE
>    }
>
>    private final String                      root;
>    private final SshFile                     delegate;
>    private final Map<String, FileSystemView> delegates; private String
> alias = null; private DelegatableSshDirectory parent = this;
>
>    /*
>     * Some notes.
>     *
>     * If absolute path is empty or "/" then we are the root of the
> delegating
>     * filesystem.
>     *
>     * If absolute path is exactly one element long, then we are at the
> root of a
>     * delegate
>     *
>     * If the absolute path is 2 elements or more, then we are deeper into a
>     * delegate.
>     */
>    public DelegatingSshFile(String path,
>          final Map<String, FileSystemView> delegates) {
>
>       if (path.equals(".")) {
>          path = "/";
>       }
>
>       String[] parts = PathUtil.headAndTail(path);
>       this.root = parts[0];
>       this.delegates = delegates;
>
>       FileSystemView delegateFSV = delegates.get(root);
>       if (null != delegateFSV) {
>          this.delegate = delegateFSV.getFile(parts[1]);
>       } else {
>          this.delegate = new NonExistantSshFile(parts[1]);
>       }
>    }
>
>    public DelegatingSshFile(final String root, final SshFile delegate,
>          final Map<String, FileSystemView> delegates) {
>       this.root = root;
>       this.delegate = delegate;
>       this.delegates = delegates;
>    }
>
>    public Disposition getDisposition() {
>
>       if (PathUtil.isBottom(root)) {
>          return Disposition.ROOT_OF_EVERYTHING;
>       }
>       if (delegate instanceof NonExistantSshFile) {
>          if (PathUtil.isBottom(delegate.getAbsolutePath())) {
>             return Disposition.ROOT_OF_EVERYTHING;
>          } else {
>             return Disposition.IN_DELEGATE;
>          }
>       }
>       if (PathUtil.isBottom(delegate.getAbsolutePath())) {
>          return Disposition.ROOT_OF_DELEGATE;
>       }
>       // else
>       return Disposition.IN_DELEGATE;
>    }
>
>    @Override
>    public String getAbsolutePath() {
>       if (PathUtil.isBottom(root)) {
>          return "/";
>       } else {
>          return PathUtil.joinPaths(root, delegate.getAbsolutePath());
>       }
>    }
>
>    @Override
>    public String getName() {
>     if(alias != null) {
>     return alias;
>     } else {
>     return getOriginalName();
>     }
>    }
>
>    private String getOriginalName() {
>       String name = delegate.getName();
>       if (PathUtil.isBottom(name)) {
>          name = root;
>       }
>       name = PathUtil.deSlashFront(name);
>
>       if (name.equals("")) {
>          name = "/";
>       }
>
>       return name;
>    }
>
>    @Override
>    public boolean isDirectory() {
>       switch (getDisposition()) {
>       case ROOT_OF_EVERYTHING:
>          return true;
>       default:
>          return delegate.isDirectory();
>       }
>    }
>
>    @Override
>    public boolean isFile() {
>       switch (getDisposition()) {
>       case ROOT_OF_EVERYTHING:
>          return false;
>       default:
>          return delegate.isFile();
>       }
>    }
>
>    @Override
>    public boolean doesExist() {
>       switch (getDisposition()) {
>       case ROOT_OF_EVERYTHING:
>       if(root.equals("")) {
>       return true;
>       } else {
>       return delegates.keySet().contains(root);
>       }
>       default:
>          return delegate.doesExist();
>       }
>    }
>
>    @Override
>    public boolean isReadable() {
>       switch (getDisposition()) {
>       case ROOT_OF_EVERYTHING:
>          return true;
>       default:
>          return delegate.isReadable();
>       }
>    }
>
>    @Override
>    public boolean isWritable() {
>       switch (getDisposition()) {
>       case ROOT_OF_EVERYTHING:
>          return false;
>       default:
>          return delegate.isWritable();
>       }
>    }
>
>    @Override
>    public boolean isExecutable() {
>       switch (getDisposition()) {
>       case ROOT_OF_EVERYTHING:
>          return true;
>       default:
>          return delegate.isExecutable();
>       }
>    }
>
>    @Override
>    public boolean isRemovable() {
>       return delegate.isRemovable();
>    }
>
>    @Override
>    public SshFile getParentFile() {
>       switch (getDisposition()) {
>       case ROOT_OF_EVERYTHING:
>          return this;
>       case ROOT_OF_DELEGATE:
>          return new DelegatingSshFile("/", delegates);
>       default:
>          return new DelegatingSshFile(root, delegate.getParentFile(),
> delegates);
>       }
>    }
>
>    @Override
>    public long getLastModified() {
>       switch (getDisposition()) {
>       case ROOT_OF_EVERYTHING:
>          return 0;
>       default:
>          return delegate.getLastModified();
>       }
>    }
>
>    @Override
>    public boolean setLastModified(final long time) {
>       switch (getDisposition()) {
>       case ROOT_OF_EVERYTHING:
>          return false;
>       default:
>          return delegate.setLastModified(time);
>       }
>    }
>
>    @Override
>    public long getSize() {
>       switch (getDisposition()) {
>       case ROOT_OF_EVERYTHING:
>          return delegates.size(); // plus . and ..
>       default:
>          return delegate.getSize();
>       }
>    }
>
>    @Override
>    public boolean mkdir() {
>       switch (getDisposition()) {
>       case ROOT_OF_EVERYTHING:
>          return false;
>       default:
>          return delegate.mkdir();
>       }
>    }
>
>    @Override
>    public boolean delete() {
>       switch (getDisposition()) {
>       case ROOT_OF_EVERYTHING:
>          return false;
>       default:
>          return delegate.delete();
>       }
>    }
>
>    @Override
>    public boolean create() throws IOException {
>       switch (getDisposition()) {
>       case ROOT_OF_EVERYTHING:
>          return false;
>       default:
>          return delegate.create();
>       }
>    }
>
>    @Override
>    public void truncate() throws IOException {
>
>    }
>
>    @Override
>    public boolean move(final SshFile destination) {
>       switch (getDisposition()) {
>       case ROOT_OF_EVERYTHING:
>          return false;
>       default:
>          return delegate.move(destination);
>       }
>    }
>
>    @Override
>    public List<SshFile> listSshFiles() {
>       switch (getDisposition()) {
>       case ROOT_OF_EVERYTHING:
>          return listDelegates();
>       default:
>          List<SshFile> files = delegate.listSshFiles();
>          return delegatify(files);
>       }
>    }
>
>    private List<SshFile> listDelegates() {
>       List<SshFile> l = new LinkedList<SshFile>();
>       l.add(copyWithAlias("."));
>       l.add(parent.copyWithAlias(".."));
>       Set<String> keys = this.delegates.keySet();
>       for (String key : keys) {
>          l.add(new DelegatingSshFile(key, delegates));
>       }
>       return l;
>    }
>
>    private List<SshFile> delegatify(final List<SshFile> plainFiles) {
>       List<SshFile> l = new LinkedList<SshFile>();
>       if(null != plainFiles) {
>       for (SshFile f : plainFiles) {
>       l.add(new DelegatingSshFile(root, f, delegates));
>       }
>       }
>       return l;
>    }
>
>    @Override
>    public OutputStream createOutputStream(final long offset) throws
> IOException {
>       switch (getDisposition()) {
>       case ROOT_OF_EVERYTHING:
>          return null;
>       default:
>          return delegate.createOutputStream(offset);
>       }
>
>    }
>
>    @Override
>    public InputStream createInputStream(final long offset) throws
> IOException {
>       return delegate.createInputStream(offset);
>    }
>
>    @Override
>    public void handleClose() throws IOException {
>       switch (getDisposition()) {
>       case ROOT_OF_EVERYTHING:
>          break;
>       default:
>          delegate.handleClose();
>       }
>
>    }
>
> @Override
>    public void setAlias(String alias) {
>    this.alias  = alias;
>    }
>  @Override
> public DelegatingSshFile copyWithAlias(String alias) { DelegatingSshFile
> copy = new DelegatingSshFile(root,delegate,delegates);
> copy.setAlias(alias);
> return copy;
> }
>
> @Override
>    public void setParent(DelegatableSshDirectory parent) {
>    this.parent  = parent;
>    }
>
> @Override
>    public String getOwner() {
>       switch (getDisposition()) {
>       case ROOT_OF_EVERYTHING:
>          return "system";
>       default:
>          return delegate.getOwner();
>       }
>    }
>  public SshFile getDelegate() {
> return delegate;
> }
> }
>
>
>
> ------------------------
>
> package com.example.apachesftp.filesystem.delegating;
>
> import java.util.Map;
>
> import org.apache.sshd.common.Session;
> import org.apache.sshd.server.FileSystemView;
> import org.apache.sshd.server.SshFile;
>
> public class DelegatingFilesystemView implements FileSystemView {
>
>    private Map<String, FileSystemView> delegates;
>
>    public DelegatingFilesystemView(final Session session,
>          final Map<String, FileSystemView> delegates) {
>       setDelegates(delegates);
>    }
>
>    public void setDelegates(final Map<String, FileSystemView> delegates) {
>       this.delegates = delegates;
>    }
>
>    @Override
>    public SshFile getFile(final String path) {
>       DelegatingSshFile f = new DelegatingSshFile(
>       PathUtil.cleanDots(path), delegates);
>       if(f instanceof DelegatableSshDirectory) {
>       DelegatingSshFile root = new DelegatingSshFile("/", delegates);
>       f.setParent(root);
>       }
>       return f;
>    }
>
>    @Override
>    public SshFile getFile(final SshFile baseDir, final String file) {
>       String fullPath = PathUtil.joinPaths(baseDir.getAbsolutePath(),
> file);
>       return getFile(fullPath);
>    }
>
> }
>
>
>
>
> On 16 October 2013 15:20, Gentian Hila <gh...@commercehub.com> wrote:
>
> > Thank you very much,
> >
> > I will take a look around the interfaces you suggest. I did not get
> > any attached files though.
> >
> >
> > Genti
> >
> > From: John Hartnup [mailto:john.hart...@gmail.com]
> > Sent: Wednesday, October 16, 2013 9:58 AM
> > To: ftpserver-users@mina.apache.org
> > Subject: Re: directory structure permissions & account locking
> >
> > The answer to any question like this is to customise the Filesystem
> > classes to do what you want.
> >
> > I've attached some Java files (not warrantied for any particular
> > purpose)  for "DelegatingFilesystem" -- you can use one of these as
> > the top of your filesystem hierarchy, with real, separately
> > configured, filesystems as delegates, which appear as subdirectories.
> >
> > To grok these, you'll need to grok the FilesystemView,
> > FilesystemViewFactory and SshFile interfaces - read the interfaces and
> > they'll probably make sense.
> >
> >
> >
> > On 16 October 2013 14:50, Gentian Hila <gh...@commercehub.com<mailto:
> > gh...@commercehub.com>> wrote:
> > We have a use case where we would want to have two subdirectories
> > under the user home directory incoming and outgoing.  Each of them
> > would have a hierarchical path.
> >
> > However, we want:
> >
> > User have read-only permissions for the outgoing directory and its
> > children.
> > User have read-write permissions for the incoming directory and its
> > children.
> > Users cannot change the structure of the directories ( I think we can
> > achieve that by disabling MKDIR and RMD).
> > Users cannot delete a file ( we can achieve that by disabling DELE
> > command).
> >
> > However I do not see a way how to apply different permissions to
> > different folders either through configuration or through extending
> > the API source code yet.
> >
> > Is this possible at all? Has anybody attempted to do this?
> >
> >
> >
> >
> > We also have a use case that basically requires that we lock an
> > account after several failed logins. I did not see a mechanism for
> > account locking and unlocking when this happens?
> >
> > Am I missing something?
> >
> >
> > Genti
> >
> >
> >
> > --
> > "There is no way to peace; peace is the way"
> >
>
>
>
> --
> "There is no way to peace; peace is the way"
>



-- 
"There is no way to peace; peace is the way"

Reply via email to