File Source: defaultsecurityrealm.java
/*
P/P * Method: void net.sourceforge.pebble.security.DefaultSecurityRealm$1(DefaultSecurityRealm)
*/
1 package net.sourceforge.pebble.security;
2
3 import net.sourceforge.pebble.Configuration;
4 import net.sourceforge.pebble.Constants;
5 import net.sourceforge.pebble.comparator.PebbleUserDetailsComparator;
6 import org.acegisecurity.providers.dao.SaltSource;
7 import org.acegisecurity.providers.encoding.PasswordEncoder;
8 import org.apache.commons.logging.Log;
9 import org.apache.commons.logging.LogFactory;
10
11 import java.io.*;
12 import java.util.*;
13
14 /**
15 * Implementation of the SecurityRealm that gets authentication
16 * credentials from the blog directory.
17 *
18 * @author Simon Brown
19 */
/*
P/P * Method: void net.sourceforge.pebble.security.DefaultSecurityRealm()
*/
20 public class DefaultSecurityRealm implements SecurityRealm {
21
/*
P/P * Method: net.sourceforge.pebble.security.DefaultSecurityRealm__static_init
*
* Postconditions:
* init'ed(log)
*/
22 private static final Log log = LogFactory.getLog(DefaultSecurityRealm.class);
23
24 private static final String REALM_DIRECTORY_NAME = "realm";
25
26 protected static final String PASSWORD = "password";
27 protected static final String ROLES = "roles";
28 protected static final String NAME = "name";
29 protected static final String EMAIL_ADDRESS = "emailAddress";
30 protected static final String WEBSITE = "website";
31 protected static final String PROFILE = "profile";
32 protected static final String DETAILS_UPDATEABLE = "detailsUpdateable";
33 protected static final String PREFERENCE = "preference.";
34
35 private Configuration configuration;
36
37 private PasswordEncoder passwordEncoder;
38
39 private SaltSource saltSource;
40
41 /**
42 * Creates the underlying security realm upon creation, if necessary.
43 */
44 public void init() {
45 try {
/*
P/P * Method: void init()
*
* Preconditions:
* (soft) this.configuration != null
* (soft) this.passwordEncoder != null
* (soft) this.saltSource != null
*
* Presumptions:
* org.apache.commons.logging.LogFactory:getLog(...)@22 != null
* defaultUser.grantedAuthories.length <= 232-1
* defaultUser.grantedAuthories[...] != null
* java.util.Set:toArray(...)@194 != null
* net.sourceforge.pebble.Constants.BLOG_ADMIN_ROLE != null
* ...
*
* Test Vectors:
* java.io.File:exists(...)@47: {1}, {0}
*/
46 File realm = getFileForRealm();
47 if (!realm.exists()) {
48 realm.mkdirs();
49 log.warn("*** Creating default user (username/password)");
50 log.warn("*** Don't forget to delete this user in a production deployment!");
51 PebbleUserDetails defaultUser = new PebbleUserDetails("username", "password", "Default User", "username@domain.com", "http://www.domain.com", "Default User...", new String[] {Constants.BLOG_OWNER_ROLE, Constants.BLOG_PUBLISHER_ROLE, Constants.BLOG_CONTRIBUTOR_ROLE, Constants.BLOG_ADMIN_ROLE}, new HashMap<String,String>(), true);
52 createUser(defaultUser);
53 }
54 } catch (SecurityRealmException e) {
55 log.error("Error while creating security realm", e);
56 }
57
58 }
59
60 /**
61 * Looks up and returns a collection of all users.
62 *
63 * @return a Collection of PebbleUserDetails objects
64 */
65 public synchronized Collection<PebbleUserDetails> getUsers() throws SecurityRealmException {
/*
P/P * Method: Collection getUsers()
*
* Preconditions:
* this.configuration != null
*
* Presumptions:
* Local_7[Local_5]@68 != null
* files.length@68 <= 232-1
* java.io.File:getName(...)@83 != null
* java.io.File:listFiles(...)@68 != null
*
* Postconditions:
* return_value == &new LinkedList(getUsers#1)
* new LinkedList(getUsers#1) num objects == 1
*/
66 LinkedList<PebbleUserDetails> users = new LinkedList<PebbleUserDetails>();
67 File realm = getFileForRealm();
68 File files[] = realm.listFiles(new FilenameFilter() {
69 /**
70 * Tests if a specified file should be included in a file list.
71 *
72 * @param dir the directory in which the file was found.
73 * @param name the name of the file.
74 * @return <code>true</code> if and only if the name should be
75 * included in the file list; <code>false</code> otherwise.
76 */
77 public boolean accept(File dir, String name) {
/*
P/P * Method: bool accept(File, String)
*
* Preconditions:
* name != null
*
* Postconditions:
* init'ed(return_value)
*/
78 return name.endsWith(".properties");
79 }
80 });
81
82 for (File file : files) {
83 PebbleUserDetails pud = getUser(file.getName().substring(0, file.getName().lastIndexOf(".")));
84 if (pud != null) {
85 users.add(pud);
86 }
87 }
88
89 Collections.sort(users, new PebbleUserDetailsComparator());
90
91 return users;
92 }
93
94 /**
95 * Looks up and returns user details for the given username.
96 *
97 * @param username the username to find details for
98 * @return a PebbleUserDetails instance
99 *
100 */
101 public synchronized PebbleUserDetails getUser(String username) throws SecurityRealmException {
/*
P/P * Method: PebbleUserDetails getUser(String)
*
* Preconditions:
* this.configuration != null
*
* Presumptions:
* java.util.Iterator:next(...)@126 != null
* java.util.Properties:getProperty(...)@114 != null
* java.util.Properties:keySet(...)@126 != null
* roles.length@114 <= 232-1
* roles[...]@114 != null
*
* Postconditions:
* return_value in Addr_Set{null,&new PebbleUserDetails(getUser#4)}
* new HashMap(PebbleUserDetails#1) num objects <= 1
* new HashMap(getUser#3) num objects <= 1
* new PebbleUserDetails(getUser#4) num objects <= 1
* init'ed(new PebbleUserDetails(getUser#4).detailsUpdateable)
* init'ed(new PebbleUserDetails(getUser#4).emailAddress)
* init'ed(new PebbleUserDetails(getUser#4).grantedAuthories)
* init'ed(new PebbleUserDetails(getUser#4).name)
* init'ed(new PebbleUserDetails(getUser#4).password)
* new PebbleUserDetails(getUser#4).preferences == &new HashMap(getUser#3)
* ...
*
* Test Vectors:
* java.io.File:exists(...)@103: {1}, {0}
* java.lang.String:startsWith(...)@128: {0}, {1}
* java.util.Iterator:hasNext(...)@126: {1}, {0}
* java.util.Properties:getProperty(...)@119: Addr_Set{null}, Inverse{null}
*/
102 File user = getFileForUser(username);
103 if (!user.exists()) {
104 return null;
105 }
106
107 try {
108 FileInputStream in = new FileInputStream(user);
109 Properties props = new Properties();
110 props.load(in);
111 in.close();
112
113 String password = props.getProperty(PASSWORD);
114 String[] roles = props.getProperty(ROLES).split(",");
115 String name = props.getProperty(NAME);
116 String emailAddress = props.getProperty(EMAIL_ADDRESS);
117 String website = props.getProperty(WEBSITE);
118 String profile = props.getProperty(PROFILE);
119 String detailsUpdateableAsString = props.getProperty(DETAILS_UPDATEABLE);
120 boolean detailsUpdateable = true;
121 if (detailsUpdateableAsString != null) {
122 detailsUpdateable = detailsUpdateableAsString.equalsIgnoreCase("true");
123 }
124
125 Map<String,String> preferences = new HashMap<String,String>();
126 for (Object key : props.keySet()) {
127 String propertyName = (String)key;
128 if (propertyName.startsWith(PREFERENCE)) {
129 preferences.put(propertyName.substring(PREFERENCE.length()), props.getProperty(propertyName));
130 }
131 }
132
133 return new PebbleUserDetails(username, password, name, emailAddress, website, profile, roles, preferences, detailsUpdateable);
134 } catch (IOException ioe) {
135 throw new SecurityRealmException(ioe);
136 }
137 }
138
139 /**
140 * Creates a new user.
141 *
142 * @param pud a PebbleUserDetails instance
143 */
144 public synchronized void createUser(PebbleUserDetails pud) throws SecurityRealmException {
/*
P/P * Method: void createUser(PebbleUserDetails)
*
* Preconditions:
* pud != null
* init'ed(pud.username)
* this.configuration != null
*
* Presumptions:
* java.io.File:exists(...)@103 == 0
*
* Preconditions:
* init'ed(pud.detailsUpdateable)
* init'ed(pud.emailAddress)
* pud.grantedAuthories != null
* pud.grantedAuthories.length <= 232-1
* init'ed(pud.name)
* init'ed(pud.preferences)
* init'ed(pud.profile)
* init'ed(pud.website)
* (soft) pud.grantedAuthories[...] != null
* (soft) init'ed(pud.password)
* ...
*/
145 if (getUser(pud.getUsername()) == null) {
146 updateUser(pud, true);
147 } else {
148 throw new SecurityRealmException("User " + pud.getUsername() + " already exists");
149 }
150 }
151
152 /**
153 * Updates user details.
154 *
155 * @param pud a PebbleUserDetails instance
156 */
157 public synchronized void updateUser(PebbleUserDetails pud) throws SecurityRealmException {
/*
P/P * Method: void updateUser(PebbleUserDetails)
*
* Preconditions:
* pud != null
* init'ed(pud.detailsUpdateable)
* init'ed(pud.emailAddress)
* pud.grantedAuthories != null
* pud.grantedAuthories.length <= 232-1
* init'ed(pud.name)
* init'ed(pud.preferences)
* init'ed(pud.profile)
* init'ed(pud.username)
* init'ed(pud.website)
* ...
*/
158 updateUser(pud, false);
159 }
160
161 /**
162 * Updates user details, except for the password
163 *
164 * @param pud a PebbleUserDetails instance
165 */
166 private void updateUser(PebbleUserDetails pud, boolean updatePassword) throws SecurityRealmException {
167 File user = getFileForUser(pud.getUsername());
168 PebbleUserDetails currentDetails = getUser(pud.getUsername());
169
170 Properties props = new Properties();
171 if (updatePassword) {
/*
P/P * Method: void updateUser(PebbleUserDetails, bool)
*
* Preconditions:
* pud != null
* init'ed(pud.detailsUpdateable)
* init'ed(pud.emailAddress)
* pud.grantedAuthories != null
* pud.grantedAuthories.length <= 232-1
* init'ed(pud.name)
* init'ed(pud.preferences)
* init'ed(pud.profile)
* init'ed(pud.username)
* init'ed(pud.website)
* ...
*
* Presumptions:
* java.io.File:exists(...)@103 == 1
* java.util.Iterator:hasNext(...)@126 == 0
* java.util.Map:keySet(...)@184 != null
*
* Test Vectors:
* updatePassword: {0}, {1}
* java.util.Iterator:hasNext(...)@184: {1}, {0}
*/
172 props.setProperty(DefaultSecurityRealm.PASSWORD, passwordEncoder.encodePassword(pud.getPassword(), saltSource.getSalt(pud)));
173 } else {
174 props.setProperty(DefaultSecurityRealm.PASSWORD, currentDetails.getPassword());
175 }
176 props.setProperty(DefaultSecurityRealm.ROLES, pud.getRolesAsString());
177 props.setProperty(DefaultSecurityRealm.NAME, pud.getName());
178 props.setProperty(DefaultSecurityRealm.EMAIL_ADDRESS, pud.getEmailAddress());
179 props.setProperty(DefaultSecurityRealm.WEBSITE, pud.getWebsite());
180 props.setProperty(DefaultSecurityRealm.PROFILE, pud.getProfile());
181 props.setProperty(DefaultSecurityRealm.DETAILS_UPDATEABLE, "" + pud.isDetailsUpdateable());
182
183 Map<String,String> preferences = pud.getPreferences();
184 for (String preference : preferences.keySet()) {
185 props.setProperty(DefaultSecurityRealm.PREFERENCE + preference, preferences.get(preference));
186 }
187
188 try {
189 FileOutputStream out = new FileOutputStream(user);
190 props.store(out, "User : " + pud.getUsername());
191 out.flush();
192 out.close();
193 } catch (IOException ioe) {
194 throw new SecurityRealmException(ioe);
195 }
196 }
197
198 /**
199 * Changes a user's password.
200 *
201 * @param username the username of the user
202 * @param password the new password
203 * @throws SecurityRealmException
204 */
205 public synchronized void changePassword(String username, String password) throws SecurityRealmException {
/*
P/P * Method: void changePassword(String, String)
*
* Preconditions:
* (soft) this.configuration != null
* (soft) this.passwordEncoder != null
* (soft) this.saltSource != null
*
* Presumptions:
* pud.grantedAuthories.length@206 <= 232-1
* pud.grantedAuthories[...]@206 != null
*/
206 PebbleUserDetails pud = getUser(username);
207 if (pud != null) {
208 pud.setPassword(password);
+ 209 updateUser(pud, true);
210 }
211 }
212
213 /**
214 * Removes user details for the given username.
215 *
216 * @param username the username of the user to remove
217 */
218 public synchronized void removeUser(String username) throws SecurityRealmException {
/*
P/P * Method: void removeUser(String)
*
* Preconditions:
* this.configuration != null
*
* Presumptions:
* java.io.File:exists(...)@224 == 0
*
* Test Vectors:
* java.io.File:exists(...)@220: {0}, {1}
*/
219 File user = getFileForUser(username);
220 if (user.exists()) {
221 user.delete();
222 }
223
224 if (user.exists()) {
225 throw new SecurityRealmException("User " + username + " could not be deleted");
226 }
227 }
228
229 protected File getFileForRealm() throws SecurityRealmException {
230 // find the directory and file corresponding to the user, of the form
231 // ${pebbleContext.dataDirectory}/realm/${username}.properties
/*
P/P * Method: File getFileForRealm()
*
* Preconditions:
* this.configuration != null
*
* Postconditions:
* return_value == &new File(getFileForRealm#1)
* new File(getFileForRealm#1) num objects == 1
*/
232 return new File(configuration.getDataDirectory(), DefaultSecurityRealm.REALM_DIRECTORY_NAME);
233 }
234
235 protected File getFileForUser(String username) throws SecurityRealmException {
236 // find the directory and file corresponding to the user, of the form
237 // ${pebbleContext.dataDirectory}/realm/${username}.properties
/*
P/P * Method: File getFileForUser(String)
*
* Preconditions:
* this.configuration != null
*
* Postconditions:
* return_value == &new File(getFileForUser#1)
* new File(getFileForUser#1) num objects == 1
*/
238 return new File(getFileForRealm(), username + ".properties");
239 }
240
241 public Configuration getConfiguration() {
/*
P/P * Method: Configuration getConfiguration()
*
* Preconditions:
* init'ed(this.configuration)
*
* Postconditions:
* return_value == this.configuration
* init'ed(return_value)
*/
242 return configuration;
243 }
244
245 public void setConfiguration(Configuration configuration) {
/*
P/P * Method: void setConfiguration(Configuration)
*
* Postconditions:
* this.configuration == configuration
* init'ed(this.configuration)
*/
246 this.configuration = configuration;
247 }
248
249 public PasswordEncoder getPasswordEncoder() {
/*
P/P * Method: PasswordEncoder getPasswordEncoder()
*
* Preconditions:
* init'ed(this.passwordEncoder)
*
* Postconditions:
* return_value == this.passwordEncoder
* init'ed(return_value)
*/
250 return passwordEncoder;
251 }
252
253 public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
/*
P/P * Method: void setPasswordEncoder(PasswordEncoder)
*
* Postconditions:
* this.passwordEncoder == passwordEncoder
* init'ed(this.passwordEncoder)
*/
254 this.passwordEncoder = passwordEncoder;
255 }
256
257 public SaltSource getSaltSource() {
/*
P/P * Method: SaltSource getSaltSource()
*
* Preconditions:
* init'ed(this.saltSource)
*
* Postconditions:
* return_value == this.saltSource
* init'ed(return_value)
*/
258 return saltSource;
259 }
260
261 public void setSaltSource(SaltSource saltSource) {
/*
P/P * Method: void setSaltSource(SaltSource)
*
* Postconditions:
* this.saltSource == saltSource
* init'ed(this.saltSource)
*/
262 this.saltSource = saltSource;
263 }
264
265 }
SofCheck Inspector Build Version : 2.22510
| defaultsecurityrealm.java |
2010-Jun-25 19:40:32 |
| defaultsecurityrealm.class |
2010-Jul-19 20:23:38 |
| defaultsecurityrealm$1.class |
2010-Jul-19 20:23:38 |