diff --git a/modules/bibcatalog/lib/Makefile.am b/modules/bibcatalog/lib/Makefile.am index f40adacaa..45f222fd9 100644 --- a/modules/bibcatalog/lib/Makefile.am +++ b/modules/bibcatalog/lib/Makefile.am @@ -1,24 +1,24 @@ ## This file is part of CDS Invenio. ## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 CERN. ## ## CDS Invenio is free software; you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation; either version 2 of the ## License, or (at your option) any later version. ## ## CDS Invenio is distributed in the hope that it will be useful, but ## WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with CDS Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. pylibdir = $(libdir)/python/invenio -pylib_DATA = bibcatalog.py bibcatalog_system.py bibcatalog_system_rt.py +pylib_DATA = bibcatalog.py bibcatalog_templates.py bibcatalog_system.py bibcatalog_system_rt.py EXTRA_DIST = $(pylib_DATA) CLEANFILES = *~ *.tmp *.pyc diff --git a/modules/bibcatalog/lib/bibcatalog_system.py b/modules/bibcatalog/lib/bibcatalog_system.py index 64ed93cb2..daef43045 100644 --- a/modules/bibcatalog/lib/bibcatalog_system.py +++ b/modules/bibcatalog/lib/bibcatalog_system.py @@ -1,156 +1,156 @@ # -*- coding: utf-8 -*- ## ## This file is part of CDS Invenio. ## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 CERN. ## ## CDS Invenio is free software; you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation; either version 2 of the ## License, or (at your option) any later version. ## ## CDS Invenio is distributed in the hope that it will be useful, but ## WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with CDS Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. """ Provide a "ticket" interface with a request tracker. Please see the help/hacking/bibcatalog-api page for details. This is a base class that cannot be instantiated. """ from invenio.webuser import get_user_preferences class BibCatalogSystem: """ A template class for ticket support.""" TICKET_ATTRIBUTES = ['ticketid', 'priority', 'recordid', 'subject', 'text', 'creator', 'owner', 'date', 'status', 'queue', 'url_display', 'url_modify', 'url_close'] def check_system(self, uid): """Check connectivity. Return a string describing the error or an empty str @param uid: invenio user id @type uid: number @return: empty string on success. Otherwise a string describing error. @rtype: string """ return "this class cannot be instantiated" def ticket_search(self, uid, recordid=-1, subject="", text="", creator="", owner="", \ date_from="", date_until="", status="", priority=""): """Search for tickets based on various criteria. Return an array of ticket numbers @param uid: invenio user id. @type uid: number @param recordid: search criteria - ticket contains this record id. @type recordid: number @param subject: search criteria - ticket has this subject (substr). @type subject: string @param text: search criteria - ticket has this text in body (substr). @type text: string @param creator: search criteria - ticket creator's id. @type creator: number @param owner: search criteria - ticket owner's id. @type owner: number @param date_from: search criteria - ticket created starting from this date. Example: '2009-01-24' @type date_until: date in yyyy-mm-dd format @param date_until: search criteria - ticket created until from this date. Example: '2009-01-24' @type date_from: date in yyyy-mm-dd format @param status: search criteria - ticket has this status. Example: 'resolved'. @type status: string @param priority: search criteria - ticket priority number. @type priority: number. """ pass def ticket_submit(self, uid, subject, recordid, text="", queue="", priority="", owner=""): """submit a ticket. Return ticket number on success, otherwise None @param uid: invenio user id @type uid: number @param subject: set this as the ticket's subject. @type subject: string @param recordid: ticket concerns this record. @type recordid: number @param text: ticket body. @type text: string @param queue: the queue for this ticket (if supported). @type queue: string @param priority: ticket priority. @type priority: number @param owner: set ticket owner to this uid. @type owner: number @return: new ticket id or None """ pass def ticket_assign(self, uid, ticketid, to_user): """assign a ticket to a user. Return 1 on success @param uid: invenio user id @type uid: number @param ticketid: ticket id @type ticketid: number @param to_user: assign ticket to this user @type to_user: number @return: 1 on success, 0 otherwise @rtype: number """ pass def ticket_set_attribute(self, uid, ticketid, attribute, new_value): """set an attribute of a ticket. Return 1 on success @param uid: invenio user id @type uid: number @param ticketid: ticket id @type ticketid: number @param attribute: This is a member of TICKET_ATTRIBUTES. @type attribute: string @param new_value: new value for this attribute. @type new_value: string @return: 1 on success, 0 otherwise @rtype: number """ pass - def ticket_get_attribute(self, uid, ticketid, attrname): + def ticket_get_attribute(self, uid, ticketid, attribute): """return an attribute @param uid: invenio user id @type uid: number @param ticketid: ticket id @type ticketid: number - @param attrname: attribute name. - @type attrname: string + @param attribute: attribute name. + @type attribute: string @return: the value of the attribute, or None if the ticket or attribute does not exist @rtype: string """ pass - def ticket_get_info(self, uid, ticketid, attrlist = None): + def ticket_get_info(self, uid, ticketid, attributes = None): """Return the attributes of a ticket as a dictionary whose fields are TICKET_ATTRIBUTES. @param uid: user id @type uid: number @param ticketid: ticket id @type ticketid: number - @param attrlist: a list of attributes, each in TICKET_ATTRIBUTES. - @type attrlist: list + @param attributes: a list of attributes, each in TICKET_ATTRIBUTES. + @type attributes: list @return: dictionary whose fields are TICKET_ATTRIBUTES @rtype: dictionary """ pass def get_bibcat_from_prefs(uid): """gets username and pw from user prefs as a tuple. if not successfull, returns None @param uid: user id @type uid: number @return: ('bibcatalog_username', 'bibcatalog_password') @rtype: tuple """ user_pref = get_user_preferences(uid) if not user_pref.has_key('bibcatalog_username'): return (None, None) if not user_pref.has_key('bibcatalog_password'): return (None, None) return (user_pref['bibcatalog_username'], user_pref['bibcatalog_password']) diff --git a/modules/bibcatalog/lib/bibcatalog_system_rt.py b/modules/bibcatalog/lib/bibcatalog_system_rt.py index fa23b34dc..f918db704 100644 --- a/modules/bibcatalog/lib/bibcatalog_system_rt.py +++ b/modules/bibcatalog/lib/bibcatalog_system_rt.py @@ -1,374 +1,374 @@ # -*- coding: utf-8 -*- ## ## This file is part of CDS Invenio. ## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 CERN. ## ## CDS Invenio is free software; you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation; either version 2 of the ## License, or (at your option) any later version. ## ## CDS Invenio is distributed in the hope that it will be useful, but ## WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with CDS Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. """ Provide a "ticket" interface with a request tracker. This is a subclass of BibCatalogSystem """ import os import os.path import invenio.webuser from invenio.shellutils import run_shell_command, escape_shell_arg from invenio.bibcatalog_system import BibCatalogSystem, get_bibcat_from_prefs from invenio.config import CFG_BIBCATALOG_SYSTEM, \ CFG_BIBCATALOG_SYSTEM_RT_CLI, \ CFG_BIBCATALOG_SYSTEM_RT_URL, \ CFG_BIBCATALOG_SYSTEM_RT_URL, \ CFG_BIBCATALOG_QUEUES class BibCatalogSystemRT(BibCatalogSystem): BIBCATALOG_RT_SERVER = "" #construct this by http://user:password@RT_URL def check_system(self, uid): """return an error string if there are problems""" user_pref = invenio.webuser.get_user_preferences(uid) if not user_pref.has_key('bibcatalog_username'): return "user " + str(uid) + " has no bibcatalog_username" rtuid = user_pref['bibcatalog_username'] if not user_pref.has_key('bibcatalog_password'): return "user " + str(uid) + " has no bibcatalog_password" rtpw = user_pref['bibcatalog_password'] if not CFG_BIBCATALOG_SYSTEM == 'RT': return "CFG_BIBCATALOG_SYSTEM is not RT though this is an RT module" if not CFG_BIBCATALOG_SYSTEM_RT_CLI: return "CFG_BIBCATALOG_SYSTEM_RT_CLI not defined or empty" if not os.path.exists(CFG_BIBCATALOG_SYSTEM_RT_CLI): return "CFG_BIBCATALOG_SYSTEM_RT_CLI " + CFG_BIBCATALOG_SYSTEM_RT_CLI + " file does not exists" #check that you can execute it.. this is a safe call unless someone can fake CFG_BIBCATALOG_SYSTEM_RT_CLI (unlikely) dummy, myout, myerr = run_shell_command(CFG_BIBCATALOG_SYSTEM_RT_CLI + " help") helpfound = False if myerr.count("help") > 0: helpfound = True if not helpfound: return "Execution of CFG_BIBCATALOG_SYSTEM_RT_CLI " + CFG_BIBCATALOG_SYSTEM_RT_CLI + " help did not produce output 'help'" if not CFG_BIBCATALOG_SYSTEM_RT_URL: return "CFG_BIBCATALOG_SYSTEM_RT_URL not defined or empty" #construct.. split RT_URL at // if CFG_BIBCATALOG_SYSTEM_RT_URL.count("http://") == 0: return "CFG_BIBCATALOG__SYSTEM_RT_URL does not start with 'http://'" httppart, siteandpath = CFG_BIBCATALOG_SYSTEM_RT_URL.split("//") BIBCATALOG_RT_SERVER = httppart + "//" + rtuid + ":" + rtpw + "@" + siteandpath #set as env var os.environ["RTUSER"] = rtuid os.environ["RTSERVER"] = BIBCATALOG_RT_SERVER #try to talk to RT server #this is a safe call since rtpw is the only variable in it, and it is escaped rtpw = escape_shell_arg(rtpw) dummy, myout, myerr = run_shell_command("echo "+rtpw+" | " + CFG_BIBCATALOG_SYSTEM_RT_CLI + " ls \"Subject like 'F00'\"") if len(myerr) > 0: return "could not connect to " + BIBCATALOG_RT_SERVER + " " + myerr #finally, check that there is some sane output like tickets or 'No matching result' saneoutput = (myout.count('matching') > 0) or (myout.count('1') > 0) if not saneoutput: return CFG_BIBCATALOG_SYSTEM_RT_CLI + " returned " + myout + " instead of 'matching' or '1'" if not CFG_BIBCATALOG_QUEUES: return "CFG_BIBCATALOG_QUEUES not defined or empty" (username, dummy) = get_bibcat_from_prefs(uid) if (username is None): return "Cannot find user preference bibcatalog_username for uid "+str(uid) return "" def ticket_search(self, uid, recordid=-1, subject="", text="", creator="", owner="", \ date_from="", date_until="", status="", priority=""): """returns a list of ticket ID's related to this record or by matching the subject, creator or owner of the ticket.""" search_atoms = [] #the search expression will be made by and'ing these if (recordid > -1): #search by recid search_atoms.append("CF.{RecordID} = " + escape_shell_arg(str(recordid))) if (len(subject) > 0): #search by subject search_atoms.append("Subject like " + escape_shell_arg(str(subject))) if (len(text) > 0): search_atoms.append("Content like " + escape_shell_arg(str(text))) if (len(str(creator)) > 0): #search for this person's bibcatalog_username in preferences creatorprefs = invenio.webuser.get_user_preferences(creator) creator = "Nobody can Have This Kind of Name" if creatorprefs.has_key("bibcatalog_username"): creator = creatorprefs["bibcatalog_username"] search_atoms.append("Creator = " + escape_shell_arg(str(creator))) if (len(str(owner)) > 0): ownerprefs = invenio.webuser.get_user_preferences(owner) owner = "Nobody can Have This Kind of Name" if ownerprefs.has_key("bibcatalog_username"): owner = ownerprefs["bibcatalog_username"] search_atoms.append("Owner = " + escape_shell_arg(str(owner))) if (len(date_from) > 0): search_atoms.append("Created >= " + escape_shell_arg(str(date_from))) if (len(date_until) > 0): search_atoms.append("Created <= " + escape_shell_arg(str(date_until))) if (len(str(status)) > 0) and (type(status) == type("this is a string")): search_atoms.append("Status = " + escape_shell_arg(str(status))) if (len(str(priority)) > 0): #try to convert to int intpri = -1 try: intpri = int(priority) except: pass if (intpri > -1): search_atoms.append("Priority = " + str(intpri)) searchexp = " and ".join(search_atoms) tickets = [] if not CFG_BIBCATALOG_SYSTEM_RT_URL: return tickets httppart, siteandpath = CFG_BIBCATALOG_SYSTEM_RT_URL.split("//") (username, passwd) = get_bibcat_from_prefs(uid) BIBCATALOG_RT_SERVER = httppart + "//" + username + ":" + passwd + "@" + siteandpath #set as env var os.environ["RTUSER"] = username os.environ["RTSERVER"] = BIBCATALOG_RT_SERVER #search.. if len(searchexp) == 0: #just make an expression that is true for all tickets searchexp = "Created > '1900-01-01'" passwd = escape_shell_arg(passwd) #make a call. This is safe since passwd and all variables in searchexp have been escaped. dummy, myout, dummyerr = run_shell_command("echo "+passwd+" | " + CFG_BIBCATALOG_SYSTEM_RT_CLI + " ls -l \"" + searchexp + "\"") statuses = [] for line in myout.split("\n"): #if there are matching lines they will look like NUM:subj.. so pick num if (line.count('id: ticket/') > 0): dummy, tnum = line.split('/') #get the ticket id try: inum = int(tnum) tickets.append(tnum) except: pass if (line.count('Status: ') > 0): dummy, tstatus = line.split('Status: ') statuses.append(tstatus) if (type(status) == type([])): #take only those tickets whose status matches with one of the status list alltickets = tickets tickets = [] for i in range(len(alltickets)): tstatus = statuses[i] tnum = alltickets[i] if (status.count(tstatus) > 0): #match tickets.append(tnum) return tickets def ticket_submit(self, uid, subject, recordid, text="", queue="", priority="", owner=""): """creates a ticket. return ticket num on success, otherwise None""" if not CFG_BIBCATALOG_SYSTEM_RT_URL: return None (username, passwd) = get_bibcat_from_prefs(uid) httppart, siteandpath = CFG_BIBCATALOG_SYSTEM_RT_URL.split("//") BIBCATALOG_RT_SERVER = httppart + "//" + username + ":" + passwd + "@" + siteandpath #set as env var os.environ["RTUSER"] = username os.environ["RTSERVER"] = BIBCATALOG_RT_SERVER queueset = "" textset = "" priorityset = "" ownerset = "" subjectset = "" if subject: subjectset = " subject=" + escape_shell_arg(subject) recidset = " CF-RecordID=" + escape_shell_arg(str(recordid)) if text: textset = " text=" + escape_shell_arg(text) if priority: priorityset = " priority=" + escape_shell_arg(str(priority)) if queue: queueset = " queue=" + escape_shell_arg(queue) if owner: #get the owner name from prefs ownerprefs = invenio.webuser.get_user_preferences(owner) if ownerprefs.has_key("bibcatalog_username"): owner = ownerprefs["bibcatalog_username"] ownerset = " owner=" + escape_shell_arg(owner) #make a command.. note that all set 'set' parts have been escaped command = CFG_BIBCATALOG_SYSTEM_RT_CLI + " create -t ticket set " + subjectset + recidset + \ queueset + textset + priorityset + ownerset passwd = escape_shell_arg(passwd) #make a call.. passwd and command have been escaped (see above) dummy, myout, dummyerr = run_shell_command("echo "+passwd+" | " + command) inum = -1 for line in myout.split("\n"): if line.count(' ') > 0: stuff = line.split(' ') try: inum = int(stuff[2]) except: pass if inum > 0: return inum return None def ticket_assign(self, uid, ticketid, to_user): """assign a ticket to an RT user. Returns 1 on success, 0 on failure""" return self.ticket_set_attribute(uid, ticketid, 'owner', to_user) def ticket_set_attribute(self, uid, ticketid, attribute, new_value): """change the ticket's attribute. Returns 1 on success, 0 on failure""" #check that the attribute is accepted.. if attribute not in BibCatalogSystem.TICKET_ATTRIBUTES: return 0 #we cannot change read-only values.. including text that is an attachment. pity if attribute in ['creator', 'date', 'ticketid', 'url_close', 'url_display', 'recordid', 'text']: return 0 #check attribute setme = "" if (attribute == 'priority'): try: dummy = int(new_value) except: return 0 setme = "set Priority=" + str(new_value) if (attribute == 'subject'): subject = escape_shell_arg(new_value) setme = "set Subject='" + subject +"'" if (attribute == 'owner'): #convert from invenio to RT ownerprefs = invenio.webuser.get_user_preferences(new_value) if not ownerprefs.has_key("bibcatalog_username"): return 0 else: owner = escape_shell_arg(ownerprefs["bibcatalog_username"]) setme = " set owner='" + owner +"'" if (attribute == 'status'): setme = " set status='" + escape_shell_arg(new_value) +"'" if (attribute == 'queue'): setme = " set queue='" + escape_shell_arg(new_value) +"'" if not CFG_BIBCATALOG_SYSTEM_RT_URL: return 0 #make sure ticketid is numeric try: dummy = int(ticketid) except: return 0 (username, passwd) = get_bibcat_from_prefs(uid) httppart, siteandpath = CFG_BIBCATALOG_SYSTEM_RT_URL.split("//") BIBCATALOG_RT_SERVER = httppart + "//" + username + ":" + passwd + "@" + siteandpath #set as env var os.environ["RTUSER"] = username os.environ["RTSERVER"] = BIBCATALOG_RT_SERVER passwd = escape_shell_arg(passwd) #make a call. safe since passwd and all variables in 'setme' have been escaped dummy, myout, dummyerr = run_shell_command("echo "+passwd+" | " + CFG_BIBCATALOG_SYSTEM_RT_CLI + " edit ticket/" + str(ticketid) + setme) respOK = False mylines = myout.split("\n") for line in mylines: if line.count('updated') > 0: respOK = True if respOK: return 1 #print str(mylines) return 0 - def ticket_get_attribute(self, uid, ticketid, attrname): + def ticket_get_attribute(self, uid, ticketid, attribute): """return an attribute of a ticket""" - ticinfo = self.ticket_get_info(uid, ticketid, [attrname]) - if ticinfo.has_key(attrname): - return ticinfo[attrname] + ticinfo = self.ticket_get_info(uid, ticketid, [attribute]) + if ticinfo.has_key(attribute): + return ticinfo[attribute] return None - def ticket_get_info(self, uid, ticketid, attrlist = None): + def ticket_get_info(self, uid, ticketid, attributes = None): """return ticket info as a dictionary of pre-defined attribute names. Or just those listed in attrlist. Returns None on failure""" if not CFG_BIBCATALOG_SYSTEM_RT_URL: return 0 #make sure ticketid is numeric try: dummy = int(ticketid) except: return 0 - if attrlist is None: - attrlist = [] + if attributes is None: + attributes = [] (username, passwd) = get_bibcat_from_prefs(uid) httppart, siteandpath = CFG_BIBCATALOG_SYSTEM_RT_URL.split("//") BIBCATALOG_RT_SERVER = httppart + "//" + username + ":" + passwd + "@" + siteandpath #set as env var os.environ["RTUSER"] = username os.environ["RTSERVER"] = BIBCATALOG_RT_SERVER passwd = escape_shell_arg(passwd) #make a call. This is safe.. passwd escaped, ticketid numeric dummy, myout, dummyerr = run_shell_command("echo "+passwd+" | " + CFG_BIBCATALOG_SYSTEM_RT_CLI + " show ticket/" + str(ticketid)) tdict = {} for line in myout.split("\n"): if line.count(": ") > 0: tattr, tvaluen = line.split(": ") tvalue = tvaluen.rstrip() tdict[tattr] = tvalue #query again to get attachments -> Contents dummy, myout, dummyerr = run_shell_command("echo "+passwd+" | " + CFG_BIBCATALOG_SYSTEM_RT_CLI + " show ticket/" + str(ticketid) + "/attachments/") attachments = [] for line in myout.split("\n"): if line.count(": ") > 1: #there is a line Attachments: 40: xxx aline = line.split(": ") attachments.append(aline[1]) #query again for each attachment for att in attachments: #passwd still escaped.. dummy, myout, dummyerr = run_shell_command("echo "+passwd+" | " + CFG_BIBCATALOG_SYSTEM_RT_CLI + " show ticket/" + str(ticketid) + "/attachments/" + att) #get the contents line for line in myout.split("\n"): if line.count("Content: ") > 0: cstuff = line.split("Content: ") tdict['Text'] = cstuff[1].rstrip() if (len(tdict) > 0): #iterate over TICKET_ATTRIBUTES to make a canonical ticket candict = {} for f in BibCatalogSystem.TICKET_ATTRIBUTES: tcased = f.title() if tdict.has_key(tcased): candict[f] = tdict[tcased] if tdict.has_key('CF.{RecordID}'): candict['recordid'] = tdict['CF.{RecordID}'] if tdict.has_key('id'): candict['ticketid'] = tdict['id'] #make specific URL attributes: url_display = CFG_BIBCATALOG_SYSTEM_RT_URL + "/Ticket/Display.html?id="+str(ticketid) candict['url_display'] = url_display url_close = CFG_BIBCATALOG_SYSTEM_RT_URL + "/Ticket/Update.html?Action=Comment&DefaultStatus=resolved&id="+str(ticketid) candict['url_close'] = url_close - url_modify = CFG_BIBCATALOG_SYSTEM_RT_URL + "/Ticket/Modify.html?id="+str(ticketid) + url_modify = CFG_BIBCATALOG_SYSTEM_RT_URL + "/Ticket/ModifyAll.html?id="+str(ticketid) candict['url_modify'] = url_modify #change the ticket owner into invenio UID if tdict.has_key('owner'): rt_owner = tdict["owner"] uid = invenio.webuser.get_uid_based_on_pref("bibcatalog_username", rt_owner) candict['owner'] = uid - if len(attrlist) == 0: #return all fields + if len(attributes) == 0: #return all fields return candict else: #return only the fields that were requested tdict = {} - for f in attrlist: - if candict.has_key(f): - tdict[f] = candict[f] + for myatt in attributes: + if candict.has_key(myatt): + tdict[myatt] = candict[myatt] return tdict else: return None diff --git a/modules/bibcatalog/lib/bibcatalog_templates.py b/modules/bibcatalog/lib/bibcatalog_templates.py new file mode 100644 index 000000000..581281603 --- /dev/null +++ b/modules/bibcatalog/lib/bibcatalog_templates.py @@ -0,0 +1,75 @@ +## This file is part of CDS Invenio. +## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 CERN. +## +## CDS Invenio is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation; either version 2 of the +## License, or (at your option) any later version. +## +## CDS Invenio is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with CDS Invenio; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +"""CDS Invenio BibCatalog HTML generator.""" + +from invenio.bibcatalog import bibcatalog_system +from invenio.messages import wash_language, gettext_set_language +from invenio.config import CFG_SITE_LANG +from invenio.webstyle_templates import Template as DefaultTemplate + +class Template(DefaultTemplate): + """ HTML generators for BibCatalog """ + + SHOW_MAX_TICKETS = 25 + + def tmpl_your_tickets(self, uid, ln=CFG_SITE_LANG, start=1): + """ make a pretty html body of tickets that belong to the user given as param """ + ln = wash_language(ln) + _ = gettext_set_language(ln) + #errors? tell what happened and get out + bibcat_probs = bibcatalog_system.check_system(uid) + if bibcat_probs: + return _("Error")+" "+bibcat_probs + + tickets = bibcatalog_system.ticket_search(uid, owner=uid) #get ticket id's + lines = "" #put result here + iter = 1 + + lines += _("You have ")+str(len(tickets))+" "+_("tickets")+".
" + + #make a prev link if needed + if (start > 1): + newstart = start - self.SHOW_MAX_TICKETS + if (newstart < 1): + newstart = 1 + lines += ''+_("Previous")+'' + lines += """""" + lastshown = len(tickets) #what was the number of the last shown ticket? + for ticket in tickets: + #get info and show only for those that within the show range + if (iter >= start) and (iter < start+self.SHOW_MAX_TICKETS): + ticket_info = bibcatalog_system.ticket_get_info(uid, ticket) + subject = ticket_info['subject'] + status = ticket_info['status'] + text = "" + if ticket_info.has_key('text'): + text = ticket_info['text'] + display = ''+_("show")+'' + close = ''+_("close")+'' + lines += "\n" + lastshown = iter + iter = iter+1 + lines += "
"+str(ticket)+""+subject+" "+text+""+status+""+display+""+close+"
" + + #make next link if needed + if (len(tickets) > lastshown): + newstart = lastshown+1 + lines += ''+_("Next")+'' + return lines + + diff --git a/modules/miscutil/lib/inveniocfg.py b/modules/miscutil/lib/inveniocfg.py index 7190fd0b3..2814278a8 100644 --- a/modules/miscutil/lib/inveniocfg.py +++ b/modules/miscutil/lib/inveniocfg.py @@ -1,1085 +1,1085 @@ # -*- coding: utf-8 -*- ## ## This file is part of CDS Invenio. ## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 CERN. ## ## CDS Invenio is free software; you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation; either version 2 of the ## License, or (at your option) any later version. ## ## CDS Invenio is distributed in the hope that it will be useful, but ## WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with CDS Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. """ Invenio configuration and administration CLI tool. Usage: inveniocfg [options] General options: -h, --help print this help -V, --version print version number Options to finish your installation: --create-apache-conf create Apache configuration files --create-tables create DB tables for Invenio --load-webstat-conf load the WebStat configuration --drop-tables drop DB tables of Invenio Options to set up and test a demo site: --create-demo-site create demo site --load-demo-records load demo records --remove-demo-records remove demo records, keeping demo site --drop-demo-site drop demo site configurations too --run-unit-tests run unit test suite (needs deme site) --run-regression-tests run regression test suite (needs demo site) --run-web-tests run web tests in a browser (needs demo site, Firefox, Selenium IDE) Options to update config files in situ: --update-all perform all the update options --update-config-py update config.py file from invenio.conf file --update-dbquery-py update dbquery.py with DB credentials from invenio.conf --update-dbexec update dbexec with DB credentials from invenio.conf --update-bibconvert-tpl update bibconvert templates with CFG_SITE_URL from invenio.conf --update-web-tests update web test cases with CFG_SITE_URL from invenio.conf Options to update DB tables: --reset-all perform all the reset options --reset-sitename reset tables to take account of new CFG_SITE_NAME* --reset-siteadminemail reset tables to take account of new CFG_SITE_ADMIN_EMAIL --reset-fieldnames reset tables to take account of new I18N names from PO files --reset-recstruct-cache reset record structure cache according to CFG_BIBUPLOAD_SERIALIZE_RECORD_STRUCTURE Options to help the work: --list print names and values of all options from conf files --get get value of a given option from conf files --conf-dir path to directory where invenio*.conf files are [optional] --detect-system-details print system details such as Apache/Python/MySQL versions """ __revision__ = "$Id$" from ConfigParser import ConfigParser import os import re import shutil import socket import sys import zlib import marshal def print_usage(): """Print help.""" print __doc__ def print_version(): """Print version information.""" print __revision__ def convert_conf_option(option_name, option_value): """ Convert conf option into Python config.py line, converting values to ints or strings as appropriate. """ ## 1) convert option name to uppercase: option_name = option_name.upper() ## 2) convert option value to int or string: if option_name in ['CFG_BIBUPLOAD_REFERENCE_TAG', 'CFG_BIBUPLOAD_EXTERNAL_SYSNO_TAG', 'CFG_BIBUPLOAD_EXTERNAL_OAIID_TAG', 'CFG_BIBUPLOAD_EXTERNAL_OAIID_PROVENANCE_TAG', 'CFG_BIBUPLOAD_STRONG_TAGS', 'CFG_SITE_EMERGENCY_PHONE_NUMBERS']: # some options are supposed be string even when they look like # numeric option_value = '"' + option_value + '"' else: try: option_value = int(option_value) except ValueError: option_value = '"' + option_value + '"' ## 3a) special cases: regexps if option_name in ['CFG_BIBINDEX_CHARS_ALPHANUMERIC_SEPARATORS', 'CFG_BIBINDEX_CHARS_PUNCTUATION']: option_value = 'r"[' + option_value[1:-1] + ']"' ## 3b) special cases: True, False, None if option_value in ['"True"', '"False"', '"None"']: option_value = option_value[1:-1] ## 3c) special cases: dicts if option_name in ['CFG_WEBSEARCH_FIELDS_CONVERT', ]: option_value = option_value[1:-1] ## 3d) special cases: comma-separated lists if option_name in ['CFG_SITE_LANGS', 'CFG_WEBSUBMIT_ADDITIONAL_KNOWN_FILE_EXTENSIONS', 'CFG_WEBSEARCH_USE_JSMATH_FOR_FORMATS', 'CFG_BIBUPLOAD_STRONG_TAGS', 'CFG_BIBSCHED_GC_TASKS_TO_REMOVE', 'CFG_BIBSCHED_GC_TASKS_TO_ARCHIVE', 'CFG_BIBUPLOAD_FFT_ALLOWED_LOCAL_PATHS', 'CFG_BIBUPLOAD_CONTROLLED_PROVENANCE_TAGS', 'CFG_WEBSEARCH_ENABLED_SEARCH_INTERFACES', 'CFG_SITE_EMERGENCY_PHONE_NUMBERS']: out = "[" for elem in option_value[1:-1].split(","): if elem: if option_name in ['CFG_WEBSEARCH_ENABLED_SEARCH_INTERFACES']: # 3d1) integer values out += "%i, " % int(elem) else: # 3d2) string values out += "'%s', " % elem out += "]" option_value = out ## 3e) special cases: multiline if option_name == 'CFG_OAI_IDENTIFY_DESCRIPTION': # make triple quotes option_value = '""' + option_value + '""' ## 3f) ignore some options: if option_name.startswith('CFG_SITE_NAME_INTL'): # treated elsewhere return ## 4) finally, return output line: return '%s = %s' % (option_name, option_value) def cli_cmd_update_config_py(conf): """ Update new config.py from conf options, keeping previous config.py in a backup copy. """ print ">>> Going to update config.py..." ## location where config.py is: configpyfile = conf.get("Invenio", "CFG_PYLIBDIR") + \ os.sep + 'invenio' + os.sep + 'config.py' ## backup current config.py file: if os.path.exists(configpyfile): shutil.copy(configpyfile, configpyfile + '.OLD') ## here we go: fdesc = open(configpyfile, 'w') ## generate preamble: fdesc.write("# -*- coding: utf-8 -*-\n") fdesc.write("# DO NOT EDIT THIS FILE! IT WAS AUTOMATICALLY GENERATED\n") fdesc.write("# FROM INVENIO.CONF BY EXECUTING:\n") fdesc.write("# " + " ".join(sys.argv) + "\n") ## special treatment for CFG_SITE_NAME_INTL options: fdesc.write("CFG_SITE_NAME_INTL = {}\n") for lang in conf.get("Invenio", "CFG_SITE_LANGS").split(","): fdesc.write("CFG_SITE_NAME_INTL['%s'] = \"%s\"\n" % (lang, conf.get("Invenio", "CFG_SITE_NAME_INTL_" + lang))) ## special treatment for CFG_SITE_SECURE_URL that may be empty, in ## which case it should be put equal to CFG_SITE_URL: if not conf.get("Invenio", "CFG_SITE_SECURE_URL"): conf.set("Invenio", "CFG_SITE_SECURE_URL", conf.get("Invenio", "CFG_SITE_URL")) ## process all the options normally: sections = conf.sections() sections.sort() for section in sections: options = conf.options(section) options.sort() for option in options: if not option.startswith('CFG_DATABASE_'): # put all options except for db credentials into config.py line_out = convert_conf_option(option, conf.get(section, option)) if line_out: fdesc.write(line_out + "\n") ## FIXME: special treatment for experimental variables ## CFG_WEBSEARCH_ENABLED_SEARCH_INTERFACES and CFG_WEBSEARCH_DEFAULT_SEARCH_INTERFACE ## (not offering them in invenio.conf since they will be refactored) fdesc.write("CFG_WEBSEARCH_DEFAULT_SEARCH_INTERFACE = 0\n") fdesc.write("CFG_WEBSEARCH_ENABLED_SEARCH_INTERFACES = [0, 1,]\n") ## generate postamble: fdesc.write("") fdesc.write("# END OF GENERATED FILE") ## we are done: fdesc.close() print "You may want to restart Apache now." print ">>> config.py updated successfully." def cli_cmd_update_dbquery_py(conf): """ Update lib/dbquery.py file with DB parameters read from conf file. Note: this edits dbquery.py in situ, taking a backup first. Use only when you know what you are doing. """ print ">>> Going to update dbquery.py..." ## location where dbquery.py is: dbquerypyfile = conf.get("Invenio", "CFG_PYLIBDIR") + \ os.sep + 'invenio' + os.sep + 'dbquery.py' ## backup current dbquery.py file: if os.path.exists(dbquerypyfile): shutil.copy(dbquerypyfile, dbquerypyfile + '.OLD') ## replace db parameters: out = '' for line in open(dbquerypyfile, 'r').readlines(): match = re.search(r'^CFG_DATABASE_(HOST|PORT|NAME|USER|PASS)(\s*=\s*)\'.*\'$', line) if match: dbparam = 'CFG_DATABASE_' + match.group(1) out += "%s%s'%s'\n" % (dbparam, match.group(2), conf.get('Invenio', dbparam)) else: out += line fdesc = open(dbquerypyfile, 'w') fdesc.write(out) fdesc.close() print "You may want to restart Apache now." print ">>> dbquery.py updated successfully." def cli_cmd_update_dbexec(conf): """ Update bin/dbexec file with DB parameters read from conf file. Note: this edits dbexec in situ, taking a backup first. Use only when you know what you are doing. """ print ">>> Going to update dbexec..." ## location where dbexec is: dbexecfile = conf.get("Invenio", "CFG_BINDIR") + \ os.sep + 'dbexec' ## backup current dbexec file: if os.path.exists(dbexecfile): shutil.copy(dbexecfile, dbexecfile + '.OLD') ## replace db parameters via sed: out = '' for line in open(dbexecfile, 'r').readlines(): match = re.search(r'^CFG_DATABASE_(HOST|PORT|NAME|USER|PASS)(\s*=\s*)\'.*\'$', line) if match: dbparam = 'CFG_DATABASE_' + match.group(1) out += "%s%s'%s'\n" % (dbparam, match.group(2), conf.get("Invenio", dbparam)) else: out += line fdesc = open(dbexecfile, 'w') fdesc.write(out) fdesc.close() print ">>> dbexec updated successfully." def cli_cmd_update_bibconvert_tpl(conf): """ Update bibconvert/config/*.tpl files looking for 856 http://.../record/ lines, replacing URL with CFG_SITE_URL taken from conf file. Note: this edits tpl files in situ, taking a backup first. Use only when you know what you are doing. """ print ">>> Going to update bibconvert templates..." ## location where bibconvert/config/*.tpl are: tpldir = conf.get("Invenio", 'CFG_ETCDIR') + \ os.sep + 'bibconvert' + os.sep + 'config' ## find all *.tpl files: for tplfilename in os.listdir(tpldir): if tplfilename.endswith(".tpl"): ## change tpl file: tplfile = tpldir + os.sep + tplfilename shutil.copy(tplfile, tplfile + '.OLD') out = '' for line in open(tplfile, 'r').readlines(): match = re.search(r'^(.*)http://.*?/record/(.*)$', line) if match: out += "%s%s/record/%s\n" % (match.group(1), conf.get("Invenio", 'CFG_SITE_URL'), match.group(2)) else: out += line fdesc = open(tplfile, 'w') fdesc.write(out) fdesc.close() print ">>> bibconvert templates updated successfully." def cli_cmd_update_web_tests(conf): """ Update web test cases lib/webtest/test_*.html looking for http://.+?[>> Going to update web tests..." ## location where test_*.html files are: testdir = conf.get("Invenio", 'CFG_PREFIX') + os.sep + \ 'lib' + os.sep + 'webtest' + os.sep + 'invenio' ## find all test_*.html files: for testfilename in os.listdir(testdir): if testfilename.startswith("test_") and \ testfilename.endswith(".html"): ## change test file: testfile = testdir + os.sep + testfilename shutil.copy(testfile, testfile + '.OLD') out = '' for line in open(testfile, 'r').readlines(): match = re.search(r'^(.*)http://.+?([)/opt/cds-invenio(.*)$', line) if match: out += "%s%s%s\n" % (match.group(1), conf.get("Invenio", 'CFG_PREFIX'), match.group(2)) else: out += line fdesc = open(testfile, 'w') fdesc.write(out) fdesc.close() print ">>> web tests updated successfully." def cli_cmd_reset_sitename(conf): """ Reset collection-related tables with new CFG_SITE_NAME and CFG_SITE_NAME_INTL* read from conf files. """ print ">>> Going to reset CFG_SITE_NAME and CFG_SITE_NAME_INTL..." from invenio.dbquery import run_sql, IntegrityError # reset CFG_SITE_NAME: sitename = conf.get("Invenio", "CFG_SITE_NAME") try: run_sql("""INSERT INTO collection (id, name, dbquery, reclist) VALUES (1,%s,NULL,NULL)""", (sitename,)) except IntegrityError: run_sql("""UPDATE collection SET name=%s WHERE id=1""", (sitename,)) # reset CFG_SITE_NAME_INTL: for lang in conf.get("Invenio", "CFG_SITE_LANGS").split(","): sitename_lang = conf.get("Invenio", "CFG_SITE_NAME_INTL_" + lang) try: run_sql("""INSERT INTO collectionname (id_collection, ln, type, value) VALUES (%s,%s,%s,%s)""", (1, lang, 'ln', sitename_lang)) except IntegrityError: run_sql("""UPDATE collectionname SET value=%s WHERE ln=%s AND id_collection=1 AND type='ln'""", (sitename_lang, lang)) print "You may want to restart Apache now." print ">>> CFG_SITE_NAME and CFG_SITE_NAME_INTL* reset successfully." def cli_cmd_reset_recstruct_cache(conf): """If CFG_BIBUPLOAD_SERIALIZE_RECORD_STRUCTURE is changed, this function will adapt the database to either store or not store the recstruct format.""" from invenio.intbitset import intbitset from invenio.dbquery import run_sql from invenio.search_engine import get_record from invenio.bibsched import server_pid, pidfile enable_recstruct_cache = conf.get("Invenio", "CFG_BIBUPLOAD_SERIALIZE_RECORD_STRUCTURE") enable_recstruct_cache = enable_recstruct_cache in ('True', '1') pid = server_pid(ping_the_process=False) if pid: print >> sys.stderr, "ERROR: bibsched seems to run with pid %d, according to %s." % (pid, pidfile) print >> sys.stderr, " Please stop bibsched before running this procedure." sys.exit(1) if enable_recstruct_cache: print ">>> Searching records which need recstruct cache resetting; this may take a while..." all_recids = intbitset(run_sql("SELECT id FROM bibrec")) good_recids = intbitset(run_sql("SELECT bibrec.id FROM bibrec JOIN bibfmt ON bibrec.id = bibfmt.id_bibrec WHERE format='recstruct' AND modification_date < last_updated")) recids = all_recids - good_recids print ">>> Generating recstruct cache..." tot = len(recids) count = 0 for recid in recids: value = zlib.compress(marshal.dumps(get_record(recid))) run_sql("INSERT INTO bibfmt(id_bibrec, format, last_updated, value) VALUES(%s, 'recstruct', NOW(), %s)", (recid, value)) count += 1 if count % 1000 == 0: print " ... done records %s/%s" % (count, tot) if count % 1000 != 0: print " ... done records %s/%s" % (count, tot) print ">>> recstruct cache generated successfully." else: print ">>> Cleaning recstruct cache..." run_sql("DELETE FROM bibfmt WHERE format='recstruct'") def cli_cmd_reset_siteadminemail(conf): """ Reset user-related tables with new CFG_SITE_ADMIN_EMAIL read from conf files. """ print ">>> Going to reset CFG_SITE_ADMIN_EMAIL..." from invenio.dbquery import run_sql siteadminemail = conf.get("Invenio", "CFG_SITE_ADMIN_EMAIL") run_sql("DELETE FROM user WHERE id=1") run_sql("""INSERT INTO user (id, email, password, note, nickname) VALUES (1, %s, AES_ENCRYPT(email, ''), 1, 'admin')""", (siteadminemail,)) print "You may want to restart Apache now." print ">>> CFG_SITE_ADMIN_EMAIL reset successfully." def cli_cmd_reset_fieldnames(conf): """ Reset I18N field names such as author, title, etc and other I18N ranking method names such as word similarity. Their translations are taken from the PO files. """ print ">>> Going to reset I18N field names..." from invenio.messages import gettext_set_language, language_list_long from invenio.dbquery import run_sql, IntegrityError ## get field id and name list: field_id_name_list = run_sql("SELECT id, name FROM field") ## get rankmethod id and name list: rankmethod_id_name_list = run_sql("SELECT id, name FROM rnkMETHOD") ## update names for every language: for lang, dummy in language_list_long(): _ = gettext_set_language(lang) ## this list is put here in order for PO system to pick names ## suitable for translation field_name_names = {"any field": _("any field"), "title": _("title"), "author": _("author"), "abstract": _("abstract"), "keyword": _("keyword"), "report number": _("report number"), "subject": _("subject"), "reference": _("reference"), "fulltext": _("fulltext"), "collection": _("collection"), "division": _("division"), "year": _("year"), "journal": _("journal"), "experiment": _("experiment"), "record ID": _("record ID")} ## update I18N names for every language: for (field_id, field_name) in field_id_name_list: if field_name_names.has_key(field_name): try: run_sql("""INSERT INTO fieldname (id_field,ln,type,value) VALUES (%s,%s,%s,%s)""", (field_id, lang, 'ln', field_name_names[field_name])) except IntegrityError: run_sql("""UPDATE fieldname SET value=%s WHERE id_field=%s AND ln=%s AND type=%s""", (field_name_names[field_name], field_id, lang, 'ln',)) ## ditto for rank methods: rankmethod_name_names = {"wrd": _("word similarity"), "demo_jif": _("journal impact factor"), "citation": _("times cited"),} for (rankmethod_id, rankmethod_name) in rankmethod_id_name_list: try: run_sql("""INSERT INTO rnkMETHODNAME (id_rnkMETHOD,ln,type,value) VALUES (%s,%s,%s,%s)""", (rankmethod_id, lang, 'ln', rankmethod_name_names[rankmethod_name])) except IntegrityError: run_sql("""UPDATE rnkMETHODNAME SET value=%s WHERE id_rnkMETHOD=%s AND ln=%s AND type=%s""", (rankmethod_name_names[rankmethod_name], rankmethod_id, lang, 'ln',)) print ">>> I18N field names reset successfully." def test_db_connection(): """ Test DB connection, and if fails, advise user how to set it up. Useful to be called during table creation. """ print "Testing DB connection...", from invenio.textutils import wrap_text_in_a_box from invenio.dbquery import run_sql, Error ## first, test connection to the DB server: try: run_sql("SHOW TABLES") except Error, err: from invenio.dbquery import CFG_DATABASE_HOST, CFG_DATABASE_PORT, \ CFG_DATABASE_NAME, CFG_DATABASE_USER, CFG_DATABASE_PASS print wrap_text_in_a_box("""\ DATABASE CONNECTIVITY ERROR %(errno)d: %(errmsg)s.\n Perhaps you need to set up database and connection rights? If yes, then please login as MySQL admin user and run the following commands now: $ mysql -h %(dbhost)s -P %(dbport)s -u root -p mysql mysql> CREATE DATABASE %(dbname)s DEFAULT CHARACTER SET utf8; mysql> GRANT ALL PRIVILEGES ON %(dbname)s.* TO %(dbuser)s@%(webhost)s IDENTIFIED BY '%(dbpass)s'; mysql> QUIT The values printed above were detected from your configuration. If they are not right, then please edit your invenio.conf file and rerun 'inveniocfg --update-all' first. If the problem is of different nature, then please inspect the above error message and fix the problem before continuing.""" % \ {'errno': err.args[0], 'errmsg': err.args[1], 'dbname': CFG_DATABASE_NAME, 'dbhost': CFG_DATABASE_HOST, 'dbport': CFG_DATABASE_PORT, 'dbuser': CFG_DATABASE_USER, 'dbpass': CFG_DATABASE_PASS, 'webhost': CFG_DATABASE_HOST == 'localhost' and 'localhost' or os.popen('hostname -f', 'r').read().strip(), }) sys.exit(1) print "ok" ## second, test insert/select of a Unicode string to detect ## possible Python/MySQL/MySQLdb mis-setup: print "Testing Python/MySQL/MySQLdb UTF-8 chain...", try: beta_in_utf8 = "β" # Greek beta in UTF-8 is 0xCEB2 run_sql("CREATE TEMPORARY TABLE test__invenio__utf8 (x char(1), y varbinary(2)) DEFAULT CHARACTER SET utf8") run_sql("INSERT INTO test__invenio__utf8 (x, y) VALUES (%s, %s)", (beta_in_utf8, beta_in_utf8)) res = run_sql("SELECT x,y,HEX(x),HEX(y),LENGTH(x),LENGTH(y),CHAR_LENGTH(x),CHAR_LENGTH(y) FROM test__invenio__utf8") assert res[0] == ('\xce\xb2', '\xce\xb2', 'CEB2', 'CEB2', 2L, 2L, 1L, 2L) run_sql("DROP TEMPORARY TABLE test__invenio__utf8") except Exception, err: print wrap_text_in_a_box("""\ DATABASE RELATED ERROR %s\n A problem was detected with the UTF-8 treatment in the chain between the Python application, the MySQLdb connector, and the MySQL database. You may perhaps have installed older versions of some prerequisite packages?\n Please check the INSTALL file and please fix this problem before continuing.""" % err) sys.exit(1) print "ok" def cli_cmd_create_tables(conf): """Create and fill Invenio DB tables. Useful for the installation process.""" print ">>> Going to create and fill tables..." from invenio.config import CFG_PREFIX test_db_connection() for cmd in ["%s/bin/dbexec < %s/lib/sql/invenio/tabcreate.sql" % (CFG_PREFIX, CFG_PREFIX), "%s/bin/dbexec < %s/lib/sql/invenio/tabfill.sql" % (CFG_PREFIX, CFG_PREFIX)]: if os.system(cmd): print "ERROR: failed execution of", cmd sys.exit(1) cli_cmd_reset_sitename(conf) cli_cmd_reset_siteadminemail(conf) cli_cmd_reset_fieldnames(conf) for cmd in ["%s/bin/webaccessadmin -u admin -c -a" % CFG_PREFIX]: if os.system(cmd): print "ERROR: failed execution of", cmd sys.exit(1) print ">>> Tables created and filled successfully." def cli_cmd_load_webstat_conf(conf): print ">>> Going to load WebStat config..." from invenio.config import CFG_PREFIX cmd = "%s/bin/webstatadmin --load-config" % CFG_PREFIX if os.system(cmd): print "ERROR: failed execution of", cmd sys.exit(1) print ">>> WebStat config load successfully." def cli_cmd_drop_tables(conf): """Drop Invenio DB tables. Useful for the uninstallation process.""" print ">>> Going to drop tables..." from invenio.config import CFG_PREFIX from invenio.textutils import wrap_text_in_a_box, wait_for_user wait_for_user(wrap_text_in_a_box("""WARNING: You are going to destroy your database tables!""")) cmd = "%s/bin/dbexec < %s/lib/sql/invenio/tabdrop.sql" % (CFG_PREFIX, CFG_PREFIX) if os.system(cmd): print "ERROR: failed execution of", cmd sys.exit(1) print ">>> Tables dropped successfully." def cli_cmd_create_demo_site(conf): """Create demo site. Useful for testing purposes.""" print ">>> Going to create demo site..." from invenio.config import CFG_PREFIX from invenio.dbquery import run_sql run_sql("TRUNCATE schTASK") run_sql("TRUNCATE session") run_sql("DELETE FROM user WHERE email=''") for cmd in ["%s/bin/dbexec < %s/lib/sql/invenio/democfgdata.sql" % \ (CFG_PREFIX, CFG_PREFIX),]: if os.system(cmd): print "ERROR: failed execution of", cmd sys.exit(1) cli_cmd_reset_fieldnames(conf) # needed for I18N demo ranking method names for cmd in ["%s/bin/webaccessadmin -u admin -c -r -D" % CFG_PREFIX, "%s/bin/webcoll -u admin" % CFG_PREFIX, "%s/bin/webcoll 1" % CFG_PREFIX,]: if os.system(cmd): print "ERROR: failed execution of", cmd sys.exit(1) print ">>> Demo site created successfully." def cli_cmd_load_demo_records(conf): """Load demo records. Useful for testing purposes.""" from invenio.config import CFG_PREFIX from invenio.dbquery import run_sql print ">>> Going to load demo records..." run_sql("TRUNCATE schTASK") for cmd in ["%s/bin/bibupload -u admin -i %s/var/tmp/demobibdata.xml" % (CFG_PREFIX, CFG_PREFIX), "%s/bin/bibupload 1" % CFG_PREFIX, "%s/bin/bibindex -u admin" % CFG_PREFIX, "%s/bin/bibindex 2" % CFG_PREFIX, "%s/bin/bibreformat -u admin -o HB" % CFG_PREFIX, "%s/bin/bibreformat 3" % CFG_PREFIX, "%s/bin/webcoll -u admin" % CFG_PREFIX, "%s/bin/webcoll 4" % CFG_PREFIX, "%s/bin/bibrank -u admin" % CFG_PREFIX, "%s/bin/bibrank 5" % CFG_PREFIX,]: if os.system(cmd): print "ERROR: failed execution of", cmd sys.exit(1) print ">>> Demo records loaded successfully." def cli_cmd_remove_demo_records(conf): """Remove demo records. Useful when you are finished testing.""" print ">>> Going to remove demo records..." from invenio.config import CFG_PREFIX from invenio.dbquery import run_sql from invenio.textutils import wrap_text_in_a_box, wait_for_user wait_for_user(wrap_text_in_a_box("""WARNING: You are going to destroy your records and documents!""")) if os.path.exists(CFG_PREFIX + os.sep + 'var' + os.sep + 'data'): shutil.rmtree(CFG_PREFIX + os.sep + 'var' + os.sep + 'data') run_sql("TRUNCATE schTASK") for cmd in ["%s/bin/dbexec < %s/lib/sql/invenio/tabbibclean.sql" % (CFG_PREFIX, CFG_PREFIX), "%s/bin/webcoll -u admin" % CFG_PREFIX, "%s/bin/webcoll 1" % CFG_PREFIX,]: if os.system(cmd): print "ERROR: failed execution of", cmd sys.exit(1) print ">>> Demo records removed successfully." def cli_cmd_drop_demo_site(conf): """Drop demo site completely. Useful when you are finished testing.""" print ">>> Going to drop demo site..." from invenio.textutils import wrap_text_in_a_box, wait_for_user wait_for_user(wrap_text_in_a_box("""WARNING: You are going to destroy your site and documents!""")) cli_cmd_drop_tables(conf) cli_cmd_create_tables(conf) cli_cmd_remove_demo_records(conf) print ">>> Demo site dropped successfully." def cli_cmd_run_unit_tests(conf): """Run unit tests, usually on the working demo site.""" from invenio.testutils import build_and_run_unit_test_suite build_and_run_unit_test_suite() def cli_cmd_run_regression_tests(conf): """Run regression tests, usually on the working demo site.""" from invenio.testutils import build_and_run_regression_test_suite build_and_run_regression_test_suite() def cli_cmd_run_web_tests(conf): """Run web tests in a browser. Requires Firefox with Selenium IDE extension.""" from invenio.testutils import build_and_run_web_test_suite build_and_run_web_test_suite() def cli_cmd_create_apache_conf(conf): """ Create Apache conf files for this site, keeping previous files in a backup copy. """ print ">>> Going to create Apache conf files..." from invenio.textutils import wrap_text_in_a_box apache_conf_dir = conf.get("Invenio", 'CFG_ETCDIR') + \ os.sep + 'apache' if not os.path.exists(apache_conf_dir): os.mkdir(apache_conf_dir) apache_vhost_file = apache_conf_dir + os.sep + \ 'invenio-apache-vhost.conf' apache_vhost_ssl_file = apache_conf_dir + os.sep + \ 'invenio-apache-vhost-ssl.conf' apache_vhost_body = """\ AddDefaultCharset UTF-8 ServerSignature Off ServerTokens Prod NameVirtualHost *:80 Listen 80 deny from all deny from all ServerName %(servername)s ServerAlias %(serveralias)s ServerAdmin %(serveradmin)s DocumentRoot %(webdir)s Options FollowSymLinks MultiViews AllowOverride None Order allow,deny allow from all ErrorLog %(logdir)s/apache.err LogLevel warn CustomLog %(logdir)s/apache.log combined DirectoryIndex index.en.html index.html - + SetHandler python-program PythonHandler invenio.webinterface_layout PythonDebug On AddHandler python-program .py PythonHandler mod_python.publisher PythonDebug On """ % {'servername': conf.get('Invenio', 'CFG_SITE_URL').replace("http://", ""), 'serveralias': conf.get('Invenio', 'CFG_SITE_URL').replace("http://", "").split('.')[0], 'serveradmin': conf.get('Invenio', 'CFG_SITE_ADMIN_EMAIL'), 'webdir': conf.get('Invenio', 'CFG_WEBDIR'), 'logdir': conf.get('Invenio', 'CFG_LOGDIR'), } apache_vhost_ssl_body = """\ ServerSignature Off ServerTokens Prod Listen 443 NameVirtualHost *:443 #SSLCertificateFile /etc/apache2/ssl/apache.pem SSLCertificateFile /etc/apache2/ssl/server.crt SSLCertificateKeyFile /etc/apache2/ssl/server.key deny from all deny from all ServerName %(servername)s ServerAlias %(serveralias)s ServerAdmin %(serveradmin)s SSLEngine on DocumentRoot %(webdir)s Options FollowSymLinks MultiViews AllowOverride None Order allow,deny allow from all ErrorLog %(logdir)s/apache-ssl.err LogLevel warn CustomLog %(logdir)s/apache-ssl.log combined DirectoryIndex index.en.html index.html - + SetHandler python-program PythonHandler invenio.webinterface_layout PythonDebug On AddHandler python-program .py PythonHandler mod_python.publisher PythonDebug On """ % {'servername': conf.get('Invenio', 'CFG_SITE_SECURE_URL').replace("https://", ""), 'serveralias': conf.get('Invenio', 'CFG_SITE_SECURE_URL').replace("https://", "").split('.')[0], 'serveradmin': conf.get('Invenio', 'CFG_SITE_ADMIN_EMAIL'), 'webdir': conf.get('Invenio', 'CFG_WEBDIR'), 'logdir': conf.get('Invenio', 'CFG_LOGDIR'), } # write HTTP vhost snippet: if os.path.exists(apache_vhost_file): shutil.copy(apache_vhost_file, apache_vhost_file + '.OLD') fdesc = open(apache_vhost_file, 'w') fdesc.write(apache_vhost_body) fdesc.close() print "Created file", apache_vhost_file # write HTTPS vhost snippet: if conf.get('Invenio', 'CFG_SITE_SECURE_URL') != \ conf.get('Invenio', 'CFG_SITE_URL'): if os.path.exists(apache_vhost_ssl_file): shutil.copy(apache_vhost_ssl_file, apache_vhost_ssl_file + '.OLD') fdesc = open(apache_vhost_ssl_file, 'w') fdesc.write(apache_vhost_ssl_body) fdesc.close() print "Created file", apache_vhost_ssl_file print wrap_text_in_a_box("""\ Apache virtual host configurations for your site have been created. You can check created files and put the following include statements in your httpd.conf:\n Include %s Include %s """ % (apache_vhost_file, apache_vhost_ssl_file)) print ">>> Apache conf files created." def cli_cmd_get(conf, varname): """ Return value of VARNAME read from CONF files. Useful for third-party programs to access values of conf options such as CFG_PREFIX. Return None if VARNAME is not found. """ # do not pay attention to upper/lower case: varname = varname.lower() # do not pay attention to section names yet: all_options = {} for section in conf.sections(): for option in conf.options(section): all_options[option] = conf.get(section, option) return all_options.get(varname, None) def cli_cmd_list(conf): """ Print a list of all conf options and values from CONF. """ sections = conf.sections() sections.sort() for section in sections: options = conf.options(section) options.sort() for option in options: print option.upper(), '=', conf.get(section, option) def _grep_version_from_executable(path_to_exec, version_regexp): """ Try to detect a program version by digging into its binary PATH_TO_EXEC and looking for VERSION_REGEXP. Return program version as a string. Return empty string if not succeeded. """ from invenio.shellutils import run_shell_command exec_version = "" if os.path.exists(path_to_exec): dummy1, cmd2_out, dummy2 = run_shell_command("strings %s | grep %s", (path_to_exec, version_regexp)) if cmd2_out: for cmd2_out_line in cmd2_out.split("\n"): if len(cmd2_out_line) > len(exec_version): # the longest the better exec_version = cmd2_out_line return exec_version def detect_apache_version(): """ Try to detect Apache version by localizing httpd or apache executables and grepping inside binaries. Return list of all found Apache versions and paths. (For a given executable, the returned format is 'apache_version [apache_path]'.) Return empty list if no success. """ from invenio.shellutils import run_shell_command out = [] dummy1, cmd_out, dummy2 = run_shell_command("locate bin/httpd bin/apache") for apache in cmd_out.split("\n"): apache_version = _grep_version_from_executable(apache, '^Apache\/') if apache_version: out.append("%s [%s]" % (apache_version, apache)) return out def detect_modpython_version(): """ Try to detect mod_python version, either from mod_python import or from grepping inside mod_python.so, like Apache. Return list of all found mod_python versions and paths. Return empty list if no success. """ out = [] try: from mod_python import version out.append(version) except ImportError: # try to detect via looking at mod_python.so: from invenio.shellutils import run_shell_command version = "" dummy1, cmd_out, dummy2 = run_shell_command("locate /mod_python.so") for modpython in cmd_out.split("\n"): modpython_version = _grep_version_from_executable(modpython, '^mod_python\/') if modpython_version: out.append("%s [%s]" % (modpython_version, modpython)) return out def cli_cmd_detect_system_details(conf): """ Detect and print system details such as Apache/Python/MySQL versions etc. Useful for debugging problems on various OS. """ import MySQLdb print ">>> Going to detect system details..." print "* Hostname: " + socket.gethostname() print "* Invenio version: " + conf.get("Invenio", "CFG_VERSION") print "* Python version: " + sys.version.replace("\n", " ") print "* Apache version: " + ";\n ".join(detect_apache_version()) print "* mod_python version: " + ";\n ".join(detect_modpython_version()) print "* MySQLdb version: " + MySQLdb.__version__ try: from invenio.dbquery import run_sql print "* MySQL version:" for key, val in run_sql("SHOW VARIABLES LIKE 'version%'") + \ run_sql("SHOW VARIABLES LIKE 'charact%'") + \ run_sql("SHOW VARIABLES LIKE 'collat%'"): if False: print " - %s: %s" % (key, val) elif key in ['version', 'character_set_client', 'character_set_connection', 'character_set_database', 'character_set_results', 'character_set_server', 'character_set_system', 'collation_connection', 'collation_database', 'collation_server']: print " - %s: %s" % (key, val) except ImportError: print "* ERROR: cannot import dbquery" print ">>> System details detected successfully." def main(): """Main entry point.""" conf = ConfigParser() if '--help' in sys.argv or \ '-h' in sys.argv: print_usage() elif '--version' in sys.argv or \ '-V' in sys.argv: print_version() else: confdir = None if '--conf-dir' in sys.argv: try: confdir = sys.argv[sys.argv.index('--conf-dir') + 1] except IndexError: pass # missing --conf-dir argument value if not os.path.exists(confdir): print "ERROR: bad or missing --conf-dir option value." sys.exit(1) else: ## try to detect path to conf dir (relative to this bin dir): confdir = re.sub(r'/bin$', '/etc', sys.path[0]) ## read conf files: for conffile in [confdir + os.sep + 'invenio.conf', confdir + os.sep + 'invenio-autotools.conf', confdir + os.sep + 'invenio-local.conf',]: if os.path.exists(conffile): conf.read(conffile) else: if not conffile.endswith("invenio-local.conf"): # invenio-local.conf is optional, otherwise stop print "ERROR: Badly guessed conf file location", conffile print "(Please use --conf-dir option.)" sys.exit(1) ## decide what to do: done = False for opt_idx in range(0, len(sys.argv)): opt = sys.argv[opt_idx] if opt == '--conf-dir': # already treated before, so skip silently: pass elif opt == '--get': try: varname = sys.argv[opt_idx + 1] except IndexError: print "ERROR: bad or missing --get option value." sys.exit(1) if varname.startswith('-'): print "ERROR: bad or missing --get option value." sys.exit(1) varvalue = cli_cmd_get(conf, varname) if varvalue is not None: print varvalue else: sys.exit(1) done = True elif opt == '--list': cli_cmd_list(conf) done = True elif opt == '--detect-system-details': cli_cmd_detect_system_details(conf) done = True elif opt == '--create-tables': cli_cmd_create_tables(conf) done = True elif opt == '--load-webstat-conf': cli_cmd_load_webstat_conf(conf) done = True elif opt == '--drop-tables': cli_cmd_drop_tables(conf) done = True elif opt == '--create-demo-site': cli_cmd_create_demo_site(conf) done = True elif opt == '--load-demo-records': cli_cmd_load_demo_records(conf) done = True elif opt == '--remove-demo-records': cli_cmd_remove_demo_records(conf) done = True elif opt == '--drop-demo-site': cli_cmd_drop_demo_site(conf) done = True elif opt == '--run-unit-tests': cli_cmd_run_unit_tests(conf) done = True elif opt == '--run-regression-tests': cli_cmd_run_regression_tests(conf) done = True elif opt == '--run-web-tests': cli_cmd_run_web_tests(conf) done = True elif opt == '--update-all': cli_cmd_update_config_py(conf) cli_cmd_update_dbquery_py(conf) cli_cmd_update_dbexec(conf) cli_cmd_update_bibconvert_tpl(conf) cli_cmd_update_web_tests(conf) done = True elif opt == '--update-config-py': cli_cmd_update_config_py(conf) done = True elif opt == '--update-dbquery-py': cli_cmd_update_dbquery_py(conf) done = True elif opt == '--update-dbexec': cli_cmd_update_dbexec(conf) done = True elif opt == '--update-bibconvert-tpl': cli_cmd_update_bibconvert_tpl(conf) done = True elif opt == '--update-web-tests': cli_cmd_update_web_tests(conf) done = True elif opt == '--reset-all': cli_cmd_reset_sitename(conf) cli_cmd_reset_siteadminemail(conf) cli_cmd_reset_fieldnames(conf) cli_cmd_reset_recstruct_cache(conf) done = True elif opt == '--reset-sitename': cli_cmd_reset_sitename(conf) done = True elif opt == '--reset-siteadminemail': cli_cmd_reset_siteadminemail(conf) done = True elif opt == '--reset-fieldnames': cli_cmd_reset_fieldnames(conf) done = True elif opt == '--reset-recstruct-cache': cli_cmd_reset_recstruct_cache(conf) done = True elif opt == '--create-apache-conf': cli_cmd_create_apache_conf(conf) done = True elif opt.startswith("-") and opt != '--yes-i-know': print "ERROR: unknown option", opt sys.exit(1) if not done: print """ERROR: Please specify a command. Please see '--help'.""" sys.exit(1) if __name__ == '__main__': main() diff --git a/modules/websession/lib/webaccount.py b/modules/websession/lib/webaccount.py index 8a273658c..8f2fd1f96 100644 --- a/modules/websession/lib/webaccount.py +++ b/modules/websession/lib/webaccount.py @@ -1,427 +1,432 @@ ## This file is part of CDS Invenio. ## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 CERN. ## ## CDS Invenio is free software; you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation; either version 2 of the ## License, or (at your option) any later version. ## ## CDS Invenio is distributed in the hope that it will be useful, but ## WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with CDS Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. __revision__ = "$Id$" import re import MySQLdb import urllib from invenio.config import \ CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS, \ CFG_CERN_SITE, \ CFG_SITE_LANG, \ CFG_SITE_SUPPORT_EMAIL, \ CFG_SITE_ADMIN_EMAIL, \ CFG_SITE_SECURE_URL, \ CFG_VERSION, \ CFG_DATABASE_HOST, \ CFG_DATABASE_NAME +from invenio.access_control_engine import acc_authorize_action from invenio.access_control_config import CFG_EXTERNAL_AUTHENTICATION, SUPERADMINROLE from invenio.dbquery import run_sql from invenio.webuser import getUid,isGuestUser, get_user_preferences, \ collect_user_info from invenio.access_control_admin import acc_find_user_role_actions from invenio.messages import gettext_set_language from invenio.external_authentication import InvenioWebAccessExternalAuthError import invenio.template websession_templates = invenio.template.load('websession') def perform_info(req, ln): """Display the main features of CDS personalize""" out = "" uid = getUid(req) user_info = collect_user_info(req) return websession_templates.tmpl_account_info( ln = ln, uid = uid, guest = isGuestUser(uid), CFG_CERN_SITE = CFG_CERN_SITE, ) def perform_display_external_user_settings(settings, ln): """show external user settings which is a dictionary.""" _ = gettext_set_language(ln) html_settings = "" print_settings = False settings_keys = settings.keys() settings_keys.sort() for key in settings_keys: value = settings[key] if key.startswith("EXTERNAL_") and not "HIDDEN_" in key: print_settings = True key = key[9:].capitalize() html_settings += websession_templates.tmpl_external_setting(ln, key, value) return print_settings and websession_templates.tmpl_external_user_settings(ln, html_settings) or "" def perform_youradminactivities(user_info, ln): """Return text for the `Your Admin Activities' box. Analyze whether user UID has some admin roles, and if yes, then print suitable links for the actions he can do. If he's not admin, print a simple non-authorized message.""" your_role_actions = acc_find_user_role_actions(user_info) your_roles = [] your_admin_activities = [] guest = isGuestUser(user_info['uid']) for (role, action) in your_role_actions: if role not in your_roles: your_roles.append(role) if action not in your_admin_activities: your_admin_activities.append(action) if SUPERADMINROLE in your_roles: for action in ("runbibedit", "cfgbibformat", "cfgbibharvest", "cfgoairepository", "cfgbibrank", "cfgbibindex", "cfgwebaccess", "cfgwebcomment", "cfgwebsearch", "cfgwebsubmit"): if action not in your_admin_activities: your_admin_activities.append(action) return websession_templates.tmpl_account_adminactivities( ln = ln, uid = user_info['uid'], guest = guest, roles = your_roles, activities = your_admin_activities, ) def perform_display_account(req, username, bask, aler, sear, msgs, loan, grps, sbms, appr, admn, ln): """Display a dynamic page that shows the user's account.""" # load the right message language _ = gettext_set_language(ln) uid = getUid(req) user_info = collect_user_info(req) #your account if isGuestUser(uid): user = "guest" login = "%s/youraccount/login?ln=%s" % (CFG_SITE_SECURE_URL, ln) accBody = _("You are logged in as guest. You may want to %(x_url_open)slogin%(x_url_close)s as a regular user.") %\ {'x_url_open': '', 'x_url_close': ''} accBody += "

" bask=aler=msgs= _("The %(x_fmt_open)sguest%(x_fmt_close)s users need to %(x_url_open)sregister%(x_url_close)s first") %\ {'x_fmt_open': '', 'x_fmt_close': '', 'x_url_open': '', 'x_url_close': ''} sear= _("No queries found") else: user = username accBody = websession_templates.tmpl_account_body( ln = ln, user = user, ) #Display warnings if user is superuser roles = acc_find_user_role_actions(user_info) warnings = "0" for role in roles: if "superadmin" in role: warnings = "1" break warning_list = superuser_account_warnings() + #check if tickets ok + tickets = (acc_authorize_action(user_info, 'runbibedit')[0] == 0) + return websession_templates.tmpl_account_page( ln = ln, warnings = warnings, warning_list = warning_list, accBody = accBody, baskets = bask, alerts = aler, searches = sear, messages = msgs, loans = loan, groups = grps, submissions = sbms, approvals = appr, + tickets = tickets, administrative = admn ) def superuser_account_warnings(): """Check to see whether admin accounts have default / blank password etc. Returns a list""" warning_array = [] #Try and connect to the mysql database with the default invenio password try: conn = MySQLdb.connect (host = CFG_DATABASE_HOST, user = "root", passwd = "my123p$ss", db = "mysql") conn.close() warning_array.append("warning_mysql_password_equal_to_invenio_password") except: pass #Try and connect to the invenio database with the default invenio password try: conn = MySQLdb.connect (host = CFG_DATABASE_HOST, user = "cdsinvenio", passwd = "my123p$ss", db = CFG_DATABASE_NAME) conn.close () warning_array.append("warning_invenio_password_equal_to_default") except: pass #Check if the admin password is empty res = run_sql("SELECT password, email from user where nickname = 'admin'") res1 = run_sql("SELECT email from user where nickname = 'admin' and password = AES_ENCRYPT(%s,'')", (res[0][1], )) for user in res1: warning_array.append("warning_empty_admin_password") #Check if the admin email has been changed from the default if (CFG_SITE_ADMIN_EMAIL == "cds.support@cern.ch" or CFG_SITE_SUPPORT_EMAIL == "cds.support@cern.ch") and CFG_CERN_SITE == 0: warning_array.append("warning_site_support_email_equal_to_default") #Check for a new release of CDS Invenio try: find = re.compile('CDS Invenio v[0-9]+.[0-9]+.[0-9]+ is released') webFile = urllib.urlopen("http://cdsware.cern.ch/download/RELEASE-NOTES") temp = "" version = "" version1 = "" while 1: temp = webFile.readline() match1 = find.match(temp) try: version = match1.group() break except: pass if not temp: break webFile.close() submatch = re.compile('[0-9]+.[0-9]+.[0-9]+') version1 = submatch.search(version) web_version = version1.group().split(".") local_version = CFG_VERSION.split(".") if web_version[0] > local_version[0]: warning_array.append("note_new_release_available") elif web_version[0] == local_version[0] and web_version[1] > local_version[1]: warning_array.append("note_new_release_available") elif web_version[0] == local_version[0] and web_version[1] == local_version[1] and web_version[2] > local_version[2]: warning_array.append("note_new_release_available") except: warning_array.append("error_cannot_download_release_notes") return warning_array def template_account(title, body, ln): """It is a template for print each of the options from the user's account.""" return websession_templates.tmpl_account_template( ln = ln, title = title, body = body ) def warning_guest_user(type, ln=CFG_SITE_LANG): """It returns an alert message,showing that the user is a guest user and should log into the system.""" # load the right message language _ = gettext_set_language(ln) return websession_templates.tmpl_warning_guest_user( ln = ln, type = type, ) def perform_delete(ln): """Delete the account of the user, not implement yet.""" # TODO return websession_templates.tmpl_account_delete(ln = ln) def perform_set(email, ln, can_config_bibcatalog = False, verbose = 0): """Perform_set(email,password): edit your account parameters, email and password. If can_config_bibcatalog is True, show the bibcatalog dialog (if configured). """ try: res = run_sql("SELECT id, nickname FROM user WHERE email=%s", (email,)) uid = res[0][0] nickname = res[0][1] except: uid = 0 nickname = "" CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS_LOCAL = CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS prefs = get_user_preferences(uid) if CFG_EXTERNAL_AUTHENTICATION.has_key(prefs['login_method']) and CFG_EXTERNAL_AUTHENTICATION[prefs['login_method']][0]: CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS_LOCAL = 3 out = websession_templates.tmpl_user_preferences( ln = ln, email = email, email_disabled = (CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS_LOCAL >= 2), password_disabled = (CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS_LOCAL >= 3), nickname = nickname, ) if len(CFG_EXTERNAL_AUTHENTICATION) > 1: try: uid = run_sql("SELECT id FROM user where email=%s", (email,)) uid = uid[0][0] except: uid = 0 current_login_method = prefs['login_method'] methods = CFG_EXTERNAL_AUTHENTICATION.keys() # Filtering out methods that don't provide user_exists to check if # a user exists in the external auth method before letting him/her # to switch. for method in methods: if CFG_EXTERNAL_AUTHENTICATION[method][0]: try: if not CFG_EXTERNAL_AUTHENTICATION[method][0].user_exists(email): methods.remove(method) except (AttributeError, InvenioWebAccessExternalAuthError): methods.remove(method) methods.sort() if len(methods) > 1: out += websession_templates.tmpl_user_external_auth( ln = ln, methods = methods, current = current_login_method, method_disabled = (CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS >= 4) ) current_group_records = prefs.get('websearch_group_records', 10) show_latestbox = prefs.get('websearch_latestbox', True) show_helpbox = prefs.get('websearch_helpbox', True) out += websession_templates.tmpl_user_websearch_edit( ln = ln, current = current_group_records, show_latestbox = show_latestbox, show_helpbox = show_helpbox, ) preferred_lang = prefs.get('language', ln) out += websession_templates.tmpl_user_lang_edit( ln = ln, preferred_lang = preferred_lang ) #show this dialog only if the system has been configured to use a ticket system from invenio.config import CFG_BIBCATALOG_SYSTEM if CFG_BIBCATALOG_SYSTEM and can_config_bibcatalog: bibcatalog_username = prefs.get('bibcatalog_username', "") bibcatalog_password = prefs.get('bibcatalog_password', "") out += websession_templates.tmpl_user_bibcatalog_auth(bibcatalog_username, \ bibcatalog_password, ln=ln) if verbose >= 9: for key, value in prefs.items(): out += "%s:%s
" % (key, value) out += perform_display_external_user_settings(prefs, ln) return out def create_register_page_box(referer='', ln=CFG_SITE_LANG): """Register a new account.""" return websession_templates.tmpl_register_page( referer = referer, ln = ln, level = CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS, ) ## create_login_page_box(): ask for the user's email and password, for login into the system def create_login_page_box(referer='', apache_msg="", ln=CFG_SITE_LANG): # List of referer regexep and message to print _ = gettext_set_language(ln) login_referrer2msg = ( (re.compile(r"/search"), "

" + _("This collection is restricted. If you think you have right to access it, please authenticate yourself.") + "

"), ) msg = "" for regexp, txt in login_referrer2msg: if regexp.search(referer): msg = txt break # FIXME: Temporary Hack to help CDS current migration if CFG_CERN_SITE and apache_msg: return msg + apache_msg if apache_msg: msg += apache_msg + "

2) Otherwise please authenticate yourself" \ " in the following form:

" internal = None for system in CFG_EXTERNAL_AUTHENTICATION.keys(): if not CFG_EXTERNAL_AUTHENTICATION[system][0]: internal = system break register_available = CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS <= 1 and internal methods = CFG_EXTERNAL_AUTHENTICATION.keys() methods.sort() selected = '' for method in methods: if CFG_EXTERNAL_AUTHENTICATION[method][1]: selected = method break return websession_templates.tmpl_login_form( ln = ln, referer = referer, internal = internal, register_available = register_available, methods = methods, selected_method = selected, msg = msg, ) # perform_logout: display the message of not longer authorized, def perform_logout(req, ln): return websession_templates.tmpl_account_logout(ln = ln) #def perform_lost: ask the user for his email, in order to send him the lost password def perform_lost(ln): return websession_templates.tmpl_lost_password_form(ln) #def perform_reset_password: ask the user for a new password to reset the lost one def perform_reset_password(ln, email, reset_key, msg=''): return websession_templates.tmpl_reset_password_form(ln, email, reset_key, msg) # perform_emailSent(email): confirm that the password has been emailed to 'email' address def perform_emailSent(email, ln): return websession_templates.tmpl_account_emailSent(ln = ln, email = email) # peform_emailMessage : display a error message when the email introduced is not correct, and sugest to try again def perform_emailMessage(eMsg, ln): return websession_templates.tmpl_account_emailMessage( ln = ln, msg = eMsg ) # perform_back(): template for return to a previous page, used for login,register and setting def perform_back(mess, url, linkname, ln='en'): return websession_templates.tmpl_back_form( ln = ln, message = mess, url = url, link = linkname, ) diff --git a/modules/websession/lib/websession_templates.py b/modules/websession/lib/websession_templates.py index 011fe56af..9b3f21507 100644 --- a/modules/websession/lib/websession_templates.py +++ b/modules/websession/lib/websession_templates.py @@ -1,2324 +1,2330 @@ ## This file is part of CDS Invenio. ## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 CERN. ## ## CDS Invenio is free software; you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation; either version 2 of the ## License, or (at your option) any later version. ## ## CDS Invenio is distributed in the hope that it will be useful, but ## WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with CDS Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. __revision__ = "$Id$" import urllib import cgi from invenio.config import \ CFG_CERN_SITE, \ CFG_SITE_LANG, \ CFG_SITE_NAME, \ CFG_SITE_NAME_INTL, \ CFG_SITE_SUPPORT_EMAIL, \ CFG_SITE_SECURE_URL, \ CFG_SITE_URL, \ CFG_WEBSESSION_RESET_PASSWORD_EXPIRE_IN_DAYS, \ CFG_WEBSESSION_ADDRESS_ACTIVATION_EXPIRE_IN_DAYS, \ CFG_WEBSESSION_DIFFERENTIATE_BETWEEN_GUESTS, \ CFG_WEBSEARCH_MAX_RECORDS_IN_GROUPS from invenio.access_control_config import CFG_EXTERNAL_AUTH_USING_SSO, \ CFG_EXTERNAL_AUTH_LOGOUT_SSO from invenio.urlutils import make_canonical_urlargd, create_url, create_html_link from invenio.htmlutils import escape_html, nmtoken_from_string from invenio.messages import gettext_set_language, language_list_long from invenio.websession_config import CFG_WEBSESSION_GROUP_JOIN_POLICY class Template: def tmpl_back_form(self, ln, message, url, link): """ A standard one-message-go-back-link page. Parameters: - 'ln' *string* - The language to display the interface in - 'message' *string* - The message to display - 'url' *string* - The url to go back to - 'link' *string* - The link text """ out = """
%(message)s %(link)s
"""% { 'message' : message, 'url' : url, 'link' : link, 'ln' : ln } return out def tmpl_external_setting(self, ln, key, value): _ = gettext_set_language(ln) out = """ %s: %s """ % (key, value) return out def tmpl_external_user_settings(self, ln, html_settings): _ = gettext_set_language(ln) out = """

%(external_user_settings)s

%(html_settings)s

%(external_user_groups)s

%(consult_external_groups)s

""" % { 'external_user_settings' : _('External account settings'), 'html_settings' : html_settings, 'consult_external_groups' : _('You can consult the list of your external groups directly in the %(x_url_open)sgroups page%(x_url_close)s.') % { 'x_url_open' : '' % ln, 'x_url_close' : '' }, 'external_user_groups' : _('External user groups'), } return out def tmpl_user_preferences(self, ln, email, email_disabled, password_disabled, nickname): """ Displays a form for the user to change his email/password. Parameters: - 'ln' *string* - The language to display the interface in - 'email' *string* - The email of the user - 'email_disabled' *boolean* - If the user has the right to edit his email - 'password_disabled' *boolean* - If the user has the right to edit his password - 'nickname' *string* - The nickname of the user (empty string if user does not have it) """ # load the right message language _ = gettext_set_language(ln) out = """

%(edit_params)s

%(change_user)s


(%(mandatory)s)
%(nickname_prefix)s%(nickname)s%(nickname_suffix)s
%(note)s: %(fixed_nickname_note)s

(%(mandatory)s)

%(example)s: john.doe@example.com
   
""" % { 'change_user' : _("If you want to change your email or set for the first time your nickname, please set new values in the form below."), 'edit_params' : _("Edit login credentials"), 'nickname_label' : _("Nickname"), 'nickname' : nickname, 'nickname_prefix' : nickname=='' and '
'+_("Example")+':johnd' or '', 'new_email' : _("New email address"), 'mandatory' : _("mandatory"), 'example' : _("Example"), 'note' : _("Note"), 'set_values' : _("Set new values"), 'email' : email, 'email_disabled' : email_disabled and "readonly" or "", 'sitesecureurl': CFG_SITE_SECURE_URL, 'fixed_nickname_note' : _('Since this is considered as a signature for comments and reviews, once set it can not be changed.') } if not password_disabled and not CFG_EXTERNAL_AUTH_USING_SSO: out += """

%(change_pass)s



%(note)s: %(old_password_note)s


%(note)s: %(password_note)s
   
""" % { 'change_pass' : _("If you want to change your password, please enter the old one and set the new value in the form below."), 'mandatory' : _("mandatory"), 'old_password' : _("Old password"), 'new_password' : _("New password"), 'optional' : _("optional"), 'note' : _("Note"), 'password_note' : _("The password phrase may contain punctuation, spaces, etc."), 'old_password_note' : _("You must fill the old password in order to set a new one."), 'retype_password' : _("Retype password"), 'set_values' : _("Set new password"), 'password_disabled' : password_disabled and "disabled" or "", 'sitesecureurl': CFG_SITE_SECURE_URL, } elif not CFG_EXTERNAL_AUTH_USING_SSO and CFG_CERN_SITE: out += "

" + _("""If you are using a lightweight CERN account you can %(x_url_open)sreset the password%(x_url_close)s.""") % \ {'x_url_open' : \ '' \ % (make_canonical_urlargd({'email': email, 'returnurl' : CFG_SITE_SECURE_URL + '/youraccount/edit' + make_canonical_urlargd({'lang' : ln}, {})}, {})), 'x_url_close' : ''} + "

" elif CFG_EXTERNAL_AUTH_USING_SSO and CFG_CERN_SITE: out += "

" + _("""You can change or reset your CERN account password by means of the %(x_url_open)sCERN account system%(x_url_close)s.""") % \ {'x_url_open' : '', 'x_url_close' : ''} + "

" return out def tmpl_user_bibcatalog_auth(self, bibcatalog_username="", bibcatalog_password="", ln=CFG_SITE_LANG): """template for setting username and pw for bibcatalog backend""" _ = gettext_set_language(ln) out = """

%(edit_bibcatalog_settings)s

%(username)s: %(password)s:
""" % { 'sitesecureurl' : CFG_SITE_SECURE_URL, 'bibcatalog_username' : bibcatalog_username, 'bibcatalog_password' : bibcatalog_password, 'edit_bibcatalog_settings' : _("Edit cataloging interface settings"), 'username' : _("Username"), 'password' : _("Password"), 'update_settings' : _('Update settings') } return out def tmpl_user_lang_edit(self, ln, preferred_lang): _ = gettext_set_language(ln) out = """

%(edit_lang_settings)s

""" % { 'select_lang' : _('Select desired language of the web interface.'), 'update_settings' : _('Update settings') } return out def tmpl_user_websearch_edit(self, ln, current = 10, show_latestbox = True, show_helpbox = True): _ = gettext_set_language(ln) out = """

%(edit_websearch_settings)s

""" % { 'update_settings' : _("Update settings"), 'select_group_records' : _("Number of search results per page"), } return out def tmpl_user_external_auth(self, ln, methods, current, method_disabled): """ Displays a form for the user to change his authentication method. Parameters: - 'ln' *string* - The language to display the interface in - 'methods' *array* - The methods of authentication - 'method_disabled' *boolean* - If the user has the right to change this - 'current' *string* - The currently selected method """ # load the right message language _ = gettext_set_language(ln) out = """
%(edit_method)s

%(explain_method)s:

%(select_method)s: """ % { 'edit_method' : _("Edit login method"), 'explain_method' : _("Please select which login method you would like to use to authenticate yourself"), 'select_method' : _("Select method"), 'sitesecureurl': CFG_SITE_SECURE_URL, } for system in methods: out += """
""" % { 'system' : system, 'disabled' : method_disabled and 'disabled="disabled"' or "", 'selected' : current == system and 'checked="checked"' or "", 'id' : nmtoken_from_string(system), } out += """
 
""" % { 'select_method' : _("Select method"), } return out def tmpl_lost_password_form(self, ln): """ Displays a form for the user to ask for his password sent by email. Parameters: - 'ln' *string* - The language to display the interface in - 'msg' *string* - Explicative message on top of the form. """ # load the right message language _ = gettext_set_language(ln) out = "

" + _("If you have lost the password for your %(sitename)s %(x_fmt_open)sinternal account%(x_fmt_close)s, then please enter your email address in the following form in order to have a password reset link emailed to you.") % {'x_fmt_open' : '', 'x_fmt_close' : '', 'sitename' : CFG_SITE_NAME_INTL[ln]} + "

" out += """
 
""" % { 'ln': ln, 'email' : _("Email address"), 'send' : _("Send password reset link"), } if CFG_CERN_SITE: out += "

" + _("If you have been using the %(x_fmt_open)sCERN login system%(x_fmt_close)s, then you can recover your password through the %(x_url_open)sCERN authentication system%(x_url_close)s.") % {'x_fmt_open' : '', 'x_fmt_close' : '', 'x_url_open' : '' \ % make_canonical_urlargd({'lf': 'auth', 'returnURL' : CFG_SITE_SECURE_URL + '/youraccount/login?ln='+ln}, {}), 'x_url_close' : ''} + " " else: out += "

" + _("Note that if you have been using an external login system, then we cannot do anything and you have to ask there.") + " " out += _("Alternatively, you can ask %s to change your login system from external to internal.") % ("""%(email)s""" % { 'email' : CFG_SITE_SUPPORT_EMAIL }) + "

" return out def tmpl_account_info(self, ln, uid, guest, CFG_CERN_SITE): """ Displays the account information Parameters: - 'ln' *string* - The language to display the interface in - 'uid' *string* - The user id - 'guest' *boolean* - If the user is guest - 'CFG_CERN_SITE' *boolean* - If the site is a CERN site """ # load the right message language _ = gettext_set_language(ln) out = """

%(account_offer)s

""" % { 'account_offer' : _("%s offers you the possibility to personalize the interface, to set up your own personal library of documents, or to set up an automatic alert query that would run periodically and would notify you of search results by email.") % CFG_SITE_NAME_INTL[ln], } if not guest: out += """
%(your_settings)s
%(change_account)s
""" % { 'ln' : ln, 'your_settings' : _("Your Settings"), 'change_account' : _("Set or change your account email address or password. Specify your preferences about the look and feel of the interface.") } out += """
%(your_searches)s
%(search_explain)s
""" % { 'ln' : ln, 'your_searches' : _("Your Searches"), 'search_explain' : _("View all the searches you performed during the last 30 days."), } out += """
%(your_baskets)s
%(basket_explain)s""" % { 'ln' : ln, 'your_baskets' : _("Your Baskets"), 'basket_explain' : _("With baskets you can define specific collections of items, store interesting records you want to access later or share with others."), } if guest and CFG_WEBSESSION_DIFFERENTIATE_BETWEEN_GUESTS: out += self.tmpl_warning_guest_user(ln = ln, type = "baskets") out += """
%(your_alerts)s
%(explain_alerts)s""" % { 'ln' : ln, 'your_alerts' : _("Your Alerts"), 'explain_alerts' : _("Subscribe to a search which will be run periodically by our service. The result can be sent to you via Email or stored in one of your baskets."), } if guest and CFG_WEBSESSION_DIFFERENTIATE_BETWEEN_GUESTS: out += self.tmpl_warning_guest_user(type="alerts", ln = ln) out += "
" if CFG_CERN_SITE: out += """
%(your_loans)s
%(explain_loans)s
""" % { 'your_loans' : _("Your Loans"), 'explain_loans' : _("Check out book you have on loan, submit borrowing requests, etc. Requires CERN ID."), } out += """
""" return out def tmpl_warning_guest_user(self, ln, type): """ Displays a warning message about the specified type Parameters: - 'ln' *string* - The language to display the interface in - 'type' *string* - The type of data that will get lost in case of guest account (for the moment: 'alerts' or 'baskets') """ # load the right message language _ = gettext_set_language(ln) if (type=='baskets'): msg = _("You are logged in as a guest user, so your baskets will disappear at the end of the current session.") + ' ' elif (type=='alerts'): msg = _("You are logged in as a guest user, so your alerts will disappear at the end of the current session.") + ' ' msg += _("If you wish you can %(x_url_open)slogin or register here%(x_url_close)s.") % {'x_url_open': '', 'x_url_close': ''} return """
%s
""" % msg def tmpl_account_body(self, ln, user): """ Displays the body of the actions of the user Parameters: - 'ln' *string* - The language to display the interface in - 'user' *string* - The username (nickname or email) """ # load the right message language _ = gettext_set_language(ln) out = _("You are logged in as %(x_user)s. You may want to a) %(x_url1_open)slogout%(x_url1_close)s; b) edit your %(x_url2_open)saccount settings%(x_url2_close)s.") %\ {'x_user': user, 'x_url1_open': '', 'x_url1_close': '', 'x_url2_open': '', 'x_url2_close': '', } return out + "

" def tmpl_account_template(self, title, body, ln, url): """ Displays a block of the your account page Parameters: - 'ln' *string* - The language to display the interface in - 'title' *string* - The title of the block - 'body' *string* - The body of the block - 'url' *string* - The URL to go to the proper section """ out =""" """ % (url, title, body) return out - def tmpl_account_page(self, ln, warnings, warning_list, accBody, baskets, alerts, searches, messages, loans, groups, submissions, approvals, administrative): + def tmpl_account_page(self, ln, warnings, warning_list, accBody, baskets, alerts, searches, messages, loans, groups, submissions, approvals, tickets, administrative): """ Displays the your account page Parameters: - 'ln' *string* - The language to display the interface in - 'accBody' *string* - The body of the heading block - 'baskets' *string* - The body of the baskets block - 'alerts' *string* - The body of the alerts block - 'searches' *string* - The body of the searches block - 'messages' *string* - The body of the messages block - 'groups' *string* - The body of the groups block - 'submissions' *string* - The body of the submission block - 'approvals' *string* - The body of the approvals block - 'administrative' *string* - The body of the administrative block """ # load the right message language _ = gettext_set_language(ln) out = "" if warnings == "1": out += self.tmpl_general_warnings(warning_list) out += self.tmpl_account_template(_("Your Account"), accBody, ln, '/youraccount/edit?ln=%s' % ln) if messages: out += self.tmpl_account_template(_("Your Messages"), messages, ln, '/yourmessages/display?ln=%s' % ln) if loans: out += self.tmpl_account_template(_("Your Loans"), loans, ln, '/yourloans/display?ln=%s' % ln) if baskets: out += self.tmpl_account_template(_("Your Baskets"), baskets, ln, '/yourbaskets/display?ln=%s' % ln) if alerts: out += self.tmpl_account_template(_("Your Alert Searches"), alerts, ln, '/youralerts/list?ln=%s' % ln) if searches: out += self.tmpl_account_template(_("Your Searches"), searches, ln, '/youralerts/display?ln=%s' % ln) if groups: groups_description = _("You can consult the list of %(x_url_open)syour groups%(x_url_close)s you are administering or are a member of.") groups_description %= {'x_url_open': '', 'x_url_close': ''} out += self.tmpl_account_template(_("Your Groups"), groups_description, ln, '/yourgroups/display?ln=%s' % ln) if submissions: submission_description = _("You can consult the list of %(x_url_open)syour submissions%(x_url_close)s and inquire about their status.") submission_description %= {'x_url_open': '', 'x_url_close': ''} out += self.tmpl_account_template(_("Your Submissions"), submission_description, ln, '/yoursubmissions.py?ln=%s' % ln) if approvals: approval_description = _("You can consult the list of %(x_url_open)syour approvals%(x_url_close)s with the documents you approved or refereed.") approval_description %= {'x_url_open': '', 'x_url_close': ''} out += self.tmpl_account_template(_("Your Approvals"), approval_description, ln, '/yourapprovals.py?ln=%s' % ln) + #check if this user might have tickets + if tickets: + ticket_description = _("You can consult the list of %(x_url_open)syour tickets%(x_url_close)s.") + ticket_description %= {'x_url_open': '', + 'x_url_close': ''} + out += self.tmpl_account_template(_("Your Tickets"), ticket_description, ln, '/yourtickets?ln=%s' % ln) if administrative: out += self.tmpl_account_template(_("Your Administrative Activities"), administrative, ln, '/admin') return out def tmpl_account_emailMessage(self, ln, msg): """ Displays a link to retrieve the lost password Parameters: - 'ln' *string* - The language to display the interface in - 'msg' *string* - Explicative message on top of the form. """ # load the right message language _ = gettext_set_language(ln) out ="" out +=""" %(msg)s %(try_again)s """ % { 'ln' : ln, 'msg' : msg, 'try_again' : _("Try again") } return out def tmpl_account_reset_password_email_body(self, email, reset_key, ip_address, ln=CFG_SITE_LANG): """ The body of the email that sends lost internal account passwords to users. """ _ = gettext_set_language(ln) out = """ %(intro)s %(intro2)s <%(link)s> %(outro)s %(outro2)s""" % { 'intro': _("Somebody (possibly you) coming from %(x_ip_address)s " "has asked\nfor a password reset at %(x_sitename)s\nfor " "the account \"%(x_email)s\"." % { 'x_sitename' :CFG_SITE_NAME_INTL.get(ln, CFG_SITE_NAME), 'x_email' : email, 'x_ip_address' : ip_address, } ), 'intro2' : _("If you want to reset the password for this account, please go to:"), 'link' : "%s/youraccount/access%s" % (CFG_SITE_SECURE_URL, make_canonical_urlargd({ 'ln' : ln, 'mailcookie' : reset_key }, {})), 'outro' : _("in order to confirm the validity of this request."), 'outro2' : _("Please note that this URL will remain valid for about %(days)s days only.") % {'days': CFG_WEBSESSION_RESET_PASSWORD_EXPIRE_IN_DAYS}, } return out def tmpl_account_address_activation_email_body(self, email, address_activation_key, ip_address, ln=CFG_SITE_LANG): """ The body of the email that sends email address activation cookie passwords to users. """ _ = gettext_set_language(ln) out = """ %(intro)s %(intro2)s <%(link)s> %(outro)s %(outro2)s""" % { 'intro': _("Somebody (possibly you) coming from %(x_ip_address)s " "has asked\nto register a new account at %(x_sitename)s\nfor the " "email address \"%(x_email)s\"." % { 'x_sitename' :CFG_SITE_NAME_INTL.get(ln, CFG_SITE_NAME), 'x_email' : email, 'x_ip_address' : ip_address, } ), 'intro2' : _("If you want to complete this account registration, please go to:"), 'link' : "%s/youraccount/access%s" % (CFG_SITE_SECURE_URL, make_canonical_urlargd({ 'ln' : ln, 'mailcookie' : address_activation_key }, {})), 'outro' : _("in order to confirm the validity of this request."), 'outro2' : _("Please note that this URL will remain valid for about %(days)s days only.") % {'days' : CFG_WEBSESSION_ADDRESS_ACTIVATION_EXPIRE_IN_DAYS}, } return out def tmpl_account_emailSent(self, ln, email): """ Displays a confirmation message for an email sent Parameters: - 'ln' *string* - The language to display the interface in - 'email' *string* - The email to which the message has been sent """ # load the right message language _ = gettext_set_language(ln) out ="" out += _("Okay, a password reset link has been emailed to %s.") % email return out def tmpl_account_delete(self, ln): """ Displays a confirmation message about deleting the account Parameters: - 'ln' *string* - The language to display the interface in """ # load the right message language _ = gettext_set_language(ln) out = "

" + _("""Deleting your account""") + '

' return out def tmpl_account_logout(self, ln): """ Displays a confirmation message about logging out Parameters: - 'ln' *string* - The language to display the interface in """ # load the right message language _ = gettext_set_language(ln) out = _("You are no longer recognized by our system.") + ' ' if CFG_EXTERNAL_AUTH_USING_SSO and CFG_EXTERNAL_AUTH_LOGOUT_SSO: out += _("""You are still recognized by the centralized %(x_fmt_open)sSSO%(x_fmt_close)s system. You can %(x_url_open)slogout from SSO%(x_url_close)s, too.""") % \ {'x_fmt_open' : '', 'x_fmt_close' : '', 'x_url_open' : '' % CFG_EXTERNAL_AUTH_LOGOUT_SSO, 'x_url_close' : ''} out += '
' out += _("If you wish you can %(x_url_open)slogin here%(x_url_close)s.") % \ {'x_url_open': '', 'x_url_close': ''} return out def tmpl_login_form(self, ln, referer, internal, register_available, methods, selected_method, msg=None): """ Displays a login form Parameters: - 'ln' *string* - The language to display the interface in - 'referer' *string* - The referer URL - will be redirected upon after login - 'internal' *boolean* - If we are producing an internal authentication - 'register_available' *boolean* - If users can register freely in the system - 'methods' *array* - The available authentication methods - 'selected_method' *string* - The default authentication method - 'msg' *string* - The message to print before the form, if needed """ # load the right message language _ = gettext_set_language(ln) if msg is "": out = "

%(please_login)s

" % { 'please_login' : _("If you already have an account, please login using the form below.") } if CFG_CERN_SITE: out += "

" + _("If you don't own a CERN account yet, you can register a %(x_url_open)snew CERN lightweight account%(x_url_close)s.") % {'x_url_open' : '', 'x_url_close' : ''} + "

" else: if register_available: out += "

"+_("If you don't own an account yet, please %(x_url_open)sregister%(x_url_close)s an internal account.") %\ {'x_url_open': '', 'x_url_close': ''} + "

" else: out += "

" + _("It is not possible to create an account yourself. Contact %s if you want an account.") % ('%s' % (CFG_SITE_SUPPORT_EMAIL, CFG_SITE_SUPPORT_EMAIL)) + "

" else: out = "

%s

" % msg out += """
""" if len(methods) > 1: # more than one method, must make a select login_select = """" out += """ """ % { 'login_title' : _("Login method:"), 'login_select' : login_select, } else: # only one login method available out += """""" % (methods[0]) out += """
%(login_select)s
""" % { 'ln': ln, 'referer' : cgi.escape(referer), 'username' : _("Username"), 'password' : _("Password"), 'remember_me' : _("Remember login on this computer."), 'login' : _("login"), } if internal: out += """   (%(lost_pass)s)""" % { 'ln' : ln, 'lost_pass' : _("Lost your password?") } out += """
""" out += """

%(note)s: %(note_text)s

""" % { 'note' : _("Note"), 'note_text': _("You can use your nickname or your email address to login.")} return out def tmpl_lost_your_password_teaser(self, ln=CFG_SITE_LANG): """Displays a short sentence to attract user to the fact that maybe he lost his password. Used by the registration page. """ _ = gettext_set_language(ln) out = "" out += """%(maybe_lost_pass)s""" % { 'ln' : ln, 'maybe_lost_pass': ("Maybe you have lost your password?") } return out def tmpl_reset_password_form(self, ln, email, reset_key, msg=''): """Display a form to reset the password.""" _ = gettext_set_language(ln) out = "" out = "

%s

" % _("Your request is valid. Please set the new " "desired password in the following form.") if msg: out += """

%s

""" % msg out += """
%(set_password_for)s:%(email)s
""" % { 'ln' : ln, 'reset_key' : reset_key, 'email' : email, 'set_password_for' : _('Set a new password for'), 'type_new_password' : _('Type the new password'), 'type_it_again' : _('Type again the new password'), 'set_new_password' : _('Set the new password') } return out def tmpl_register_page(self, ln, referer, level): """ Displays a login form Parameters: - 'ln' *string* - The language to display the interface in - 'referer' *string* - The referer URL - will be redirected upon after login - 'level' *int* - Login level (0 - all access, 1 - accounts activated, 2+ - no self-registration) """ # load the right message language _ = gettext_set_language(ln) out = "" if level <= 1: out += _("Please enter your email address and desired nickname and password:") if level == 1: out += _("It will not be possible to use the account before it has been verified and activated.") out += """

(%(mandatory)s)

%(example)s: john.doe@example.com

(%(mandatory)s)

%(example)s: johnd

(%(optional)s)

%(note)s: %(password_contain)s

%(note)s: %(explain_acc)s""" % { 'referer' : cgi.escape(referer), 'ln' : cgi.escape(ln), 'email_address' : _("Email address"), 'nickname' : _("Nickname"), 'password' : _("Password"), 'mandatory' : _("mandatory"), 'optional' : _("optional"), 'example' : _("Example"), 'note' : _("Note"), 'password_contain' : _("The password phrase may contain punctuation, spaces, etc."), 'retype' : _("Retype Password"), 'register' : _("register"), 'explain_acc' : _("Please do not use valuable passwords such as your Unix, AFS or NICE passwords with this service. Your email address will stay strictly confidential and will not be disclosed to any third party. It will be used to identify you for personal services of %s. For example, you may set up an automatic alert search that will look for new preprints and will notify you daily of new arrivals by email.") % CFG_SITE_NAME, } return out def tmpl_account_adminactivities(self, ln, uid, guest, roles, activities): """ Displays the admin activities block for this user Parameters: - 'ln' *string* - The language to display the interface in - 'uid' *string* - The used id - 'guest' *boolean* - If the user is guest - 'roles' *array* - The current user roles - 'activities' *array* - The user allowed activities """ # load the right message language _ = gettext_set_language(ln) out = "" # guest condition if guest: return _("You seem to be a guest user. You have to %(x_url_open)slogin%(x_url_close)s first.") % \ {'x_url_open': '', 'x_url_close': ''} # no rights condition if not roles: return "

" + _("You are not authorized to access administrative functions.") + "

" # displaying form out += "

" + _("You are enabled to the following roles: %(x_role)s.") % {'x_role': ('' + ", ".join(roles) + "")} + '

' if activities: # print proposed links: activities.sort(lambda x, y: cmp(x.lower(), y.lower())) tmp_out = '' for action in activities: if action == "runbibedit": tmp_out += """
   
%s""" % (CFG_SITE_URL, _("Run Record Editor")) if action == "runbibcirculation": tmp_out += """
    %s""" % (CFG_SITE_URL, ln, _("Run BibCirculation")) if action == "cfgbibformat": tmp_out += """
    %s""" % (CFG_SITE_URL, ln, _("Configure BibFormat")) if action == "cfgbibharvest": tmp_out += """
    %s""" % (CFG_SITE_URL, ln, _("Configure BibHarvest")) if action == "cfgoairepository": tmp_out += """
    %s""" % (CFG_SITE_URL, ln, _("Configure OAI Repository")) if action == "cfgbibindex": tmp_out += """
    %s""" % (CFG_SITE_URL, ln, _("Configure BibIndex")) if action == "cfgbibrank": tmp_out += """
    %s""" % (CFG_SITE_URL, ln, _("Configure BibRank")) if action == "cfgwebaccess": tmp_out += """
    %s""" % (CFG_SITE_URL, ln, _("Configure WebAccess")) if action == "cfgwebcomment": tmp_out += """
    %s""" % (CFG_SITE_URL, ln, _("Configure WebComment")) if action == "cfgwebsearch": tmp_out += """
    %s""" % (CFG_SITE_URL, ln, _("Configure WebSearch")) if action == "cfgwebsubmit": tmp_out += """
    %s""" % (CFG_SITE_URL, ln, _("Configure WebSubmit")) if tmp_out: out += _("Here are some interesting web admin links for you:") + tmp_out out += "
" + _("For more admin-level activities, see the complete %(x_url_open)sAdmin Area%(x_url_close)s.") %\ {'x_url_open': '', 'x_url_close': ''} return out def tmpl_create_userinfobox(self, ln, url_referer, guest, username, submitter, referee, admin, usebaskets, usemessages, usealerts, usegroups, useloans, usestats): """ Displays the user block Parameters: - 'ln' *string* - The language to display the interface in - 'url_referer' *string* - URL of the page being displayed - 'guest' *boolean* - If the user is guest - 'username' *string* - The username (nickname or email) - 'submitter' *boolean* - If the user is submitter - 'referee' *boolean* - If the user is referee - 'admin' *boolean* - If the user is admin - 'usebaskets' *boolean* - If baskets are enabled for the user - 'usemessages' *boolean* - If messages are enabled for the user - 'usealerts' *boolean* - If alerts are enabled for the user - 'usegroups' *boolean* - If groups are enabled for the user - 'useloans' *boolean* - If loans are enabled for the user - 'usestats' *boolean* - If stats are enabled for the user """ # load the right message language _ = gettext_set_language(ln) out = """ """ % CFG_SITE_URL if guest: out += """%(guest_msg)s :: %(login)s""" % { 'sitesecureurl': CFG_SITE_SECURE_URL, 'ln' : ln, 'guest_msg' : _("guest"), 'referer' : url_referer and ('&referer=%s' % urllib.quote(url_referer)) or '', 'login' : _('login') } else: out += """%(username)s :: %(account)s :: """ % { 'sitesecureurl' : CFG_SITE_SECURE_URL, 'ln' : ln, 'account' : _("account"), 'username' : username } if usemessages: out += """%(messages)s :: """ % { 'sitesecureurl' : CFG_SITE_SECURE_URL, 'ln' : ln, 'messages' : _('messages') } if useloans: out += """%(loans)s :: """ % { 'sitesecureurl' : CFG_SITE_SECURE_URL, 'ln' : ln, 'loans': _("loans") } if usebaskets: out += """%(baskets)s :: """ % { 'sitesecureurl' : CFG_SITE_SECURE_URL, 'ln' : ln, 'baskets' : _("baskets") } if usealerts: out += """%(alerts)s :: """ % { 'sitesecureurl' : CFG_SITE_SECURE_URL, 'ln' : ln, 'alerts' : _("alerts"), } if usegroups: out += """%(groups)s :: """ % { 'sitesecureurl' : CFG_SITE_SECURE_URL, 'ln' : ln, 'groups' : _("groups"), } if usestats: out += """%(stats)s :: """ % { 'siteurl' : CFG_SITE_URL, 'ln' : ln, 'stats' : _("statistics"), } if submitter: out += """%(submission)s :: """ % { 'sitesecureurl' : CFG_SITE_SECURE_URL, 'ln' : ln, 'submission' : _("submissions"), } if referee: out += """%(approvals)s :: """ % { 'sitesecureurl' : CFG_SITE_SECURE_URL, 'ln' : ln, 'approvals' : _("approvals"), } if admin: out += """%(administration)s :: """ % { 'sitesecureurl' : CFG_SITE_SECURE_URL, 'ln' : ln, 'administration' : _("administration"), } out += """%(logout)s""" % { 'sitesecureurl' : CFG_SITE_SECURE_URL, 'ln' : ln, 'logout' : _("logout"), } return out def tmpl_warning(self, warnings, ln=CFG_SITE_LANG): """ Prepare the warnings list @param warnings: list of warning tuples (warning_msg, arg1, arg2, etc) @return: html string of warnings """ from invenio.errorlib import get_msgs_for_code_list span_class = 'important' out = "" if type(warnings) is not list: warnings = [warnings] if len(warnings) > 0: warnings_parsed = get_msgs_for_code_list(warnings, 'warning', ln) for (warning_code, warning_text) in warnings_parsed: if not warning_code.startswith('WRN'): #display only warnings that begin with WRN to user continue span_class = 'important' out += ''' %(warning)s
''' % \ { 'span_class' : span_class, 'warning' : warning_text } return out else: return "" def tmpl_warnings(self, warnings, ln=CFG_SITE_LANG): """ Display len(warnings) warning fields @param infos: list of strings @param ln=language @return: html output """ if not((type(warnings) is list) or (type(warnings) is tuple)): warnings = [warnings] warningbox = "" if warnings != []: warningbox = "
\n Warning:\n" for warning in warnings: lines = warning.split("\n") warningbox += "

" for line in lines[0:-1]: warningbox += line + "
\n" warningbox += lines[-1] + "

" warningbox += "

\n" return warningbox def tmpl_display_all_groups(self, infos, admin_group_html, member_group_html, external_group_html = None, warnings=[], ln=CFG_SITE_LANG): """ Displays the 3 tables of groups: admin, member and external Parameters: - 'ln' *string* - The language to display the interface in - 'admin_group_html' *string* - HTML code for displaying all the groups the user is the administrator of - 'member_group_html' *string* - HTML code for displaying all the groups the user is member of - 'external_group_html' *string* - HTML code for displaying all the external groups the user is member of """ _ = gettext_set_language(ln) group_text = self.tmpl_infobox(infos) group_text += self.tmpl_warning(warnings) if external_group_html: group_text += """
%s

%s

%s
""" %(admin_group_html, member_group_html, external_group_html) else: group_text += """
%s

%s
""" %(admin_group_html, member_group_html) return group_text def tmpl_display_admin_groups(self, groups, ln=CFG_SITE_LANG): """ Display the groups the user is admin of. Parameters: - 'ln' *string* - The language to display the interface in - 'groups' *list* - All the group the user is admin of - 'infos' *list* - Display infos on top of admin group table """ _ = gettext_set_language(ln) img_link = """ %(text)s
%(text)s
""" out = self.tmpl_group_table_title(img="/img/group_admin.png", text=_("You are an administrator of the following groups:") ) out += """ """ %(_("Group"), _("Description")) if len(groups) == 0: out += """ """ %(_("You are not an administrator of any groups."),) for group_data in groups: (grpID, name, description) = group_data edit_link = img_link % {'siteurl' : CFG_SITE_URL, 'grpID' : grpID, 'ln': ln, 'img':"webbasket_create_small.png", 'text':_("Edit group"), 'action':"edit" } members_link = img_link % {'siteurl' : CFG_SITE_URL, 'grpID' : grpID, 'ln': ln, 'img':"webbasket_usergroup.png", 'text':_("Edit %s members") % '', 'action':"members" } out += """ """ % (cgi.escape(name), cgi.escape(description), edit_link, members_link) out += """
%s %s    
%s
%s %s %s %s
     
""" % {'ln': ln, 'write_label': _("Create new group"), } return out def tmpl_display_member_groups(self, groups, ln=CFG_SITE_LANG): """ Display the groups the user is member of. Parameters: - 'ln' *string* - The language to display the interface in - 'groups' *list* - All the group the user is member of """ _ = gettext_set_language(ln) group_text = self.tmpl_group_table_title(img="/img/webbasket_us.png", text=_("You are a member of the following groups:")) group_text += """ """ % (_("Group"), _("Description")) if len(groups) == 0: group_text += """ """ %(_("You are not a member of any groups."),) for group_data in groups: (id, name, description) = group_data group_text += """ """ % (cgi.escape(name), cgi.escape(description)) group_text += """
%s %s
%s
%s %s
""" % {'ln': ln, 'join_label': _("Join new group"), 'leave_label':_("Leave group") } return group_text def tmpl_display_external_groups(self, groups, ln=CFG_SITE_LANG): """ Display the external groups the user is member of. Parameters: - 'ln' *string* - The language to display the interface in - 'groups' *list* - All the group the user is member of """ _ = gettext_set_language(ln) group_text = self.tmpl_group_table_title(img="/img/webbasket_us.png", text=_("You are a member of the following external groups:")) group_text += """ """ % (_("Group"), _("Description")) if len(groups) == 0: group_text += """ """ %(_("You are not a member of any external groups."),) for group_data in groups: (id, name, description) = group_data group_text += """ """ % (cgi.escape(name), cgi.escape(description)) group_text += """
%s %s
%s
%s %s
""" return group_text def tmpl_display_input_group_info(self, group_name, group_description, join_policy, act_type="create", grpID="", warnings=[], ln=CFG_SITE_LANG): """ Display group data when creating or updating a group: Name, description, join_policy. Parameters: - 'ln' *string* - The language to display the interface in - 'group_name' *string* - name of the group - 'group_description' *string* - description of the group - 'join_policy' *string* - join policy - 'act_type' *string* - info about action : create or edit(update) - 'grpID' *string* - ID of the group(not null in case of group editing) - 'warnings' *list* - Display warning if values are not correct """ _ = gettext_set_language(ln) #default hidden_id ="" form_name = "create_group" action = CFG_SITE_URL + '/yourgroups/create' button_label = _("Create new group") button_name = "create_button" label = _("Create new group") delete_text = "" if act_type == "update": form_name = "update_group" action = CFG_SITE_URL + '/yourgroups/edit' button_label = _("Update group") button_name = "update" label = _('Edit group %s') % cgi.escape(group_name) delete_text = """""" delete_text %= (_("Delete group"),"delete") if grpID != "": hidden_id = """""" hidden_id %= grpID out = self.tmpl_warning(warnings) out += """
%(label)s %(label)s
%(join_policy_label)s %(join_policy)s
%(hidden_id)s
%(delete_text)s
""" out %= {'action' : action, 'logo': CFG_SITE_URL + '/img/webbasket_create.png', 'label': label, 'form_name' : form_name, 'name_label': _("Group name:"), 'delete_text': delete_text, 'description_label': _("Group description:"), 'join_policy_label': _("Group join policy:"), 'group_name': cgi.escape(group_name, 1), 'group_description': cgi.escape(group_description, 1), 'button_label': button_label, 'button_name':button_name, 'cancel_label':_("Cancel"), 'hidden_id':hidden_id, 'ln': ln, 'join_policy' :self.__create_join_policy_selection_menu("join_policy", join_policy, ln) } return out def tmpl_display_input_join_group(self, group_list, group_name, group_from_search, search, warnings=[], ln=CFG_SITE_LANG): """ Display the groups the user can join. He can use default select list or the search box Parameters: - 'ln' *string* - The language to display the interface in - 'group_list' *list* - All the group the user can join - 'group_name' *string* - Name of the group the user is looking for - 'group_from search' *list* - List of the group the user can join matching group_name - 'search' *int* - User is looking for group using group_name - 'warnings' *list* - Display warning if two group are selected """ _ = gettext_set_language(ln) out = self.tmpl_warning(warnings) search_content = "" if search: search_content = """ """ if group_from_search != []: search_content += self.__create_select_menu('grpID', group_from_search, _("Please select:")) else: search_content += _("No matching group") search_content += """ """ out += """
%(label)s %(label)s
%(search_content)s
%(list_label)s %(group_list)s  



""" out %= {'action' : CFG_SITE_URL + '/yourgroups/join', 'logo': CFG_SITE_URL + '/img/webbasket_create.png', 'label': _("Join group"), 'group_name': cgi.escape(group_name, 1), 'label2':_("or find it") + ': ', 'list_label':_("Choose group:"), 'ln': ln, 'find_label': _("Find group"), 'cancel_label':_("Cancel"), 'group_list' :self.__create_select_menu("grpID",group_list, _("Please select:")), 'search_content' : search_content } return out def tmpl_display_manage_member(self, grpID, group_name, members, pending_members, infos=[], warnings=[], ln=CFG_SITE_LANG): """Display current members and waiting members of a group. Parameters: - 'ln' *string* - The language to display the interface in - 'grpID *string* - ID of the group - 'group_name' *string* - Name of the group - 'members' *list* - List of the current members - 'pending_members' *list* - List of the waiting members - 'infos' *tuple of 2 lists* - Message to inform user about his last action - 'warnings' *list* - Display warning if two group are selected """ _ = gettext_set_language(ln) out = self.tmpl_warning(warnings) out += self.tmpl_infobox(infos) out += """

%(title)s

%(img_alt_header1)s %(header1)s
 
%(member_text)s
%(img_alt_header2)s %(header2)s
 
%(pending_text)s
%(img_alt_header3)s %(header3)s
 
%(invite_text)s
""" if members : member_list = self.__create_select_menu("member_id", members, _("Please select:")) member_text = """ %s """ % (member_list,_("Remove member")) else : member_text = """%s""" % _("No members.") if pending_members : pending_list = self.__create_select_menu("pending_member_id", pending_members, _("Please select:")) pending_text = """ %s """ % (pending_list,_("Accept member"), _("Reject member")) else : pending_text = """%s""" % _("No members awaiting approval.") header1 = self.tmpl_group_table_title(text=_("Current members")) header2 = self.tmpl_group_table_title(text=_("Members awaiting approval")) header3 = _("Invite new members") write_a_message_url = create_url( "%s/yourmessages/write" % CFG_SITE_URL, { 'ln' : ln, 'msg_subject' : _('Invitation to join "%s" group' % escape_html(group_name)), 'msg_body' : _("""\ Hello: I think you might be interested in joining the group "%s". You can join by clicking here: %s. Best regards. """) % (group_name, create_html_link("%s/yourgroups/join" % CFG_SITE_URL, { 'grpID' : grpID, 'join_button' : "1", }, link_label=group_name, escape_urlargd=True, escape_linkattrd=True))}) link_open = '' % escape_html(write_a_message_url) invite_text = _("If you want to invite new members to join your group, please use the %(x_url_open)sweb message%(x_url_close)s system.") % \ {'x_url_open': link_open, 'x_url_close': ''} action = CFG_SITE_URL + '/yourgroups/members?ln=' + ln out %= {'title':_('Group: %s') % escape_html(group_name), 'member_text' : member_text, 'pending_text' :pending_text, 'action':action, 'grpID':grpID, 'header1': header1, 'header2': header2, 'header3': header3, 'img_alt_header1': _("Current members"), 'img_alt_header2': _("Members awaiting approval"), 'img_alt_header3': _("Invite new members"), 'invite_text': invite_text, 'imgurl': CFG_SITE_URL + '/img', 'cancel_label':_("Cancel"), 'ln':ln } return out def tmpl_display_input_leave_group(self, groups, warnings=[], ln=CFG_SITE_LANG): """Display groups the user can leave. Parameters: - 'ln' *string* - The language to display the interface in - 'groups' *list* - List of groups the user is currently member of - 'warnings' *list* - Display warning if no group is selected """ _ = gettext_set_language(ln) out = self.tmpl_warning(warnings) out += """
%(label)s %(label)s
%(list_label)s %(groups)s  
%(submit)s
""" if groups: groups = self.__create_select_menu("grpID", groups, _("Please select:")) list_label = _("Group list") submit = """""" % _("Leave group") else : groups = _("You are not member of any group.") list_label = "" submit = "" action = CFG_SITE_URL + '/yourgroups/leave?ln=%s' action %= (ln) out %= {'groups' : groups, 'list_label' : list_label, 'action':action, 'logo': CFG_SITE_URL + '/img/webbasket_create.png', 'label' : _("Leave group"), 'cancel_label':_("Cancel"), 'ln' :ln, 'submit' : submit } return out def tmpl_confirm_delete(self, grpID, ln=CFG_SITE_LANG): """ display a confirm message when deleting a group @param ln: language @return: html output """ _ = gettext_set_language(ln) action = CFG_SITE_URL + '/yourgroups/edit' out = """
%(message)s
"""% {'message': _("Are you sure you want to delete this group?"), 'ln':ln, 'yes_label': _("Yes"), 'no_label': _("No"), 'grpID':grpID, 'action': action } return out def tmpl_confirm_leave(self, uid, grpID, ln=CFG_SITE_LANG): """ display a confirm message @param ln: language @return: html output """ _ = gettext_set_language(ln) action = CFG_SITE_URL + '/yourgroups/leave' out = """
%(message)s
"""% {'message': _("Are you sure you want to leave this group?"), 'ln':ln, 'yes_label': _("Yes"), 'no_label': _("No"), 'grpID':grpID, 'action': action } return out def __create_join_policy_selection_menu(self, name, current_join_policy, ln=CFG_SITE_LANG): """Private function. create a drop down menu for selection of join policy @param current_join_policy: join policy as defined in CFG_WEBSESSION_GROUP_JOIN_POLICY @param ln: language """ _ = gettext_set_language(ln) elements = [(CFG_WEBSESSION_GROUP_JOIN_POLICY['VISIBLEOPEN'], _("Visible and open for new members")), (CFG_WEBSESSION_GROUP_JOIN_POLICY['VISIBLEMAIL'], _("Visible but new members need approval")) ] select_text = _("Please select:") return self.__create_select_menu(name, elements, select_text, selected_key=current_join_policy) def __create_select_menu(self, name, elements, select_text, multiple=0, selected_key=None): """ private function, returns a popup menu @param name: name of HTML control @param elements: list of (key, value) """ if multiple : out = """ """ % name out += '' % (select_text) for (key, label) in elements: selected = '' if key == selected_key: selected = ' selected="selected"' out += ''% (key, selected, label) out += '' return out def tmpl_infobox(self, infos, ln=CFG_SITE_LANG): """Display len(infos) information fields @param infos: list of strings @param ln=language @return: html output """ _ = gettext_set_language(ln) if not((type(infos) is list) or (type(infos) is tuple)): infos = [infos] infobox = "" for info in infos: infobox += '
' lines = info.split("\n") for line in lines[0:-1]: infobox += line + "
\n" infobox += lines[-1] + "
\n" return infobox def tmpl_navtrail(self, ln=CFG_SITE_LANG, title=""): """ display the navtrail, e.g.: Your account > Your group > title @param title: the last part of the navtrail. Is not a link @param ln: language return html formatted navtrail """ _ = gettext_set_language(ln) nav_h1 = '%s' nav_h2 = "" if (title != ""): nav_h2 = ' > %s' nav_h2 = nav_h2 % (CFG_SITE_URL, _("Your Groups")) return nav_h1 % (CFG_SITE_URL, _("Your Account")) + nav_h2 def tmpl_group_table_title(self, img="", text="", ln=CFG_SITE_LANG): """ display the title of a table: - 'img' *string* - img path - 'text' *string* - title - 'ln' *string* - The language to display the interface in """ out = "
" if img: out += """ """ % (CFG_SITE_URL + img) out += """ %s
""" % text return out def tmpl_admin_msg(self, group_name, grpID, ln=CFG_SITE_LANG): """ return message content for joining group - 'group_name' *string* - name of the group - 'grpID' *string* - ID of the group - 'ln' *string* - The language to display the interface in """ _ = gettext_set_language(ln) subject = _("Group %s: New membership request") % group_name url = CFG_SITE_URL + "/yourgroups/members?grpID=%i&ln=%s" url %= (int(grpID), ln) # FIXME: which user? We should show his nickname. body = (_("A user wants to join the group %s.") % group_name) + '
' body += _("Please %(x_url_open)saccept or reject%(x_url_close)s this user's request.") % {'x_url_open': '', 'x_url_close': ''} body += '
' return subject, body def tmpl_member_msg(self, group_name, accepted=0, ln=CFG_SITE_LANG): """ return message content when new member is accepted/rejected - 'group_name' *string* - name of the group - 'accepted' *int* - 1 if new membership has been accepted, 0 if it has been rejected - 'ln' *string* - The language to display the interface in """ _ = gettext_set_language(ln) if accepted: subject = _("Group %s: Join request has been accepted") % (group_name) body = _("Your request for joining group %s has been accepted.") % (group_name) else: subject = _("Group %s: Join request has been rejected") % (group_name) body = _("Your request for joining group %s has been rejected.") % (group_name) url = CFG_SITE_URL + "/yourgroups/display?ln=" + ln body += '
' body += _("You can consult the list of %(x_url_open)syour groups%(x_url_close)s.") % {'x_url_open': '', 'x_url_close': ''} body += '
' return subject, body def tmpl_delete_msg(self, group_name, ln=CFG_SITE_LANG): """ return message content when new member is accepted/rejected - 'group_name' *string* - name of the group - 'ln' *string* - The language to display the interface in """ _ = gettext_set_language(ln) subject = _("Group %s has been deleted") % group_name url = CFG_SITE_URL + "/yourgroups/display?ln=" + ln body = _("Group %s has been deleted by its administrator.") % group_name body += '
' body += _("You can consult the list of %(x_url_open)syour groups%(x_url_close)s.") % {'x_url_open': '', 'x_url_close': ''} body += '
' return subject, body def tmpl_group_info(self, nb_admin_groups=0, nb_member_groups=0, nb_total_groups=0, ln=CFG_SITE_LANG): """ display infos about groups (used by myaccount.py) @param nb_admin_group: number of groups the user is admin of @param nb_member_group: number of groups the user is member of @param total_group: number of groups the user belongs to @param ln: language return: html output. """ _ = gettext_set_language(ln) out = _("You can consult the list of %(x_url_open)s%(x_nb_total)i groups%(x_url_close)s you are subscribed to (%(x_nb_member)i) or administering (%(x_nb_admin)i).") out %= {'x_url_open': '', 'x_nb_total': nb_total_groups, 'x_url_close': '', 'x_nb_admin': nb_admin_groups, 'x_nb_member': nb_member_groups} return out def tmpl_general_warnings(self, warning_list, ln=CFG_SITE_LANG): """ display information to the admin user about possible ssecurity problems in the system. """ message = "" _ = gettext_set_language(ln) #Try and connect to the mysql database with the default invenio password if "warning_mysql_password_equal_to_invenio_password" in warning_list: message += "

" message += _("Warning : The password set for MySQL is the same as the default CDS-Invenio password. For security purposes, you might want to change the password.") message += "

" #Try and connect to the invenio database with the default invenio password if "warning_invenio_password_equal_to_default" in warning_list: message += "

" message += _("Warning : The password set for the CDS Invenio database is the same as the default CDS-Invenio password. For security purposes, you might want to change the password.") message += "

" #Check if the admin password is empty if "warning_empty_admin_password" in warning_list: message += "

" message += _("Warning : The password set for the CDS-Invenio admin user is currently empty. For security purposes, it is strongly recommended that you add a password.") message += "

" #Check if the admin email has been changed from the default if "warning_site_support_email_equal_to_default" in warning_list: message += "

" message += _("Warning : The email address set for support email is currently set to cds.support@cern.ch . It is recommended that you change this to change this to your own address.") message += "

" #Check for a new release if "note_new_release_available" in warning_list: message += "

" message += _("A newer version of CDS-Invenio is available for download. Please visit ") message += "cdsware" message += "

" #Error downloading release notes if "error_cannot_download_release_notes" in warning_list: message += "

" message += _("Cannot download release notes from http://cdsware.cern.ch/, please check your internet connection") message += "

" return message diff --git a/modules/websession/lib/websession_webinterface.py b/modules/websession/lib/websession_webinterface.py index a93a6bc4a..9da3b197d 100644 --- a/modules/websession/lib/websession_webinterface.py +++ b/modules/websession/lib/websession_webinterface.py @@ -1,1255 +1,1291 @@ # -*- coding: utf-8 -*- ## ## This file is part of CDS Invenio. ## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 CERN. ## ## CDS Invenio is free software; you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation; either version 2 of the ## License, or (at your option) any later version. ## ## CDS Invenio is distributed in the hope that it will be useful, but ## WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with CDS Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. """CDS Invenio ACCOUNT HANDLING""" __revision__ = "$Id$" __lastupdated__ = """$Date$""" import cgi +import os from datetime import timedelta from invenio.config import \ CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS, \ CFG_ACCESS_CONTROL_LEVEL_SITE, \ CFG_ACCESS_CONTROL_NOTIFY_USER_ABOUT_NEW_ACCOUNT, \ CFG_SITE_NAME, \ CFG_SITE_NAME_INTL, \ CFG_SITE_SUPPORT_EMAIL, \ CFG_SITE_SECURE_URL, \ CFG_SITE_URL, \ CFG_CERN_SITE, \ CFG_WEBSESSION_RESET_PASSWORD_EXPIRE_IN_DAYS from invenio import webuser from invenio.webpage import page from invenio import webaccount from invenio import webbasket from invenio import webalert from invenio.dbquery import run_sql from invenio.webmessage import account_new_mail from invenio.access_control_engine import make_apache_message, make_list_apache_firerole, acc_authorize_action from invenio.webinterface_handler import wash_urlargd, WebInterfaceDirectory from invenio.urlutils import redirect_to_url, make_canonical_urlargd from invenio import webgroup +from invenio import bibcatalog_system from invenio import webgroup_dblayer from invenio.messages import gettext_set_language, wash_language from invenio.mailutils import send_email from invenio.access_control_mailcookie import mail_cookie_retrieve_kind, \ mail_cookie_check_pw_reset, mail_cookie_delete_cookie, \ mail_cookie_create_pw_reset, mail_cookie_check_role, \ mail_cookie_check_mail_activation, InvenioWebAccessMailCookieError, \ InvenioWebAccessMailCookieDeletedError, mail_cookie_check_authorize_action from invenio.access_control_config import CFG_WEBACCESS_WARNING_MSGS, \ CFG_EXTERNAL_AUTH_USING_SSO, CFG_EXTERNAL_AUTH_LOGOUT_SSO, \ CFG_EXTERNAL_AUTHENTICATION import invenio.template websession_templates = invenio.template.load('websession') +bibcatalog_templates = invenio.template.load('bibcatalog') class WebInterfaceYourAccountPages(WebInterfaceDirectory): _exports = ['', 'edit', 'change', 'lost', 'display', 'send_email', 'youradminactivities', 'access', 'delete', 'logout', 'login', 'register', 'resetpassword'] _force_https = True def index(self, req, form): redirect_to_url(req, '%s/youraccount/display' % CFG_SITE_SECURE_URL) def access(self, req, form): args = wash_urlargd(form, {'mailcookie' : (str, '')}) _ = gettext_set_language(args['ln']) title = _("Mail Cookie Service") try: kind = mail_cookie_retrieve_kind(args['mailcookie']) if kind == 'pw_reset': redirect_to_url(req, '%s/youraccount/resetpassword?k=%s&ln=%s' % (CFG_SITE_SECURE_URL, args['mailcookie'], args['ln'])) elif kind == 'role': uid = webuser.getUid(req) try: (role_name, expiration) = mail_cookie_check_role(args['mailcookie'], uid) except InvenioWebAccessMailCookieDeletedError: return page(title=_("Role authorization request"), req=req, body=_("This request for an authorization has already been authorized."), uid=webuser.getUid(req), navmenuid='youraccount', language=args['ln']) return page(title=title, body=webaccount.perform_back( _("You have successfully obtained an authorization as %(x_role)s! " "This authorization will last until %(x_expiration)s and until " "you close your browser if you are a guest user.") % {'x_role' : '%s' % role_name, 'x_expiration' : '%s' % expiration.strftime("%Y-%m-%d %H:%M:%S")}, '/youraccount/display?ln=%s' % args['ln'], _('login'), args['ln']), req=req, uid=webuser.getUid(req), language=args['ln'], lastupdated=__lastupdated__, navmenuid='youraccount') elif kind == 'mail_activation': try: email = mail_cookie_check_mail_activation(args['mailcookie']) if not email: raise StandardError webuser.confirm_email(email) body = "

" + _("You have confirmed the validity of your email" " address!") + "

" if CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS == 1: body += "

" + _("Please, wait for the administrator to " "enable your account.") + "

" else: uid = webuser.update_Uid(req, email) body += "

" + _("You can now go to %(x_url_open)syour account page%(x_url_close)s.") % {'x_url_open' : '' % args['ln'], 'x_url_close' : ''} + "

" return page(title=_("Email address successfully activated"), body=body, req=req, language=args['ln'], uid=webuser.getUid(req), lastupdated=__lastupdated__, navmenuid='youraccount') except InvenioWebAccessMailCookieDeletedError, e: body = "

" + _("You have already confirmed the validity of your email address!") + "

" if CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS == 1: body += "

" + _("Please, wait for the administrator to " "enable your account.") + "

" else: body += "

" + _("You can now go to %(x_url_open)syour account page%(x_url_close)s.") % {'x_url_open' : '' % args['ln'], 'x_url_close' : ''} + "

" return page(title=_("Email address successfully activated"), body=body, req=req, language=args['ln'], uid=webuser.getUid(req), lastupdated=__lastupdated__, navmenuid='youraccount') return webuser.page_not_authorized(req, "../youraccount/access", text=_("This request for confirmation of an email " "address is not valid or" " is expired."), navmenuid='youraccount') except InvenioWebAccessMailCookieError: return webuser.page_not_authorized(req, "../youraccount/access", text=_("This request for an authorization is not valid or" " is expired."), navmenuid='youraccount') def resetpassword(self, req, form): args = wash_urlargd(form, { 'k' : (str, ''), 'reset' : (int, 0), 'password' : (str, ''), 'password2' : (str, '') }) _ = gettext_set_language(args['ln']) email = mail_cookie_check_pw_reset(args['k']) reset_key = args['k'] title = _('Reset password') if email is None or CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS >= 3: return webuser.page_not_authorized(req, "../youraccount/resetpassword", text=_("This request for resetting the password is not valid or" " is expired."), navmenuid='youraccount') if not args['reset']: return page(title=title, body=webaccount.perform_reset_password(args['ln'], email, reset_key), req=req, secure_page_p = 1, language=args['ln'], lastupdated=__lastupdated__, navmenuid='youraccount') elif args['password'] != args['password2']: msg = _('The two provided passwords aren\'t equal.') return page(title=title, body=webaccount.perform_reset_password(args['ln'], email, reset_key, msg), req=req, secure_page_p = 1, language=args['ln'], lastupdated=__lastupdated__, navmenuid='youraccount') run_sql('UPDATE user SET password=AES_ENCRYPT(email,%s) WHERE email=%s', (args['password'], email)) mail_cookie_delete_cookie(reset_key) return page(title=title, body=webaccount.perform_back( _("The password was successfully set! " "You can now proceed with the login."), '/youraccount/login?ln=%s' % args['ln'], _('login'), args['ln']), req=req, language=args['ln'], lastupdated=__lastupdated__, navmenuid='youraccount') def display(self, req, form): args = wash_urlargd(form, {}) uid = webuser.getUid(req) # load the right message language _ = gettext_set_language(args['ln']) if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return webuser.page_not_authorized(req, "../youraccount/display", navmenuid='youraccount') if webuser.isGuestUser(uid): return page(title=_("Your Account"), body=webaccount.perform_info(req, args['ln']), description="%s Personalize, Main page" % CFG_SITE_NAME_INTL.get(args['ln'], CFG_SITE_NAME), keywords=_("%s, personalize") % CFG_SITE_NAME_INTL.get(args['ln'], CFG_SITE_NAME), uid=uid, req=req, secure_page_p = 1, language=args['ln'], lastupdated=__lastupdated__, navmenuid='youraccount') username = webuser.get_nickname_or_email(uid) user_info = webuser.collect_user_info(req) bask = user_info['precached_usebaskets'] and webbasket.account_list_baskets(uid, ln=args['ln']) or '' aler = user_info['precached_usealerts'] and webalert.account_list_alerts(uid, ln=args['ln']) or '' sear = webalert.account_list_searches(uid, ln=args['ln']) msgs = user_info['precached_usemessages'] and account_new_mail(uid, ln=args['ln']) or '' grps = user_info['precached_usegroups'] and webgroup.account_group(uid, ln=args['ln']) or '' appr = user_info['precached_useapprove'] sbms = user_info['precached_viewsubmissions'] loan = '' admn = webaccount.perform_youradminactivities(user_info, args['ln']) return page(title=_("Your Account"), body=webaccount.perform_display_account(req, username, bask, aler, sear, msgs, loan, grps, sbms, appr, admn, args['ln']), description="%s Personalize, Main page" % CFG_SITE_NAME_INTL.get(args['ln'], CFG_SITE_NAME), keywords=_("%s, personalize") % CFG_SITE_NAME_INTL.get(args['ln'], CFG_SITE_NAME), uid=uid, req=req, secure_page_p = 1, language=args['ln'], lastupdated=__lastupdated__, navmenuid='youraccount') def edit(self, req, form): args = wash_urlargd(form, {"verbose" : (int, 0)}) uid = webuser.getUid(req) # load the right message language _ = gettext_set_language(args['ln']) if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return webuser.page_not_authorized(req, "../youraccount/edit", navmenuid='youraccount') if webuser.isGuestUser(uid): return webuser.page_not_authorized(req, "../youraccount/edit", text=_("This functionality is forbidden to guest users."), navmenuid='youraccount') body = '' user_info = webuser.collect_user_info(req) if args['verbose'] == 9: keys = user_info.keys() keys.sort() for key in keys: body += "%s:%s
" % (key, user_info[key]) #check if the user should see bibcatalog user name / passwd in the settings can_config_bibcatalog = (acc_authorize_action(user_info, 'runbibedit')[0] == 0) return page(title= _("Your Settings"), body=body+webaccount.perform_set(webuser.get_email(uid), args['ln'], can_config_bibcatalog, verbose=args['verbose']), navtrail="""""" % (CFG_SITE_SECURE_URL, args['ln']) + _("Your Account") + """""", description=_("%s Personalize, Your Settings") % CFG_SITE_NAME_INTL.get(args['ln'], CFG_SITE_NAME), keywords=_("%s, personalize") % CFG_SITE_NAME_INTL.get(args['ln'], CFG_SITE_NAME), uid=uid, req=req, secure_page_p = 1, language=args['ln'], lastupdated=__lastupdated__, navmenuid='youraccount') def change(self, req, form): args = wash_urlargd(form, { 'nickname': (str, None), 'email': (str, None), 'old_password': (str, None), 'password': (str, None), 'password2': (str, None), 'login_method': (str, ""), 'group_records' : (int, None), 'latestbox' : (int, None), 'helpbox' : (int, None), 'lang' : (str, None), 'bibcatalog_username' : (str, None), 'bibcatalog_password' : (str, None), }) ## Wash arguments: args['login_method'] = wash_login_method(args['login_method']) if args['email']: args['email'] = args['email'].lower() ## Load the right message language: _ = gettext_set_language(args['ln']) ## Identify user and load old preferences: uid = webuser.getUid(req) prefs = webuser.get_user_preferences(uid) ## Check rights: if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return webuser.page_not_authorized(req, "../youraccount/change", navmenuid='youraccount') # FIXME: the branching below is far from optimal. Should be # based on the submitted form name ids, to know precisely on # which form the user clicked. Not on the passed values, as # is the case now. The function body is too big and in bad # need of refactoring anyway. ## Will hold the output messages: mess = '' ## Change login method if needed: if args['login_method'] and CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS < 4 \ and args['login_method'] in CFG_EXTERNAL_AUTHENTICATION.keys(): title = _("Settings edited") act = "/youraccount/display?ln=%s" % args['ln'] linkname = _("Show account") if prefs['login_method'] != args['login_method']: if CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS >= 4: mess += '

' + _("Unable to change login method.") elif not CFG_EXTERNAL_AUTHENTICATION[args['login_method']][0]: # Switching to internal authentication: we drop any external datas p_email = webuser.get_email(uid) webuser.drop_external_settings(uid) webgroup_dblayer.drop_external_groups(uid) prefs['login_method'] = args['login_method'] webuser.set_user_preferences(uid, prefs) mess += "

" + _("Switched to internal login method.") + " " mess += _("Please note that if this is the first time that you are using this account " "with the internal login method then the system has set for you " "a randomly generated password. Please click the " "following button to obtain a password reset request " "link sent to you via email:") + '

' mess += """

""" % (p_email, _("Send Password")) else: query = """SELECT email FROM user WHERE id = %i""" res = run_sql(query % uid) if res: email = res[0][0] else: email = None if not email: mess += '

' + _("Unable to switch to external login method %s, because your email address is unknown.") % cgi.escape(args['login_method']) else: try: if not CFG_EXTERNAL_AUTHENTICATION[args['login_method']][0].user_exists(email): mess += '

' + _("Unable to switch to external login method %s, because your email address is unknown to the external login system.") % cgi.escape(args['login_method']) else: prefs['login_method'] = args['login_method'] webuser.set_user_preferences(uid, prefs) mess += '

' + _("Login method successfully selected.") except AttributeError: mess += '

' + _("The external login method %s does not support email address based logins. Please contact the site administrators.") % cgi.escape(args['login_method']) ## Change email or nickname: if args['email'] or args['nickname']: uid2 = webuser.emailUnique(args['email']) uid_with_the_same_nickname = webuser.nicknameUnique(args['nickname']) if (CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS >= 2 or (CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS <= 1 and \ webuser.email_valid_p(args['email']))) \ and (args['nickname'] is None or webuser.nickname_valid_p(args['nickname'])) \ and uid2 != -1 and (uid2 == uid or uid2 == 0) \ and uid_with_the_same_nickname != -1 and (uid_with_the_same_nickname == uid or uid_with_the_same_nickname == 0): if CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS < 3: change = webuser.updateDataUser(uid, args['email'], args['nickname']) else: return webuser.page_not_authorized(req, "../youraccount/change", navmenuid='youraccount') if change: mess += '

' + _("Settings successfully edited.") mess += '

' + _("Note that if you have changed your email address, " "you will have to %(x_url_open)sreset your password%(x_url_close)s anew.") % \ {'x_url_open': '' % (CFG_SITE_SECURE_URL + '/youraccount/lost?ln=%s' % args['ln']), 'x_url_close': ''} act = "/youraccount/display?ln=%s" % args['ln'] linkname = _("Show account") title = _("Settings edited") elif args['nickname'] is not None and not webuser.nickname_valid_p(args['nickname']): mess += '

' + _("Desired nickname %s is invalid.") % cgi.escape(args['nickname']) mess += " " + _("Please try again.") act = "/youraccount/edit?ln=%s" % args['ln'] linkname = _("Edit settings") title = _("Editing settings failed") elif not webuser.email_valid_p(args['email']): mess += '

' + _("Supplied email address %s is invalid.") % cgi.escape(args['email']) mess += " " + _("Please try again.") act = "/youraccount/edit?ln=%s" % args['ln'] linkname = _("Edit settings") title = _("Editing settings failed") elif uid2 == -1 or uid2 != uid and not uid2 == 0: mess += '

' + _("Supplied email address %s already exists in the database.") % cgi.escape(args['email']) mess += " " + websession_templates.tmpl_lost_your_password_teaser(args['ln']) mess += " " + _("Or please try again.") act = "/youraccount/edit?ln=%s" % args['ln'] linkname = _("Edit settings") title = _("Editing settings failed") elif uid_with_the_same_nickname == -1 or uid_with_the_same_nickname != uid and not uid_with_the_same_nickname == 0: mess += '

' + _("Desired nickname %s is already in use.") % cgi.escape(args['nickname']) mess += " " + _("Please try again.") act = "/youraccount/edit?ln=%s" % args['ln'] linkname = _("Edit settings") title = _("Editing settings failed") ## Change passwords: if args['old_password'] or args['password'] or args['password2']: if CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS >= 3: mess += '

' + _("Users cannot edit passwords on this site.") else: res = run_sql("SELECT id FROM user " "WHERE AES_ENCRYPT(email,%s)=password AND id=%s", (args['old_password'], uid)) if res: if args['password'] == args['password2']: webuser.updatePasswordUser(uid, args['password']) mess += '

' + _("Password successfully edited.") act = "/youraccount/display?ln=%s" % args['ln'] linkname = _("Show account") title = _("Password edited") else: mess += '

' + _("Both passwords must match.") mess += " " + _("Please try again.") act = "/youraccount/edit?ln=%s" % args['ln'] linkname = _("Edit settings") title = _("Editing password failed") else: mess += '

' + _("Wrong old password inserted.") mess += " " + _("Please try again.") act = "/youraccount/edit?ln=%s" % args['ln'] linkname = _("Edit settings") title = _("Editing password failed") ## Change search-related settings: if args['group_records']: prefs = webuser.get_user_preferences(uid) prefs['websearch_group_records'] = args['group_records'] prefs['websearch_latestbox'] = args['latestbox'] prefs['websearch_helpbox'] = args['helpbox'] webuser.set_user_preferences(uid, prefs) title = _("Settings edited") act = "/youraccount/display?ln=%s" % args['ln'] linkname = _("Show account") mess += '

' + _("User settings saved correctly.") ## Change language-related settings: if args['lang']: lang = wash_language(args['lang']) prefs = webuser.get_user_preferences(uid) prefs['language'] = lang args['ln'] = lang _ = gettext_set_language(lang) webuser.set_user_preferences(uid, prefs) title = _("Settings edited") act = "/youraccount/display?ln=%s" % args['ln'] linkname = _("Show account") mess += '

' + _("User settings saved correctly.") ## Edit cataloging-related settings: if args['bibcatalog_username'] or args['bibcatalog_password']: act = "/youraccount/display?ln=%s" % args['ln'] linkname = _("Show account") if ((len(args['bibcatalog_username']) == 0) or (len(args['bibcatalog_password']) == 0)): title = _("Editing bibcatalog authorization failed") mess += '

' + _("Empty username or password") else: title = _("Settings edited") prefs['bibcatalog_username'] = args['bibcatalog_username'] prefs['bibcatalog_password'] = args['bibcatalog_password'] webuser.set_user_preferences(uid, prefs) mess += '

' + _("User settings saved correctly.") if not mess: mess = _("Unable to update settings.") if not act: act = "/youraccount/edit?ln=%s" % args['ln'] if not linkname: linkname = _("Edit settings") if not title: title = _("Editing settings failed") ## Finally, output the results: return page(title=title, body=webaccount.perform_back(mess, act, linkname, args['ln']), navtrail="""""" % (CFG_SITE_SECURE_URL, args['ln']) + _("Your Account") + """""", description="%s Personalize, Main page" % CFG_SITE_NAME_INTL.get(args['ln'], CFG_SITE_NAME), keywords=_("%s, personalize") % CFG_SITE_NAME_INTL.get(args['ln'], CFG_SITE_NAME), uid=uid, req=req, secure_page_p = 1, language=args['ln'], lastupdated=__lastupdated__, navmenuid='youraccount') def lost(self, req, form): args = wash_urlargd(form, {}) uid = webuser.getUid(req) # load the right message language _ = gettext_set_language(args['ln']) if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return webuser.page_not_authorized(req, "../youraccount/lost", navmenuid='youraccount') return page(title=_("Lost your password?"), body=webaccount.perform_lost(args['ln']), navtrail="""""" % (CFG_SITE_SECURE_URL, args['ln']) + _("Your Account") + """""", description="%s Personalize, Main page" % CFG_SITE_NAME_INTL.get(args['ln'], CFG_SITE_NAME), keywords=_("%s, personalize") % CFG_SITE_NAME_INTL.get(args['ln'], CFG_SITE_NAME), uid=uid, req=req, secure_page_p = 1, language=args['ln'], lastupdated=__lastupdated__, navmenuid='youraccount') def send_email(self, req, form): # set all the declared query fields as local variables args = wash_urlargd(form, {'p_email': (str, None)}) uid = webuser.getUid(req) # load the right message language _ = gettext_set_language(args['ln']) if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return webuser.page_not_authorized(req, "../youraccount/send_email", navmenuid='youraccount') user_prefs = webuser.get_user_preferences(webuser.emailUnique(args['p_email'])) if user_prefs: if CFG_EXTERNAL_AUTHENTICATION.has_key(user_prefs['login_method']) and \ CFG_EXTERNAL_AUTHENTICATION[user_prefs['login_method']][0] is not None: eMsg = _("Cannot send password reset request since you are using external authentication system.") return page(title=_("Your Account"), body=webaccount.perform_emailMessage(eMsg, args['ln']), description="%s Personalize, Main page" % CFG_SITE_NAME_INTL.get(args['ln'], CFG_SITE_NAME), keywords=_("%s, personalize" % CFG_SITE_NAME_INTL.get(args['ln'], CFG_SITE_NAME)), uid=uid, req=req, secure_page_p = 1, language=args['ln'], lastupdated=__lastupdated__, navmenuid='youraccount') try: reset_key = mail_cookie_create_pw_reset(args['p_email'], cookie_timeout=timedelta(days=CFG_WEBSESSION_RESET_PASSWORD_EXPIRE_IN_DAYS)) except InvenioWebAccessMailCookieError: reset_key = None if reset_key is None: eMsg = _("The entered email address does not exist in the database.") return page(title=_("Your Account"), body=webaccount.perform_emailMessage(eMsg, args['ln']), description="%s Personalize, Main page" % CFG_SITE_NAME_INTL.get(args['ln'], CFG_SITE_NAME), keywords=_("%s, personalize") % CFG_SITE_NAME_INTL.get(args['ln'], CFG_SITE_NAME), uid=uid, req=req, secure_page_p = 1, language=args['ln'], lastupdated=__lastupdated__, navmenuid='youraccount') ip_address = req.connection.remote_host or req.connection.remote_ip if not send_email(CFG_SITE_SUPPORT_EMAIL, args['p_email'], "%s %s" % (_("Password reset request for"), CFG_SITE_NAME_INTL.get(args['ln'], CFG_SITE_NAME)), websession_templates.tmpl_account_reset_password_email_body( args['p_email'],reset_key, ip_address, args['ln'])): eMsg = _("The entered email address is incorrect, please check that it is written correctly (e.g. johndoe@example.com).") return page(title=_("Incorrect email address"), body=webaccount.perform_emailMessage(eMsg, args['ln']), description="%s Personalize, Main page" % CFG_SITE_NAME_INTL.get(args['ln'], CFG_SITE_NAME), keywords=_("%s, personalize") % CFG_SITE_NAME_INTL.get(args['ln'], CFG_SITE_NAME), uid=uid, req=req, secure_page_p = 1, language=args['ln'], lastupdated=__lastupdated__, navmenuid='youraccount') return page(title=_("Reset password link sent"), body=webaccount.perform_emailSent(args['p_email'], args['ln']), description="%s Personalize, Main page" % CFG_SITE_NAME_INTL.get(args['ln'], CFG_SITE_NAME), keywords=_("%s, personalize") % CFG_SITE_NAME_INTL.get(args['ln'], CFG_SITE_NAME), uid=uid, req=req, secure_page_p = 1, language=args['ln'], lastupdated=__lastupdated__, navmenuid='youraccount') def youradminactivities(self, req, form): args = wash_urlargd(form, {}) uid = webuser.getUid(req) user_info = webuser.collect_user_info(req) # load the right message language _ = gettext_set_language(args['ln']) if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return webuser.page_not_authorized(req, "../youraccount/youradminactivities", navmenuid='admin') return page(title=_("Your Administrative Activities"), body=webaccount.perform_youradminactivities(user_info, args['ln']), navtrail="""""" % (CFG_SITE_SECURE_URL, args['ln']) + _("Your Account") + """""", description="%s Personalize, Main page" % CFG_SITE_NAME_INTL.get(args['ln'], CFG_SITE_NAME), keywords=_("%s, personalize") % CFG_SITE_NAME_INTL.get(args['ln'], CFG_SITE_NAME), uid=uid, req=req, secure_page_p = 1, language=args['ln'], lastupdated=__lastupdated__, navmenuid='admin') def delete(self, req, form): args = wash_urlargd(form, {}) uid = webuser.getUid(req) # load the right message language _ = gettext_set_language(args['ln']) if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return webuser.page_not_authorized(req, "../youraccount/delete", navmenuid='youraccount') return page(title=_("Delete Account"), body=webaccount.perform_delete(args['ln']), navtrail="""""" % (CFG_SITE_SECURE_URL, args['ln']) + _("Your Account") + """""", description="%s Personalize, Main page" % CFG_SITE_NAME_INTL.get(args['ln'], CFG_SITE_NAME), keywords=_("%s, personalize") % CFG_SITE_NAME_INTL.get(args['ln'], CFG_SITE_NAME), uid=uid, req=req, secure_page_p = 1, language=args['ln'], lastupdated=__lastupdated__, navmenuid='youraccount') def logout(self, req, form): args = wash_urlargd(form, {}) uid = webuser.logoutUser(req) # load the right message language _ = gettext_set_language(args['ln']) if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return webuser.page_not_authorized(req, "../youraccount/logout", navmenuid='youraccount') if CFG_EXTERNAL_AUTH_USING_SSO: return redirect_to_url(req, CFG_EXTERNAL_AUTH_LOGOUT_SSO) return page(title=_("Logout"), body=webaccount.perform_logout(req, args['ln']), navtrail="""""" % (CFG_SITE_SECURE_URL, args['ln']) + _("Your Account") + """""", description="%s Personalize, Main page" % CFG_SITE_NAME_INTL.get(args['ln'], CFG_SITE_NAME), keywords=_("%s, personalize") % CFG_SITE_NAME_INTL.get(args['ln'], CFG_SITE_NAME), uid=uid, req=req, secure_page_p = 1, language=args['ln'], lastupdated=__lastupdated__, navmenuid='youraccount') def login(self, req, form): args = wash_urlargd(form, { 'p_un': (str, None), 'p_pw': (str, None), 'login_method': (str, None), 'action': (str, ''), 'remember_me' : (str, ''), 'referer': (str, '')}) # sanity checks: args['login_method'] = wash_login_method(args['login_method']) if args['p_un']: args['p_un'] = args['p_un'].strip() args['remember_me'] = args['remember_me'] != '' locals().update(args) if CFG_ACCESS_CONTROL_LEVEL_SITE > 0: return webuser.page_not_authorized(req, "../youraccount/login?ln=%s" % args['ln'], navmenuid='youraccount') uid = webuser.getUid(req) # load the right message language _ = gettext_set_language(args['ln']) apache_msg = "" if args['action']: cookie = args['action'] try: action, arguments = mail_cookie_check_authorize_action(cookie) apache_msg = make_apache_message(action, arguments, args['referer']) # FIXME: Temporary Hack to help CDS current migration if CFG_CERN_SITE: roles = make_list_apache_firerole(action, arguments) if len(roles) == 1: # There's only one role enabled to see this collection # Let's redirect to log to it! return redirect_to_url(req, '%s/%s' % (CFG_SITE_SECURE_URL, make_canonical_urlargd({'realm' : roles[0][0], 'referer' : args['referer']}, {}))) except InvenioWebAccessMailCookieError: pass if not CFG_EXTERNAL_AUTH_USING_SSO: if args['p_un'] is None or not args['login_method']: return page(title=_("Login"), body=webaccount.create_login_page_box(args['referer'], apache_msg, args['ln']), navtrail="""""" % (CFG_SITE_SECURE_URL, args['ln']) + _("Your Account") + """""", description="%s Personalize, Main page" % CFG_SITE_NAME_INTL.get(args['ln'], CFG_SITE_NAME), keywords="%s , personalize" % CFG_SITE_NAME_INTL.get(args['ln'], CFG_SITE_NAME), uid=uid, req=req, secure_page_p = 1, language=args['ln'], lastupdated=__lastupdated__, navmenuid='youraccount') (iden, args['p_un'], args['p_pw'], msgcode) = webuser.loginUser(req, args['p_un'], args['p_pw'], args['login_method']) else: # Fake parameters for p_un & p_pw because SSO takes them from the environment (iden, args['p_un'], args['p_pw'], msgcode) = webuser.loginUser(req, '', '', CFG_EXTERNAL_AUTH_USING_SSO) args['remember_me'] = False if len(iden)>0: uid = webuser.update_Uid(req, args['p_un'], args['remember_me']) uid2 = webuser.getUid(req) if uid2 == -1: webuser.logoutUser(req) return webuser.page_not_authorized(req, "../youraccount/login?ln=%s" % args['ln'], uid=uid, navmenuid='youraccount') # login successful! if args['referer']: redirect_to_url(req, args['referer']) else: return self.display(req, form) else: mess = CFG_WEBACCESS_WARNING_MSGS[msgcode] % cgi.escape(args['login_method']) if msgcode == 14: if webuser.username_exists_p(args['p_un']): mess = CFG_WEBACCESS_WARNING_MSGS[15] % cgi.escape(args['login_method']) act = '/youraccount/login%s' % make_canonical_urlargd({'ln' : args['ln'], 'referer' : args['referer']}, {}) return page(title=_("Login"), body=webaccount.perform_back(mess, act, _("login"), args['ln']), navtrail="""""" % (CFG_SITE_SECURE_URL, args['ln']) + _("Your Account") + """""", description="%s Personalize, Main page" % CFG_SITE_NAME_INTL.get(args['ln'], CFG_SITE_NAME), keywords="%s , personalize" % CFG_SITE_NAME_INTL.get(args['ln'], CFG_SITE_NAME), uid=uid, req=req, secure_page_p = 1, language=args['ln'], lastupdated=__lastupdated__, navmenuid='youraccount') def register(self, req, form): args = wash_urlargd(form, { 'p_nickname': (str, None), 'p_email': (str, None), 'p_pw': (str, None), 'p_pw2': (str, None), 'action': (str, "login"), 'referer': (str, "")}) if CFG_ACCESS_CONTROL_LEVEL_SITE > 0: return webuser.page_not_authorized(req, "../youraccount/register?ln=%s" % args['ln'], navmenuid='youraccount') uid = webuser.getUid(req) # load the right message language _ = gettext_set_language(args['ln']) if args['p_nickname'] is None or args['p_email'] is None: return page(title=_("Register"), body=webaccount.create_register_page_box(args['referer'], args['ln']), navtrail="""""" % (CFG_SITE_SECURE_URL, args['ln']) + _("Your Account") + """""", description=_("%s Personalize, Main page") % CFG_SITE_NAME_INTL.get(args['ln'], CFG_SITE_NAME), keywords="%s , personalize" % CFG_SITE_NAME_INTL.get(args['ln'], CFG_SITE_NAME), uid=uid, req=req, secure_page_p = 1, language=args['ln'], lastupdated=__lastupdated__, navmenuid='youraccount') mess = "" act = "" if args['p_pw'] == args['p_pw2']: ruid = webuser.registerUser(req, args['p_email'], args['p_pw'], args['p_nickname'], ln=args['ln']) else: ruid = -2 if ruid == 0: mess = _("Your account has been successfully created.") title = _("Account created") if CFG_ACCESS_CONTROL_NOTIFY_USER_ABOUT_NEW_ACCOUNT == 1: mess += " " + _("In order to confirm its validity, an email message containing an account activation key has been sent to the given email address.") mess += " " + _("Please follow instructions presented there in order to complete the account registration process.") if CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS >= 1: mess += " " + _("A second email will be sent when the account has been activated and can be used.") elif CFG_ACCESS_CONTROL_NOTIFY_USER_ABOUT_NEW_ACCOUNT != 1: uid = webuser.update_Uid(req, args['p_email']) mess += " " + _("You can now access your %(x_url_open)saccount%(x_url_close)s.") %\ {'x_url_open': '', 'x_url_close': ''} elif ruid == -2: mess = _("Both passwords must match.") mess += " " + _("Please try again.") act = "/youraccount/register?ln=%s" % args['ln'] title = _("Registration failure") elif ruid == 1: mess = _("Supplied email address %s is invalid.") % cgi.escape(args['p_email']) mess += " " + _("Please try again.") act = "/youraccount/register?ln=%s" % args['ln'] title = _("Registration failure") elif ruid == 2: mess = _("Desired nickname %s is invalid.") % cgi.escape(args['p_nickname']) mess += " " + _("Please try again.") act = "/youraccount/register?ln=%s" % args['ln'] title = _("Registration failure") elif ruid == 3: mess = _("Supplied email address %s already exists in the database.") % cgi.escape(args['p_email']) mess += " " + websession_templates.tmpl_lost_your_password_teaser(args['ln']) mess += " " + _("Or please try again.") act = "/youraccount/register?ln=%s" % args['ln'] title = _("Registration failure") elif ruid == 4: mess = _("Desired nickname %s already exists in the database.") % cgi.escape(args['p_nickname']) mess += " " + _("Please try again.") act = "/youraccount/register?ln=%s" % args['ln'] title = _("Registration failure") elif ruid == 5: mess = _("Users cannot register themselves, only admin can register them.") act = "/youraccount/register?ln=%s" % args['ln'] title = _("Registration failure") elif ruid == 6: mess = _("The site is having troubles in sending you an email for confirming your email address.") + _("The error has been logged and will be taken in consideration as soon as possible.") act = "/youraccount/register?ln=%s" % args['ln'] title = _("Registration failure") else: # this should never happen mess = _("Internal Error") act = "/youraccount/register?ln=%s" % args['ln'] title = _("Registration failure") return page(title=title, body=webaccount.perform_back(mess,act, _("register"), args['ln']), navtrail="""""" % (CFG_SITE_SECURE_URL, args['ln']) + _("Your Account") + """""", description=_("%s Personalize, Main page") % CFG_SITE_NAME_INTL.get(args['ln'], CFG_SITE_NAME), keywords="%s , personalize" % CFG_SITE_NAME_INTL.get(args['ln'], CFG_SITE_NAME), uid=uid, req=req, secure_page_p = 1, language=args['ln'], lastupdated=__lastupdated__, navmenuid='youraccount') +class WebInterfaceYourTicketsPages(WebInterfaceDirectory): + #support for /yourtickets url + _exports = ['', 'display'] + + def __call__(self, req, form): + #if there is no trailing slash + self.index(req, form) + + def index(self, req, form): + #take all the parameters.. + unparsed_uri = req.unparsed_uri + qstr = "" + if unparsed_uri.count('?') > 0: + dummy, qstr = unparsed_uri.split('?') + qstr = '?'+qstr + redirect_to_url(req, '/yourtickets/display'+qstr) + + def display(self, req, form): + #show tickets for this user + argd = wash_urlargd(form, {'ln': (str, ''), 'start': (int, 1) }) + uid = webuser.getUid(req) + ln = argd['ln'] + start = argd['start'] + _ = gettext_set_language(ln) + body = bibcatalog_templates.tmpl_your_tickets(uid, ln, start) + return page(title=_("Your tickets"), + body=body, + navtrail="""""" % (CFG_SITE_SECURE_URL, argd['ln']) + _("Your Account") + """""", + uid=uid, + req=req, + language=argd['ln'], + lastupdated=__lastupdated__) + class WebInterfaceYourGroupsPages(WebInterfaceDirectory): _exports = ['', 'display', 'create', 'join', 'leave', 'edit', 'members'] def index(self, req, form): redirect_to_url(req, '/yourgroups/display') def display(self, req, form): """ Displays groups the user is admin of and the groups the user is member of(but not admin) @param ln: language @return: the page for all the groups """ argd = wash_urlargd(form, {}) uid = webuser.getUid(req) # load the right message language _ = gettext_set_language(argd['ln']) if uid == -1 or webuser.isGuestUser(uid) or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return webuser.page_not_authorized(req, "../yourgroups/display", navmenuid='yourgroups') user_info = webuser.collect_user_info(req) if not user_info['precached_usegroups']: return webuser.page_not_authorized(req, "../", \ text = _("You are not authorized to use groups.")) (body, errors, warnings) = webgroup.perform_request_groups_display(uid=uid, ln=argd['ln']) return page(title = _("Your Groups"), body = body, navtrail = webgroup.get_navtrail(argd['ln']), uid = uid, req = req, language = argd['ln'], lastupdated = __lastupdated__, errors = errors, warnings = warnings, navmenuid = 'yourgroups') def create(self, req, form): """create(): interface for creating a new group @param group_name: : name of the new webgroup.Must be filled @param group_description: : description of the new webgroup.(optionnal) @param join_policy: : join policy of the new webgroup.Must be chosen @param *button: which button was pressed @param ln: language @return: the compose page Create group """ argd = wash_urlargd(form, {'group_name': (str, ""), 'group_description': (str, ""), 'join_policy': (str, ""), 'create_button':(str, ""), 'cancel':(str, "") }) uid = webuser.getUid(req) # load the right message language _ = gettext_set_language(argd['ln']) if uid == -1 or webuser.isGuestUser(uid) or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return webuser.page_not_authorized(req, "../yourgroups/create", navmenuid='yourgroups') user_info = webuser.collect_user_info(req) if not user_info['precached_usegroups']: return webuser.page_not_authorized(req, "../", \ text = _("You are not authorized to use groups.")) if argd['cancel']: url = CFG_SITE_URL + '/yourgroups/display?ln=%s' url %= argd['ln'] redirect_to_url(req, url) if argd['create_button'] : (body, errors, warnings)= webgroup.perform_request_create_group(uid=uid, group_name=argd['group_name'], group_description=argd['group_description'], join_policy=argd['join_policy'], ln = argd['ln']) else: (body, errors, warnings) = webgroup.perform_request_input_create_group(group_name=argd['group_name'], group_description=argd['group_description'], join_policy=argd['join_policy'], ln=argd['ln']) title = _("Create new group") return page(title = title, body = body, navtrail = webgroup.get_navtrail(argd['ln'], title), uid = uid, req = req, language = argd['ln'], lastupdated = __lastupdated__, errors = errors, warnings = warnings, navmenuid = 'yourgroups') def join(self, req, form): """join(): interface for joining a new group @param grpID: : list of the group the user wants to become a member. The user must select only one group. @param group_name: : will search for groups matching group_name @param *button: which button was pressed @param ln: language @return: the compose page Join group """ argd = wash_urlargd(form, {'grpID':(list, []), 'group_name':(str, ""), 'find_button':(str, ""), 'join_button':(str, ""), 'cancel':(str, "") }) uid = webuser.getUid(req) # load the right message language _ = gettext_set_language(argd['ln']) if uid == -1 or webuser.isGuestUser(uid) or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return webuser.page_not_authorized(req, "../yourgroups/join", navmenuid='yourgroups') user_info = webuser.collect_user_info(req) if not user_info['precached_usegroups']: return webuser.page_not_authorized(req, "../", \ text = _("You are not authorized to use groups.")) if argd['cancel']: url = CFG_SITE_URL + '/yourgroups/display?ln=%s' url %= argd['ln'] redirect_to_url(req, url) if argd['join_button']: search = 0 if argd['group_name']: search = 1 (body, errors, warnings) = webgroup.perform_request_join_group(uid, argd['grpID'], argd['group_name'], search, argd['ln']) else: search = 0 if argd['find_button']: search = 1 (body, errors, warnings) = webgroup.perform_request_input_join_group(uid, argd['group_name'], search, ln=argd['ln']) title = _("Join New Group") return page(title = title, body = body, navtrail = webgroup.get_navtrail(argd['ln'], title), uid = uid, req = req, language = argd['ln'], lastupdated = __lastupdated__, errors = errors, warnings = warnings, navmenuid = 'yourgroups') def leave(self, req, form): """leave(): interface for leaving a group @param grpID: : group the user wants to leave. @param group_name: : name of the group the user wants to leave @param *button: which button was pressed @param confirmed: : the user is first asked to confirm @param ln: language @return: the compose page Leave group """ argd = wash_urlargd(form, {'grpID':(str, ""), 'group_name':(str, ""), 'leave_button':(str, ""), 'cancel':(str, ""), 'confirmed': (int, 0) }) uid = webuser.getUid(req) # load the right message language _ = gettext_set_language(argd['ln']) if uid == -1 or webuser.isGuestUser(uid) or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return webuser.page_not_authorized(req, "../yourgroups/leave", navmenuid='yourgroups') user_info = webuser.collect_user_info(req) if not user_info['precached_usegroups']: return webuser.page_not_authorized(req, "../", \ text = _("You are not authorized to use groups.")) if argd['cancel']: url = CFG_SITE_URL + '/yourgroups/display?ln=%s' url %= argd['ln'] redirect_to_url(req, url) if argd['leave_button']: (body, errors, warnings) = webgroup.perform_request_leave_group(uid, argd['grpID'], argd['confirmed'], argd['ln']) else: (body, errors, warnings) = webgroup.perform_request_input_leave_group(uid=uid, ln=argd['ln']) title = _("Leave Group") return page(title = title, body = body, navtrail = webgroup.get_navtrail(argd['ln'], title), uid = uid, req = req, language = argd['ln'], lastupdated = __lastupdated__, errors = errors, warnings = warnings, navmenuid = 'yourgroups') def edit(self, req, form): """edit(): interface for editing group @param grpID: : group ID @param group_name: : name of the new webgroup.Must be filled @param group_description: : description of the new webgroup.(optionnal) @param join_policy: : join policy of the new webgroup.Must be chosen @param update: button update group pressed @param delete: button delete group pressed @param cancel: button cancel pressed @param confirmed: : the user is first asked to confirm before deleting @param ln: language @return: the main page displaying all the groups """ argd = wash_urlargd(form, {'grpID': (str, ""), 'update': (str, ""), 'cancel': (str, ""), 'delete': (str, ""), 'group_name': (str, ""), 'group_description': (str, ""), 'join_policy': (str, ""), 'confirmed': (int, 0) }) uid = webuser.getUid(req) # load the right message language _ = gettext_set_language(argd['ln']) if uid == -1 or webuser.isGuestUser(uid) or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return webuser.page_not_authorized(req, "../yourgroups/display", navmenuid='yourgroups') user_info = webuser.collect_user_info(req) if not user_info['precached_usegroups']: return webuser.page_not_authorized(req, "../", \ text = _("You are not authorized to use groups.")) if argd['cancel']: url = CFG_SITE_URL + '/yourgroups/display?ln=%s' url %= argd['ln'] redirect_to_url(req, url) elif argd['delete']: (body, errors, warnings) = webgroup.perform_request_delete_group(uid=uid, grpID=argd['grpID'], confirmed=argd['confirmed']) elif argd['update']: (body, errors, warnings) = webgroup.perform_request_update_group(uid= uid, grpID=argd['grpID'], group_name=argd['group_name'], group_description=argd['group_description'], join_policy=argd['join_policy'], ln=argd['ln']) else : (body, errors, warnings)= webgroup.perform_request_edit_group(uid=uid, grpID=argd['grpID'], ln=argd['ln']) title = _("Edit Group") return page(title = title, body = body, navtrail = webgroup.get_navtrail(argd['ln'], title), uid = uid, req = req, language = argd['ln'], lastupdated = __lastupdated__, errors = errors, warnings = warnings, navmenuid = 'yourgroups') def members(self, req, form): """member(): interface for managing members of a group @param grpID: : group ID @param add_member: button add_member pressed @param remove_member: button remove_member pressed @param reject_member: button reject__member pressed @param delete: button delete group pressed @param member_id: : ID of the existing member selected @param pending_member_id: : ID of the pending member selected @param cancel: button cancel pressed @param info: : info about last user action @param ln: language @return: the same page with data updated """ argd = wash_urlargd(form, {'grpID': (int, 0), 'cancel': (str, ""), 'add_member': (str, ""), 'remove_member': (str, ""), 'reject_member': (str, ""), 'member_id': (int, 0), 'pending_member_id': (int, 0) }) uid = webuser.getUid(req) # load the right message language _ = gettext_set_language(argd['ln']) if uid == -1 or webuser.isGuestUser(uid) or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return webuser.page_not_authorized(req, "../yourgroups/display", navmenuid='yourgroups') user_info = webuser.collect_user_info(req) if not user_info['precached_usegroups']: return webuser.page_not_authorized(req, "../", \ text = _("You are not authorized to use groups.")) if argd['cancel']: url = CFG_SITE_URL + '/yourgroups/display?ln=%s' url %= argd['ln'] redirect_to_url(req, url) if argd['remove_member']: (body, errors, warnings) = webgroup.perform_request_remove_member(uid=uid, grpID=argd['grpID'], member_id=argd['member_id'], ln=argd['ln']) elif argd['reject_member']: (body, errors, warnings) = webgroup.perform_request_reject_member(uid=uid, grpID=argd['grpID'], user_id=argd['pending_member_id'], ln=argd['ln']) elif argd['add_member']: (body, errors, warnings) = webgroup.perform_request_add_member(uid=uid, grpID=argd['grpID'], user_id=argd['pending_member_id'], ln=argd['ln']) else: (body, errors, warnings)= webgroup.perform_request_manage_member(uid=uid, grpID=argd['grpID'], ln=argd['ln']) title = _("Edit group members") return page(title = title, body = body, navtrail = webgroup.get_navtrail(argd['ln'], title), uid = uid, req = req, language = argd['ln'], lastupdated = __lastupdated__, errors = errors, warnings = warnings, navmenuid = 'yourgroups') def wash_login_method(login_method): """ Wash the login_method parameter that came from the web input form. @param login_method: Wanted login_method value as it came from the web input form. @type login_method: string @return: Washed version of login_method. If the login_method value is valid, then return it. If it is not valid, then return `Local' (the default login method). @rtype: string @warning: Beware, 'Local' is hardcoded here! """ if login_method in CFG_EXTERNAL_AUTHENTICATION.keys(): return login_method else: return 'Local' diff --git a/modules/webstyle/lib/webinterface_layout.py b/modules/webstyle/lib/webinterface_layout.py index 51757947c..d3df0a384 100644 --- a/modules/webstyle/lib/webinterface_layout.py +++ b/modules/webstyle/lib/webinterface_layout.py @@ -1,218 +1,226 @@ # -*- coding: utf-8 -*- ## This file is part of CDS Invenio. ## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 CERN. ## ## CDS Invenio is free software; you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation; either version 2 of the ## License, or (at your option) any later version. ## ## CDS Invenio is distributed in the hope that it will be useful, but ## WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with CDS Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. """ Global organisation of the application's URLs. This module binds together CDS Invenio's modules and maps them to their corresponding URLs (ie, /search to the websearch modules,...) """ __revision__ = \ "$Id$" from invenio.webinterface_handler import create_handler from invenio.errorlib import register_exception from invenio.webinterface_handler import WebInterfaceDirectory class WebInterfaceDumbPages(WebInterfaceDirectory): """This class implements a dumb interface to use as a fallback in case of errors importing particular module pages.""" _exports = [''] def __call__(self, req, form): try: from invenio.webpage import page except ImportError: page = lambda *args: args[1] from mod_python import apache req.status = apache.HTTP_INTERNAL_SERVER_ERROR msg = "

This functionality is facing a temporary failure.

" msg += "

The administrator has been informed about the problem.

" try: from invenio.config import CFG_SITE_ADMIN_EMAIL msg += """

You can contact %s in case of questions.

""" % \ CFG_SITE_ADMIN_EMAIL except ImportError: pass msg += """

We hope to restore the service soon.

Sorry for the inconvenience.

""" try: return page('Service failure', msg) except: return msg def _lookup(self, component, path): return WebInterfaceDumbPages(), path index = __call__ try: from invenio.websearch_webinterface import WebInterfaceSearchInterfacePages except: register_exception(alert_admin=True, subject='EMERGENCY') WebInterfaceSearchInterfacePages = WebInterfaceDumbPages try: from invenio.websearch_webinterface import WebInterfaceAuthorPages except: register_exception(alert_admin=True, subject='EMERGENCY') WebInterfaceAuthorPages = WebInterfaceDumbPages try: from invenio.websearch_webinterface import WebInterfaceRSSFeedServicePages except: register_exception(alert_admin=True, subject='EMERGENCY') WebInterfaceRSSFeedServicePages = WebInterfaceDumbPages try: from invenio.websearch_webinterface import WebInterfaceUnAPIPages except: register_exception(alert_admin=True, subject='EMERGENCY') WebInterfaceUnAPIPages = WebInterfaceDumbPages try: from invenio.websubmit_webinterface import websubmit_legacy_getfile except: register_exception(alert_admin=True, subject='EMERGENCY') websubmit_legacy_getfile = WebInterfaceDumbPages try: from invenio.websubmit_webinterface import WebInterfaceSubmitPages except: register_exception(alert_admin=True, subject='EMERGENCY') WebInterfaceSubmitPages = WebInterfaceDumbPages try: from invenio.websession_webinterface import WebInterfaceYourAccountPages except: register_exception(alert_admin=True, subject='EMERGENCY') WebInterfaceYourAccountPages = WebInterfaceDumbPages +try: + from invenio.websession_webinterface import WebInterfaceYourTicketsPages +except: + register_exception(alert_admin=True, subject='EMERGENCY') + WebInterfaceYourTicketsPages = WebInterfaceDumbPages + try: from invenio.websession_webinterface import WebInterfaceYourGroupsPages except: register_exception(alert_admin=True, subject='EMERGENCY') WebInterfaceYourGroupsPages = WebInterfaceDumbPages try: from invenio.webalert_webinterface import WebInterfaceYourAlertsPages except: register_exception(alert_admin=True, subject='EMERGENCY') WebInterfaceYourAlertsPages = WebInterfaceDumbPages try: from invenio.webbasket_webinterface import WebInterfaceYourBasketsPages except: register_exception(alert_admin=True, subject='EMERGENCY') WebInterfaceYourBasketsPages = WebInterfaceDumbPages try: from invenio.webcomment_webinterface import WebInterfaceCommentsPages except: register_exception(alert_admin=True, subject='EMERGENCY') WebInterfaceCommentsPages = WebInterfaceDumbPages try: from invenio.webmessage_webinterface import WebInterfaceYourMessagesPages except: register_exception(alert_admin=True, subject='EMERGENCY') WebInterfaceYourMessagesPages = WebInterfaceDumbPages try: from invenio.errorlib_webinterface import WebInterfaceErrorPages except: register_exception(alert_admin=True, subject='EMERGENCY') WebInterfaceErrorPages = WebInterfaceDumbPages try: from invenio.oai_repository_webinterface import WebInterfaceOAIProviderPages except: register_exception(alert_admin=True, subject='EMERGENCY') WebInterfaceOAIProviderPages = WebInterfaceDumbPages try: from invenio.webstat_webinterface import WebInterfaceStatsPages except: register_exception(alert_admin=True, subject='EMERGENCY') WebInterfaceStatsPages = WebInterfaceDumbPages try: from invenio.bibcirculation_webinterface import WebInterfaceYourLoansPages except: register_exception(alert_admin=True, subject='EMERGENCY') WebInterfaceYourLoansPages = WebInterfaceDumbPages try: from invenio.webjournal_webinterface import WebInterfaceJournalPages except: register_exception(alert_admin=True, subject='EMERGENCY') WebInterfaceJournalPages = WebInterfaceDumbPages try: from invenio.webdoc_webinterface import WebInterfaceDocumentationPages except: register_exception(alert_admin=True, subject='EMERGENCY') WebInterfaceDocumentationPages = WebInterfaceDumbPages class WebInterfaceInvenio(WebInterfaceSearchInterfacePages): """ The global URL layout is composed of the search API plus all the other modules.""" _exports = WebInterfaceSearchInterfacePages._exports + \ WebInterfaceAuthorPages._exports + [ 'youraccount', 'youralerts', 'yourbaskets', 'yourmessages', 'yourloans', 'yourgroups', + 'yourtickets', 'comments', 'error', 'oai2d', ('oai2d.py', 'oai2d'), ('getfile.py', 'getfile'), 'submit', 'rss', 'stats', 'journal', 'help', 'unapi' ] def __init__(self): self.getfile = websubmit_legacy_getfile author = WebInterfaceAuthorPages() submit = WebInterfaceSubmitPages() youraccount = WebInterfaceYourAccountPages() youralerts = WebInterfaceYourAlertsPages() yourbaskets = WebInterfaceYourBasketsPages() yourmessages = WebInterfaceYourMessagesPages() yourloans = WebInterfaceYourLoansPages() yourgroups = WebInterfaceYourGroupsPages() + yourtickets = WebInterfaceYourTicketsPages() comments = WebInterfaceCommentsPages() error = WebInterfaceErrorPages() oai2d = WebInterfaceOAIProviderPages() rss = WebInterfaceRSSFeedServicePages() stats = WebInterfaceStatsPages() journal = WebInterfaceJournalPages() help = WebInterfaceDocumentationPages() unapi = WebInterfaceUnAPIPages() # This creates the 'handler' function, which will be invoked directly # by mod_python. handler = create_handler(WebInterfaceInvenio())