001/* 002 Licensed to the Apache Software Foundation (ASF) under one 003 or more contributor license agreements. See the NOTICE file 004 distributed with this work for additional information 005 regarding copyright ownership. The ASF licenses this file 006 to you under the Apache License, Version 2.0 (the 007 "License"); you may not use this file except in compliance 008 with the License. You may obtain a copy of the License at 009 010 http://www.apache.org/licenses/LICENSE-2.0 011 012 Unless required by applicable law or agreed to in writing, 013 software distributed under the License is distributed on an 014 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 KIND, either express or implied. See the License for the 016 specific language governing permissions and limitations 017 under the License. 018 */ 019package org.apache.wiki.auth.user; 020 021import org.apache.wiki.api.core.Engine; 022import org.apache.wiki.api.exceptions.NoRequiredPropertyException; 023import org.apache.wiki.auth.NoSuchPrincipalException; 024import org.apache.wiki.auth.WikiSecurityException; 025 026import java.security.Principal; 027import java.util.Properties; 028 029/** 030 * Defines an interface for loading, persisting and storing users. 031 * 032 * @since 2.3 033 */ 034public interface UserDatabase { 035 036 /** 037 * Looks up and deletes the first {@link UserProfile} in the user database that matches a profile having a given login name. If the 038 * user database does not contain a user with a matching attribute, throws a {@link NoSuchPrincipalException}. This method is intended 039 * to be atomic; results cannot be partially committed. If the commit fails, it should roll back its state appropriately. Implementing 040 * classes that persist to the file system may wish to make this method <code>synchronized</code>. 041 * 042 * @param loginName the login name of the user profile that shall be deleted 043 */ 044 void deleteByLoginName( String loginName ) throws NoSuchPrincipalException, WikiSecurityException; 045 046 /** 047 * <p> 048 * Looks up the Principals representing a user from the user database. These are defined as a set of Principals manufactured from the 049 * login name, full name, and wiki name. The order of the Principals returned is not significant. If the user database does not contain 050 * a user with the supplied identifier, throws a {@link NoSuchPrincipalException}. 051 * </p> 052 * <p> 053 * Note that if an implementation wishes to mark one of the returned Principals as representing the user's common name, it should 054 * instantiate this Principal using {@link org.apache.wiki.auth.WikiPrincipal#WikiPrincipal(String, String)} with the <code>type</code> 055 * parameter set to {@link org.apache.wiki.auth.WikiPrincipal#WIKI_NAME}. The method 056 * {@link org.apache.wiki.api.core.Session#getUserPrincipal()} will return this principal as the "primary" principal. Note that this method 057 * can also be used to mark a WikiPrincipal as a login name or a wiki name. 058 * </p> 059 * 060 * @param identifier the name of the user to retrieve; this corresponds to value returned by the user profile's {@link UserProfile#getLoginName()} method. 061 * @return the array of Principals representing the user's identities 062 * @throws NoSuchPrincipalException If the user database does not contain user with the supplied identifier 063 */ 064 Principal[] getPrincipals( String identifier ) throws NoSuchPrincipalException; 065 066 /** 067 * Returns all WikiNames that are stored in the UserDatabase as an array of Principal objects. If the database does not 068 * contain any profiles, this method will return a zero-length array. 069 * 070 * @return the WikiNames 071 * @throws org.apache.wiki.auth.WikiSecurityException 072 */ 073 Principal[] getWikiNames() throws WikiSecurityException; 074 075 /** 076 * Looks up and returns the first {@link UserProfile} in the user database that whose login name, full name, or wiki name matches the 077 * supplied string. This method provides a "forgiving" search algorithm for resolving Principal names when the exact profile attribute 078 * that supplied the name is unknown. 079 * 080 * @param index the login name, full name, or wiki name 081 * @return non null 082 * @throws org.apache.wiki.auth.NoSuchPrincipalException 083 * @deprecated depending on the use case, this API's usage can be dangerous. 084 * Recommend using other APIs for more explicit lookup types. see JSPWIKI-130 085 * for additional details. 086 */ 087 @Deprecated 088 UserProfile find( String index ) throws NoSuchPrincipalException; 089 090 /** 091 * Looks up and returns the first {@link UserProfile} in the user database that matches a profile having a given e-mail address. If 092 * the user database does not contain a user with a matching attribute, throws a {@link NoSuchPrincipalException}. 093 * 094 * @param index the e-mail address of the desired user profile 095 * @return the user profile 096 * @throws org.apache.wiki.auth.NoSuchPrincipalException 097 */ 098 UserProfile findByEmail( String index ) throws NoSuchPrincipalException; 099 100 /** 101 * Looks up and returns the first {@link UserProfile} in the user database that matches a profile having a given login name. If the 102 * user database does not contain a user with a matching attribute, throws a {@link NoSuchPrincipalException}. 103 * 104 * @param index the login name of the desired user profile 105 * @return the user profile 106 * @throws org.apache.wiki.auth.NoSuchPrincipalException 107 */ 108 UserProfile findByLoginName( String index ) throws NoSuchPrincipalException; 109 110 /** 111 * Looks up and returns the first {@link UserProfile} in the user database that matches a profile having a given unique ID (uid). If 112 * the user database does not contain a user with a unique ID, it throws a {@link NoSuchPrincipalException}. 113 * 114 * @param uid the unique identifier of the desired user profile 115 * @return the user profile 116 * @throws org.apache.wiki.auth.NoSuchPrincipalException 117 * @since 2.8 118 */ 119 UserProfile findByUid( String uid ) throws NoSuchPrincipalException; 120 121 /** 122 * Looks up and returns the first {@link UserProfile} in the user database that matches a profile having a given wiki name. If the user 123 * database does not contain a user with a matching attribute, throws a {@link NoSuchPrincipalException}. 124 * 125 * @param index the wiki name of the desired user profile 126 * @return the user profile 127 * @throws org.apache.wiki.auth.NoSuchPrincipalException 128 */ 129 UserProfile findByWikiName( String index ) throws NoSuchPrincipalException; 130 131 /** 132 * Looks up and returns the first {@link UserProfile} in the user database that matches a profile having a given full name. If the user 133 * database does not contain a user with a matching attribute, throws a {@link NoSuchPrincipalException}. 134 * 135 * @param index the fill name of the desired user profile 136 * @return the user profile 137 * @throws org.apache.wiki.auth.NoSuchPrincipalException 138 */ 139 UserProfile findByFullName( String index ) throws NoSuchPrincipalException; 140 141 /** Initializes the user database based on values from a Properties object. 142 * @param engine 143 * @param props 144 * @throws org.apache.wiki.api.exceptions.NoRequiredPropertyException 145 * @throws org.apache.wiki.auth.WikiSecurityException */ 146 void initialize( Engine engine, Properties props ) throws NoRequiredPropertyException, WikiSecurityException; 147 148 /** 149 * Factory method that instantiates a new user profile. The {@link UserProfile#isNew()} method of profiles created using 150 * this method should return <code>true</code>. 151 * @return user profile 152 */ 153 UserProfile newProfile(); 154 155 /** 156 * <p>Renames a {@link UserProfile} in the user database by changing the profile's login name. Because the login name is the profile's 157 * unique identifier, implementations should verify that the identifier is "safe" to change before actually changing it. Specifically: 158 * the profile with the supplied login name must already exist, and the proposed new name must not be in use by another profile.</p> 159 * <p>This method is intended to be atomic; results cannot be partially committed. If the commit fails, it should roll back its state 160 * appropriately. Implementing classes that persist to the file system may wish to make this method <code>synchronized</code>.</p> 161 * 162 * @param loginName the existing login name for the profile 163 * @param newName the proposed new login name 164 * @throws NoSuchPrincipalException if the user profile identified by <code>loginName</code> does not exist 165 * @throws DuplicateUserException if another user profile with the proposed new login name already exists 166 * @throws WikiSecurityException if the profile cannot be renamed for any reason, such as an I/O error, database connection failure 167 * or lack of support for renames. 168 */ 169 void rename( String loginName, String newName ) throws NoSuchPrincipalException, DuplicateUserException, WikiSecurityException; 170 171 /** 172 * <p> 173 * Saves a {@link UserProfile}to the user database, overwriting the existing profile if it exists. The user name under which the profile 174 * should be saved is returned by the supplied profile's {@link UserProfile#getLoginName()} method. 175 * </p> 176 * <p> 177 * The database implementation is responsible for detecting potential duplicate user profiles; specifically, the login name, wiki name, 178 * and full name must be unique. The implementation is not required to check for validity of passwords or e-mail addresses. Special 179 * case: if the profile already exists and the password is null, it should retain its previous value, rather than being set to null. 180 * </p> 181 * <p>Implementations are <em>required</em> to time-stamp the creation or modification fields of the UserProfile./p> 182 * <p>This method is intended to be atomic; results cannot be partially committed. If the commit fails, it should roll back its state 183 * appropriately. Implementing classes that persist to the file system may wish to make this method <code>synchronized</code>.</p> 184 * 185 * @param profile the user profile to save 186 * @throws WikiSecurityException if the profile cannot be saved 187 */ 188 void save( UserProfile profile ) throws WikiSecurityException; 189 190 /** 191 * Determines whether a supplied user password is valid, given a login name and password. It is up to the implementing class to 192 * determine how the comparison should be made. For example, the password might be hashed before comparing it to the value persisted 193 * in the back-end data store. 194 * 195 * @param loginName the login name 196 * @param password the password 197 * @return <code>true</code> if the password is valid, <code>false</code> otherwise 198 */ 199 boolean validatePassword( String loginName, String password ); 200 201 /** 202 * validates that the proposed password has not been recently used. 203 * @param loginName 204 * @param password 205 * @return false if the password has been recently used, true otherwise 206 * @since 3.0.0 207 */ 208 boolean validatePasswordReuse( final String loginName, final String password ); 209}