extensions/net.sf.basedb.ftp/trunk/src/net/sf/basedb/clients/ftp/BaseUser.java

Code
Comments
Other
Rev Date Author Line
716 02 Jun 08 nicklas 1 /**
716 02 Jun 08 nicklas 2   $Id $
716 02 Jun 08 nicklas 3
716 02 Jun 08 nicklas 4   Copyright (C) 2008 Nicklas Nordborg
716 02 Jun 08 nicklas 5
1381 15 Aug 11 martin 6   This file is part of the FTP Server extension for BASE.
716 02 Jun 08 nicklas 7   Available at http://baseplugins.thep.lu.se/
1381 15 Aug 11 martin 8   BASE main site: http://base.thep.lu.se/
1381 15 Aug 11 martin 9   -----------------------------------------------------------
1381 15 Aug 11 martin 10   
1381 15 Aug 11 martin 11   This is free software; you can redistribute it and/or
716 02 Jun 08 nicklas 12   modify it under the terms of the GNU General Public License
1381 15 Aug 11 martin 13   as published by the Free Software Foundation; either version 3
716 02 Jun 08 nicklas 14   of the License, or (at your option) any later version.
1381 15 Aug 11 martin 15   
1381 15 Aug 11 martin 16   The software is distributed in the hope that it will be useful,
716 02 Jun 08 nicklas 17   but WITHOUT ANY WARRANTY; without even the implied warranty of
716 02 Jun 08 nicklas 18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
716 02 Jun 08 nicklas 19   GNU General Public License for more details.
1381 15 Aug 11 martin 20   
1381 15 Aug 11 martin 21   You should have received a copy of the GNU General Public License
1381 15 Aug 11 martin 22   along with BASE. If not, see <http://www.gnu.org/licenses/>.
716 02 Jun 08 nicklas 23
716 02 Jun 08 nicklas 24 */
714 30 May 08 nicklas 25 package net.sf.basedb.clients.ftp;
714 30 May 08 nicklas 26
714 30 May 08 nicklas 27 import java.util.ArrayList;
714 30 May 08 nicklas 28 import java.util.List;
714 30 May 08 nicklas 29
714 30 May 08 nicklas 30 import org.apache.ftpserver.ftplet.Authority;
714 30 May 08 nicklas 31 import org.apache.ftpserver.ftplet.AuthorizationRequest;
716 02 Jun 08 nicklas 32 import org.slf4j.Logger;
716 02 Jun 08 nicklas 33 import org.slf4j.LoggerFactory;
714 30 May 08 nicklas 34
714 30 May 08 nicklas 35 import net.sf.basedb.core.Application;
714 30 May 08 nicklas 36 import net.sf.basedb.core.DbControl;
714 30 May 08 nicklas 37 import net.sf.basedb.core.Directory;
1399 10 Oct 11 nicklas 38 import net.sf.basedb.core.Include;
1399 10 Oct 11 nicklas 39 import net.sf.basedb.core.ItemQuery;
714 30 May 08 nicklas 40 import net.sf.basedb.core.PermissionDeniedException;
1399 10 Oct 11 nicklas 41 import net.sf.basedb.core.Project;
714 30 May 08 nicklas 42 import net.sf.basedb.core.SessionControl;
714 30 May 08 nicklas 43 import net.sf.basedb.core.SystemItems;
1399 10 Oct 11 nicklas 44 import net.sf.basedb.core.Type;
714 30 May 08 nicklas 45 import net.sf.basedb.core.User;
2281 13 Mar 14 nicklas 46 import net.sf.basedb.core.authentication.LoginRequest;
1399 10 Oct 11 nicklas 47 import net.sf.basedb.core.query.Expressions;
1399 10 Oct 11 nicklas 48 import net.sf.basedb.core.query.Hql;
1399 10 Oct 11 nicklas 49 import net.sf.basedb.core.query.Restrictions;
714 30 May 08 nicklas 50
714 30 May 08 nicklas 51 /**
714 30 May 08 nicklas 52   Represents a known-to-exist (logged in) BASE user or
714 30 May 08 nicklas 53   a user that has not yet logged in, so we don't
714 30 May 08 nicklas 54   know if the user exists or not.
716 02 Jun 08 nicklas 55   @author Nicklas
716 02 Jun 08 nicklas 56   @version 1.0
714 30 May 08 nicklas 57 */
714 30 May 08 nicklas 58 public class BaseUser 
714 30 May 08 nicklas 59   implements org.apache.ftpserver.ftplet.User 
714 30 May 08 nicklas 60 {
714 30 May 08 nicklas 61
716 02 Jun 08 nicklas 62   private static final Logger log = LoggerFactory.getLogger(BaseUser.class);
716 02 Jun 08 nicklas 63
714 30 May 08 nicklas 64   private final String login;
915 11 Dec 08 nicklas 65   private final List<Authority> authorities;
714 30 May 08 nicklas 66   
714 30 May 08 nicklas 67   SessionControl sc;
714 30 May 08 nicklas 68   private User user;
1399 10 Oct 11 nicklas 69   private Project project;
915 11 Dec 08 nicklas 70   private BaseFtpFile home;
714 30 May 08 nicklas 71   
716 02 Jun 08 nicklas 72   /**
716 02 Jun 08 nicklas 73     Creates a new, not yet logged in, user object.
716 02 Jun 08 nicklas 74     
716 02 Jun 08 nicklas 75     @param login The login of the user
716 02 Jun 08 nicklas 76     @param authorities The permissions of the user
716 02 Jun 08 nicklas 77   */
915 11 Dec 08 nicklas 78   public BaseUser(String login, List<Authority> authorities)
714 30 May 08 nicklas 79   {
714 30 May 08 nicklas 80     this.login = login;
714 30 May 08 nicklas 81     this.authorities = authorities;
714 30 May 08 nicklas 82   }
714 30 May 08 nicklas 83   
714 30 May 08 nicklas 84   /*
714 30 May 08 nicklas 85     From the User interface
714 30 May 08 nicklas 86     -----------------------
714 30 May 08 nicklas 87   */
714 30 May 08 nicklas 88   @Override
714 30 May 08 nicklas 89   public String getName() 
714 30 May 08 nicklas 90   {
714 30 May 08 nicklas 91     return login;
714 30 May 08 nicklas 92   }
714 30 May 08 nicklas 93
714 30 May 08 nicklas 94   /**
714 30 May 08 nicklas 95     Always null, since we have no access to passwords.
714 30 May 08 nicklas 96   */
714 30 May 08 nicklas 97   @Override
714 30 May 08 nicklas 98   public String getPassword() 
714 30 May 08 nicklas 99   {
714 30 May 08 nicklas 100     return null;
714 30 May 08 nicklas 101   }
714 30 May 08 nicklas 102   
714 30 May 08 nicklas 103   /**
1399 10 Oct 11 nicklas 104     Get the {@link Application#sessionCacheTimeout()} value
714 30 May 08 nicklas 105     and convert it to seconds.
714 30 May 08 nicklas 106   */
714 30 May 08 nicklas 107   @Override
714 30 May 08 nicklas 108   public int getMaxIdleTime() 
714 30 May 08 nicklas 109   {
714 30 May 08 nicklas 110     return Application.sessionCacheTimeout() * 60;
714 30 May 08 nicklas 111   }
714 30 May 08 nicklas 112   
714 30 May 08 nicklas 113   /**
714 30 May 08 nicklas 114     Always TRUE since a user can't log in if it has been disabled,
714 30 May 08 nicklas 115    */
714 30 May 08 nicklas 116   @Override
714 30 May 08 nicklas 117   public boolean getEnabled() 
714 30 May 08 nicklas 118   {
714 30 May 08 nicklas 119     return true;
714 30 May 08 nicklas 120   }
714 30 May 08 nicklas 121   
714 30 May 08 nicklas 122   /**
714 30 May 08 nicklas 123     If the user hasn't been logged in or if the logged in user doesn't have a
714 30 May 08 nicklas 124     home directory, '/'. Otherwise, the logged in user's home directory.
714 30 May 08 nicklas 125   */
714 30 May 08 nicklas 126   @Override
714 30 May 08 nicklas 127   public String getHomeDirectory() 
714 30 May 08 nicklas 128   {
915 11 Dec 08 nicklas 129     return home == null ? "/" : home.getAbsolutePath();
714 30 May 08 nicklas 130   }
714 30 May 08 nicklas 131   
716 02 Jun 08 nicklas 132   /**
716 02 Jun 08 nicklas 133     Checks if the permissions for a user contains the requested
716 02 Jun 08 nicklas 134     permission. This method returns the <code>request</code>
716 02 Jun 08 nicklas 135     parameter if there is at least one permission that can
716 02 Jun 08 nicklas 136     authorize the request ({@link Authority#canAuthorize(AuthorizationRequest)}
716 02 Jun 08 nicklas 137     and all that can must accept it ({@link Authority#authorize(AuthorizationRequest)}).
716 02 Jun 08 nicklas 138     <p>
716 02 Jun 08 nicklas 139     If there is no permission that accepts the request, null is
716 02 Jun 08 nicklas 140     returned.
716 02 Jun 08 nicklas 141   */
714 30 May 08 nicklas 142   @Override
714 30 May 08 nicklas 143   public AuthorizationRequest authorize(AuthorizationRequest request) 
714 30 May 08 nicklas 144   {
716 02 Jun 08 nicklas 145     boolean debug = log.isDebugEnabled();
716 02 Jun 08 nicklas 146     if (debug)
716 02 Jun 08 nicklas 147     {
716 02 Jun 08 nicklas 148       log.debug("Trying to authorize: login=" + login + "; request="+request);
716 02 Jun 08 nicklas 149     }
714 30 May 08 nicklas 150     boolean authorized = false;
714 30 May 08 nicklas 151     /*
714 30 May 08 nicklas 152       To get the permission we must check all registered
714 30 May 08 nicklas 153       Authority:s. There must be at least one that CAN 
714 30 May 08 nicklas 154       authorize the request, and all that can must accept
714 30 May 08 nicklas 155       the request.
714 30 May 08 nicklas 156         */
714 30 May 08 nicklas 157     for (Authority auth : authorities)
714 30 May 08 nicklas 158     {
714 30 May 08 nicklas 159       if (auth.canAuthorize(request))
714 30 May 08 nicklas 160       {
716 02 Jun 08 nicklas 161         if (debug) log.debug("Can authorize: auth=" + auth);
716 02 Jun 08 nicklas 162         if (auth.authorize(request) == null) 
716 02 Jun 08 nicklas 163         {
716 02 Jun 08 nicklas 164           if (debug) log.debug("Permission denied: auth=" + auth + "; request=" + request);
716 02 Jun 08 nicklas 165           return null;
716 02 Jun 08 nicklas 166         }
716 02 Jun 08 nicklas 167         if (debug) log.debug("Accepted: auth=" + auth + "; request=" + request);
714 30 May 08 nicklas 168         authorized = true;
714 30 May 08 nicklas 169       }
716 02 Jun 08 nicklas 170       else
716 02 Jun 08 nicklas 171       {
716 02 Jun 08 nicklas 172         if (debug) log.debug("Can't authorize: auth=" + auth);
716 02 Jun 08 nicklas 173       }
714 30 May 08 nicklas 174     }
716 02 Jun 08 nicklas 175     if (debug)
716 02 Jun 08 nicklas 176     {
716 02 Jun 08 nicklas 177       log.debug(authorized ? "Accepted: " + request : "Permission denied: " + request);
716 02 Jun 08 nicklas 178     }
714 30 May 08 nicklas 179     return authorized ? request : null;
714 30 May 08 nicklas 180   }
714 30 May 08 nicklas 181   
714 30 May 08 nicklas 182   @Override
915 11 Dec 08 nicklas 183   public List<Authority> getAuthorities() 
714 30 May 08 nicklas 184   {
714 30 May 08 nicklas 185     return authorities;
714 30 May 08 nicklas 186   }
714 30 May 08 nicklas 187
714 30 May 08 nicklas 188   @Override
915 11 Dec 08 nicklas 189   public List<Authority> getAuthorities(Class<? extends Authority> clazz) 
714 30 May 08 nicklas 190   {
714 30 May 08 nicklas 191     List<Authority> selected = new ArrayList<Authority>();
714 30 May 08 nicklas 192         for (Authority auth : authorities)
714 30 May 08 nicklas 193         {
714 30 May 08 nicklas 194           if (auth.getClass().equals(clazz))
714 30 May 08 nicklas 195           {
714 30 May 08 nicklas 196             selected.add(auth);
714 30 May 08 nicklas 197           }
714 30 May 08 nicklas 198         }
915 11 Dec 08 nicklas 199         return selected;  
714 30 May 08 nicklas 200   }
714 30 May 08 nicklas 201   // ------------------------
714 30 May 08 nicklas 202   
716 02 Jun 08 nicklas 203   /*
716 02 Jun 08 nicklas 204     From the Object class
716 02 Jun 08 nicklas 205     ---------------------
716 02 Jun 08 nicklas 206   */
716 02 Jun 08 nicklas 207   @Override
716 02 Jun 08 nicklas 208   public String toString() 
716 02 Jun 08 nicklas 209   {
716 02 Jun 08 nicklas 210     return "BaseUser[login=" + login + "]";
716 02 Jun 08 nicklas 211   }
716 02 Jun 08 nicklas 212   // ------------------------
716 02 Jun 08 nicklas 213   
716 02 Jun 08 nicklas 214   
714 30 May 08 nicklas 215   /**
714 30 May 08 nicklas 216     Check if this object represents a logged in user
714 30 May 08 nicklas 217     or not.
714 30 May 08 nicklas 218   */
714 30 May 08 nicklas 219   public boolean isLoggedIn()
714 30 May 08 nicklas 220   {
714 30 May 08 nicklas 221     return sc != null && sc.isLoggedIn();
714 30 May 08 nicklas 222   }
714 30 May 08 nicklas 223   
714 30 May 08 nicklas 224   /**
714 30 May 08 nicklas 225     Login to BASE. The login to use was specified in the constructor.
714 30 May 08 nicklas 226     @param password The user's password
714 30 May 08 nicklas 227     @param remoteId The  ip address the user is using.
714 30 May 08 nicklas 228   */
714 30 May 08 nicklas 229   public void login(String password, String remoteId, String clientId)
714 30 May 08 nicklas 230   {
714 30 May 08 nicklas 231     if (isLoggedIn()) return;
716 02 Jun 08 nicklas 232     log.info("Trying to login: " + login + "; ip="+remoteId);
716 02 Jun 08 nicklas 233     log.debug("Password:" + password);
714 30 May 08 nicklas 234     SessionControl sc = Application.newSessionControl(clientId, remoteId, null);
2281 13 Mar 14 nicklas 235     sc.login(new LoginRequest(login, password));
716 02 Jun 08 nicklas 236     log.debug("Login ok, loading user info and home directory. SessionID=" + sc.getId());
714 30 May 08 nicklas 237     
714 30 May 08 nicklas 238     // Login was ok
714 30 May 08 nicklas 239     // If no FTP client has been registered only, the root user is allowed to login
714 30 May 08 nicklas 240     if (clientId == null && sc.getLoggedInUserId() != SystemItems.getId(User.ROOT))
714 30 May 08 nicklas 241     {
716 02 Jun 08 nicklas 242       log.warn("FTP Server not registered, only ROOT is allowed to login");
714 30 May 08 nicklas 243       throw new PermissionDeniedException("Only root is allowed to login");
714 30 May 08 nicklas 244     }
714 30 May 08 nicklas 245     
714 30 May 08 nicklas 246     DbControl dc = sc.newDbControl();
714 30 May 08 nicklas 247     try
714 30 May 08 nicklas 248     {
714 30 May 08 nicklas 249       User u = User.getById(dc, sc.getLoggedInUserId());
714 30 May 08 nicklas 250       Directory homeDir = u.getHomeDirectory();
714 30 May 08 nicklas 251       if (homeDir == null)
714 30 May 08 nicklas 252       {
714 30 May 08 nicklas 253         homeDir = Directory.getById(dc, SystemItems.getId(Directory.ROOT));
714 30 May 08 nicklas 254       }
714 30 May 08 nicklas 255       this.sc = sc;
714 30 May 08 nicklas 256       this.user = u;
915 11 Dec 08 nicklas 257       this.home = new BaseFtpFile(this, homeDir);
714 30 May 08 nicklas 258     }
716 02 Jun 08 nicklas 259     catch (RuntimeException ex)
716 02 Jun 08 nicklas 260     {
716 02 Jun 08 nicklas 261       log.error("Failed to load user info and home directory: login=" + login, ex);
716 02 Jun 08 nicklas 262       throw ex;
716 02 Jun 08 nicklas 263     }
714 30 May 08 nicklas 264     finally
714 30 May 08 nicklas 265     {
714 30 May 08 nicklas 266       if (dc != null) dc.close();
714 30 May 08 nicklas 267     }
716 02 Jun 08 nicklas 268     log.debug("Login complete: login="+login);
714 30 May 08 nicklas 269   }
714 30 May 08 nicklas 270   
714 30 May 08 nicklas 271   /**
1399 10 Oct 11 nicklas 272     Activate the project with the given name.
1399 10 Oct 11 nicklas 273     @param name The name of the project, or null to deactive 
1399 10 Oct 11 nicklas 274   */
1399 10 Oct 11 nicklas 275   public void setProject(String name)
1399 10 Oct 11 nicklas 276   {
1399 10 Oct 11 nicklas 277     if (!isLoggedIn()) return;
1399 10 Oct 11 nicklas 278     
1399 10 Oct 11 nicklas 279     if (name == null)
1399 10 Oct 11 nicklas 280     {
1399 10 Oct 11 nicklas 281       log.info("Deactivating current project: " + project);
1399 10 Oct 11 nicklas 282       this.project = null;
1399 10 Oct 11 nicklas 283       sc.setActiveProject(null);
1399 10 Oct 11 nicklas 284       return;
1399 10 Oct 11 nicklas 285     }
1399 10 Oct 11 nicklas 286     
1399 10 Oct 11 nicklas 287     log.info("Looking up project: " + name);
1399 10 Oct 11 nicklas 288     
1399 10 Oct 11 nicklas 289     ItemQuery<Project> projectQuery = Project.getQuery();
1399 10 Oct 11 nicklas 290     projectQuery.include(Include.MINE, Include.SHARED);
1399 10 Oct 11 nicklas 291     projectQuery.restrict(Restrictions.eq(Hql.property("name"), Expressions.parameter("name", name, Type.STRING)));
1399 10 Oct 11 nicklas 292
1399 10 Oct 11 nicklas 293     DbControl dc = null;
1399 10 Oct 11 nicklas 294     try
1399 10 Oct 11 nicklas 295     {
1399 10 Oct 11 nicklas 296       dc = sc.newDbControl();
1399 10 Oct 11 nicklas 297       List<Project> projects = projectQuery.list(dc);
1399 10 Oct 11 nicklas 298       log.debug("Found " + projects.size() + " projects for name: " + name);
1399 10 Oct 11 nicklas 299       if (projects.size() > 0) 
1399 10 Oct 11 nicklas 300       {
1399 10 Oct 11 nicklas 301         this.project = projects.get(0);
1399 10 Oct 11 nicklas 302         log.info("Activating project: " + project);
1399 10 Oct 11 nicklas 303         sc.setActiveProject(project);
1399 10 Oct 11 nicklas 304       }
1399 10 Oct 11 nicklas 305     }
1399 10 Oct 11 nicklas 306     catch (RuntimeException ex)
1399 10 Oct 11 nicklas 307     {
1399 10 Oct 11 nicklas 308       log.error("Failed to activate project: name=" + name, ex);
1399 10 Oct 11 nicklas 309       throw ex;
1399 10 Oct 11 nicklas 310     }
1399 10 Oct 11 nicklas 311     finally
1399 10 Oct 11 nicklas 312     {
1399 10 Oct 11 nicklas 313       if (dc != null) dc.close();
1399 10 Oct 11 nicklas 314     }    
1399 10 Oct 11 nicklas 315   }
1399 10 Oct 11 nicklas 316
1399 10 Oct 11 nicklas 317   
1399 10 Oct 11 nicklas 318   /**
716 02 Jun 08 nicklas 319     Logout and close the session.
716 02 Jun 08 nicklas 320   */
714 30 May 08 nicklas 321   public void logout()
714 30 May 08 nicklas 322   {
714 30 May 08 nicklas 323     if (sc != null)
714 30 May 08 nicklas 324     {
716 02 Jun 08 nicklas 325       log.info("Logging out: login=" + login + "; SessionID=" + sc.getId());
714 30 May 08 nicklas 326       sc.logout();
714 30 May 08 nicklas 327       sc.close();
714 30 May 08 nicklas 328     }
714 30 May 08 nicklas 329     this.sc = null;
714 30 May 08 nicklas 330     this.user = null;
714 30 May 08 nicklas 331     this.home = null;
714 30 May 08 nicklas 332   }
714 30 May 08 nicklas 333   
714 30 May 08 nicklas 334   /**
714 30 May 08 nicklas 335     Get the logged in user, or null if not logged in.
714 30 May 08 nicklas 336   */
714 30 May 08 nicklas 337   public User getUser()
714 30 May 08 nicklas 338   {
714 30 May 08 nicklas 339     return user;
714 30 May 08 nicklas 340   }
714 30 May 08 nicklas 341
714 30 May 08 nicklas 342   /**
714 30 May 08 nicklas 343     Get the home directory of the logged in user, or null
714 30 May 08 nicklas 344     if no user is logged in.
714 30 May 08 nicklas 345   */
915 11 Dec 08 nicklas 346   public BaseFtpFile getHome()
714 30 May 08 nicklas 347   {
714 30 May 08 nicklas 348     return home;
714 30 May 08 nicklas 349   }
714 30 May 08 nicklas 350
714 30 May 08 nicklas 351 }