001    // This file is part of AceWiki.
002    // Copyright 2008-2012, AceWiki developers.
003    // 
004    // AceWiki is free software: you can redistribute it and/or modify it under the terms of the GNU
005    // Lesser General Public License as published by the Free Software Foundation, either version 3 of
006    // the License, or (at your option) any later version.
007    // 
008    // AceWiki is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
009    // even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
010    // Lesser General Public License for more details.
011    // 
012    // You should have received a copy of the GNU Lesser General Public License along with AceWiki. If
013    // not, see http://www.gnu.org/licenses/.
014    
015    package ch.uzh.ifi.attempto.acewiki.core;
016    
017    import java.security.MessageDigest;
018    import java.util.ArrayList;
019    import java.util.List;
020    import java.util.Map;
021    
022    /**
023     * This class represents an AceWiki user.
024     * 
025     * @author Tobias Kuhn
026     */
027    public class User {
028            
029            private final long id;
030            private String name;
031            private String hashedPw;
032            private Map<String, String> userdata;
033            private final UserBase userBase;
034            
035            /**
036             * Creates a new user.
037             * 
038             * @param id The user id.
039             * @param name The name of the user.
040             * @param hashedPw The hashed password.
041             * @param userdata The user data map.
042             */
043            User(long id, String name, String hashedPw, Map<String, String> userdata, UserBase userBase) {
044                    this.id = id;
045                    this.name = name;
046                    this.hashedPw = hashedPw;
047                    this.userdata = userdata;
048                    this.userBase = userBase;
049                    save();
050            }
051            
052            /**
053             * Creates a new user.
054             * 
055             * @param id The user id.
056             * @param name The name of the user.
057             * @param pw The password in plain text.
058             * @param userdata The user data map.
059             * @return The new user object.
060             */
061            static User createUser(long id, String name, String pw, Map<String, String> userdata, UserBase userBase) {
062                    return new User(id, name, getPasswordHash(pw), userdata, userBase);
063            }
064            
065            /**
066             * Returns the id of the user.
067             * 
068             * @return The id.
069             */
070            public long getId() {
071                    return id;
072            }
073            
074            /**
075             * Returns the name of the user.
076             * 
077             * @return The name of the user.
078             */
079            public String getName() {
080                    return name;
081            }
082            
083            /**
084             * Returns the hashed password.
085             * 
086             * @return The hashed password.
087             */
088            public String getHashedPassword() {
089                    return hashedPw;
090            }
091            
092            /**
093             * Returns the user data with the given property name.
094             * 
095             * @param name The property name.
096             * @return The data for the respective name.
097             */
098            public String getUserData(String name) {
099                    String value = userdata.get(name);
100                    if (value == null) return "";
101                    return value;
102            }
103            
104            /**
105             * Sets the user data element with the respective name.
106             * 
107             * @param name The name of the user data element.
108             * @param value The value to be set.
109             */
110            public void setUserData(String name, String value) {
111                    userdata.put(name, value);
112                    save();
113            }
114            
115            /**
116             * Changes the password for the user.
117             * 
118             * @param oldPw The old password in plain text.
119             * @param newPw The new password in plain text.
120             */
121            public void changePassword(String oldPw, String newPw) {
122                    if (!isCorrectPassword(oldPw)) return;
123                    hashedPw = getPasswordHash(newPw);
124                    save();
125            }
126            
127            /**
128             * Adds to a counter in the user data.
129             * 
130             * @param name The name of the user data element.
131             * @param c The value by which the counter should be increased.
132             */
133            public void addToUserDataCounter(String name, int c) {
134                    String value = userdata.get(name);
135                    if (value == null) {
136                            userdata.put(name, c + "");
137                    } else {
138                            int v;
139                            try {
140                                    v = new Integer(value);
141                            } catch (NumberFormatException ex) {
142                                    v = 0;
143                            }
144                            userdata.put(name, (v + c) + "");
145                    }
146                    save();
147            }
148            
149            /**
150             * Checks whether a certain password is the correct password for this user.
151             * 
152             * @param pw The password to be checked in plain text.
153             * @return true if the password is correct.
154             */
155            public boolean isCorrectPassword(String pw) {
156                    return getPasswordHash(pw).equals(hashedPw);
157            }
158            
159            /**
160             * Returns a hash value for a given plain-text password using the SHA-256 algorithm.
161             * 
162             * @param password The plain-text password for which a hash value should be created.
163             * @return The hash value.
164             */
165            public static String getPasswordHash(String password) {
166                    try {
167                            MessageDigest md = MessageDigest.getInstance("SHA-256");
168                            md.update(password.getBytes());
169                            byte[] byteData = md.digest();
170                            StringBuffer sb = new StringBuffer();
171                            for (int i = 0; i < byteData.length; i++) {
172                                    sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
173                            }
174                            return sb.toString();
175                    } catch (Exception ex) {
176                            ex.printStackTrace();
177                            return null;
178                    }
179            }
180            
181            /**
182             * Returns the user base to which this user belongs.
183             * 
184             * @return The user base.
185             */
186            public UserBase getUserBase() {
187                    return userBase;
188            }
189            
190            /**
191             * Returns all key of this user's properties in the form of key/value pairs.
192             * 
193             * @return All user data keys.
194             */
195            public List<String> getUserDataKeys() {
196                    return new ArrayList<String>(userdata.keySet());
197            }
198            
199            private void save() {
200                    userBase.getStorage().save(this);
201            }
202    
203    }