adding algorithm debug statments. fixing / improving build
[Bookkeeping.git] / src / com / interrupt / bookkeeping / cc / bkell / aauth / Aauthentication.java
blob8f4ebb5b169c0c8e8718dc72904b6e5a7baed91a
1 package com.interrupt.bookkeeping.cc.bkell.aauth;
3 import java.io.File;
4 import java.io.UnsupportedEncodingException;
5 import java.security.MessageDigest;
6 import java.security.NoSuchAlgorithmException;
7 import java.util.Iterator;
8 import java.util.List;
10 import javax.security.auth.callback.CallbackHandler;
11 import javax.security.auth.login.LoginContext;
12 import javax.security.auth.login.LoginException;
14 import org.apache.log4j.Logger;
15 import org.xmldb.api.DatabaseManager;
16 import org.xmldb.api.base.Collection;
17 import org.xmldb.api.base.XMLDBException;
19 import com.interrupt.bob.base.Bob;
20 import com.interrupt.bob.base.IBob;
21 import com.interrupt.bob.base.IVisitor;
22 import com.interrupt.bookkeeping.cc.bkell.command.ICommand;
23 import com.interrupt.bookkeeping.exception.AuthorisationException;
24 import com.interrupt.bookkeeping.exception.SystemException;
25 import com.interrupt.bookkeeping.http.BookkeepingSystemFacade;
26 import com.interrupt.bookkeeping.system.BookkeepingSystem;
27 import com.interrupt.bookkeeping.system.BookkeepingSystemProperties;
28 import com.interrupt.bookkeeping.users.GGroups;
29 import com.interrupt.bookkeeping.users.Group;
30 import com.interrupt.bookkeeping.users.Groups;
31 import com.interrupt.bookkeeping.users.IGroup;
32 import com.interrupt.bookkeeping.users.IGroups;
33 import com.interrupt.bookkeeping.users.IUser;
34 import com.interrupt.bookkeeping.users.IUserSession;
35 import com.interrupt.bookkeeping.users.IUsers;
36 import com.interrupt.bookkeeping.users.User;
37 import com.interrupt.bookkeeping.users.UserSession;
38 import com.interrupt.bookkeeping.users.Users;
39 import com.interrupt.spittoon.Spittoon;
40 import com.interrupt.util.IdGenerator;
42 public class Aauthentication extends GAauthentication implements java.io.Serializable {
45 public static final String AAUTHENTICATION = "aauthentication";
46 private Logger logger = Logger.getLogger(Aauthentication.class);
47 private static Aauthentication instance = null;
49 private ThreadGroup userThreadGroup = new ThreadGroup("UserThreadGroup");
50 private Spittoon spittoon = null;
51 private AauthenticationMediator aauthenticationMediator = null;
52 private Bob bob = new Bob();
53 private IBob loadedAuthorise = null;
54 private UserSession userSession = null;
55 //private IUsers aauthUsers = null;
56 //private IGroups aauthGroups = null;
58 public Aauthentication() {
60 //spittoon = Spittoon.instance();
61 this.setId("main.authentication");
64 public static synchronized Aauthentication instance() {
66 if(instance == null) {
67 instance = new Aauthentication();
68 instance.initialise();
70 return instance;
74 public synchronized void setup() {
76 //loadedAuthorise = bob.load(Aauthentication.class.getResourceAsStream("/bookkeeping.system.xml"), BookkeepingSystemProperties.instance().getProperty("bob.def"));
77 //logger.debug("loadedAuthorise:: "+ loadedAuthorise.toXML() );
79 //IUsers userResult = (IUsers)loadedAuthorise.find("users", "aauth.users");
80 //logger.debug("userResult:: "+ userResult.toXML() );
83 //spittoon.addDocument(BookkeepingSystemProperties.instance().getProperty("db.url") + "system/aauthentication/users/", userResult);
85 // put a default '/groups/' in the xml database
86 //IGroups groupResult = (IGroups)loadedAuthorise.find("groups", "aauth.groups");
87 //spittoon.addDocument(BookkeepingSystemProperties.instance().getProperty("db.url") + "system/aauthentication/groups/", groupResult);
90 public synchronized void teardown() throws XMLDBException {
92 // remove default collections
93 //spittoon.removeCollection(BookkeepingSystemProperties.instance().getProperty("db.url") + "system/aauthentication/");
97 public synchronized void initialise() {
99 //BookkeepingSystemProperties bsproperties = BookkeepingSystemProperties.instance();
100 //IUsers rootUsers = (IUsers)spittoon.getDocument(
101 // bsproperties.getProperty("db.url") + "system/aauthentication/users/", "users", "aauth.users");
102 //IGroups rootGroups = (IGroups)spittoon.getDocument(
103 // bsproperties.getProperty("db.url") + "system/aauthentication/groups/", "groups", "aauth.groups");
104 //IUsers rootUsers = null;
105 //IGroups rootGroups = null;
107 //this.setUsers(rootUsers);
108 //this.setGroups(rootGroups);
112 public String hashPassword(String passwd) throws SystemException {
114 MessageDigest digest = null;
115 byte[] input = null;
116 try {
118 digest = MessageDigest.getInstance("SHA");
119 digest.reset();
120 input = digest.digest(passwd.getBytes("UTF-8"));
122 catch(NoSuchAlgorithmException e) {
123 throw new SystemException(e);
125 catch(UnsupportedEncodingException e) {
126 throw new SystemException(e);
129 String hashString = new String(input);
130 return hashString;
133 public synchronized AauthenticationMediator getAauthenticationMediator() {
134 return aauthenticationMediator;
136 public synchronized void setAauthenticationMediator(AauthenticationMediator aauthenticationMediator) {
137 this.aauthenticationMediator = aauthenticationMediator;
139 public UserSession getUserSession() { return userSession; }
140 public void setUserSession(UserSession userSession) { this.userSession = userSession; }
141 public synchronized IUsers getUsers() {
142 return this.findUsersById("aauth.users");
144 public synchronized void setUsers(IUsers users) {
145 users.setId("aauth.users");
146 this.removeAllUsers();
147 this.addUsers(users);
149 public synchronized IGroups getGroups() {
150 return this.findGroupsById("aauth.groups");
152 public synchronized void setGroups(IGroups groups) {
153 groups.setId("aauth.groups");
154 this.removeAllGroups();
155 this.addGroups(groups);
157 public Spittoon getSpittoon() {
158 return spittoon;
160 public void setSpittoon(Spittoon spittoon) {
161 this.spittoon = spittoon;
165 public synchronized IUserSession authenticate(String groupid, IUser user) {
168 logger.debug("Aauthenticate::authenticate > groupid["+groupid+"] / user["+user+"]");
170 //** check if group contains the user
171 IGroup agroup = this.getGroups().findGroupById(groupid);
172 if(agroup == null) {
173 throw new AuthorisationException("This associated group does not exist");
175 IUser auser = agroup.findUserById(user.getId());
176 if((auser == null ) && (!agroup.getOwner().equals(user.getId()))) {
178 throw new AuthorisationException("The user is not associated with the group");
182 IUsers users = this.getUsers();
183 IUser iuser = users.findUserById(user.getId());
185 //String passwdHash = hashPassword(user.getPassword());
186 String passwdHash = user.getPassword();
189 //** TODO - come up with a better authentication scheme
190 if( user.getUsername().equals(iuser.getUsername()) &&
191 passwdHash.equals(iuser.getPassword())) {
193 logger.debug("authenticated ok!!!");
195 this.userSession = new UserSession();
196 try {
197 this.userSession.setTimeout(Long.parseLong(user.getLogintimeout()));
199 catch(java.lang.NumberFormatException e) {
200 throw new AuthorisationException("Please set a login timeout for user["+user.getId()+"]");
202 this.userSession.setId(IdGenerator.generateId());
203 this.userSession.setGroupid(groupid);
204 this.userSession.setUserid(user.getId());
206 //** this visitor will authenticate the use and fire
207 // off the UserSession thread
208 AuthenticateUserVisitor auvisitor = new AuthenticateUserVisitor();
209 auvisitor.setUname( user.getUsername() );
210 auvisitor.setPasswd( user.getPassword() );
211 auvisitor.setUserSession(this.userSession);
213 this.accept(auvisitor);
214 return this.userSession;
217 return null;
219 public synchronized boolean authenticated(IUser user) {
221 IUsers users = this.getUsers();
222 User iuser = (User)users.findUserById(user.getId());
223 if(iuser.isAuthenticated()) {
224 return true;
226 return false;
228 public synchronized IUserSession getUserSession(String sessionid) {
230 return (IUserSession)this.find("userSession", sessionid);
235 public synchronized boolean logout(IUser user) {
237 //IUsers users = this.getUsers();
238 //IUser iuser = users.findUserById(user.getId());
240 /*IGroup agroup = this.getGroups().findGroupById(groupid);
241 if(agroup == null) {
242 throw new AuthorisationException("This associated group does not exist");
244 IUser auser = agroup.findUserById(user.getId());
245 if((auser == null ) && (!agroup.getOwner().equals(user.getId()))) {
247 throw new AuthorisationException("The user is not associated with the group");
251 ////** TODO - come up with a better authentication scheme
252 //if( user.getUsername().equals(iuser.getUsername()) &&
253 // user.getPassword().equals(iuser.getPassword())) {
255 LogoutUserVisitor auvisitor = new LogoutUserVisitor();
256 auvisitor.setUname( user.getUsername() );
257 auvisitor.setPasswd( user.getPassword() );
258 this.accept(auvisitor);
259 return true;
264 public synchronized boolean authorised(IUser user, ICommand command) {
266 if(!this.authenticated(user)) {
267 return false;
270 IAllowedActions resultAllowed = (IAllowedActions)this.find("allowedActions", user.getId() + ".allowedActions");
271 List commands = resultAllowed.allCommand();
272 Iterator iter = commands.iterator();
273 ICommand eachCommand = null;
274 while(iter.hasNext()) {
276 eachCommand = (ICommand)iter.next();
277 //logger.debug(">>> each command: "+ eachCommand.toXML());
279 if( eachCommand.getName().equals(command.getName()) ) {
280 return true;
284 return false;
287 public synchronized IUser findUser(String userid) {
289 return (IUser)this.getUsers().findUserById(userid);
291 public synchronized IGroup findGroup(String groupid) {
293 return (IGroup)this.getGroups().findGroupById(groupid);
296 public synchronized void addGroup(Group group) throws AuthorisationException {
298 // 1. check that there's an owner reference
299 if(group.getOwner() == null || group.getOwner().trim().length() == 0) {
300 throw new AuthorisationException("A group must have an owner (user) that is referenced");
303 // 2. check that there's not a duplicate group
304 Group duplicateGroupCheck = (Group)this.find("group", group.getId());
305 if(duplicateGroupCheck != null) {
306 throw new AuthorisationException("There is already a group with the id["+group.getId()+"]");
309 // 3. check that the owner actually exists as a user
310 String dburl = spittoon.getAauthDbUrl();
311 StringBuffer sbuffer = new
312 StringBuffer("/system[ @id='main.system' ]/aauthentication[ @id='main.authentication' ]/users[ @id='aauth.users' ]");
313 sbuffer.append("/user[ @id='");
314 sbuffer.append(group.getOwner());
315 sbuffer.append("']");
316 String xpath = sbuffer.toString();
318 User aauthUser = (User)spittoon.retrieve(dburl, xpath, false);
320 if(aauthUser == null) {
321 throw new AuthorisationException("The referenced owner / user ["+ group.getOwner() +"] does not exist");
324 //** add the group
325 this.resetPull();
326 IBob nextPull = this.pullNext();
327 while( nextPull != null) {
329 if( nextPull.getTagName().equals("groups") &&
330 nextPull.getAttributes().getValue("id").equals("aauth.groups")) {
332 ((GGroups)nextPull).addGroup(group);
333 break;
335 nextPull = this.pullNext();
340 public synchronized void removeGroup(String groupId) {
342 // 1. ensure there are no more users besides the default user before deleting
343 Group targetGroup = (Group)(this.getGroups().findGroupById(groupId));
344 if(targetGroup != null) {
346 List userList = targetGroup.allUser();
347 if(userList.size() > 1) {
348 throw new AuthorisationException("There are more users than the default owner");
352 // 2. move group / bookkeeping data to a removed folder for future reference
353 this.aauthenticationMediator.messageMoveGroupBookkeepingToAttic(groupId);
358 public synchronized void addUser(User user) {
360 //** 1. check that there's not an existing user
361 //** this assumes that the existing user list is current with what's in the database
362 logger.debug("Aauthentication.addUser 1: "+ (Users)this.getUsers());
363 logger.debug("Aauthentication.addUser 2: "+ user);
364 logger.debug("");
366 User existingUser = (User)this.getUsers().findUserById(user.getId());
367 if(existingUser != null) {
368 throw new AuthorisationException("There is already existing user with id["+user.getId()+"]");
372 //** 2. now add a default group corresponding to the new user
373 // this is the default group to add
374 Group defaultGroup =
375 (Group)bob.load(
376 Aauthentication.class.getResourceAsStream("/add.usergroup.xml"),
377 BookkeepingSystemProperties.instance().getProperty("bob.def"));
378 defaultGroup.setId(user.getId() + ".group");
379 defaultGroup.setName(user.getId() + ".group");
380 defaultGroup.setOwner(user.getId());
382 //** 3. add to aauth.groups
383 String dburl = spittoon.getAauthDbUrl();
384 String groupsXpath =
385 "/system[ @id='main.system' ]/aauthentication[ @id='main.authentication' ]/groups[ @id='aauth.groups' ]" +
386 "/group[ @id='"+ defaultGroup.getId() +"' ]";
387 spittoon.createR(dburl, groupsXpath, defaultGroup.toXML(false));
390 //** 4. add the user to the database
391 user.setDefaultGroup(defaultGroup.getId()); // set this user's default group name
392 String authXpath = "/system[ @id='main.system' ]/aauthentication[ @id='main.authentication' ]/users[ @id='aauth.users' ]";
393 Users aauthUsers = (Users)spittoon.retrieve(dburl, authXpath, false);
394 aauthUsers.addUser(user);
395 this.setUsers( aauthUsers );
398 //** 5. add the user to the database
399 spittoon.createR(dburl, authXpath + "/user[ @id='"+user.getId()+"' ]", user.toXML(false));
401 this.aauthenticationMediator.addGroupSetAssociatedBookkeeping(defaultGroup);
405 public synchronized void removeUser(String userId) {
407 // 1. first remove the associated group
408 Group defaultGroup = (Group)this.getGroups().removeGroupByOwner(userId);
409 this.removeGroup(defaultGroup.getId());
412 // 2. remove the user
413 class RemoveUserVisitor implements IVisitor {
414 public String userid = null;
415 public void visit(IBob bob) {
416 if( bob.getTagName().equals("user") &&
417 bob.getAttributes().getValue("id").equals(userid)) {
419 ((Users)bob.getParent()).removeUserById(userid);
423 RemoveUserVisitor ruVisitor = new RemoveUserVisitor();
424 ruVisitor.userid = userId;
425 this.accept(ruVisitor);
430 public synchronized void addUserToGroup(String groupId, User user) {
432 this.getGroups().findGroupById(groupId).addUser(user);
435 public synchronized void removeUserFromGroup(String groupid, String userid) {
437 // 1. check if group exists
438 Group group = (Group)this.getGroups().findGroupById(groupid);
439 if(group == null) {
440 throw new AuthorisationException("There is no group with id '"+groupid+"'");
443 // 2. check if user exists
444 User user = (User)this.getUsers().findUserById(userid);
445 if(user == null) {
446 throw new AuthorisationException("There is no user with id '"+userid+"'");
449 // 3. check if user is in the group
450 User removedUser = (User)group.removeUserById(user.getId());
451 if(removedUser == null) {
452 throw new AuthorisationException("The user '"+user.getId()+"' does not exist in the group '"+group.getId()+"'");
455 this.getGroups().findGroupById(groupid).removeUserById(userid);
460 class SavePersistor {
462 private String baseDir = null;
463 private String groupDir = "system/aauthentication/groups/";
464 private String usersDir = "system/aauthentication/users/";
465 private BookkeepingSystemProperties bsprops = null;
466 private Spittoon spittoon = null;
468 public SavePersistor() {
469 bsprops = BookkeepingSystemProperties.instance();
471 public void setSpittoon(Spittoon spit) {
472 spittoon = spit;
474 public Spittoon getSpittoon() {
475 return spittoon;
477 public void setBaseDir(String bdir) {
478 baseDir = bdir;
480 public String getBaseDir() {
481 return baseDir;
483 public void visit(IBob persistable) {
485 if(persistable instanceof IGroups && ((IGroups)persistable).getId().equals("aauth.groups")) {
487 //** save to system/aauthentication/groups/
488 //spittoon.updateDocument(
489 // BookkeepingSystemProperties.instance().getProperty("db.url") + "system/aauthentication/groups/",
490 // persistable.getTagName(),
491 // persistable.getAttributes().getValue("id"),
492 // persistable);
495 else if(persistable instanceof IUsers && ((IUsers)persistable).getId().equals("aauth.users")) {
497 //** save to system/aauthentication/users/
498 //spittoon.updateDocument(
499 // BookkeepingSystemProperties.instance().getProperty("db.url") + "system/aauthentication/users/",
500 // persistable.getTagName(),
501 // persistable.getAttributes().getValue("id"),
502 // persistable);
509 public boolean ii = true;
510 public void run() {
512 //** run until an shutdown interruption
513 //...
514 // 1. how to communicate with running thread -> calling a synchronized method
515 // 2. how to send a shutdown signal -> interrupt();
516 while(ii) {
518 logger.debug("...running");
524 * @param args
526 public static void main(String[] args) {
528 Logger.getLogger(Aauthentication.class).debug("Starting");
530 // Aauthentication aauth = Aauthentication.instance();
531 // Thread aauthThread = new Thread(aauth);
533 // Logger.getLogger(Aauthentication.class).debug("Helloooooooooooooooooooooooooooooooooooooooooo");
534 // aauthThread.start();
536 /*boolean ii = true;
537 while(ii) {
538 //try { aauthThread.join(); } catch(Throwable e) { }
539 //aauthThread.interrupt();
540 //ii = false;
541 for(int j=0; j < 1000; j++) {}
542 aauth.ii = false;
544 // aauth.ii = false;
545 //Logger.getLogger(Aauthentication.class).debug("Ending");