blob: 5fdf723a673256bea8d61076162253c1adb61d02 [file] [log] [blame]
/****************************************************************
* Licensed to the Apache Software Foundation (ASF) under one *
* or more contributor license agreements. See the NOTICE file *
* distributed with this work for additional information *
* regarding copyright ownership. The ASF licenses this file *
* to you under the Apache License, Version 2.0 (the *
* "License"); you may not use this file except in compliance *
* with the License. You may obtain a copy of the License at *
* *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, *
* software distributed under the License is distributed on an *
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
* KIND, either express or implied. See the License for the *
* specific language governing permissions and limitations *
* under the License. *
****************************************************************/
package org.apache.james.user.api;
import java.util.Iterator;
import java.util.Optional;
import org.apache.james.core.Domain;
import org.apache.james.core.MailAddress;
import org.apache.james.core.Username;
import org.apache.james.user.api.model.User;
import org.apache.james.util.ReactorUtils;
import org.reactivestreams.Publisher;
import com.github.fge.lambdas.Throwing;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
/**
* Interface for a repository of users. A repository represents a logical
* grouping of users, typically by common purpose. E.g. the users served by an
* email server or the members of a mailing list.
*/
public interface UsersRepository {
/**
* Adds a user to the repository with the specified password
*
* @param username
* the username of the user to be added
* @param password
* the password of the user to add
* @throws UsersRepositoryException
* if error
*
*/
void addUser(Username username, String password) throws UsersRepositoryException;
/**
* Get the user object with the specified user name. Return null if no such
* user.
*
* @param name
* the name of the user to retrieve
* @return the user being retrieved, null if the user doesn't exist
* @throws UsersRepositoryException
* if error
*/
User getUserByName(Username name) throws UsersRepositoryException;
/**
* Update the repository with the specified user object. A user object with
* this username must already exist.
*
* @throws UsersRepositoryException
* if error
*/
void updateUser(User user) throws UsersRepositoryException;
/**
* Removes a user from the repository
*
* @param name
* the user to remove from the repository
* @throws UsersRepositoryException
* if error
*/
void removeUser(Username name) throws UsersRepositoryException;
/**
* Returns whether or not this user is in the repository
*
* @param name
* the name to check in the repository
* @return whether the user is in the repository
* @throws UsersRepositoryException
* if error
*/
boolean contains(Username name) throws UsersRepositoryException;
Publisher<Boolean> containsReactive(Username name);
/**
* Test if user with login name 'name' has password 'password'.
*
* @param name
* the login name of the user to be tested
* @param password
* the password to be tested
*
* @return Optional of a Username if the test is successful, an empty Optional if the user doesn't exist
* or if the password is incorrect
* @throws UsersRepositoryException
* if error
*
*/
Optional<Username> test(Username name, String password) throws UsersRepositoryException;
/**
* Returns a count of the users in the repository.
*
* @return the number of users in the repository
* @throws UsersRepositoryException
* if error
*/
int countUsers() throws UsersRepositoryException;
/**
* List users in repository.
*
* @return Iterator over a collection of Strings, each being one user in the
* repository.
* @throws UsersRepositoryException
* if error
*/
Iterator<Username> list() throws UsersRepositoryException;
Publisher<Username> listReactive();
/**
* Return true if virtualHosting support is enabled, otherwise false
*
* @return true or false
*/
boolean supportVirtualHosting() throws UsersRepositoryException;
/**
* Returns username to be used for a given MailAddress
*
* @return Username used by James for this mailAddress
*/
default Username getUsername(MailAddress mailAddress) throws UsersRepositoryException {
if (supportVirtualHosting()) {
return Username.of(mailAddress.asString());
} else {
return Username.of(mailAddress.getLocalPart());
}
}
/**
* Returns one of the possible mail addresses to be used to send a mail to that user
*
* This makes sense as it handles virtual-hosting logic.
*/
MailAddress getMailAddressFor(Username username) throws UsersRepositoryException;
/**
* Return true if the user is an admin for this repository
*/
boolean isAdministrator(Username username) throws UsersRepositoryException;
/**
* @return true if one can use {@link UsersRepository#updateUser(User)} {@link UsersRepository#addUser(Username, String)}
* {@link UsersRepository#removeUser(Username)} and false overwhise
*/
boolean isReadOnly();
default void assertValid(Username username) throws UsersRepositoryException {
if (username.getDomainPart().isPresent() != supportVirtualHosting()) {
throw new UsersRepositoryException(username.asString() + " username candidate do not match the virtualHosting strategy");
}
}
default Mono<Void> assertValidReactive(Username username) {
return Mono.fromRunnable(Throwing.runnable(() -> assertValid(username)).sneakyThrow())
.subscribeOn(ReactorUtils.BLOCKING_CALL_WRAPPER)
.then();
}
default Publisher<Username> listUsersOfADomainReactive(Domain domain) {
return Flux.from(listReactive())
.filter(username -> username.getDomainPart()
.map(domain::equals)
.orElse(false));
}
}