Coverage Report - org.mockftpserver.fake.UserAccount
 
Classes in this File Line Coverage Branch Coverage Complexity
UserAccount
98%
71/72
100%
48/48
2
 
 1  
 /*
 2  
  * Copyright 2008 the original author or authors.
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *      http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package org.mockftpserver.fake;
 17  
 
 18  
 import org.mockftpserver.core.util.Assert;
 19  
 import org.mockftpserver.fake.filesystem.FileSystemEntry;
 20  
 import org.mockftpserver.fake.filesystem.Permissions;
 21  
 
 22  
 import java.util.List;
 23  
 
 24  
 /**
 25  
  * Represents a single user account on the server, including the username, password, home
 26  
  * directory, list of groups to which this user belongs, and default permissions applied to
 27  
  * newly-created files and directories.
 28  
  * <p/>
 29  
  * The <code>username</code> and <code>homeDirectory</code> property must be non-null
 30  
  * and non-empty. The <code>homeDirectory</code> property must also match the name of an existing
 31  
  * directory within the file system configured for the <code>FakeFtpServer</code>.
 32  
  * <p/>
 33  
  * The group name applied to newly created files/directories is determined by the <code>groups</code> property.
 34  
  * If null or empty, then the default group name ("users") is used. Otherwise, the first value in the
 35  
  * <code>groups</code> List is used. The <code>groups</code> property defaults to an empty List.
 36  
  * <p/>
 37  
  * The default value for <code>defaultPermissionsForNewFile</code> is read and write permissions for
 38  
  * all (user/group/world). The default value for <code>defaultPermissionsForNewDirectory</code> is read,
 39  
  * write and execute permissions for all (user/group/world).
 40  
  * <p/>
 41  
  * The <code>isValidPassword()</code> method returns true if the specified password matches
 42  
  * the password value configured for this user account. This implementation uses the
 43  
  * <code>isEquals()</code> method to compare passwords.
 44  
  * <p/>
 45  
  * If you want to provide a custom comparison, for instance using encrypted passwords, you can
 46  
  * subclass this class and override the <code>comparePassword()</code> method to provide your own
 47  
  * custom implementation.
 48  
  * <p/>
 49  
  * If the <code>passwordCheckedDuringValidation</code> property is set to false, then the password
 50  
  * value is ignored, and the <code>isValidPassword()</code> method just returns <code<true</code>.
 51  
  * <p/>
 52  
  * The <code>accountRequiredForLogin</code> property defaults to false. If it is set to true, then
 53  
  * it is expected that the login for this account will require an ACCOUNT (ACCT) command after the
 54  
  * PASSWORD (PASS) command is completed.
 55  
  */
 56  
 public class UserAccount {
 57  
 
 58  
     public static final String DEFAULT_USER = "system";
 59  
     public static final String DEFAULT_GROUP = "users";
 60  1
     public static final Permissions DEFAULT_PERMISSIONS_FOR_NEW_FILE = new Permissions("rw-rw-rw-");
 61  1
     public static final Permissions DEFAULT_PERMISSIONS_FOR_NEW_DIRECTORY = Permissions.ALL;
 62  
 
 63  
     private String username;
 64  
     private String password;
 65  
     private String homeDirectory;
 66  
     private List groups;
 67  392
     private boolean passwordRequiredForLogin = true;
 68  392
     private boolean passwordCheckedDuringValidation = true;
 69  392
     private boolean accountRequiredForLogin = false;
 70  392
     private Permissions defaultPermissionsForNewFile = DEFAULT_PERMISSIONS_FOR_NEW_FILE;
 71  392
     private Permissions defaultPermissionsForNewDirectory = DEFAULT_PERMISSIONS_FOR_NEW_DIRECTORY;
 72  
 
 73  
 
 74  
     /**
 75  
      * Construct a new uninitialized instance.
 76  
      */
 77  334
     public UserAccount() {
 78  334
     }
 79  
 
 80  
     /**
 81  
      * Construct a new initialized instance.
 82  
      *
 83  
      * @param username      - the user name
 84  
      * @param password      - the password
 85  
      * @param homeDirectory - the home directory
 86  
      */
 87  58
     public UserAccount(String username, String password, String homeDirectory) {
 88  58
         setUsername(username);
 89  58
         setPassword(password);
 90  58
         setHomeDirectory(homeDirectory);
 91  58
     }
 92  
 
 93  
     public String getUsername() {
 94  49
         return username;
 95  
     }
 96  
 
 97  
     public void setUsername(String username) {
 98  93
         this.username = username;
 99  93
     }
 100  
 
 101  
     public String getPassword() {
 102  3
         return password;
 103  
     }
 104  
 
 105  
     public void setPassword(String password) {
 106  64
         this.password = password;
 107  64
     }
 108  
 
 109  
     public String getHomeDirectory() {
 110  136
         return homeDirectory;
 111  
     }
 112  
 
 113  
     public void setHomeDirectory(String homeDirectory) {
 114  77
         this.homeDirectory = homeDirectory;
 115  77
     }
 116  
 
 117  
     public List getGroups() {
 118  1
         return groups;
 119  
     }
 120  
 
 121  
     public void setGroups(List groups) {
 122  5
         this.groups = groups;
 123  5
     }
 124  
 
 125  
     public boolean isPasswordRequiredForLogin() {
 126  43
         return passwordRequiredForLogin;
 127  
     }
 128  
 
 129  
     public void setPasswordRequiredForLogin(boolean passwordRequiredForLogin) {
 130  1
         this.passwordRequiredForLogin = passwordRequiredForLogin;
 131  1
     }
 132  
 
 133  
     public boolean isPasswordCheckedDuringValidation() {
 134  0
         return passwordCheckedDuringValidation;
 135  
     }
 136  
 
 137  
     public void setPasswordCheckedDuringValidation(boolean passwordCheckedDuringValidation) {
 138  2
         this.passwordCheckedDuringValidation = passwordCheckedDuringValidation;
 139  2
     }
 140  
 
 141  
     public boolean isAccountRequiredForLogin() {
 142  88
         return accountRequiredForLogin;
 143  
     }
 144  
 
 145  
     public void setAccountRequiredForLogin(boolean accountRequiredForLogin) {
 146  2
         this.accountRequiredForLogin = accountRequiredForLogin;
 147  2
     }
 148  
 
 149  
     public Permissions getDefaultPermissionsForNewFile() {
 150  20
         return defaultPermissionsForNewFile;
 151  
     }
 152  
 
 153  
     public void setDefaultPermissionsForNewFile(Permissions defaultPermissionsForNewFile) {
 154  1
         this.defaultPermissionsForNewFile = defaultPermissionsForNewFile;
 155  1
     }
 156  
 
 157  
     public Permissions getDefaultPermissionsForNewDirectory() {
 158  4
         return defaultPermissionsForNewDirectory;
 159  
     }
 160  
 
 161  
     public void setDefaultPermissionsForNewDirectory(Permissions defaultPermissionsForNewDirectory) {
 162  1
         this.defaultPermissionsForNewDirectory = defaultPermissionsForNewDirectory;
 163  1
     }
 164  
 
 165  
     /**
 166  
      * Return the name of the primary group to which this user belongs. If this account has no associated
 167  
      * groups set, then this method returns the <code>DEFAULT_GROUP</code>. Otherwise, this method
 168  
      * returns the first group name in the <code>groups</code> list.
 169  
      *
 170  
      * @return the name of the primary group for this user
 171  
      */
 172  
     public String getPrimaryGroup() {
 173  4
         return (groups == null || groups.isEmpty()) ? DEFAULT_GROUP : (String) groups.get(0);
 174  
     }
 175  
 
 176  
     /**
 177  
      * Return true if the specified password is the correct, valid password for this user account.
 178  
      * This implementation uses standard (case-sensitive) String comparison. Subclasses can provide
 179  
      * custom comparison behavior, for instance using encrypted password values, by overriding this
 180  
      * method.
 181  
      *
 182  
      * @param password - the password to compare against the configured value
 183  
      * @return true if the password is correct and valid
 184  
      * @throws org.mockftpserver.core.util.AssertFailedException
 185  
      *          - if the username property is null
 186  
      */
 187  
     public boolean isValidPassword(String password) {
 188  54
         Assert.notNullOrEmpty(username, "username");
 189  52
         return !passwordCheckedDuringValidation || comparePassword(password);
 190  
     }
 191  
 
 192  
     /**
 193  
      * @return true if this UserAccount object is valid; i.e. if the homeDirectory is non-null and non-empty.
 194  
      */
 195  
     public boolean isValid() {
 196  95
         return homeDirectory != null && homeDirectory.length() > 0;
 197  
     }
 198  
 
 199  
     /**
 200  
      * @return the String representation of this object
 201  
      */
 202  
     public String toString() {
 203  193
         return "UserAccount[username=" + username + "; password=" + password + "; homeDirectory="
 204  
                 + homeDirectory + "; passwordRequiredForLogin=" + passwordRequiredForLogin + "]";
 205  
     }
 206  
 
 207  
     /**
 208  
      * Return true if this user has read access to the file/directory represented by the specified FileSystemEntry object.
 209  
      *
 210  
      * @param entry - the FileSystemEntry representing the file or directory
 211  
      * @return true if this use has read access
 212  
      */
 213  
     public boolean canRead(FileSystemEntry entry) {
 214  47
         Permissions permissions = entry.getPermissions();
 215  47
         if (permissions == null) {
 216  30
             return true;
 217  
         }
 218  
 
 219  17
         if (equalOrBothNull(username, entry.getOwner())) {
 220  9
             return permissions.canUserRead();
 221  
         }
 222  8
         if (groups != null && groups.contains(entry.getGroup())) {
 223  2
             return permissions.canGroupRead();
 224  
         }
 225  6
         return permissions.canWorldRead();
 226  
     }
 227  
 
 228  
     /**
 229  
      * Return true if this user has write access to the file/directory represented by the specified FileSystemEntry object.
 230  
      *
 231  
      * @param entry - the FileSystemEntry representing the file or directory
 232  
      * @return true if this use has write access
 233  
      */
 234  
     public boolean canWrite(FileSystemEntry entry) {
 235  58
         Permissions permissions = entry.getPermissions();
 236  58
         if (permissions == null) {
 237  37
             return true;
 238  
         }
 239  
 
 240  21
         if (equalOrBothNull(username, entry.getOwner())) {
 241  15
             return permissions.canUserWrite();
 242  
         }
 243  6
         if (groups != null && groups.contains(entry.getGroup())) {
 244  2
             return permissions.canGroupWrite();
 245  
         }
 246  4
         return permissions.canWorldWrite();
 247  
     }
 248  
 
 249  
     /**
 250  
      * Return true if this user has execute access to the file/directory represented by the specified FileSystemEntry object.
 251  
      *
 252  
      * @param entry - the FileSystemEntry representing the file or directory
 253  
      * @return true if this use has execute access
 254  
      */
 255  
     public boolean canExecute(FileSystemEntry entry) {
 256  52
         Permissions permissions = entry.getPermissions();
 257  52
         if (permissions == null) {
 258  34
             return true;
 259  
         }
 260  
 
 261  18
         if (equalOrBothNull(username, entry.getOwner())) {
 262  11
             return permissions.canUserExecute();
 263  
         }
 264  7
         if (groups != null && groups.contains(entry.getGroup())) {
 265  2
             return permissions.canGroupExecute();
 266  
         }
 267  5
         return permissions.canWorldExecute();
 268  
     }
 269  
 
 270  
     /**
 271  
      * Return true if the specified password matches the password configured for this user account.
 272  
      * This implementation uses standard (case-sensitive) String comparison. Subclasses can provide
 273  
      * custom comparison behavior, for instance using encrypted password values, by overriding this
 274  
      * method.
 275  
      *
 276  
      * @param password - the password to compare against the configured value
 277  
      * @return true if the passwords match
 278  
      */
 279  
     protected boolean comparePassword(String password) {
 280  48
         return password != null && password.equals(this.password);
 281  
     }
 282  
 
 283  
     /**
 284  
      * Return true only if both Strings are null or they are equal (have the same contents).
 285  
      *
 286  
      * @param string1 - the first String
 287  
      * @param string2 - the second String
 288  
      * @return true if both are null or both are equal
 289  
      */
 290  
     protected boolean equalOrBothNull(String string1, String string2) {
 291  56
         return (string1 == null && string2 == null) || (string1 != null && string1.equals(string2));
 292  
     }
 293  
 
 294  
 }