/hostadmiral/trunk/doc/todo.txt |
---|
1,8 → 1,14 |
Host Admiral TODO |
================= |
+ Save user id for all db-update operations. |
+/- Listeners for all operations. |
Allow configuration of each listener. |
Transaction control for listners. |
+/- Save user id for all db-update operations. |
Set 'editor' for an object by loading and not require it for each property change? |
Then problem with objects inside (lazy loaded) collections. |
17,7 → 23,7 |
(because it makes no sense to parse html pages). |
The scenario for the model test can be used. |
Cascade object deletion, confirmation page. |
+/- Cascade object deletion, confirmation page. |
Store user and malbox passwords in several forms; e.g. clear text, md5, encrypt. Allow |
admin to specify which forms to use. |
61,8 → 67,6 |
+ User login history. |
Listeners for all operations. |
Basic scripts to push changes to the system. |
If mailbox is created, create an user and a mail alias for it in one step - as option. |
/hostadmiral/trunk/src/ak/hostadmiral/core/CoreResources.properties |
---|
89,6 → 89,10 |
ak.hostadmiral.page.system.logout.login=start new session |
ak.hostadmiral.page.system.logout.back=return to system |
ak.hostadmiral.page.deleting.title=Delete an object from system |
ak.hostadmiral.page.deleting.delete=delete |
ak.hostadmiral.page.deleting.back=back |
ak.hostadmiral.page.user.password.change.title=Host Admiral - change password |
ak.hostadmiral.page.user.password.change.old_password=Old password |
ak.hostadmiral.page.user.password.change.new_password=New password |
249,7 → 253,7 |
ak.hostadmiral.page.mail.box.edit.domain=Domain |
ak.hostadmiral.page.mail.box.edit.domain.empty=-- please select -- |
ak.hostadmiral.page.mail.box.edit.owner=Owner |
ak.hostadmiral.page.mail.box.edit.owner.empty=-- create an user -- |
ak.hostadmiral.page.mail.box.edit.owner.empty=-- create a new user -- |
ak.hostadmiral.page.mail.box.edit.systemuser=System user |
ak.hostadmiral.page.mail.box.edit.systemuser.empty=-- please select -- |
ak.hostadmiral.page.mail.box.edit.viruscheck=check mails for viruses |
/hostadmiral/trunk/src/ak/hostadmiral/core/model/MailAliasDestinationManager.java |
---|
74,7 → 74,7 |
if(!mailAliasDestination.editableBy(editor)) |
throw new ModelSecurityException(); |
mailAliasDestination.setModUser(editor); |
//mailAliasDestination.setModUser(editor); // FIXME |
// FIXME: the mod_user is not set when changing a destination as element of collection |
try { |
/hostadmiral/trunk/src/ak/hostadmiral/core/model/TransactionController.java |
---|
0,0 → 1,34 |
package ak.hostadmiral.core.model; |
import java.util.Map; |
import java.util.HashMap; |
import ak.hostadmiral.util.ModelException; |
// FIXME: implement it |
public class TransactionController |
{ |
private static TransactionController transactionController = null; |
public static TransactionController getInstance() |
{ |
return transactionController; |
} |
private Map listeners = new HashMap(); |
public void beginTransaction(Object transaction) |
{ |
} |
public void commitTransaction(Object transaction) |
{ |
} |
public void rollbackTransaction(Object transaction) |
{ |
} |
public void addObject(Object transaction, Object object) |
{ |
} |
} |
/hostadmiral/trunk/src/ak/hostadmiral/core/model/Mailbox.java |
---|
206,7 → 206,9 |
public boolean editableBy(User user) |
{ |
return user.isSuperuser() || user.equals(domain.getOwner()); |
return user.isSuperuser() |
|| (domain == null) // just created |
|| user.equals(domain.getOwner()); |
} |
public boolean deleteableBy(User user) |
/hostadmiral/trunk/src/ak/hostadmiral/core/model/TransactionListener.java |
---|
0,0 → 1,43 |
package ak.hostadmiral.core.model; |
import java.util.Collection; |
import ak.hostadmiral.util.ModelException; |
/** |
* One could implement this interface to receive transaction start, commit and |
* rollback events. |
* An object will be informed about this events if it actualy interacts with the |
* transaction, e.g. if it is registered as listener for object modifications. |
*/ |
public interface TransactionListener |
{ |
/** |
* called when this object first time interacts with given transaction, |
* before any other callbacks of this object in the transaction |
* |
* @param id some transaction identifier, the same for all transaction* methods |
* @throws ModelException if transaction must be aborted immediately |
*/ |
public void transactionBegin(Object id) |
throws ModelException; |
/** |
* called when transaction is commited |
* |
* @param id some transaction identifier, the same as in corresponding transactionBegin |
* method call |
* @throws ModelException logged, but ignored |
*/ |
public void transactionCommited(Object id) |
throws ModelException; |
/** |
* called when transaction is rolled back |
* |
* @param id some transaction identifier, the same as in corresponding transactionBegin |
* method call |
* @throws ModelException logged, but ignored |
*/ |
public void transactionRolledBack(Object id) |
throws ModelException; |
} |
/hostadmiral/trunk/src/ak/hostadmiral/core/model/MailAlias.java |
---|
145,7 → 145,9 |
public boolean editableBy(User user) |
{ |
return user.isSuperuser() || user.equals(domain.getOwner()); |
return user.isSuperuser() |
|| (domain == null) // just created |
|| user.equals(domain.getOwner()); |
} |
public boolean mayChangeDestinations(User user) |
/hostadmiral/trunk/src/ak/hostadmiral/core/model/UserManager.java |
---|
25,11 → 25,12 |
registered = true; |
try { |
/* |
HibernateUtil.getConfiguration().addResource( |
"ak/hostadmiral/core/model/User.hbm.xml"); |
HibernateUtil.getConfiguration().addResource( |
"ak/hostadmiral/core/model/UserLogin.hbm.xml"); |
*/ |
userManager = new UserManager(); |
} |
catch(Exception ex) { |
43,7 → 44,10 |
register(); |
} |
private Collection createdListeners = new ArrayList(); |
private Collection modifiedListeners = new ArrayList(); |
private Collection beforeDeleteListeners = new ArrayList(); |
private Collection deletedListeners = new ArrayList(); |
private Map loggedinUsers = new WeakHashMap(); |
private UserManager() |
56,7 → 60,13 |
{ |
if(!allowedToCreate(editor)) throw new ModelSecurityException(); |
return new User(); |
User user = new User(); |
if(!user.mayChangeBoss(editor)) { // ordinal user can create only own "subusers" |
user.setBoss(editor); |
} |
return user; |
} |
public boolean allowedToCreate(User editor) |
73,8 → 83,7 |
try { |
user = (User)HibernateUtil.currentSession().load(User.class, id); |
} |
catch(HibernateException ex) |
{ |
catch(HibernateException ex) { |
throw new ModelException(ex); |
} |
100,8 → 109,7 |
new Type[] { Hibernate.STRING, Hibernate.entity(User.class) } ) |
.next()).intValue() > 0; |
} |
catch(HibernateException ex) |
{ |
catch(HibernateException ex) { |
throw new ModelException(ex); |
} |
} |
120,8 → 128,7 |
else |
return (User)list.get(0); |
} |
catch(HibernateException ex) |
{ |
catch(HibernateException ex) { |
throw new ModelException(ex); |
} |
} |
135,13 → 142,15 |
throw new ModelSecurityException(); |
} |
user.setModUser(editor); |
boolean isNew = user.isNew(); |
//user.setModUser(editor); // FIXME: disabled because hb throws exception |
// if user edits itself |
try { |
HibernateUtil.currentSession().saveOrUpdate(user); |
} |
catch(HibernateException ex) |
{ |
catch(HibernateException ex) { |
throw new ModelException(ex); |
} |
151,8 → 160,44 |
if(u.equals(user)) |
u.update(user); |
} |
// inform listeners |
if(isNew) { |
for(Iterator i = createdListeners.iterator(); i.hasNext(); ) { |
UserCreatedListener listener = (UserCreatedListener)i.next(); |
listener.userCreated(editor, user); |
} |
} |
else { |
User oldUser = user.getOrigin(); |
if(oldUser == null) oldUser = user; |
for(Iterator i = modifiedListeners.iterator(); i.hasNext(); ) { |
UserModifiedListener listener = (UserModifiedListener)i.next(); |
listener.userModified(editor, user, oldUser); |
} |
} |
} |
public void addCreatedListener(UserCreatedListener listener) |
{ |
createdListeners.add(listener); |
} |
public void removeCreatedListener(UserCreatedListener listener) |
{ |
createdListeners.remove(listener); |
} |
public void addModifiedListener(UserModifiedListener listener) |
{ |
modifiedListeners.add(listener); |
} |
public void removeModifiedListener(UserModifiedListener listener) |
{ |
modifiedListeners.remove(listener); |
} |
public void addBeforeDeleteListener(UserBeforeDeleteListener listener) |
{ |
beforeDeleteListeners.add(listener); |
163,6 → 208,16 |
beforeDeleteListeners.remove(listener); |
} |
public void addDeletedListener(UserDeletedListener listener) |
{ |
deletedListeners.add(listener); |
} |
public void removeDeletedListener(UserDeletedListener listener) |
{ |
deletedListeners.remove(listener); |
} |
public Collection beforeDelete(User editor, User user, Collection known) |
throws ModelException |
{ |
181,16 → 236,26 |
public void delete(User editor, User user) |
throws ModelException |
{ |
// chech rights |
if(!user.deleteableBy(editor)) |
throw new ModelSecurityException(); |
// backup copy |
User oldUser = new User(user); |
// delete it |
try { |
HibernateUtil.currentSession().delete(user); |
} |
catch(HibernateException ex) |
{ |
catch(HibernateException ex) { |
throw new ModelException(ex); |
} |
// inform listeners |
for(Iterator i = deletedListeners.iterator(); i.hasNext(); ) { |
UserDeletedListener listener = (UserDeletedListener)i.next(); |
listener.userDeleted(editor, oldUser); |
} |
} |
public Collection listUsers(User editor) |
207,8 → 272,7 |
new Type[] { Hibernate.entity(User.class), Hibernate.entity(User.class) } ); |
} |
} |
catch(HibernateException ex) |
{ |
catch(HibernateException ex) { |
throw new ModelException(ex); |
} |
} |
228,8 → 292,7 |
.next()).intValue() > 0; |
} |
} |
catch(HibernateException ex) |
{ |
catch(HibernateException ex) { |
throw new ModelException(ex); |
} |
} |
245,12 → 308,12 |
try { |
HibernateUtil.currentSession().saveOrUpdate(userLogin); |
} |
catch(HibernateException ex) |
{ |
catch(HibernateException ex) { |
throw new ModelException(ex); |
} |
if(success) { |
user = new User(user); // unbind the user from hibernate |
loggedinUsers.put(user, Boolean.TRUE); |
return user; |
} |
272,9 → 335,8 |
"from UserLogin where success = ?", |
Boolean.FALSE, Hibernate.BOOLEAN); |
} |
catch(HibernateException ex) |
{ |
throw new ModelException(ex); |
catch(HibernateException ex) { |
throw new ModelException(ex); |
} |
} |
288,8 → 350,7 |
"from User where boss = ?", |
user, Hibernate.entity(User.class) ); |
} |
catch(HibernateException ex) |
{ |
catch(HibernateException ex) { |
throw new ModelException(ex); |
} |
/hostadmiral/trunk/src/ak/hostadmiral/core/model/UserDeletedListener.java |
---|
0,0 → 1,20 |
package ak.hostadmiral.core.model; |
import java.util.Collection; |
import ak.hostadmiral.util.ModelException; |
public interface UserDeletedListener |
{ |
/** |
* called if some user is just deleted. |
* |
* @param editor who is doing the operation |
* @param user the user deleted |
* @throws ModelException in case of any *fatal* errors, |
* Note: throw it on fatal errors only, because database transaction |
* will be rolled back but any other UserDeletedListeners might be already called |
* and (possible) they will not restore their original state. |
*/ |
public void userDeleted(User editor, User user) |
throws ModelException; |
} |
/hostadmiral/trunk/src/ak/hostadmiral/core/model/UserCreatedListener.java |
---|
0,0 → 1,20 |
package ak.hostadmiral.core.model; |
import java.util.Collection; |
import ak.hostadmiral.util.ModelException; |
public interface UserCreatedListener |
{ |
/** |
* called if new user is just created. |
* |
* @param editor who is doing the operation |
* @param user the new user |
* @throws ModelException in case of any *fatal* errors, |
* Note: throw it on fatal errors only, because database transaction |
* will be rolled back but any other UserCreatedListeners might be already called |
* and (possible) they will not restore their original state. |
*/ |
public void userCreated(User editor, User user) |
throws ModelException; |
} |
/hostadmiral/trunk/src/ak/hostadmiral/core/model/User.java |
---|
2,6 → 2,7 |
import java.util.Collection; |
import java.util.Collections; |
import java.util.HashSet; |
import java.util.Locale; |
import java.util.StringTokenizer; |
22,11 → 23,37 |
private Boolean superuser; |
private Locale locale = Locale.getDefault(); |
private Collection loginHistory; |
private User origin; // save original object state before any changes |
protected User() |
{ |
} |
protected User(User origin) |
{ |
super(origin); |
this.login = origin.login; |
this.password = origin.password; |
this.boss = origin.boss; |
this.superuser = origin.superuser; |
this.locale = origin.locale; |
if(origin.loginHistory == null) |
this.loginHistory = null; |
else |
this.loginHistory = new HashSet(origin.loginHistory); |
} |
protected User getOrigin() |
{ |
return origin; |
} |
protected void backupMe() |
{ |
if(origin == null) |
origin = new User(this); |
} |
/** |
* |
* @hibernate.property |
47,6 → 74,10 |
if(!editableBy(editor)) |
throw new ModelSecurityException(); |
// FIXME: domain owner is allowed to change user login |
// with some patern only, e.g. user@domain.com |
backupMe(); |
this.login = login; |
} |
73,6 → 104,7 |
if(password == null) |
throw new NullPointerException("Null password"); |
backupMe(); |
this.password = Digest.encode(password); |
} |
106,9 → 138,10 |
public void setBoss(User editor, User boss) |
throws ModelException |
{ |
if(!editableBy(editor)) |
if(!mayChangeBoss(editor)) |
throw new ModelSecurityException(); |
backupMe(); |
this.boss = boss; |
} |
137,6 → 170,7 |
if(!mayChangeSuperuser(editor)) |
throw new ModelSecurityException(); |
backupMe(); |
this.superuser = superuser; |
} |
174,6 → 208,7 |
if(!partEditableBy(editor)) |
throw new ModelSecurityException(); |
backupMe(); |
setLocaleName(localeName); |
} |
188,6 → 223,7 |
if(!partEditableBy(editor)) |
throw new ModelSecurityException(); |
backupMe(); |
this.locale = locale; |
} |
272,6 → 308,11 |
return user.isSuperuser() || user.equals(boss) || user.equals(this); |
} |
public boolean mayChangeBoss(User user) |
{ |
return user.isSuperuser(); |
} |
public boolean mayChangeSuperuser(User user) |
{ |
return user.isSuperuser() && !user.equals(this); |
285,7 → 326,9 |
protected static boolean allowedToCreate(UserManager manager, User editor) |
throws ModelException |
{ |
return editor.isSuperuser(); |
return editor.isSuperuser() |
|| InetDomainManager.getInstance().areInetDomainsAvailable(editor); |
// FIXME: or allow any user to create "subusers"? |
} |
protected static User createLimitedCopy(User origin) |
294,4 → 337,9 |
u.setLogin(origin.getLogin()); |
return u; |
} |
public String toString() |
{ |
return getClass().getName() + " [" + getId() + "] [" + getLogin() + "]"; |
} |
} |
/hostadmiral/trunk/src/ak/hostadmiral/core/model/SystemUserManager.java |
---|
167,7 → 167,7 |
if(!systemUser.editableBy(editor)) |
throw new ModelSecurityException(); |
systemUser.setModUser(editor); |
//systemUser.setModUser(editor); // FIXME |
try { |
HibernateUtil.currentSession().saveOrUpdate(systemUser); |
/hostadmiral/trunk/src/ak/hostadmiral/core/model/InetDomainManager.java |
---|
128,7 → 128,7 |
if(!domain.editableBy(editor)) |
throw new ModelSecurityException(); |
domain.setModUser(editor); |
//domain.setModUser(editor); // FIXME |
try { |
HibernateUtil.currentSession().saveOrUpdate(domain); |
/hostadmiral/trunk/src/ak/hostadmiral/core/model/UserModifiedListener.java |
---|
0,0 → 1,21 |
package ak.hostadmiral.core.model; |
import java.util.Collection; |
import ak.hostadmiral.util.ModelException; |
public interface UserModifiedListener |
{ |
/** |
* called if some user is just changed. |
* |
* @param editor who is doing the operation |
* @param user the user in its new state |
* @param oldUser copy of user as it was before the operation |
* @throws ModelException in case of any *fatal* errors, |
* Note: throw it on fatal errors only, because database transaction |
* will be rolled back but any other UserCreatedListeners might be already called |
* and (possible) they will not restore their original state. |
*/ |
public void userModified(User editor, User user, User oldUser) |
throws ModelException; |
} |
/hostadmiral/trunk/src/ak/hostadmiral/core/model/GeneralModelObject.java |
---|
13,6 → 13,27 |
private Date modStamp; |
private User modUser; |
protected GeneralModelObject() |
{ |
} |
protected GeneralModelObject(GeneralModelObject origin) |
{ |
this.id = origin.id; |
this.enabled = origin.enabled; |
this.comment = origin.comment; |
this.modStamp = origin.modStamp; |
this.modUser = origin.modUser; |
} |
/** |
* @return true if the object is not yet saved in DB |
*/ |
public boolean isNew() |
{ |
return (id == null); |
} |
/** |
* |
* @hibernate.id generator-class="native" |
/hostadmiral/trunk/src/ak/hostadmiral/core/model/MailboxManager.java |
---|
137,7 → 137,7 |
if(!mailbox.editableBy(editor)) |
throw new ModelSecurityException(); |
mailbox.setModUser(editor); |
//mailbox.setModUser(editor); // FIXME |
try { |
HibernateUtil.currentSession().saveOrUpdate(mailbox); |
/hostadmiral/trunk/src/ak/hostadmiral/core/model/MailAliasManager.java |
---|
121,7 → 121,7 |
if(!mailAlias.editableBy(editor)) |
throw new ModelSecurityException(); |
mailAlias.setModUser(editor); |
//mailAlias.setModUser(editor); // FIXME |
try { |
HibernateUtil.currentSession().saveOrUpdate(mailAlias); |
/hostadmiral/trunk/src/ak/hostadmiral/core/servlet/ListenerRegistratorServlet.java |
---|
0,0 → 1,75 |
package ak.hostadmiral.core.servlet; |
import java.io.IOException; |
import javax.servlet.ServletRequest; |
import javax.servlet.ServletResponse; |
import javax.servlet.GenericServlet; |
import javax.servlet.ServletException; |
import org.apache.log4j.Logger; |
import ak.hostadmiral.core.model.*; |
public class ListenerRegistratorServlet |
extends GenericServlet |
{ |
private static final Logger logger = Logger.getLogger(ListenerRegistratorServlet.class); |
public void init() |
throws ServletException |
{ |
// users |
register("UserCreatedListener", new Registrar() { |
public void reg(Object o) { |
UserManager.getInstance().addCreatedListener((UserCreatedListener)o); |
} |
}); |
register("UserModifiedListener", new Registrar() { |
public void reg(Object o) { |
UserManager.getInstance().addModifiedListener((UserModifiedListener)o); |
} |
}); |
register("UserBeforeDeleteListener", new Registrar() { |
public void reg(Object o) { |
UserManager.getInstance().addBeforeDeleteListener((UserBeforeDeleteListener)o); |
} |
}); |
register("UserDeletedListener", new Registrar() { |
public void reg(Object o) { |
UserManager.getInstance().addDeletedListener((UserDeletedListener)o); |
} |
}); |
} |
private void register(String paramName, Registrar registrar) |
{ |
String param = getInitParameter(paramName); |
if(param == null) return; |
String[] names = param.split("\\s*;\\s*"); |
for(int i = 0; i < names.length; i++) { |
String name = names[i].trim(); |
if(name.equals("")) continue; |
try { |
Class c = Class.forName(name); |
registrar.reg(c.newInstance()); |
} |
catch(ClassCastException ex) { |
logger.error("class " + name + " has wrong type", ex); |
} |
catch(Exception ex) { |
logger.error("cannot get class " + name, ex); |
} |
} |
} |
public void service(ServletRequest req, ServletResponse res) |
throws ServletException, IOException |
{ |
} |
private interface Registrar |
{ |
public void reg(Object o); |
} |
} |
/hostadmiral/trunk/src/ak/hostadmiral/core/listener/dummy/UserModifiedDummyListener.java |
---|
0,0 → 1,16 |
package ak.hostadmiral.core.listener.dummy; |
import ak.hostadmiral.util.ModelException; |
import ak.hostadmiral.core.model.User; |
import ak.hostadmiral.core.model.UserModifiedListener; |
public class UserModifiedDummyListener |
implements UserModifiedListener |
{ |
public void userModified(User editor, User user, User oldUser) |
throws ModelException |
{ |
System.out.println("UserCreatedDummyListener.userModified: from " + oldUser |
+ " to " + user + " by " + editor); |
} |
} |
/hostadmiral/trunk/src/ak/hostadmiral/core/listener/dummy/UserDeletedDummyListener.java |
---|
0,0 → 1,16 |
package ak.hostadmiral.core.listener.dummy; |
import ak.hostadmiral.util.ModelException; |
import ak.hostadmiral.core.model.User; |
import ak.hostadmiral.core.model.UserDeletedListener; |
public class UserDeletedDummyListener |
implements UserDeletedListener |
{ |
public void userDeleted(User editor, User user) |
throws ModelException |
{ |
System.out.println("UserCreatedDummyListener.userDeleted: " |
+ user + " by " + editor); |
} |
} |
/hostadmiral/trunk/src/ak/hostadmiral/core/listener/dummy/UserCreatedDummyListener.java |
---|
0,0 → 1,16 |
package ak.hostadmiral.core.listener.dummy; |
import ak.hostadmiral.util.ModelException; |
import ak.hostadmiral.core.model.User; |
import ak.hostadmiral.core.model.UserCreatedListener; |
public class UserCreatedDummyListener |
implements UserCreatedListener |
{ |
public void userCreated(User editor, User user) |
throws ModelException |
{ |
System.out.println("UserCreatedDummyListener.userCreated: " |
+ user + " by " + editor); |
} |
} |
/hostadmiral/trunk/src/ak/hostadmiral/core/listener/file/UserCreatedFileListener.java |
---|
0,0 → 1,22 |
package ak.hostadmiral.core.listener.file; |
import ak.hostadmiral.util.ModelException; |
import ak.hostadmiral.core.model.User; |
import ak.hostadmiral.core.model.UserCreatedListener; |
import org.apache.log4j.Logger; |
public class UserCreatedFileListener |
implements UserCreatedListener |
{ |
private static final Logger logger = Logger.getLogger(UserCreatedFileListener.class); |
public void userCreated(User editor, User user) |
throws ModelException |
{ |
InterfaceFile.send("user\tcreate\t" + InterfaceFile.escape(user.getLogin()) + "\t" |
+ InterfaceFile.escape(/* FIXME user.getPassword() */ "") + "\t" |
+ user.getEnabled() + "\t" |
+ InterfaceFile.escape(user.getComment())); |
} |
} |
/hostadmiral/trunk/src/ak/hostadmiral/core/listener/file/InterfaceFile.java |
---|
0,0 → 1,68 |
package ak.hostadmiral.core.listener.file; |
import java.io.Writer; |
import java.io.BufferedWriter; |
import java.io.FileWriter; |
import ak.hostadmiral.util.ModelException; |
import ak.hostadmiral.core.model.User; |
import ak.hostadmiral.core.model.UserModifiedListener; |
import org.apache.log4j.Logger; |
public class InterfaceFile |
{ |
private static final Logger logger = Logger.getLogger(InterfaceFile.class); |
private static String fileName; |
protected static Object lock = new Object(); |
public static final String PROTOCOL_NAME = "HostAdmiral_FileInterface"; |
public static final String PROTOCOL_VERSION = "0.1"; |
public static String getFileName() |
{ |
return fileName; |
} |
public static void setFileName(String fileName_) |
{ |
fileName = fileName_; |
} |
protected static String escape(String s) |
{ |
// FIXME: any other problem characters? optimize it? |
s = s.replaceAll("\0", "\\\\0"); |
s = s.replaceAll("\\\\", "\\\\\\\\"); |
s = s.replaceAll("\t", "\\\\t"); |
s = s.replaceAll("\n", "\\\\n"); |
return s; |
} |
protected static void send(String message) |
throws ModelException |
{ |
synchronized(lock) { |
try { |
Writer out = new BufferedWriter(new FileWriter(fileName)); |
if(PROTOCOL_NAME != null) { |
out.write(PROTOCOL_NAME); |
out.write(" "); |
} |
if(PROTOCOL_VERSION != null) { |
out.write(PROTOCOL_VERSION); |
out.write("\n"); |
} |
out.write(message); |
out.write("\n\n"); |
out.close(); |
} |
catch(Exception ex) { |
logger.error("Cannot save message to file", ex); |
throw new ModelException("Cannot save message to file:" + ex.getMessage()); |
// FIMXE: or just throw "internal server error" message? |
} |
} |
} |
} |
/hostadmiral/trunk/src/ak/hostadmiral/core/listener/file/UserModifiedFileListener.java |
---|
0,0 → 1,23 |
package ak.hostadmiral.core.listener.file; |
import ak.hostadmiral.util.ModelException; |
import ak.hostadmiral.core.model.User; |
import ak.hostadmiral.core.model.UserModifiedListener; |
import org.apache.log4j.Logger; |
public class UserModifiedFileListener |
implements UserModifiedListener |
{ |
private static final Logger logger = Logger.getLogger(UserModifiedFileListener.class); |
public void userModified(User editor, User user, User oldUser) |
throws ModelException |
{ |
InterfaceFile.send("user\tmodify\t" + InterfaceFile.escape(oldUser.getLogin()) + "\t" |
+ InterfaceFile.escape(user.getLogin()) + "\t" |
+ InterfaceFile.escape(/* FIXME user.getPassword() */ "") + "\t" |
+ user.getEnabled() + "\t" |
+ InterfaceFile.escape(user.getComment())); |
} |
} |
/hostadmiral/trunk/src/ak/hostadmiral/core/listener/file/ConfigServlet.java |
---|
0,0 → 1,26 |
package ak.hostadmiral.core.listener.file; |
import java.io.IOException; |
import javax.servlet.ServletRequest; |
import javax.servlet.ServletResponse; |
import javax.servlet.GenericServlet; |
import javax.servlet.ServletException; |
import org.apache.log4j.Logger; |
public class ConfigServlet |
extends GenericServlet |
{ |
private static final Logger logger = Logger.getLogger(ConfigServlet.class); |
public void init() |
throws ServletException |
{ |
InterfaceFile.setFileName(getInitParameter("fileName")); |
} |
public void service(ServletRequest req, ServletResponse res) |
throws ServletException, IOException |
{ |
} |
} |
/hostadmiral/trunk/src/ak/hostadmiral/core/listener/file/UserDeletedFileListener.java |
---|
0,0 → 1,19 |
package ak.hostadmiral.core.listener.file; |
import ak.hostadmiral.util.ModelException; |
import ak.hostadmiral.core.model.User; |
import ak.hostadmiral.core.model.UserDeletedListener; |
import org.apache.log4j.Logger; |
public class UserDeletedFileListener |
implements UserDeletedListener |
{ |
private static final Logger logger = Logger.getLogger(UserCreatedFileListener.class); |
public void userDeleted(User editor, User user) |
throws ModelException |
{ |
InterfaceFile.send("user\tdelete\t" + InterfaceFile.escape(user.getLogin())); |
} |
} |
/hostadmiral/trunk/src/ak/hostadmiral/core/action/MailAliasAction.java |
---|
147,6 → 147,21 |
throw new UserException("ak.hostadmiral.core.mail.alias.edit.owner.wrong"); |
} |
alias.setDomain(user, InetDomainManager.getInstance().get(user, |
StringConverter.parseLong(theForm.get("domain")))); |
String address = (String)theForm.get("address"); |
if(MailAliasManager.getInstance().addressExists(user, alias, address)) { |
handleErrors(mapping, form, request, response); |
throw new UserException(CoreResources.NONUNIQUE_MAIL_ALIAS_ADDRESS); |
} |
alias.setAddress(user, address); |
alias.setOwner(user, UserManager.getInstance().get(user, |
StringConverter.parseLong(theForm.get("owner")))); |
alias.setEnabled(user, (Boolean)theForm.get("enabled")); |
alias.setComment(user, (String)theForm.get("comment")); |
alias.getDestinations(user).clear(); |
for(int i = 0; i < dests.length; i++) { |
// FIXME: validate dest id, mailbox id, email |
183,21 → 198,6 |
dest.setComment(user, dests[i].getComment()); |
} |
alias.setDomain(user, InetDomainManager.getInstance().get(user, |
StringConverter.parseLong(theForm.get("domain")))); |
String address = (String)theForm.get("address"); |
if(MailAliasManager.getInstance().addressExists(user, alias, address)) { |
handleErrors(mapping, form, request, response); |
throw new UserException(CoreResources.NONUNIQUE_MAIL_ALIAS_ADDRESS); |
} |
alias.setAddress(user, address); |
alias.setOwner(user, UserManager.getInstance().get(user, |
StringConverter.parseLong(theForm.get("owner")))); |
alias.setEnabled(user, (Boolean)theForm.get("enabled")); |
alias.setComment(user, (String)theForm.get("comment")); |
// update alias |
MailAliasManager.getInstance().save(user, alias); |
/hostadmiral/trunk/src/ak/hostadmiral/core/action/UserAction.java |
---|
69,6 → 69,9 |
List list = new ArrayList(UserManager.getInstance().listUsers(user)); |
Collections.sort(list, UserManager.LOGIN_COMPARATOR); |
request.setAttribute("users", list); |
request.setAttribute("allowedToCreate", |
Boolean.valueOf(UserManager.getInstance().allowedToCreate(user))); |
request.setAttribute("mayViewAllLogins", Boolean.valueOf(user.mayViewAllLogins())); |
return mapping.findForward("default"); |
} |
169,13 → 172,15 |
} |
u.setLogin(user, login); |
if(u.editableBy(user)) { |
if(u.mayChangeBoss(user)) { |
Long bossId = StringConverter.parseLong(theForm.get("boss")); |
if(bossId == null) |
u.setBoss(user, null); |
else |
u.setBoss(user, UserManager.getInstance().get(user, bossId)); |
} |
if(u.editableBy(user)) { |
u.setLocaleName(user, (String)theForm.get("locale")); |
u.setEnabled(user, (Boolean)theForm.get("enabled")); |
u.setComment(user, (String)theForm.get("comment")); |
/hostadmiral/trunk/build.xml |
---|
64,6 → 64,7 |
> |
<fileset dir="src"> |
<include name="**/*.java" /> |
<exclude name="ak/hostadmiral/core/servlet/*.java" /> |
</fileset> |
<hibernate version="2.0" /> |
</hibernatedoclet> |
/hostadmiral/trunk/webapp/mail/box/edit.jsp |
---|
1,4 → 1,4 |
<%@ page contentType="text/html;charset=UTF-8" language="java" %> |
<%@ page contentType="text/html;charset=UTF-8" language="java" %> |
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %> |
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %> |
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %> |
38,9 → 38,6 |
<td><html:text property="login" /></td> |
</tr> |
<tr> |
<td colspan=2>FIXME: checkbox to get password from owner</td> |
</tr> |
<tr> |
<th><bean:message key="ak.hostadmiral.page.mail.box.edit.password" /></th> |
<td><html:password property="password" redisplay="false" /></td> |
</tr> |
99,6 → 96,12 |
</tr> |
</table> |
<p>FIXME: checkbox to create a mail alias if new mailbox is created</p> |
<p>FIXME: special case: by editing a mailbox which login is the same |
as its user and/or mail alias allow to change all them at once. Do the for |
user/mail alias edit pages too?</p> |
<p>FIXME: checkbox to get password from owner</p> |
</html:form> |
</body> |
/hostadmiral/trunk/webapp/deleting.jsp |
---|
1,4 → 1,4 |
<%@ page contentType="text/html;charset=UTF-8" language="java" %> |
<%@ page contentType="text/html;charset=UTF-8" language="java" %> |
<%@ page import="java.util.*,ak.hostadmiral.core.model.*" %> |
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %> |
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %> |
10,17 → 10,18 |
<head> |
<meta http-equiv="expires" content="0"> |
<title><bean:message key="ak.hostadmiral.page.index.title" /></title> |
<title><bean:message key="ak.hostadmiral.page.deleting.title" /></title> |
<link rel="stylesheet" type="text/css" href="<strutsx:root />/style/general.css"> |
</head> |
<body> |
<h1><bean:message key="ak.hostadmiral.page.index.title" /></h1> |
<h1><bean:message key="ak.hostadmiral.page.deleting.title" /></h1> |
<p>Object: <bean:write name="object" property="identKey" /></p> |
<p>Object: <bean:write name="object" property="identKey" /> <bean:write name="object" property="id" /></p> |
<p>Action: <bean:write name="action" /></p> |
<p>FIXME: draw a real object tree here</p> |
<ul> |
<% |
Collection cascade = (Collection)request.getAttribute("cascade"); |
48,7 → 49,8 |
</ul> |
<br> |
<backpath:backlink><bean:message key="ak.hostadmiral.page.user.list.back" /></backpath:backlink> |
<backpath:currentlink action="<%= (String)request.getAttribute("action") %>" paramId="id" paramName="object" paramProperty="id"><bean:message key="ak.hostadmiral.page.deleting.delete" /></backpath:currentlink> |
<backpath:backlink><bean:message key="ak.hostadmiral.page.deleting.back" /></backpath:backlink> |
</body> |
/hostadmiral/trunk/webapp/WEB-INF/lib/hibernate2.jar |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/hostadmiral/trunk/webapp/WEB-INF/lib/backpath.jar |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/hostadmiral/trunk/webapp/WEB-INF/ak-backpath.tld |
---|
1,4 → 1,4 |
<?xml version="1.0" encoding="UTF-8"?> |
<?xml version="1.0" encoding="UTF-8"?> |
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd"> |
<taglib> |
<tlibversion>1.0</tlibversion> |
208,6 → 208,210 |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>onclick</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>ondblclick</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>onfocus</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>onkeydown</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>onkeypress</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>onkeyup</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>onmousedown</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>onmousemove</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>onmouseout</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>onmouseover</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>onmouseup</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>page</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>paramId</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>paramName</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>paramProperty</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>paramScope</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>property</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>scope</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>style</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>styleClass</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>styleId</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>tabindex</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>target</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>title</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>titleKey</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>transaction</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>backPathKey</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>backPathParam</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>backPathIgnore</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>zip</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
</tag> |
<tag> |
<name>currentlink</name> |
<tagclass>ak.backpath.taglib.CurrentLinkTag</tagclass> |
<attribute> |
<name>accesskey</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>action</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>anchor</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>forward</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>href</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>indexed</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>indexId</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>linkName</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>name</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>onblur</name> |
<required>false</required> |
<rtexprvalue>true</rtexprvalue> |
</attribute> |
<attribute> |
<name>onclick</name> |
<required>false</required> |
/hostadmiral/trunk/webapp/WEB-INF/web.xml |
---|
78,6 → 78,41 |
<load-on-startup>2</load-on-startup> |
</servlet> |
<servlet> |
<servlet-name>ListenerRegistratorServlet</servlet-name> |
<servlet-class>ak.hostadmiral.core.servlet.ListenerRegistratorServlet</servlet-class> |
<init-param> |
<param-name>UserCreatedListener</param-name> |
<param-value> |
ak.hostadmiral.core.listener.dummy.UserCreatedDummyListener; |
ak.hostadmiral.core.listener.file.UserCreatedFileListener; |
</param-value> |
</init-param> |
<init-param> |
<param-name>UserModifiedListener</param-name> |
<param-value> |
ak.hostadmiral.core.listener.dummy.UserModifiedDummyListener; |
ak.hostadmiral.core.listener.file.UserModifiedFileListener; |
</param-value> |
</init-param> |
<init-param> |
<param-name>UserDeletedListener</param-name> |
<param-value> |
ak.hostadmiral.core.listener.dummy.UserDeletedDummyListener; |
ak.hostadmiral.core.listener.file.UserDeletedFileListener; |
</param-value> |
</init-param> |
<load-on-startup>1</load-on-startup> |
</servlet> |
<servlet> |
<servlet-name>ConfigServlet</servlet-name> |
<servlet-class>ak.hostadmiral.core.listener.file.ConfigServlet</servlet-class> |
<init-param> |
<param-name>fileName</param-name> |
<param-value>/tmp/hostadmiral</param-value> |
</init-param> |
<load-on-startup>2</load-on-startup> |
</servlet> |
<!-- Standard Action Servlet Mapping --> |
<servlet-mapping> |
/hostadmiral/trunk/webapp/user/edit.jsp |
---|
1,4 → 1,4 |
<%@ page contentType="text/html;charset=UTF-8" language="java" %> |
<%@ page contentType="text/html;charset=UTF-8" language="java" %> |
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %> |
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %> |
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %> |
48,10 → 48,15 |
<tr> |
<th><bean:message key="ak.hostadmiral.page.user.edit.boss" /></th> |
<td> |
<html:select property="boss"> |
<html:option value="" key="ak.hostadmiral.page.user.edit.boss.empty"/> |
<core:options collection="users" property="id" /> |
</html:select> |
<core:rights name="u" method="mayChangeBoss"> |
<html:select property="boss"> |
<html:option value="" key="ak.hostadmiral.page.user.edit.boss.empty"/> |
<core:options collection="users" property="id" /> |
</html:select> |
</core:rights> |
<core:noRights name="u" method="mayChangeBoss"> |
<bean:write name="u" property="boss.login" /> |
</core:noRights> |
</td> |
</tr> |
<tr> |
/hostadmiral/trunk/webapp/user/list.jsp |
---|
1,4 → 1,4 |
<%@ page contentType="text/html;charset=UTF-8" language="java" %> |
<%@ page contentType="text/html;charset=UTF-8" language="java" %> |
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %> |
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %> |
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %> |
87,10 → 87,14 |
</logic:iterate> |
</table> |
<backpath:link action="/user/edit"><bean:message key="ak.hostadmiral.page.user.list.add" /></backpath:link> |
<br> |
<backpath:link action="/user/failedLogins"><bean:message key="ak.hostadmiral.page.user.list.logins.failed" /></backpath:link> |
<br> |
<logic:equal name="allowedToCreate" value="true"> |
<backpath:link action="/user/edit"><bean:message key="ak.hostadmiral.page.user.list.add" /></backpath:link> |
<br> |
</logic:equal> |
<logic:equal name="mayViewAllLogins" value="true"> |
<backpath:link action="/user/failedLogins"><bean:message key="ak.hostadmiral.page.user.list.logins.failed" /></backpath:link> |
<br> |
</logic:equal> |
<backpath:backlink><bean:message key="ak.hostadmiral.page.user.list.back" /></backpath:backlink> |
</body> |
/hostadmiral/trunk/sql/00.tables.sql |
---|
1,7 → 1,7 |
-- |
-- hostadmiral sql tables |
-- |
-- FIXME: which values has boolean in hibernate - '1':' ' or '1':'0'? |
-- FIXME: which values has boolean in hibernate - '1':'0' or '1':'0'? |
create sequence hibernate_sequence; |
17,9 → 17,9 |
login varchar(255) not null, |
password varchar(255) not null, |
boss integer, |
superuser char(1) default ' ' check (superuser = '1' or superuser = ' '), |
superuser char(1) default '0' check (superuser = '1' or superuser = '0'), |
locale varchar(5) default 'en', -- language_country |
enabled char(1) default '1' check (enabled = '1' or enabled = ' '), |
enabled char(1) default '1' check (enabled = '1' or enabled = '0'), |
comment text, |
mod_stamp timestamp, |
mod_user integer, |
54,7 → 54,7 |
uid integer not null, |
name varchar(255) not null, |
owner integer, |
enabled char(1) default '1' check (enabled = '1' or enabled = ' '), |
enabled char(1) default '1' check (enabled = '1' or enabled = '0'), |
comment text, |
mod_stamp timestamp, |
mod_user integer, |
70,7 → 70,7 |
id integer not null, |
name varchar(255) not null, |
owner integer not null, |
enabled char(1) default '1' check (enabled = '1' or enabled = ' '), |
enabled char(1) default '1' check (enabled = '1' or enabled = '0'), |
comment text, |
mod_stamp timestamp, |
mod_user integer, |
89,10 → 89,10 |
password varchar(255), -- if null, then owner's password is used |
domain integer not null, |
owner integer not null, |
virusCheck char(1) default '1' check (virusCheck = '1' or virusCheck = ' '), |
spamCheck char(1) default '1' check (spamCheck = '1' or spamCheck = ' '), |
virusCheck char(1) default '1' check (virusCheck = '1' or virusCheck = '0'), |
spamCheck char(1) default '1' check (spamCheck = '1' or spamCheck = '0'), |
systemuser integer, |
enabled char(1) default '1' check (enabled = '1' or enabled = ' '), |
enabled char(1) default '1' check (enabled = '1' or enabled = '0'), |
comment text, |
mod_stamp timestamp, |
mod_user integer, |
111,7 → 111,7 |
address varchar(255) not null, |
domain integer not null, |
owner integer not null, |
enabled char(1) default '1' check (enabled = '1' or enabled = ' '), |
enabled char(1) default '1' check (enabled = '1' or enabled = '0'), |
comment text, |
mod_stamp timestamp, |
mod_user integer, |
128,7 → 128,7 |
alias integer not null, |
mailbox integer, |
email varchar(255), |
enabled char(1) default '1' check (enabled = '1' or enabled = ' '), |
enabled char(1) default '1' check (enabled = '1' or enabled = '0'), |
comment text, |
mod_stamp timestamp, |
mod_user integer, |