001 /* 002 * PAVLOV -- Multiple Choice Study System 003 * Copyright (C) 2000 - 2004 T.J. Willis 004 * 005 * This program is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU General Public License 007 * as published by the Free Software Foundation; either version 2 008 * of the License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU General Public License for more details. 014 * 015 * You should have received a copy of the GNU General Public License 016 * along with this program; if not, write to the Free Software 017 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. 018 * 019 * $Header: /cvsroot/pavlov/net/sourceforge/pavlov/controllers/LoginController.java,v 1.4 2004/07/01 05:50:19 tj_willis Exp $ 020 */ 021 package net.sourceforge.pavlov.controllers; 022 023 import java.awt.*; 024 import java.awt.event.*; 025 import java.util.*; 026 import javax.swing.*; 027 import javax.swing.event.HyperlinkEvent; 028 import javax.swing.event.HyperlinkListener; 029 import javax.swing.text.html.*; 030 import net.sourceforge.pavlov.event.*; 031 import net.sourceforge.pavlov.main.standalone.ResourceBroker; 032 import net.sourceforge.pavlov.user.*; 033 import net.sourceforge.sillyview.*; 034 import java.awt.Dimension; 035 import java.awt.Point; 036 import org.apache.log4j.*; 037 038 /** 039 * Creates and manages model, view, and controller for the Logon system. 040 * 041 *@author Haus 042 *@created May 10, 2004 043 *@since 1.1 044 */ 045 public class LoginController extends Widget 046 implements LogonListener, HyperlinkListener 047 { 048 //FIXED: isolate strings 049 //FIXED: implement in MVC 050 //FIXED: replace UserList with UserLoader 051 //FIXED: method should be its own class 052 //FIXED: break into smaller methods 053 //FIXME: improve javadocs 054 //FIXME: get strings from resourcebroker 055 //FIXME: provide resourcebroker to template? 056 //FIXME: the view should be passed in, not hardcoded here 057 /** 058 * Token for communicating with velocity model 059 */ 060 public final static String CHOOSE_ANOTHER_PASSWORD = "CHOOSEANOTHERPASSWORD"; 061 /** 062 * Token for communicating with velocity model 063 */ 064 public final static String CREATE_NEW_USER = "CREATENEWUSER"; 065 /** 066 * Token for communicating with velocity model 067 */ 068 public final static String NAME_IN_USE = "NAME_IN_USE"; 069 /** 070 * Token for communicating with velocity model 071 */ 072 public final static String PASSWORD = "PASSWORD"; 073 /** 074 * Token for communicating with velocity model 075 */ 076 public final static String USER_NAME = "USER_NAME"; 077 /** 078 * Token for communicating with velocity model 079 */ 080 public final static String WRONG_PASSWORD = "WRONGPASSWORD"; 081 /** 082 * Token for communicating with velocity model 083 */ 084 public final static String MODE = "MODE"; 085 /** 086 * Token for communicating with velocity model 087 */ 088 public final static String CREATE = "CREATE"; 089 090 public static final String ERROR = "ERROR"; 091 092 private ResourceBroker rb; 093 //private WidgetView loginView; //JFrameView loginView; 094 private Vector<LogonListener> listeners; 095 //private VelocityModel model; FIXED: thanks FindBugs 096 private Category cat 097 = Category.getInstance(LoginController.class.getName()); 098 099 public LoginController (WidgetView vu) throws Exception { 100 super(vu); 101 rb = ResourceBroker.getInstance(); 102 //model = (VelocityModel)view.getModel();//new VelocityModel(templateFileName); 103 listeners = new Vector<LogonListener>(); 104 105 view.setToken(JPanelView.HYPERLINK_LISTENER,this); 106 view.setToken(JPanelView.TITLE,rb.getString(rb.PAVLOV_LOGIN)); 107 108 109 } 110 /** 111 * Returns true if a file exists for the given user. 112 *@return Description of the Return Value 113 */ 114 protected boolean userNameExists(String name) 115 { 116 if (name == null) { 117 return false; 118 } 119 UserFile uf = null; 120 try { 121 uf = new LocalUserFile(name); 122 return (uf.exists()); 123 } catch (Exception ex) { 124 //return false; 125 } 126 return false; 127 } 128 129 130 /** 131 * Returns true if the user file exists, and its password 132 * is equal to the one provided. Returns false for usernames 133 * less than 2 characters and passwords less than 3 characters. 134 * 135 *@param name Username to check 136 *@param pass Password provided by user 137 *@return Whether password is correct 138 */ 139 protected boolean goodPassword(String name, String pass) 140 { 141 if (name == null || name.length() < 2) { 142 return false; 143 } 144 if (pass == null || pass.length() < 3) { 145 return false; 146 } 147 UserFile uf = null; 148 User user = null; 149 try { 150 uf = new LocalUserFile(name); 151 if (uf.exists()) { 152 user = uf.read(pass); 153 //wasteful 154 if (user == null) { 155 return false; 156 } 157 } else { 158 // this falls through to the "return true" below 159 // FIXME: should limit the types of passwords that are 160 // created. Checks above for at least 3 characters. 161 } 162 } catch (Exception ex) { 163 return false; 164 } 165 return true; 166 } 167 168 169 /** 170 * Creates a new user with the given name and password. 171 * 172 *@param username Description of the Parameter 173 *@param pass Description of the Parameter 174 *@return Description of the Return Value 175 */ 176 protected User createNewUser(String username, String pass) 177 { 178 User newGuy = null; 179 try { 180 UserFile uf = new LocalUserFile(username); 181 newGuy = new User(username, pass); 182 newGuy.setUserFile(uf); 183 uf.save(newGuy); 184 } catch (Exception ex) { 185 return null; 186 } 187 cat.info("CREATED NEW USER : " + username);//^ 188 return newGuy; 189 } 190 191 192 // close me and perform callback 193 /** 194 * Notifies listeners that the user has successfully logged in 195 * and closes the Login view. 196 * 197 *@param u Description of the Parameter 198 */ 199 protected void startSession(User u) 200 { 201 notify(new LogonEvent(u)); 202 cat.info("SUCCESSFULLY LOGGED IN : " + u.getName());//^ 203 //close(); 204 } 205 206 /** 207 * Description of the Method 208 * 209 *@param event Description of the Parameter 210 */ 211 public void logonAttempt(LogonEvent event) 212 { 213 String uname = event.getUserName(); 214 String pw = event.getPassword(); 215 boolean create = event.getCreateRequest(); 216 217 HashMap<Object,Object> tmp = new HashMap<Object,Object>(); 218 tmp.put(NAME_IN_USE, null); 219 tmp.put(CHOOSE_ANOTHER_PASSWORD, null); 220 tmp.put(WRONG_PASSWORD, null); 221 tmp.put(CREATE_NEW_USER, null); 222 223 if (create) { 224 // Requesting to create new user 225 // if username exists 226 if (userNameExists(uname)) { 227 tmp.put(NAME_IN_USE, uname); 228 tmp.put(USER_NAME, ""); 229 tmp.put(PASSWORD, ""); 230 } 231 else if (!goodPassword(uname, pw)) { 232 // if password is not good 233 tmp.put(PASSWORD, ""); 234 tmp.put(CHOOSE_ANOTHER_PASSWORD, "something"); 235 } 236 else { 237 User u = createNewUser(uname, pw); 238 startSession(u); 239 return; 240 } 241 } 242 else { 243 // Not requesting to create new user 244 if (userNameExists(uname)) { 245 if (goodPassword(uname, pw)) { 246 User u = getUser(uname, pw); 247 if (u != null) { 248 startSession(u); 249 } else { 250 tmp.put(ERROR, "something"); 251 } 252 } else { 253 tmp.put(WRONG_PASSWORD, "something"); 254 cat.info("Logon failed"); 255 } 256 257 } else { 258 tmp.put(CREATE_NEW_USER, uname); 259 tmp.put(CREATE, "something"); 260 tmp.put(USER_NAME, uname); 261 tmp.put(PASSWORD, pw); 262 } 263 } 264 addTokens(tmp); 265 } 266 267 268 269 /** 270 * Attempts to load the user with the given name and password. 271 * 272 *@param uname Description of the Parameter 273 *@param pass Description of the Parameter 274 *@return The user value 275 */ 276 private User getUser(String uname, String pass) 277 { 278 User newGuy = null; 279 try { 280 UserFile uf = new LocalUserFile(uname); 281 newGuy = uf.read(pass); 282 } catch (Exception ex) { 283 // fall thru to return null 284 } 285 return newGuy; 286 } 287 288 289 /** 290 * Sets the given token to the given value in the backing model. 291 * 292 *@param n The new token key 293 *@param v The new token value 294 */ 295 public void setToken(String nam, String val) 296 { 297 if (view == null) { 298 return; 299 } 300 view.setToken(nam, val); 301 } 302 303 public void addTokens(HashMap<Object,Object> map) 304 { 305 if( view==null ) return; 306 view.addTokens(map); 307 } 308 309 310 /* 311 * Closes the JFrameView. 312 313 public void close() 314 { 315 if(view inherits JComponent){ 316 JComponent swingView = (JComponent)view; 317 swingView.setVisible(false); 318 swingView = null; 319 } 320 } 321 */ 322 323 /** 324 * Converts the URL command to a LogonEvent. 325 * 326 *@param url Description of the Parameter 327 *@return Description of the Return Value 328 */ 329 protected LogonEvent parseURL(String url) 330 { 331 Hashtable h = URLParser.parseVariables(url); 332 Object u = h.get(USER_NAME); 333 Object p = h.get(PASSWORD); 334 Object q = h.get(MODE); 335 if (u == null) { 336 u = ""; 337 } 338 if (p == null) { 339 p = ""; 340 } 341 if (q == null) { 342 q = ""; 343 } 344 boolean create = q.equals("Create New User");//^ 345 return new LogonEvent(u.toString(), p.toString(), create); 346 } 347 348 349 /** 350 * Catches the form submit event, and makes a login attempt 351 * from it. 352 * 353 *@param e Description of the Parameter 354 */ 355 public void hyperlinkUpdate(HyperlinkEvent e) 356 { 357 java.net.URL uz = e.getURL(); 358 359 if (e instanceof FormSubmitEvent) { 360 FormSubmitEvent f = (FormSubmitEvent) e; 361 String data = f.getData(); 362 LogonEvent evt = parseURL(data); 363 logonAttempt(evt); 364 } 365 } 366 367 368 /** 369 * Notify listeners that a logonevent has occured. 370 * 371 *@param e Description of the Parameter 372 */ 373 protected void notify(LogonEvent e) 374 { 375 for(LogonListener l : listeners){ 376 l.logonAttempt(e); 377 } 378 } 379 380 381 /** 382 * Adds a LogonListener. 383 * 384 *@param l The feature to be added to the LogonListener attribute 385 */ 386 public void addLogonListener(LogonListener l) 387 { 388 listeners.add(l); 389 } 390 }