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 ****************************************************************/
019
020package org.apache.james.user.lib;
021
022import javax.inject.Inject;
023
024import org.apache.commons.configuration.ConfigurationException;
025import org.apache.commons.configuration.HierarchicalConfiguration;
026import org.apache.james.domainlist.api.DomainList;
027import org.apache.james.domainlist.api.DomainListException;
028import org.apache.james.lifecycle.api.Configurable;
029import org.apache.james.lifecycle.api.LogEnabled;
030import org.apache.james.user.api.AlreadyExistInUsersRepositoryException;
031import org.apache.james.user.api.UsersRepository;
032import org.apache.james.user.api.UsersRepositoryException;
033import org.apache.mailet.MailAddress;
034import org.slf4j.Logger;
035
036import com.google.common.annotations.VisibleForTesting;
037import com.google.common.base.Optional;
038
039public abstract class AbstractUsersRepository implements UsersRepository, LogEnabled, Configurable {
040
041    private DomainList domainList;
042    private boolean virtualHosting;
043    private Logger logger;
044    private Optional<String> administratorId;
045
046    protected Logger getLogger() {
047        return logger;
048    }
049
050    /**
051     * @see org.apache.james.lifecycle.api.LogEnabled#setLog(org.slf4j.Logger)
052     */
053    public void setLog(Logger logger) {
054        this.logger = logger;
055    }
056
057    /**
058     * @see
059     * org.apache.james.lifecycle.api.Configurable#configure(org.apache.commons.configuration.HierarchicalConfiguration)
060     */
061    public void configure(HierarchicalConfiguration configuration) throws ConfigurationException {
062
063        virtualHosting = configuration.getBoolean("enableVirtualHosting", getDefaultVirtualHostingValue());
064        administratorId = Optional.fromNullable(configuration.getString("administratorId"));
065
066        doConfigure(configuration);
067    }
068
069    protected boolean getDefaultVirtualHostingValue() {
070        return false;
071    }
072
073    protected void doConfigure(HierarchicalConfiguration config) throws ConfigurationException {
074    }
075
076    public void setEnableVirtualHosting(boolean virtualHosting) {
077        this.virtualHosting = virtualHosting;
078    }
079
080    @Inject
081    public void setDomainList(DomainList domainList) {
082        this.domainList = domainList;
083    }
084
085    protected void isValidUsername(String username) throws UsersRepositoryException {
086        int i = username.indexOf("@");
087        if (supportVirtualHosting()) {
088            // need a @ in the username
089            if (i == -1) {
090                throw new UsersRepositoryException("Given Username needs to contain a @domainpart");
091            } else {
092                String domain = username.substring(i + 1);
093                try {
094                    if (!domainList.containsDomain(domain)) {
095                        throw new UsersRepositoryException("Domain does not exist in DomainList");
096                    } else {
097                    }
098                } catch (DomainListException e) {
099                    throw new UsersRepositoryException("Unable to query DomainList", e);
100                }
101            }
102        } else {
103            // @ only allowed when virtualhosting is supported
104            if (i != -1) {
105                throw new UsersRepositoryException("Given Username contains a @domainpart but virtualhosting support is disabled");
106            }
107        }
108    }
109
110    /**
111     * @see org.apache.james.user.api.UsersRepository#addUser(java.lang.String,
112     * java.lang.String)
113     */
114    public void addUser(String username, String password) throws UsersRepositoryException {
115
116        if (!contains(username)) {
117            isValidUsername(username);
118            doAddUser(username, password);
119        } else {
120            throw new AlreadyExistInUsersRepositoryException("User with username " + username + " already exists!");
121        }
122
123    }
124
125    /**
126     * @see org.apache.james.user.api.UsersRepository#supportVirtualHosting()
127     */
128    public boolean supportVirtualHosting() {
129        return virtualHosting;
130    }
131
132    /**
133     * Add the user with the given username and password
134     * 
135     * @param username
136     * @param password
137     * @throws UsersRepositoryException
138     *           If an error occurred
139     */
140    protected abstract void doAddUser(String username, String password) throws UsersRepositoryException;
141
142    @Override
143    public String getUser(MailAddress mailAddress) throws UsersRepositoryException {
144        if (supportVirtualHosting()) {
145            return mailAddress.asString();
146        } else {
147            return mailAddress.getLocalPart();
148        }
149    }
150
151    @VisibleForTesting void setAdministratorId(Optional<String> username) {
152        this.administratorId = username;
153    }
154
155    @Override
156    public boolean isAdministrator(String username) throws UsersRepositoryException {
157        if (administratorId.isPresent()) {
158            return administratorId.get().equals(username);
159        }
160        return false;
161    }
162}