/* ======================= ADMINISTRATE ======================= */ #include "admin.docs" session Administrate() { protected shared string password; int id, no_cut, no_paste; string action; bool cut; /* --------------------- ADMIN LOGIN -------------------------- */ void updateAdminPassword() { bool done; string pass1, pass2; while (!done) { show UpdatePasswordDoc receive [pass1 = pass1, pass2 = pass2, action = continue]; if (action=="CANCEL") { done = true; show MsgDoc <[title = "Password Update Cancelled", msg = "Password not updated"]; } else { if (pass1!=pass2) { show MsgDoc <[title = "Passwords Not Equal", msg = "The two passwords are not equal as they should be"]; } else { done = true; writer(password) password = pass1; show MsgDoc <[title = "Password Updated", msg = "Your password has been updated"]; } } } } void adminLogin() { bool done; string pass, passwd; reader (password) passwd = password; if (passwd=="") updateAdminPassword(); // first time. while (pass!=passwd) { show AdminLoginDoc receive [pass = pass, action = continue]; if (pass!=passwd) show MsgDoc <[title = "Incorrect Password", msg = "Please try again..."]; } if (action=="CHANGE") { updateAdminPassword(); } } /* --------------------- SHOW USERS --------------------------- */ void showUsers() { int i; html H; string action; vector string del; relation User U; vector User V; relation MsgPrefs M; while (action!="BACK") { H = DeleteUserDoc; reader (users) V = sort((vector User) users; login); for (i=0; i<|V|; i++) H = H <[users = UserDoc <[login_id = V[i].login, login = V[i].login, name = V[i].name, mailto = "mailto:" + V[i].email, email = V[i].email, notify = V[i].notify, filter = V[i].filter, grayout = V[i].grayout, filter_days = V[i].filter_days, custom_filter = V[i].custom_filter, logout_time = V[i].logout_time, navbar = V[i].navbar, indent = V[i].indent, ampm = V[i].ampm, gmtoffset = V[i].gmtoffset, no_login = V[i].no_login]]; show H <[no_users = |V|] receive [del = del, action = continue]; if (action=="DELETE") { writer (users) { U = users; for (i=0; i<|del|; i++) { U = Select * from U where #.login!=del[i]; } users = U; } writer (collapse) { M = collapse; for (i=0; i<|del|; i++) { M = Select * from M where #.user_login!=del[i]; } collapse = M; } writer (has_read) { M = has_read; for (i=0; i<|del|; i++) { M = Select * from M where #.user_login!=del[i]; } has_read = M; } } } } /* --------------------- CUT'N'PASTE -------------------------- */ shared relation Message cutpaste, source, target; /* protected through `board' */ shared int cutpaste_id; /* protected through `board' */ void moveMessage(int id) { /* Moves message `id' (and offsprings) from `source' to `target' */ int i; tuple Message message; vector Message children; target = Union(target, Select * from source where #.id==id); // add `id' to target; source = Select * from source where #.id!=id; // delete `id' from source; /* find and move children recursively */ children = (vector Message) getChildren(source,id); for(i=0; i<|children|; i++) { moveMessage(children[i].id); } } void cutMessage(int id) { source = board; target = relation {}; moveMessage(id); board = source; cutpaste = factor (target) { if (#.id==id) return # << tuple { reply_to = 0 }; else return #; }; cutpaste_id = id; } void pasteMessage(int id) { source = factor (cutpaste) { if (#.id==cutpaste_id) return # << tuple { reply_to = id }; else return #; }; target = board; moveMessage(cutpaste_id); board = target; cutpaste = relation {}; cutpaste_id = 0; } /* -------------------- VIEW ADMIN BOARD ---------------------- */ html makeAdminBoard() { relation Message B, C; relation MsgPrefs empty; reader (board) { B = board; C = cutpaste; } return AdminShowBoardDoc <[no_msgs = |B|, msgs = makeBoardRec(0,0,B,empty,empty), no_cutpaste_msgs = |C|, cutpaste = makeBoardRec(0,0,C,empty,empty)]; } adminLogin(); user.indent = DEFAULT_INDENT; while (action!="QUIT") { show makeAdminBoard() receive [action = continue, cut = cut]; switch (action) { case "EMPTY": writer (board) { cutpaste = relation {}; cutpaste_id = 0; } break; case "USERS": showUsers(); break; default: if (match(action, Number)[]) { tuple Message m; id = (int) action; reader(board) m = getMessage(board,id); if (id==m.id) { // only if msg is `root' (zero) or msg exists in board if (cut) { /* move `id' from `board' into `cutpaste' */ writer (board) cutMessage(id); no_cut++; } else { /* move `cutpaste' onto `board' */ writer (board) pasteMessage(id); no_paste++; } } } break; } } exit AdminByeByeDoc <[no_cut = no_cut, no_paste = no_paste]; }