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 */ 072 Principal[] getWikiNames() throws WikiSecurityException; 073 074 /** 075 * Looks up and returns the first {@link UserProfile} in the user database that whose login name, full name, or wiki name matches the 076 * supplied string. This method provides a "forgiving" search algorithm for resolving Principal names when the exact profile attribute 077 * that supplied the name is unknown. 078 * 079 * @param index the login name, full name, or wiki name 080 */ 081 UserProfile find( String index ) throws NoSuchPrincipalException; 082 083 /** 084 * Looks up and returns the first {@link UserProfile} in the user database that matches a profile having a given e-mail address. If 085 * the user database does not contain a user with a matching attribute, throws a {@link NoSuchPrincipalException}. 086 * 087 * @param index the e-mail address of the desired user profile 088 * @return the user profile 089 */ 090 UserProfile findByEmail( String index ) throws NoSuchPrincipalException; 091 092 /** 093 * Looks up and returns the first {@link UserProfile} in the user database that matches a profile having a given login name. If the 094 * user database does not contain a user with a matching attribute, throws a {@link NoSuchPrincipalException}. 095 * 096 * @param index the login name of the desired user profile 097 * @return the user profile 098 */ 099 UserProfile findByLoginName( String index ) throws NoSuchPrincipalException; 100 101 /** 102 * Looks up and returns the first {@link UserProfile} in the user database that matches a profile having a given unique ID (uid). If 103 * the user database does not contain a user with a unique ID, it throws a {@link NoSuchPrincipalException}. 104 * 105 * @param uid the unique identifier of the desired user profile 106 * @return the user profile 107 * @since 2.8 108 */ 109 UserProfile findByUid( String uid ) throws NoSuchPrincipalException; 110 111 /** 112 * Looks up and returns the first {@link UserProfile} in the user database that matches a profile having a given wiki name. If the user 113 * database does not contain a user with a matching attribute, throws a {@link NoSuchPrincipalException}. 114 * 115 * @param index the wiki name of the desired user profile 116 * @return the user profile 117 */ 118 UserProfile findByWikiName( String index ) throws NoSuchPrincipalException; 119 120 /** 121 * Looks up and returns the first {@link UserProfile} in the user database that matches a profile having a given full name. If the user 122 * database does not contain a user with a matching attribute, throws a {@link NoSuchPrincipalException}. 123 * 124 * @param index the fill name of the desired user profile 125 * @return the user profile 126 */ 127 UserProfile findByFullName( String index ) throws NoSuchPrincipalException; 128 129 /** Initializes the user database based on values from a Properties object. */ 130 void initialize( Engine engine, Properties props ) throws NoRequiredPropertyException, WikiSecurityException; 131 132 /** 133 * Factory method that instantiates a new user profile. The {@link UserProfile#isNew()} method of profiles created using 134 * this method should return <code>true</code>. 135 */ 136 UserProfile newProfile(); 137 138 /** 139 * <p>Renames a {@link UserProfile} in the user database by changing the profile's login name. Because the login name is the profile's 140 * unique identifier, implementations should verify that the identifier is "safe" to change before actually changing it. Specifically: 141 * the profile with the supplied login name must already exist, and the proposed new name must not be in use by another profile.</p> 142 * <p>This method is intended to be atomic; results cannot be partially committed. If the commit fails, it should roll back its state 143 * appropriately. Implementing classes that persist to the file system may wish to make this method <code>synchronized</code>.</p> 144 * 145 * @param loginName the existing login name for the profile 146 * @param newName the proposed new login name 147 * @throws NoSuchPrincipalException if the user profile identified by <code>loginName</code> does not exist 148 * @throws DuplicateUserException if another user profile with the proposed new login name already exists 149 * @throws WikiSecurityException if the profile cannot be renamed for any reason, such as an I/O error, database connection failure 150 * or lack of support for renames. 151 */ 152 void rename( String loginName, String newName ) throws NoSuchPrincipalException, DuplicateUserException, WikiSecurityException; 153 154 /** 155 * <p> 156 * Saves a {@link UserProfile}to the user database, overwriting the existing profile if it exists. The user name under which the profile 157 * should be saved is returned by the supplied profile's {@link UserProfile#getLoginName()} method. 158 * </p> 159 * <p> 160 * The database implementation is responsible for detecting potential duplicate user profiles; specifically, the login name, wiki name, 161 * and full name must be unique. The implementation is not required to check for validity of passwords or e-mail addresses. Special 162 * case: if the profile already exists and the password is null, it should retain its previous value, rather than being set to null. 163 * </p> 164 * <p>Implementations are <em>required</em> to time-stamp the creation or modification fields of the UserProfile./p> 165 * <p>This method is intended to be atomic; results cannot be partially committed. If the commit fails, it should roll back its state 166 * appropriately. Implementing classes that persist to the file system may wish to make this method <code>synchronized</code>.</p> 167 * 168 * @param profile the user profile to save 169 * @throws WikiSecurityException if the profile cannot be saved 170 */ 171 void save( UserProfile profile ) throws WikiSecurityException; 172 173 /** 174 * Determines whether a supplied user password is valid, given a login name and password. It is up to the implementing class to 175 * determine how the comparison should be made. For example, the password might be hashed before comparing it to the value persisted 176 * in the back-end data store. 177 * 178 * @param loginName the login name 179 * @param password the password 180 * @return <code>true</code> if the password is valid, <code>false</code> otherwise 181 */ 182 boolean validatePassword( String loginName, String password ); 183 184}