FilesystemBasedAuthImpl.java
/*
* This file is part of Waarp Project (named also Waarp or GG).
*
* Copyright (c) 2019, Waarp SAS, and individual contributors by the @author
* tags. See the COPYRIGHT.txt in the distribution for a full listing of
* individual contributors.
*
* All Waarp Project is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Waarp is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* Waarp . If not, see <http://www.gnu.org/licenses/>.
*/
package org.waarp.common.file.filesystembased;
import org.waarp.common.command.NextCommandReply;
import org.waarp.common.command.ReplyCode;
import org.waarp.common.command.exception.Reply421Exception;
import org.waarp.common.command.exception.Reply530Exception;
import org.waarp.common.file.AbstractDir;
import org.waarp.common.file.AuthInterface;
import org.waarp.common.file.DirInterface;
import org.waarp.common.file.SessionInterface;
import org.waarp.common.utility.ParametersChecker;
import java.util.regex.Pattern;
/**
* Authentication implementation for Filesystem Based
*/
public abstract class FilesystemBasedAuthImpl implements AuthInterface {
/**
* DOUBLE SLASH pattern
*/
private static final Pattern DOUBLE_SLASH = Pattern.compile("//");
/**
* User name
*/
protected String user;
/**
* Password
*/
protected String password;
/**
* Is Identified
*/
protected boolean isIdentified;
/**
* SessionInterface
*/
protected final SessionInterface session;
/**
* Relative Path after Authentication
*/
protected String rootFromAuth;
/**
* @param session
*/
protected FilesystemBasedAuthImpl(final SessionInterface session) {
this.session = session;
isIdentified = false;
}
/**
* @return the session
*/
@Override
public final SessionInterface getSession() {
return session;
}
/**
* Set the user according to any implementation and could set the
* rootFromAuth. If NOOP is returned,
* isIdentifed must be TRUE.
*
* @param user
*
* @return (NOOP, 230) if the user is OK, else return the following command
* that must follow (usually PASS) and
* the associated reply
*
* @throws Reply421Exception if there is a problem during the
* authentication
* @throws Reply530Exception if there is a problem during the
* authentication
*/
protected abstract NextCommandReply setBusinessUser(String user)
throws Reply421Exception, Reply530Exception;
/**
* @param user the user to set
*
* @return (NOOP, 230) if the user is OK, else return the following command
* that must follow (usually PASS) and
* the associated reply
*
* @throws Reply421Exception if there is a problem during the
* authentication
* @throws Reply530Exception if there is a problem during the
* authentication
*/
@Override
public final NextCommandReply setUser(final String user)
throws Reply421Exception, Reply530Exception {
final NextCommandReply next = setBusinessUser(user);
this.user = user;
if (next.reply == ReplyCode.REPLY_230_USER_LOGGED_IN) {
setRootFromAuth();
session.getDir().initAfterIdentification();
}
return next;
}
/**
* @return the user
*/
@Override
public final String getUser() {
return user;
}
/**
* Set the password according to any implementation and could set the
* rootFromAuth. If NOOP is returned,
* isIdentifed must be TRUE.
*
* @param password
*
* @return (NOOP, 230) if the Password is OK, else return the following
* command that must follow (usually ACCT)
* and the associated reply
*
* @throws Reply421Exception if there is a problem during the
* authentication
* @throws Reply530Exception if there is a problem during the
* authentication
*/
protected abstract NextCommandReply setBusinessPassword(String password)
throws Reply421Exception, Reply530Exception;
/**
* @param password the password to set
*
* @return (NOOP, 230) if the Password is OK, else return the following
* command that must follow (usually ACCT)
* and the associated reply
*
* @throws Reply421Exception if there is a problem during the
* authentication
* @throws Reply530Exception if there is a problem during the
* authentication
*/
@Override
public final NextCommandReply setPassword(final String password)
throws Reply421Exception, Reply530Exception {
final NextCommandReply next = setBusinessPassword(password);
this.password = password;
if (next.reply == ReplyCode.REPLY_230_USER_LOGGED_IN) {
setRootFromAuth();
session.getDir().initAfterIdentification();
}
return next;
}
/**
* Set the Authentication to Identified or Not
*
* @param isIdentified
*/
protected final void setIsIdentified(final boolean isIdentified) {
this.isIdentified = isIdentified;
}
/**
* Is the current Authentication OK for full identification. It must be true
* after a correct sequence of
* identification: At most, it is true when setAccount is OK. It could be
* positive before (user name only,
* user+password only).<br>
* In the current implementation, as USER+PASS+ACCT are needed, it will be
* true only after a correct ACCT.
*
* @return True if the user has a positive login, else False
*/
@Override
public final boolean isIdentified() {
return isIdentified;
}
/**
* @return the root relative path from authentication if any or null if the
* default is used (default is /user
* or /user/account)
*
* @throws Reply421Exception if the business root is not available
*/
protected abstract String setBusinessRootFromAuth() throws Reply421Exception;
/**
* Set the root relative Path from current status of Authentication (should
* be
* the highest level for the
* current authentication). If setBusinessRootFromAuth returns null, by
* default set /user or /user/account.
*
* @throws Reply421Exception if the business root is not available
*/
protected void setRootFromAuth() throws Reply421Exception {
rootFromAuth = setBusinessRootFromAuth();
if (rootFromAuth == null) {
rootFromAuth = DirInterface.SEPARATOR + user;
}
}
@Override
public final String getBusinessPath() {
return rootFromAuth;
}
/**
* Business implementation of clean
*/
protected abstract void businessClean();
/**
* Clean object
*/
@Override
public void clear() {
businessClean();
user = null;
password = null;
rootFromAuth = null;
isIdentified = false;
}
/**
* Return the full path as a String (with mount point).
*
* @param path relative path including business one (may be null or
* empty)
*
* @return the full path as a String
*/
public final String getAbsolutePath(final String path) {
if (ParametersChecker.isEmpty(path)) {
return getBaseDirectory();
}
return AbstractDir.normalizePath(
getBaseDirectory() + DirInterface.SEPARATOR + path);
}
/**
* Return the relative path from a file (without mount point)
*
* @param file (full path with mount point)
*
* @return the relative path from a file
*/
@Override
public final String getRelativePath(final String file) {
// Work around Windows path '\'
return DOUBLE_SLASH.matcher(
file.replaceFirst(AbstractDir.normalizePath(getBaseDirectory()), ""))
.replaceAll("/");
}
}