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    
020    package org.apache.james.user.jpa.model;
021    
022    import javax.persistence.Basic;
023    import javax.persistence.Column;
024    import javax.persistence.Entity;
025    import javax.persistence.Id;
026    import javax.persistence.NamedQueries;
027    import javax.persistence.NamedQuery;
028    import javax.persistence.Table;
029    import javax.persistence.Version;
030    
031    import org.apache.commons.codec.digest.DigestUtils;
032    import org.apache.james.user.api.model.User;
033    
034    @Entity(name = "JamesUser")
035    @Table(name = "JAMES_USER")
036    @NamedQueries({ 
037        @NamedQuery(name = "findUserByName", query = "SELECT user FROM JamesUser user WHERE user.name=:name"), 
038        @NamedQuery(name = "deleteUserByName", query = "DELETE FROM JamesUser user WHERE user.name=:name"),
039        @NamedQuery(name = "containsUser", query = "SELECT COUNT(user) FROM JamesUser user WHERE user.name=:name"), 
040        @NamedQuery(name = "countUsers", query = "SELECT COUNT(user) FROM JamesUser user"), 
041        @NamedQuery(name = "listUserNames", query = "SELECT user.name FROM JamesUser user") })
042    public class JPAUser implements User {
043    
044        /**
045         * Hash password.
046         * 
047         * @param username
048         *            not null
049         * @param password
050         *            not null
051         * @return not null
052         */
053        private static String hashPassword(String username, String password, String alg) {
054            String newPass;
055            if (alg == null || alg.equals("MD5")) {
056                newPass = DigestUtils.md5Hex(password);
057            } else if (alg.equals("NONE")) {
058                newPass = "password";
059            } else if (alg.equals("SHA-256")) {
060                newPass = DigestUtils.sha256Hex(password);
061            } else if (alg.equals("SHA-512")) {
062                newPass = DigestUtils.sha512Hex(password);
063            } else {
064                newPass = DigestUtils.shaHex(password);
065            }
066            return newPass;
067        }
068    
069        /** Prevents concurrent modification */
070        @SuppressWarnings("unused")
071        @Version
072        private int version;
073    
074        /** Key by user name */
075        @Id
076        @Column(name = "USER_NAME", nullable = false, length = 100)
077        private String name;
078    
079        /** Hashed password */
080        @Basic
081        @Column(name = "PASSWORD", nullable = false, length = 100)
082        private String password;
083    
084        @Basic
085        @Column(name = "PASSWORD_HASH_ALGORITHM", nullable = false, length = 100)
086        private String alg;
087    
088        protected JPAUser() {
089        }
090    
091        public JPAUser(final String userName, String password, String alg) {
092            super();
093            this.name = userName;
094            this.alg = alg;
095            this.password = hashPassword(userName, password, alg);
096        }
097    
098        /**
099         * @see org.apache.james.user.api.model.User#getUserName()
100         */
101        public String getUserName() {
102            return name;
103        }
104    
105        /**
106         * @see org.apache.james.user.api.model.User#setPassword(java.lang.String)
107         */
108        public boolean setPassword(String newPass) {
109            final boolean result;
110            if (newPass == null) {
111                result = false;
112            } else {
113                password = hashPassword(name, newPass, alg);
114                result = true;
115            }
116            return result;
117        }
118    
119        /**
120         * @see org.apache.james.user.api.model.User#verifyPassword(java.lang.String)
121         */
122        public boolean verifyPassword(String pass) {
123            final boolean result;
124            if (pass == null) {
125                result = password == null;
126            } else if (password == null) {
127                result = false;
128            } else {
129                result = password.equals(hashPassword(name, pass, alg));
130            }
131            return result;
132        }
133    
134        @Override
135        public int hashCode() {
136            final int PRIME = 31;
137            int result = 1;
138            result = PRIME * result + ((name == null) ? 0 : name.hashCode());
139            return result;
140        }
141    
142        @Override
143        public boolean equals(Object obj) {
144            if (this == obj)
145                return true;
146            if (obj == null)
147                return false;
148            if (getClass() != obj.getClass())
149                return false;
150            final JPAUser other = (JPAUser) obj;
151            if (name == null) {
152                if (other.name != null)
153                    return false;
154            } else if (!name.equals(other.name))
155                return false;
156            return true;
157        }
158    
159        @Override
160        public String toString() {
161            return "[User " + name + "]";
162        }
163    
164    }