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