diff --git a/modules/webaccess/doc/admin/guide.html.wml b/modules/webaccess/doc/admin/guide.html.wml index 2d266915b..74b94db9c 100644 --- a/modules/webaccess/doc/admin/guide.html.wml +++ b/modules/webaccess/doc/admin/guide.html.wml @@ -1,1005 +1,1013 @@ ## $Id$ ## This file is part of CDS Invenio. ## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 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. #include "cdspage.wml" \ title="WebAccess Admin Guide" \ navtrail_previous_links="/admin/>Admin Area > /admin/webaccess/>WebAccess Admin " \ navbar_name="admin" \ navbar_select="webaccess-admin-guide"

Version <: print generate_pretty_revision_date_string('$Id$'); :>

Contents

1. Introduction, using roles
2. WebAccess admin interface
3. Example pages, illustrating snapshots
4. Managing accounts / Access policy
5. Managing login methods

1. INTRODUCTION, USING ROLES

   WebAccess is a common RBAC, role based access control, for all of
   CDS Invenio. This means that users are connected to roles that cover
   different areas of access. I.e administrator of the photo
   collection or system librarian. Users can be active in
   different areas and of course connected to as many roles as needed.
 
   The roles are connected to actions. An action identifies a task you
   can perform in CDS Invenio. It can be defined to take any number of
   arguments in order to more clearly describe what you are allowing
   connected users to do.
 
   For example the system librarian can be allowed to run bibwords on
   the different indexes. To allow system librarians to run the
   bibwords indexing on the field author we connect role system
   librarian with action runbibwords using the argument
   index='author'.
 
   WebAccess is based on allowing users to perform actions. This means
   that only allowed actions are stored in the access control engine's
   database.
 

2. WEBACCESS ADMIN INTERFACE

 All the WebAccess Administration web pages have certain
 features/design choices in common
 
 - Divided into steps
 
   The process of adding new authorizations/information is
   stepwise. The subtitle contains information about wich step you are
   on and what you are supposed to do.
 
 - Restart from any wanted step
 
   You can always start from an earlier step by simply clicking the
   wanted button. This is not a way to undo changes! No information
   about previous database is kept, so all changes are definite.
 
 - Change or new entry must confirmed
 
   On all the pages you will be asked to confirm the change, with
   information about what kind of change you are about to perform.
 
 - Links to other relevant admin areas on the right side
 
   To make it easier to perform your administration tasks, we have
   added a menu area on the right hand side of these pages. The menu
   contain links to other relevant admin pages and change according to
   the page you are on and the information you have selected.
 

3. EXAMPLE PAGES

 I. Role area
 II. Example - connecting role and user
 
 
 I. Role area
 
   Administration tasks starts in one of the administration areas. The
   role area is the main area from where you can perform all your
   managing tasks. The other admin areas are just other ways of
   entering.
 
 

Role Administration

administration with roles as access point
Users:
add or remove users from the access to a role and its priviliges.
Authorizations/Actions:
these terms means almost the same, but an authorization is a
connection between a role and an action (possibly) containing arguments.
Roles:
see all the information attached to a role and decide if you want to
delete it.
id name description users authorizations / actions role
2 photoadmin administrator of the photo col... add / remove add / modify / remove delete show details
9 submitter add / remove add / modify / remove delete show details
1 superadmin all rights add / remove add / modify / remove delete show details
4 systemlibrarian system librarian add / remove add / modify / remove delete show details
3 webaccessadmin access to web administrator in... add / remove add / modify / remove delete show details
Create new role
go here to add a new role.
Create new action
go here to add a new action.
 
 II. Example - connecting role and user
 
   One of the important tasks that can be handled via the WebAccess Admin Web Interface
   is the delegation of access rights to users. This is done by connecting them to the
   different roles offered.
 
   The task is divided into 5 simple and comprehensive steps. Below follows the pages from
   the different steps with comments on the ongoing procedure.
 
 - step 1 - select a role
 
   You must first select the role you want to connect users to. All the available roles are
   listed alfabetically in a select box. Just find the wanted role and select it. Then click on
   the button saying "select role".
 
   If you start from the Role Area, this step is already done, and you start directly on step 2.
 
 

Connect user to role

step 1 - select a role
1. select role
Create new role
go here to add a new role.
 
 - step 2 - search for users
 
   As you can see, the subtitle of the page has now changed. The subtitle always tells you
   which step you are on and what your current task is.
 
   There can be possibly thousands of users using your online library, therefore it is important
   to make it easier to identify the user you are looking for. Give part of, or the entire search
   string and all users with partly matching e-mails will be listed on the next step.
 
   You can also see that the right hand menu has changed. This area is always updated with links
   to related admin areas.
 
 

Connect user to role

step 2 - search for users
1. select role
2. search pattern
Create new role
go here to add a new role.
Remove users
remove users from role superadmin.
Connected users
show all users connected to role superadmin.
Add authorization
start adding new authorizations to role superadmin.
 
 - step 3 - select a user.
 
   The select box contains all users with partly matching e-mail addresses. Select the one
   you want to connect to the role and continue.
 
   Notice the navigation trail that tells you were on the Administrator pages you are currently
   working.
 
 

Connect user to role

step 3 - select a user
1. select role
2. search pattern
3. select user
Create new role
go here to add a new role.
Remove users
remove users from role superadmin.
Connected users
show all users connected to role superadmin.
Add authorization
start adding new authorizations to role superadmin.
 
 - step 4 - confirm to add user
 
   All WebAccess Administrator web pages display the action you are about to peform, this
   means explaining what kind of addition, change or update will be done to your access control
   data.
 
   If you are happy with your decision, simply confirm it.
 
 

Connect user to role

step 4 - confirm to add user
1. select role
2. search pattern
3. select user
add user mikael.vik@cern.ch to role superadmin?
Create new role
go here to add a new role.
Remove users
remove users from role superadmin.
Connected users
show all users connected to role superadmin.
Add authorization
start adding new authorizations to role superadmin.
 
 - step 5 - confirm user added.
 
   The user has now been added to this role. You can easily continue adding more users to this
   role be restarting from step 2 or 3. You can also go directly to another area and keep working
   on the same role.
 
 

Connect user to role

step 5 - confirm user added
1. select role
2. search pattern
3. select user
add user mikael.vik@cern.ch to role superadmin?

confirm: user mikael.vik@cern.ch added to role superadmin.

Create new role
go here to add a new role.
Remove users
remove users from role superadmin.
Connected users
show all users connected to role superadmin.
Add authorization
start adding new authorizations to role superadmin.
 
 - we are done
 
   This example is very similar to all the other pages where you administrate WebAccess. The pages
   are an easy gateway to maintaing access control rights and share a lot of features.
   - divided into steps
   - restart from any wanted step (not undo)
   - changes must be confirmed
   - link to other relevant areas
   - prevent unwanted input
 
   As an administrator with access to these pages you are free to manage the rights any way you want.
 

IV. Managing accounts and access policy

   Here you can administrate the accounts and the access policy for your CDS Invenio installation.
 
   - Access policy:
 
     To change the access policy, the general config file (or
     access_control_config.py) must be edited manually in a text
     editor. The site can there be defined as opened or closed, you can
     edit the access policy level for guest accounts, registered
     accounts and decide when to warn the owner of the account when
     something happens with it, either when it is created, deleted or
     approved.  The Apache server must be restarted after modifying
     these settings.
 
     The two levels for guest account, are:
        0 - Allow guest accounts
        1 - Do not allow guest accounts
     The five levels for normal accounts, are:
        0 - Allow user to create account, automatically activate new accounts
        1 - Allow user to create account, administrator must activate account
        2 - Only administrators can create account. User cannot edit the email address.
        3 - Users cannot register or update account information (email/password)
        4 - User cannot change default login method
     You can configure CDS Invenio to send an email:
        1. To an admin email-address when an account is created
        2. To the owner of an account when it is created
        3. To the owner of an account when it is activated
        4. To the owner of an account when it is deleted
 
     Define how open the site is:
       0 = normal operation of the site
       1 = read-only site, all write operations temporarily closed
       2 = site fully closed
       CFG_ACCESS_CONTROL_LEVEL_SITE = 0
     Access policy for guests:
       0 = Allow guests to search,
       1 = Guests cannot search (all users must login)
       CFG_ACCESS_CONTROL_LEVEL_GUESTS = 0
     Access policy for accounts:
       0 = Users can register, automatically acticate accounts
       1 = Users can register, but admin must activate the accounts
       2 = Users cannot register or change email address, only admin can register accounts.
       3 = Users cannot register or update email address or password, only admin can register accounts.
       4 = Same as 3, but user cannot change login method.
       CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS = 0
 
     Limit email addresses available to use when register a new account (example: cern.ch):
       CFG_ACCESS_CONTROL_LIMIT_REGISTRATION_TO_DOMAIN = ""
 
     Send an email when a new account is created by an user:
       CFG_ACCESS_CONTROL_NOTIFY_ADMIN_ABOUT_NEW_ACCOUNTS = 0
 
     Send an email to the user notifying when the account is created:
       CFG_ACCESS_CONTROL_NOTIFY_USER_ABOUT_NEW_ACCOUNT = 0
 
     Send an email to the user notifying when the account is activated:
       CFG_ACCESS_CONTROL_NOTIFY_USER_ABOUT_ACTIVATION = 0
 
     Send an email to the user notifying when the account is deleted/rejected:
       CFG_ACCESS_CONTROL_NOTIFY_USER_ABOUT_DELETION = 0
 
   - Account overview:
     Here you find an overview of the number of guest accounts, registered accounts and accounts
     awaiting activation, with a link to the activation page.
 
   - Create account:
     For creating new accounts, the email address must be unique. If configured to do so, an email
     will be sent to the given address when an account is created.
 
   - Edit accounts:
     For activating or rejecting accounts in addition to modifying them. An activated account can be
     inactivated for a short period of time, but this will not warn the account owner. To find accounts
     enter a part of the email address of the account and then search. This may take some time. If there
     are more than the selected number of accounts per page, you can use the next/prev links to switch
     pages. The accounts to search in can also be limited to only activated or not activated accounts.
 
   - Edit account:
     When editing one account, you can change the email address, password, delete the account, or modify
     the baskets or alerts belonging to one account. Which login method should be the default for this
     account can also be selected. To modify baskets or alerts, you need to login as the user, and
     modify the desired data as a normal user. Remember to log out as the user when you are finished
     editing.
 
 

V. Managing login methods

    CDS Invenio supports using external login systems to authenticate users.
 
    When a user wants to login, the username and password given by the user is checked against the selected
    system, if the user is authenticated by the external system, a valid email-address is returned to
    CDS Invenio and used to recognize the user within CDS Invenio.
 
    If a new user is trying to login without having an account, using an external login system, an account
    is automatically created in CDS Invenio to recognize and store the users settings. The password for the
    local account is randomly generated.
 
    If you want the user to be unable to change login method and account username / password, forcing use
    of certain external systems, set CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS to 4 as mentioned in the last paragraph.
 
    If a user is changing login method from an external one to the internal, he also need to either change the
    password before logging out, or ask to get the password sent by email, since the password is randomly
    generated for the local account when using an external login method.
 
    If a external login system is used, you may want to protect the users username / password using HTTPS.
 
    To add new system, two changes must be made (for the time being):
    - The name of the method, if it is default or not, and the classname must be added to the variable
      CFG_EXTERNAL_AUTHENTICATION in access_control_config.py. Atleast one method must be marked as the
      default one. The internal login method should be given with None as classname.
 
      Example:
       CFG_EXTERNAL_AUTHENTICATION = {"%s (internal)" % cdsname: (None, True), "CERN NICE (external)":
                                                         (AuthCernWrapper(), False)}
 
    - A class must be created derived from the class external_authentication inside file
      external_authentication.py. This class must include at least the
      function auth_user. This function returns a valid email-address in CDS Invenio if the user
      is authenticated, not necessarily the same entered by the user as username. If the user
      is not authenticated, return None.
-     The class could also provide four more methods: fetch_user_preferences, user_exists,
+     The class could also provide five more methods: fetch_user_preferences, user_exists,
      fetch_user_groups_membership and fetch_all_users_groups_membership.
      The first should take an email and eventually a password and should return a dictionary of keys
      and value representing external preferences, infos or settings. If, for some reasons, you like
      to force some kind of hiding for some particular field you should export the related key
      prefixed by "HIDDEN_". Those fields won't be displayed in tables and pages regarding external
      settings.
      The second method should check through the external system if a particular email exists. If you
      provide such a method then a user will be able to switch from and to this authorization method.
      The third method should take an email and (if necessary) a password
      and should return a dictionary of external_groups_names toghether with their description, for which
      the user has a membership. Those groups will be merged into the groups system.
      The user will be a member of those groups and will be able to use them in any place
      where groups are useful, but won't be able to unsubscribe or to administrate them.
      The fourth method should just return a dictionary of external groups as keys and touples containing
      a group description and a list of email of users belonging to each groups. Those memberships
      will be merged into the database in the way done by the previous method, but could
      provide batch synchronization of groups.
+     The fifth method should just return the nickname as is known by the external authentication
+     system, given the usual email/username and the password.
      Note: if your system has more than one external login methods then incoherence in the groups
      memberships could happen when a user switch his login method. This will be fixed some times in the
      future.
 
      Example template:
 
      from invenio.external_authentication import ExternalAuth, WebAccessExternalAuthError
 
      class ExternalAuthFoo(ExternalAuth):
          """External authentication template example."""
 
          def __init__(self):
              """Initialize stuff here."""
              self.name = None
              pass
 
          def auth_user(self, username, password):
              """Authenticate user-supplied USERNAME and PASSWORD.
              Return None if authentication failed, or the email address of the
              person if the authentication was successful.  In order to do
              this you may perhaps have to keep a translation table between
              usernames and email addresses.
              Raise WebAccessExternalAuthError in case of external troubles.
              """
              raise NotImplementedError
              #return None
 
          def user_exists(self, email):
              """Checks against external_authentication for existance of email.
              @return True if the user exists, False otherwise
              """
              raise NotImplementedError
 
          def fetch_user_groups_membership(self, username, password=None):
              """Given a username, returns a dictionary of groups
              and their description to which the user is subscribed.
              Raise WebAccessExternalAuthError in case of troubles.
              """
              raise NotImplementedError
              #return {}
 
          def fetch_user_preferences(self, username, password=None):
              """Given a username and a password, returns a dictionary of keys and
              values, corresponding to external infos and settings.
 
              userprefs = {"telephone": "2392489",
              "address": "10th Downing Street"}
              """
              raise NotImplementedError
             #return {}
 
          def fetch_all_users_groups_membership(self):
              """Fetch all the groups with a description, and users who belong to
              each groups.
              @return {'mygroup': ('description', ['email1', 'email2', ...]), ...}
              """
              raise NotImplementedError
 
+         def fetch_user_nickname(self, username, password):
+             """Given a username and a password, returns the right nickname belonging
+             to that user (username could be an email).
+             """
+             raise NotImplementedError
+             #return Nickname
 
 
 - end of file -
 
diff --git a/modules/webaccess/lib/access_control_config.py b/modules/webaccess/lib/access_control_config.py index d04a67a20..b6bfffa36 100644 --- a/modules/webaccess/lib/access_control_config.py +++ b/modules/webaccess/lib/access_control_config.py @@ -1,155 +1,154 @@ ## $Id$ ## ## This file is part of CDS Invenio. ## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 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 Access Control Config. """ __revision__ = \ "$Id$" # pylint: disable-msg=C0301 import external_authentication_cern from invenio.config import cdsname, sweburl, supportemail # VALUES TO BE EXPORTED # CURRENTLY USED BY THE FILES access_control_engine.py access_control_admin.py webaccessadmin_lib.py # name of the role giving superadmin rights SUPERADMINROLE = 'superadmin' # name of the webaccess webadmin role WEBACCESSADMINROLE = 'webaccessadmin' # name of the action allowing roles to access the web administrator interface WEBACCESSACTION = 'cfgwebaccess' # name of the action allowing roles to delegate the rights to other roles # ex: libraryadmin to delegate libraryworker DELEGATEADDUSERROLE = 'accdelegaterole' # max number of users to display in the drop down selects MAXSELECTUSERS = 25 # max number of users to display in a page (mainly for user area) MAXPAGEUSERS = 25 # Use external source for access control? # Atleast one must be added # Adviced not to change the name, since it is used to identify the account # Format is: System name: (System class, Default True/Flase), atleast one # must be default -CFG_EXTERNAL_AUTHENTICATION = {"%s (internal)" % cdsname: (None, True)} -#CFG_EXTERNAL_AUTHENTICATION = {"%s (internal)" % cdsname: (None, True), \ -# "CERN (external)": (external_authentication_cern.ExternalAuthCern(), False)} - +CFG_EXTERNAL_AUTHENTICATION = {"Local": (None, True)} +#CFG_EXTERNAL_AUTHENTICATION = {"Local": (None, True), \ +# "CERN": (external_authentication_cern.ExternalAuthCern(), False)} # default data for the add_default_settings function # roles # name description DEF_ROLES = ((SUPERADMINROLE, 'superuser with all rights'), ('photoadmin', 'Photo collection administrator'), (WEBACCESSADMINROLE, 'WebAccess administrator')) # users # list of e-mail addresses DEF_USERS = [] # actions # name desc allowedkeywords optional DEF_ACTIONS = ( ('cfgwebsearch', 'configure WebSearch', '', 'no'), ('cfgbibformat', 'configure BibFormat', '', 'no'), ('cfgwebsubmit', 'configure WebSubmit', '', 'no'), ('runbibindex', 'run BibIndex', '', 'no'), ('runbibupload', 'run BibUpload', '', 'no'), ('runwebcoll', 'run webcoll', 'collection', 'yes'), ('runbibformat', 'run BibFormat', 'format', 'yes'), (WEBACCESSACTION, 'configure WebAccess', '', 'no'), (DELEGATEADDUSERROLE, 'delegate subroles inside WebAccess', 'role', 'no'), ('runbibtaskex', 'run BibTaskEx example', '', 'no'), ('referee', 'referee document type doctype/category categ', 'doctype,categ', 'yes'), ('submit', 'use webSubmit', 'doctype,act', 'yes'), ('runbibrank', 'run BibRank', '', 'no'), ('cfgbibrank', 'configure BibRank', '', 'no'), ('cfgbibharvest', 'configure BibHarvest', '', 'no'), ('runoaiharvest', 'run oaiharvest task', '', 'no'), ('cfgwebcomment', 'configure WebComment', '', 'no'), ('runoaiarchive', 'run oaiarchive task', '', 'no'), ('runbibedit', 'run BibEdit', '', 'no'), ) # authorizations # role action arglistid optional arguments DEF_AUTHS = ( (SUPERADMINROLE, 'cfgwebsearch', -1, 0, {}), (SUPERADMINROLE, 'cfgbibformat', -1, 0, {}), (SUPERADMINROLE, 'cfgwebsubmit', -1, 0, {}), (SUPERADMINROLE, 'runbibindex', -1, 0, {}), (SUPERADMINROLE, 'runbibupload', -1, 0, {}), (SUPERADMINROLE, 'runbibformat', -1, 1, {}), (SUPERADMINROLE, WEBACCESSACTION, -1, 0, {}), ('photoadmin', 'runwebcoll', -1, 0, {'collection': 'Pictures'}), (WEBACCESSADMINROLE,WEBACCESSACTION, -1, 0, {}), (SUPERADMINROLE, 'runtaskex', -1, 0, {}), (SUPERADMINROLE, 'referee', -1, 1, {}), (SUPERADMINROLE, 'submit', -1, 1, {}), (SUPERADMINROLE, 'runbibrank', -1, 0, {}), (SUPERADMINROLE, 'cfgbibrank', -1, 0, {}), (SUPERADMINROLE, 'cfgbibharvest', -1, 0, {}), (SUPERADMINROLE, 'runoaiharvest', -1, 0, {}), (SUPERADMINROLE, 'cfgwebcomment', -1, 0, {}), (SUPERADMINROLE, 'runoaiarchive', -1, 0, {}), (SUPERADMINROLE, 'runbibedit', -1, 0, {}), ) CFG_WEBACCESS_MSGS = { 0: 'Try to login with another account.' % (sweburl, sweburl, "%s"), 1: '
If you think this is not correct, please contact: %s' % (supportemail, supportemail), 2: '
If you have any questions, please write to %s' % (supportemail, supportemail), 3: 'Guest users are not allowed, please login.' % sweburl, 4: 'The site is temporarily closed for maintenance. Please come back soon.', 5: 'Authorization failure', 6: '%s temporarily closed' % cdsname, 7: 'This functionality is temporarily closed due to server maintenance. Please use only the search engine in the meantime.', 8: 'Functionality temporarily closed' } CFG_WEBACCESS_WARNING_MSGS = { 0: 'Authorization granted', 1: 'Error(1): You are not authorized to perform this action.', 2: 'Error(2): You are not authorized to perform any action.', 3: 'Error(3): The action %s does not exist.', 4: 'Error(4): Unexpected error occurred.', 5: 'Error(5): Missing mandatory keyword argument(s) for this action.', 6: 'Error(6): Guest accounts are not authorized to perform this action.', 7: 'Error(7): Not enough arguments, user ID and action name required.', 8: 'Error(8): Incorrect keyword argument(s) for this action.', 9: """Error(9): Account '%s' is not yet activated.""", 10: """Error(10): You were not authorized by the authentication method '%s'.""", 11: """Error(11): The selected login method '%s' is not the default method for this account, please try another one.""", 12: """Error(12): Selected login method '%s' does not exist.""", 13: """Error(13): Could not register '%s' account.""", 14: """Error(14): Could not login using '%s', because this user is unknown.""", 15: """Error(15): Could not login using your '%s' account, because you have introduced a wrong password.""", 16: """Error(16): External authentication troubles using '%s' (maybe temporary network problems).""", } diff --git a/modules/webaccess/lib/external_authentication.py b/modules/webaccess/lib/external_authentication.py index 3016e80e4..781f26432 100644 --- a/modules/webaccess/lib/external_authentication.py +++ b/modules/webaccess/lib/external_authentication.py @@ -1,87 +1,100 @@ # -*- coding: utf-8 -*- ## ## $Id$ ## ## This file is part of CDS Invenio. ## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 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. """External user authentication for CDS Invenio.""" __revision__ = \ "$Id$" class WebAccessExternalAuthError(Exception): """Exception to signaling general external trouble.""" pass class ExternalAuth: """External authentication template example.""" def __init__(self): """Initialize stuff here""" self.name = None + # Set the following variable to True in order to import the externally + # provided nickname into Invenio during the first login of a user + # through this external authentication system. + # If the nickname is already taken into Invenio, then it won't be + # considered. + self.enforce_external_nicknames = False pass def auth_user(self, username, password): """Authenticate user-supplied USERNAME and PASSWORD. Return None if authentication failed, or the email address of the person if the authentication was successful. In order to do this you may perhaps have to keep a translation table between usernames and email addresses. Raise WebAccessExternalAuthError in case of external troubles. """ raise NotImplementedError #return None def user_exists(self, email): """Check the external authentication system for existance of email. @return True if the user exists, False otherwise """ raise NotImplementedError - def fetch_user_groups_membership(self, username, password=None): - """Given a username, returns a dictionary of groups + def fetch_user_groups_membership(self, username, password): + """Given a username and a password, returns a dictionary of groups and their description to which the user is subscribed. Raise WebAccessExternalAuthError in case of troubles. """ raise NotImplementedError #return {} + def fetch_user_nickname(self, username, password): + """Given a username and a password, returns the right nickname belonging + to that user (username could be an email). + """ + raise NotImplementedError + #return Nickname + def fetch_user_preferences(self, username, password=None): """Given a username and a password, returns a dictionary of keys and values, corresponding to external infos and settings. userprefs = {"telephone": "2392489", "address": "10th Downing Street"} (WEBUSER WILL erase all prefs that starts by EXTERNAL_ and will store: "EXTERNAL_telephone"; all internal preferences can use whatever name but starting with EXTERNAL). If a pref begins with HIDDEN_ it will be ignored. """ raise NotImplementedError #return {} def fetch_all_users_groups_membership(self): """Fetch all the groups with a description, and users who belong to each groups. @return {'mygroup': ('description', ['email1', 'email2', ...]), ...} """ raise NotImplementedError diff --git a/modules/webaccess/lib/external_authentication_cern.py b/modules/webaccess/lib/external_authentication_cern.py index c1966be4c..fe6d6e448 100644 --- a/modules/webaccess/lib/external_authentication_cern.py +++ b/modules/webaccess/lib/external_authentication_cern.py @@ -1,120 +1,149 @@ # -*- coding: utf-8 -*- ## ## $Id$ ## ## This file is part of CDS Invenio. ## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 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. """External user authentication for CERN NICE/CRA Invenio.""" __revision__ = \ "$Id$" import httplib import socket from invenio.external_authentication import ExternalAuth, \ WebAccessExternalAuthError from invenio.external_authentication_cern_wrapper import AuthCernWrapper + +# Tunable list of settings to be hidden +CFG_EXTERNAL_AUTH_CERN_HIDDEN_SETTINGS = ['auth', 'respccid', 'ccid'] +# Tunable list of groups to be hidden +CFG_EXTERNAL_AUTH_CERN_HIDDEN_GROUPS = ['All Exchange People'] + class ExternalAuthCern(ExternalAuth): """ External authentication example for a custom HTTPS-based authentication service (called "CERN NICE"). """ def __init__(self): """Initialize stuff here""" ExternalAuth.__init__(self) try: self.connection = AuthCernWrapper() except (httplib.CannotSendRequest, socket.error, AttributeError, IOError, TypeError): # Let the user note that no connection is available self.connection = None def _try_twice(self, funct, params): """Try twice to execute funct on self.connection passing it params. If for various reason the connection doesn't work it's restarted """ try: ret = funct(self.connection, **params) except (httplib.CannotSendRequest, socket.error, AttributeError, IOError, TypeError): try: self.connection = AuthCernWrapper() ret = funct(self.connection, **params) except (httplib.CannotSendRequest, socket.error, AttributeError, IOError, TypeError): self.connection = None raise WebAccessExternalAuthError return ret def auth_user(self, username, password): """ Check USERNAME and PASSWORD against CERN NICE/CRA database. - Return None if authentication failed, email address of the - person if authentication succeeded. + Return None if authentication failed, or the email address of the + person if the authentication was successful. In order to do + this you may perhaps have to keep a translation table between + usernames and email addresses. + It can also return a tuple (actually a couple) (email, nickname). + If it is the first time the user logs in Invenio the nickname is + stored alongside the email. If this nickname is unfortunatly already + in use it is discarded. Otherwise it is ignored. + Raise WebAccessExternalAuthError in case of external troubles. """ infos = self._try_twice(funct=AuthCernWrapper.get_user_info, \ params={"user_name":username, "password":password}) if "email" in infos: return infos["email"] else: return None def user_exists(self, email): """Checks against CERN NICE/CRA for existance of email. @return True if the user exists, False otherwise """ users = self._try_twice(funct=AuthCernWrapper.list_users, \ params={"display_name":email}) return email.upper() in [user['email'].upper() for user in users] - def fetch_user_groups_membership(self, email, password=None): + def fetch_user_groups_membership(self, email, password): """Fetch user groups membership from the CERN NICE/CRA account. @return a dictionary of groupname, group description """ groups = self._try_twice(funct=AuthCernWrapper.get_groups_for_user, \ params={"user_name":email}) + # Filtering out uncomfortable groups + groups = [group for group in groups if group not in CFG_EXTERNAL_AUTH_CERN_HIDDEN_GROUPS] return dict(map(lambda x: (x, '@' in x and x + ' (Mailing list)' \ or x + ' (Group)'), groups)) + def fetch_user_nickname(self, username, password): + """Given a username and a password, returns the right nickname belonging + to that user (username could be an email). + """ + infos = self._try_twice(funct=AuthCernWrapper.get_user_info, \ + params={"user_name":username, "password":password}) + if "login" in infos: + return infos["login"] + else: + return None + def fetch_user_preferences(self, username, password=None): """Fetch user preferences/settings from the CERN Nice account. the external key will be '1' if the account is external to NICE/CRA, otherwise 0 @return a dictionary. Note: auth and respccid are hidden """ prefs = self._try_twice(funct=AuthCernWrapper.get_user_info, \ params={"user_name":username, "password":password}) ret = {} + try: + if int(prefs['auth']) == 3 \ + and (int(prefs['respccid']) > 0 \ + or not prefs['email'].endswith('@cern.ch')): + ret['external'] = '1' + else: + ret['external'] = '0' + except KeyError: + ret['external'] = '1' for key, value in prefs.items(): - if key in ['auth', 'respccid', 'ccid']: + if key in CFG_EXTERNAL_AUTH_CERN_HIDDEN_SETTINGS: ret['HIDDEN_' + key] = value else: ret[key] = value - if int(ret['HIDDEN_auth']) == 3 \ - and (int(ret['HIDDEN_respccid']) > 0 \ - or not ret['email'].endswith('@cern.ch')): - ret['external'] = '1' - else: - ret['external'] = '0' return ret diff --git a/modules/websession/lib/websession_templates.py b/modules/websession/lib/websession_templates.py index 5e727955f..4a1caae34 100644 --- a/modules/websession/lib/websession_templates.py +++ b/modules/websession/lib/websession_templates.py @@ -1,2041 +1,2041 @@ ## $Id$ ## This file is part of CDS Invenio. ## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 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 time import cgi import gettext import string import locale from invenio.config import \ CFG_CERN_SITE, \ bibformat, \ cdslang, \ cdsname, \ cdsnameintl, \ supportemail, \ sweburl, \ version, \ weburl from invenio.messages import gettext_set_language from invenio.textutils import indent_text from invenio.websession_config import CFG_WEBSESSION_GROUP_JOIN_POLICY class Template: def tmpl_lost_password_message(self, ln, supportemail): """ Defines the text that will be displayed on the 'lost password' page Parameters: - 'ln' *string* - The language to display the interface in - 'supportemail' *string* - The email of the support team """ # load the right message language _ = gettext_set_language(ln) return _("If you have lost password for your CDS Invenio internal account, then please enter your email address below and the lost password will be emailed to you.") +\ "

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

" def tmpl_back_form(self, ln, message, act, 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 - 'act' *string* - The action to accomplish when going back - 'link' *string* - The link text """ out = """ -
%(message)s + %(message)s %(link)s
"""% { 'message' : message, 'act' : act, 'link' : link } 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, 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' *string* - The password of the user - '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

%(nickname_label)s:
(%(mandatory)s)
%(nickname_prefix)s%(nickname)s%(nickname_suffix)s
%(new_email)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 "", 'sweburl': sweburl, } if not password_disabled: out += """

%(change_pass)s

%(old_password)s:
(%(mandatory)s)

%(note)s: %(old_password_note)s
%(new_password)s:
(%(optional)s)

%(note)s: %(password_note)s
%(retype_password)s:
   
""" % { 'change_pass' : _("If you want to change your password, please fill in the old one and set new values 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' : password, 'password_disabled' : password_disabled and "disabled" or "", 'sweburl': sweburl, } 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

%(show_latestbox)s
%(show_helpbox)s
%(select_group_records)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"), 'sweburl': sweburl, } for system in methods: out += """%(system)s
""" % { 'system' : system, 'disabled' : method_disabled and "disabled" or "", 'selected' : current == system and "checked" or "", } out += """
""" % { 'select_method' : _("Select method"), } return out def tmpl_lost_password_form(self, ln, msg): """ 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 = """
%(msg)s
%(email)s:
""" % { 'msg' : msg, 'ln': ln, 'email' : _("Email address"), 'send' : _("Send lost password"), } 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.") % cdsnameintl[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
%(your_baskets)s
%(basket_explain)s""" % { 'ln' : ln, 'your_searches' : _("Your Searches"), 'search_explain' : _("View all the searches you performed during the last 30 days."), '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: 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: out += self.tmpl_warning_guest_user(type="alerts", ln = ln) 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): """ 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 """ out ="" out +=""" """ % (title, body) return out def tmpl_account_page(self, ln, weburl, accBody, baskets, alerts, searches, messages, groups, administrative): """ Displays the your account page Parameters: - 'ln' *string* - The language to display the interface in - 'weburl' *string* - The URL of CDS Invenio - '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 - 'administrative' *string* - The body of the administrative block """ # load the right message language _ = gettext_set_language(ln) out = "" out += self.tmpl_account_template(_("Your Account"), accBody, ln) out += self.tmpl_account_template(_("Your Messages"), messages, ln) out += self.tmpl_account_template(_("Your Baskets"), baskets, ln) out += self.tmpl_account_template(_("Your Alert Searches"), alerts, ln) out += self.tmpl_account_template(_("Your Searches"), searches, ln) 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) 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) 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) out += self.tmpl_account_template(_("Your Administrative Activities"), administrative, ln) 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_lost_password_email_body(self, username, password, ln=cdslang): """ The body of the email that sends lost internal account passwords to users. """ _ = gettext_set_language(ln) out = """\ %(hello)s: %(here_are_your_user_credentials_for)s %(cdsnameintl)s: %(label_username)s: %(username)s %(label_password)s: %(password)s %(you_can_login_at)s: <%(login_url)s> %(best_regards)s -- %(cdsnameintl)s <%(weburl)s> %(need_intervention_please_contact)s <%(supportemail)s> """ % { 'hello': _("Hello"), 'here_are_your_user_credentials_for': _("Here are your user credentials for"), 'cdsnameintl': cdsnameintl[ln], 'label_username': _("username"), 'username': username, 'label_password': _("password"), 'password': password, 'you_can_login_at': _("You can login at"), 'login_url': "%s/youraccount/login?ln=%s" % (sweburl, ln), 'best_regards': _("Best regards"), 'weburl': weburl, 'need_intervention_please_contact': _("Need human intervention? Contact"), 'supportemail': supportemail } 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, password 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.") + ' ' 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, supportemail): """ 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 - 'supportemail' *string* - The email of the support team """ # load the right message language _ = gettext_set_language(ln) out = "

%(please_login)s
" % { 'please_login' : _("If you already have an account, please login using the form below.") } 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' % (supportemail, supportemail)) 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_title)s %(login_select)s
%(username)s:
%(password)s:
""" % { 'ln': ln, 'referer' : cgi.escape(referer), 'username' : _("Username"), 'password' : _("Password"), '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=cdslang): """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_register_page(self, ln, referer, level, supportemail, cdsname): """ 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) - 'supportemail' *string* - The email of the support team - 'cdsname' *string* - The name of the installation """ # 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 += """

%(email_address)s:
(%(mandatory)s)

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

%(example)s: johnd
%(password)s:
(%(optional)s)

%(note)s: %(password_contain)s
%(retype)s:

%(note)s: %(explain_acc)s""" % { 'referer' : cgi.escape(referer), '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.") % cdsname, } return out def tmpl_account_adminactivities(self, ln, weburl, uid, guest, roles, activities): """ Displays the admin activities block for this user Parameters: - 'ln' *string* - The language to display the interface in - 'weburl' *string* - The address of the site - '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 seem to be %(x_role)s.") % {'x_role': ('' + string.join(roles, ", ") + " ")} + '

' out += _("Here are some interesting web admin links for you:") # print proposed links: activities.sort(lambda x, y: cmp(string.lower(x), string.lower(y))) for action in activities: if action == "runbibedit": out += """
   
%s""" % (weburl, ln, _("Run BibEdit")) if action == "cfgbibformat": out += """
    %s""" % (weburl, ln, _("Configure BibFormat")) if action == "cfgbibharvest": out += """
    %s""" % (weburl, _("Configure BibHarvest")) if action == "cfgbibindex": out += """
    %s""" % (weburl, ln, _("Configure BibIndex")) if action == "cfgbibrank": out += """
    %s""" % (weburl, ln, _("Configure BibRank")) if action == "cfgwebaccess": out += """
    %s""" % (weburl, ln, _("Configure WebAccess")) if action == "cfgwebcomment": out += """
    %s""" % (weburl, ln, _("Configure WebComment")) if action == "cfgwebsearch": out += """
    %s""" % (weburl, ln, _("Configure WebSearch")) if action == "cfgwebsubmit": out += """
    %s""" % (weburl, ln, _("Configure WebSubmit")) 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): """ 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 """ # load the right message language _ = gettext_set_language(ln) out = """""" % weburl if guest: out += """%(guest_msg)s :: %(session)s :: %(baskets)s :: %(alerts)s :: %(login)s""" % { 'weburl' : weburl, 'sweburl': sweburl, 'ln' : ln, 'guest_msg' : _("guest"), 'session' : _("session"), 'alerts' : _("alerts"), 'baskets' : _("baskets"), 'login' : _("login"), } else: out += """%(username)s :: %(account)s :: %(messages)s :: %(baskets)s :: %(alerts)s :: %(groups)s :: """ % { 'username' : username, 'weburl' : weburl, 'sweburl' : sweburl, 'ln' : ln, 'account' : _("account"), 'alerts' : _("alerts"), 'messages': _("messages"), 'baskets' : _("baskets"), 'groups' : _("groups"), } if submitter: out += """%(submission)s :: """ % { 'weburl' : weburl, 'ln' : ln, 'submission' : _("submissions"), } if referee: out += """%(approvals)s :: """ % { 'weburl' : weburl, 'ln' : ln, 'approvals' : _("approvals"), } if admin: out += """%(administration)s :: """ % { 'sweburl' : sweburl, 'ln' : ln, 'administration' : _("administration"), } out += """%(logout)s""" % { 'sweburl' : sweburl, 'ln' : ln, 'logout' : _("logout"), } return out def tmpl_warning(self, warnings, ln=cdslang): """ 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=cdslang): """ 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=cdslang): """ 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=cdslang): """ 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 % {'weburl' : weburl, 'grpID' : grpID, 'ln': ln, 'img':"webbasket_create_small.png", 'text':_("Edit group"), 'action':"edit" } members_link = img_link % {'weburl' : weburl, '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 indent_text(out, 2) def tmpl_display_member_groups(self, groups, ln=cdslang): """ 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 indent_text(group_text, 2) def tmpl_display_external_groups(self, groups, ln=cdslang): """ 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 indent_text(group_text, 2) def tmpl_display_input_group_info(self, group_name, group_description, join_policy, act_type="create", grpID="", warnings=[], ln=cdslang): """ 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 = weburl + '/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 = weburl + '/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
%(name_label)s
%(description_label)s
%(join_policy_label)s %(join_policy)s
%(hidden_id)s
%(delete_text)s
""" out %= {'action' : action, 'logo': weburl + '/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 indent_text(out, 2) def tmpl_display_input_join_group(self, group_list, group_name, group_from_search, search, warnings=[], ln=cdslang): """ 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  

%(label2)s


""" out %= {'action' : weburl + '/yourgroups/join', 'logo': weburl + '/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 indent_text(out, 2) def tmpl_display_manage_member(self, grpID, group_name, members, pending_members, infos=[], warnings=[], ln=cdslang): """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

%(header1)s %(header1)s
 
%(member_text)s
%(header2)s %(header2)s
 
%(pending_text)s
%(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") link_open = '' link_open %= (weburl, ln) 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 = weburl + '/yourgroups/members?ln=' + ln out %= {'title':_('Group: %s') % group_name, 'member_text' : member_text, 'pending_text' :pending_text, 'action':action, 'grpID':grpID, 'header1': header1, 'header2': header2, 'header3': header3, 'invite_text': invite_text, 'imgurl': weburl + '/img', 'cancel_label':_("Cancel"), 'ln':ln } return indent_text(out, 2) def tmpl_display_input_leave_group(self, groups, warnings=[], ln=cdslang): """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 = weburl + '/yourgroups/leave?ln=%s' action %= (ln) out %= {'groups' : groups, 'list_label' : list_label, 'action':action, 'logo': weburl + '/img/webbasket_create.png', 'label' : _("Leave group"), 'cancel_label':_("Cancel"), 'ln' :ln, 'submit' : submit } return indent_text(out, 2) def tmpl_confirm_delete(self, grpID, ln=cdslang): """ display a confirm message when deleting a group @param ln: language @return html output """ _ = gettext_set_language(ln) action = weburl + '/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 indent_text(out, 2) def tmpl_confirm_leave(self, uid, grpID, ln=cdslang): """ display a confirm message @param ln: language @return html output """ _ = gettext_set_language(ln) action = weburl + '/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 indent_text(out, 2) def __create_join_policy_selection_menu(self, name, current_join_policy, ln=cdslang): """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 += indent_text('' % (select_text)) for (key, label) in elements: selected = '' if key == selected_key: selected = ' selected="selected"' out += indent_text(''% (key, selected, label), 1) out += '' return out def tmpl_infobox(self, infos, ln=cdslang): """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=cdslang, 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 % (weburl, _("Your Groups")) return nav_h1 % (weburl, _("Your Account")) + nav_h2 def tmpl_group_table_title(self, img="", text="", ln=cdslang): """ 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 += """ """ % (weburl + img) out += """ %s
""" % text return out def tmpl_admin_msg(self, group_name, grpID, ln=cdslang): """ 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 = weburl + "/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=cdslang): """ 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 = weburl + "/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=cdslang): """ 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 = weburl + "/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=cdslang): """ 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 diff --git a/modules/websession/lib/websession_webinterface.py b/modules/websession/lib/websession_webinterface.py index 9733a68ff..c34bb5f19 100644 --- a/modules/websession/lib/websession_webinterface.py +++ b/modules/websession/lib/websession_webinterface.py @@ -1,933 +1,943 @@ # -*- coding: utf-8 -*- ## ## $Id$ ## ## This file is part of CDS Invenio. ## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 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$""" from mod_python import apache import smtplib from invenio.config import \ CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS, \ CFG_ACCESS_CONTROL_LEVEL_SITE, \ CFG_ACCESS_CONTROL_NOTIFY_USER_ABOUT_NEW_ACCOUNT, \ cdsname, \ supportemail, \ sweburl, \ weburl 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_config import * 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 webgroup_dblayer from invenio.messages import gettext_set_language import invenio.template websession_templates = invenio.template.load('websession') class WebInterfaceYourAccountPages(WebInterfaceDirectory): _exports = ['', 'edit', 'change', 'lost', 'display', 'send_email', 'youradminactivities', 'delete', 'logout', 'login', 'register'] _force_https = True def index(self, req, form): redirect_to_url(req, '%s/youraccount/display' % sweburl) 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") if webuser.isGuestUser(uid): return page(title=_("Your Account"), body=webaccount.perform_info(req, args['ln']), description="CDS Personalize, Main page", keywords="CDS, personalize", uid=uid, req=req, secure_page_p = 1, language=args['ln'], lastupdated=__lastupdated__) username = webuser.get_nickname_or_email(uid) bask = webbasket.account_list_baskets(uid, ln=args['ln']) aler = webalert.account_list_alerts(uid, ln=args['ln']) sear = webalert.account_list_searches(uid, ln=args['ln']) msgs = account_new_mail(uid, ln=args['ln']) grps = webgroup.account_group(uid, ln=args['ln']) return page(title=_("Your Account"), body=webaccount.perform_display_account(req,username,bask,aler,sear,msgs,grps,args['ln']), description="CDS Personalize, Main page", keywords="CDS, personalize", uid=uid, req=req, secure_page_p = 1, language=args['ln'], lastupdated=__lastupdated__) 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") if webuser.isGuestUser(uid): return webuser.page_not_authorized(req, "../youraccount/edit", text=_("This functionality is forbidden to guest users.")) return page(title= _("Your Settings"), body=webaccount.perform_set(webuser.get_email(uid), webuser.get_password(uid), args['ln'], verbose=args['verbose']), navtrail="""""" % (sweburl, args['ln']) + _("Your Account") + """""", description="CDS Personalize, Your Settings", keywords="CDS, personalize", uid=uid, req=req, secure_page_p = 1, language=args['ln'], lastupdated=__lastupdated__) 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), }) uid = webuser.getUid(req) current_password = webuser.get_password(uid) if current_password == None: current_password = "" # 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/change") prefs = webuser.get_user_preferences(uid) if args['login_method'] and CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS < 4 \ and args['login_method'] in CFG_EXTERNAL_AUTHENTICATION.keys(): title = _("Settings edited") act = "display" linkname = _("Show account") if prefs['login_method'] != args['login_method']: if 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 = _("

Switched to internal login method. ") + mess += _("""Please note, that if this is the first time that + you are using this account with the internal method + then the system has set for you a random generated password + which you can obtain via email clicking on the following + button:

""") + 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.") % 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.") % 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.") % args['login_method'] elif args['login_method'] and CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS >= 4: return webuser.page_not_authorized(req, "../youraccount/change") elif args['email']: # We should ignore the password if the authentication method is an # external one. ignore_password_p = CFG_EXTERNAL_AUTHENTICATION[prefs['login_method']][0] != None 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") if change: mess = _("Settings successfully edited.") act = "display" 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.") % args['nickname'] mess += " " + _("Please try again.") act = "edit" linkname = _("Edit settings") title = _("Editing settings failed") elif not webuser.email_valid_p(args['email']): mess = _("Supplied email address %s is invalid.") % args['email'] mess += " " + _("Please try again.") act = "edit" 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.") % args['email'] mess += " " + websession_templates.tmpl_lost_your_password_teaser(args['ln']) mess += " " + _("Or please try again.") act = "edit" 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.") % args['nickname'] mess += " " + _("Please try again.") act = "edit" linkname = _("Edit settings") title = _("Editing settings failed") elif args['old_password'] != None and CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS < 3: if args['old_password'] == current_password: if args['password'] == args['password2']: webuser.updatePasswordUser(uid, args['password']) mess = _("Password successfully edited.") act = "display" linkname = _("Show account") title = _("Password edited") else: mess = _("Both passwords must match.") mess += " " + _("Please try again.") act = "edit" linkname = _("Edit settings") title = _("Editing password failed") else: mess = _("Wrong old password inserted.") mess += " " + _("Please try again.") act = "edit" linkname = _("Edit settings") title = _("Editing password failed") elif 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 = "display" linkname = _("Show account") mess = _("User settings saved correctly.") else: mess = _("Unable to update settings.") act = "edit" linkname = _("Edit settings") title = _("Editing settings failed") return page(title=title, - body=webaccount.perform_back(mess,act, linkname, args['ln']), + body=webaccount.perform_back(mess, act, linkname, args['ln']), navtrail="""""" % (sweburl, args['ln']) + _("Your Account") + """""", description="CDS Personalize, Main page", keywords="CDS, personalize", uid=uid, req=req, secure_page_p = 1, language=args['ln'], lastupdated=__lastupdated__) 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") return page(title=_("Lost your password?"), body=webaccount.perform_lost(args['ln']), navtrail="""""" % (sweburl, args['ln']) + _("Your Account") + """""", description="CDS Personalize, Main page", keywords="CDS, personalize", uid=uid, req=req, secure_page_p = 1, language=args['ln'], lastupdated=__lastupdated__) 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") 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 by email since you are using external authentication system.") return page(title=_("Your Account"), body=webaccount.perform_emailMessage(eMsg, args['ln']), description="CDS Personalize, Main page", keywords="CDS, personalize", uid=uid, req=req, secure_page_p = 1, language=args['ln'], lastupdated=__lastupdated__) passw = webuser.givePassword(args['p_email']) if passw == -999: eMsg = _("The entered email address does not exist in the database.") return page(title=_("Your Account"), body=webaccount.perform_emailMessage(eMsg, args['ln']), description="CDS Personalize, Main page", keywords="CDS, personalize", uid=uid, req=req, secure_page_p = 1, language=args['ln'], lastupdated=__lastupdated__) fromaddr = "From: %s" % supportemail toaddr = "To: " + args['p_email'] subject = "Subject: %s %s" % (_("Credentials for"), cdsname) body = websession_templates.tmpl_account_lost_password_email_body(args['p_email'], passw, args['ln']) msg = toaddr + "\n" + subject + "\n\n" + body server = smtplib.SMTP('localhost') server.set_debuglevel(1) try: server.sendmail(fromaddr, toaddr, msg) except smtplib.SMTPRecipientsRefused: 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="CDS Personalize, Main page", keywords="CDS, personalize", uid=uid, req=req, secure_page_p = 1, language=args['ln'], lastupdated=__lastupdated__) server.quit() return page(title=_("Lost password sent"), body=webaccount.perform_emailSent(args['p_email'], args['ln']), description="CDS Personalize, Main page", keywords="CDS, personalize", uid=uid, req=req, secure_page_p = 1, language=args['ln'], lastupdated=__lastupdated__) def youradminactivities(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/youradminactivities") return page(title=_("Your Administrative Activities"), body=webaccount.perform_youradminactivities(uid, args['ln']), navtrail="""""" % (sweburl, args['ln']) + _("Your Account") + """""", description="CDS Personalize, Main page", keywords="CDS, personalize", uid=uid, req=req, secure_page_p = 1, language=args['ln'], lastupdated=__lastupdated__) 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") return page(title=_("Delete Account"), body=webaccount.perform_delete(args['ln']), navtrail="""""" % (sweburl, args['ln']) + _("Your Account") + """""", description="CDS Personalize, Main page", keywords="CDS, personalize", uid=uid, req=req, secure_page_p = 1, language=args['ln'], lastupdated=__lastupdated__) 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") return page(title=_("Logout"), body=webaccount.perform_logout(req, args['ln']), navtrail="""""" % (sweburl, args['ln']) + _("Your Account") + """""", description="CDS Personalize, Main page", keywords="CDS, personalize", uid=uid, req=req, secure_page_p = 1, language=args['ln'], lastupdated=__lastupdated__) def login(self, req, form): args = wash_urlargd(form, { 'p_un': (str, None), 'p_pw': (str, None), 'login_method': (str, None), 'action': (str, 'login'), 'referer': (str, '')}) locals().update(args) if CFG_ACCESS_CONTROL_LEVEL_SITE > 0: return webuser.page_not_authorized(req, "../youraccount/login?ln=%s" % args['ln']) uid = webuser.getUid(req) # load the right message language _ = gettext_set_language(args['ln']) #return action+_("login") if args['action'] == "login" or args['action'] == _("login"): if args['p_un'] is None or not args['login_method']: return page(title=_("Login"), body=webaccount.create_login_page_box(args['referer'], args['ln']), navtrail="""""" % (sweburl, args['ln']) + _("Your Account") + """""", description="CDS Personalize, Main page", keywords="CDS, personalize", uid=uid, req=req, secure_page_p = 1, language=args['ln'], lastupdated=__lastupdated__) (iden, args['p_un'], args['p_pw'], msgcode) = webuser.loginUser(req, args['p_un'], args['p_pw'], args['login_method']) if len(iden)>0: uid = webuser.update_Uid(req, args['p_un']) uid2 = webuser.getUid(req) if uid2 == -1: webuser.logoutUser(req) return webuser.page_not_authorized(req, "../youraccount/login?ln=%s" % args['ln'], uid=uid) # login successful! if args['referer']: req.err_headers_out.add("Location", args['referer']) raise apache.SERVER_RETURN, apache.HTTP_MOVED_PERMANENTLY else: return self.display(req, form) else: mess = CFG_WEBACCESS_WARNING_MSGS[msgcode] % args['login_method'] if msgcode == 14: if webuser.username_exists_p(args['p_un']): mess = CFG_WEBACCESS_WARNING_MSGS[15] % args['login_method'] act = "login" return page(title=_("Login"), body=webaccount.perform_back(mess, act, _("login"), args['ln']), navtrail="""""" % (sweburl, args['ln']) + _("Your Account") + """""", description="CDS Personalize, Main page", keywords="CDS, personalize", uid=uid, req=req, secure_page_p = 1, language=args['ln'], lastupdated=__lastupdated__) else: return "This should have never happened. Please contact %s." % supportemail 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']) 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="""""" % (sweburl, args['ln']) + _("Your Account") + """""", description="CDS Personalize, Main page", keywords="CDS, personalize", uid=uid, req=req, secure_page_p = 1, language=args['ln'], lastupdated=__lastupdated__) mess = "" act = "" if args['p_pw'] == args['p_pw2']: ruid = webuser.registerUser(req, args['p_email'], args['p_pw'], args['p_nickname']) else: ruid = -2 if ruid == 0: uid = webuser.update_Uid(req, args['p_email']) mess = _("Your account has been successfully created.") title = _("Account created") if CFG_ACCESS_CONTROL_NOTIFY_USER_ABOUT_NEW_ACCOUNT == 1: mess += _("An email has been sent to the given address with the account information.") if CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS >= 1: mess += _("A second email will be sent when the account has been activated and can be used.") else: 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 = "register" title = _("Registration failure") elif ruid == 1: mess = _("Supplied email address %s is invalid.") % args['p_email'] mess += " " + _("Please try again.") act = "register" title = _("Registration failure") elif ruid == 2: mess = _("Desired nickname %s is invalid.") % args['p_nickname'] mess += " " + _("Please try again.") act = "register" title = _("Registration failure") elif ruid == 3: mess = _("Supplied email address %s already exists in the database.") % args['p_email'] mess += " " + websession_templates.tmpl_lost_your_password_teaser(args['ln']) mess += " " + _("Or please try again.") act = "register" title = _("Registration failure") elif ruid == 4: mess = _("Desired nickname %s already exists in the database.") % args['p_nickname'] mess += " " + _("Please try again.") act = "register" title = _("Registration failure") elif ruid == 5: mess = _("Users cannot register themselves, only admin can register them.") act = "register" title = _("Registration failure") else: # this should never happen mess = _("Internal Error") act = "register" title = _("Registration failure") return page(title=title, body=webaccount.perform_back(mess,act, (act == 'register' and _("register") or ""), args['ln']), navtrail="""""" % (sweburl, args['ln']) + _("Your Account") + """""", description="CDS Personalize, Main page", keywords="CDS, personalize", uid=uid, req=req, secure_page_p = 1, language=args['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") (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) 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") if argd['cancel']: url = weburl + '/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) 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") if argd['cancel']: url = weburl + '/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) 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") if argd['cancel']: url = weburl + '/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) 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") if argd['cancel']: url = weburl + '/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) 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") if argd['cancel']: url = weburl + '/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) diff --git a/modules/websession/lib/webuser.py b/modules/websession/lib/webuser.py index 4c667974a..5b3d9b7cb 100644 --- a/modules/websession/lib/webuser.py +++ b/modules/websession/lib/webuser.py @@ -1,790 +1,802 @@ # -*- coding: utf-8 -*- ## ## $Id$ ## ## This file is part of CDS Invenio. ## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 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. """ This file implements all methods necessary for working with users and sessions in CDS Invenio. Contains methods for logging/registration when a user log/register into the system, checking if it is a guest user or not. At the same time this presents all the stuff it could need with sessions managements, working with websession. It also contains Apache-related user authentication stuff. """ __revision__ = "$Id$" from marshal import loads, dumps from zlib import compress, decompress import time import os import crypt import string import smtplib import sre from invenio.config import \ CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS, \ CFG_ACCESS_CONTROL_LEVEL_GUESTS, \ CFG_ACCESS_CONTROL_LEVEL_SITE, \ CFG_ACCESS_CONTROL_LIMIT_REGISTRATION_TO_DOMAIN, \ CFG_ACCESS_CONTROL_NOTIFY_ADMIN_ABOUT_NEW_ACCOUNTS, \ CFG_ACCESS_CONTROL_NOTIFY_USER_ABOUT_NEW_ACCOUNT, \ CFG_APACHE_GROUP_FILE, \ CFG_APACHE_PASSWORD_FILE, \ adminemail, \ cdslang, \ cdsname, \ supportemail, \ sweburl, \ tmpdir, \ version, \ weburl from invenio import session, websession from invenio.dbquery import run_sql, escape_string, OperationalError from invenio.websession import pSession, pSessionMapping from invenio.session import SessionError from invenio.access_control_config import * from invenio.access_control_engine import acc_authorize_action from invenio.access_control_admin import acc_findUserRoleActions from invenio.messages import gettext_set_language from invenio.external_authentication import WebAccessExternalAuthError import invenio.template tmpl = invenio.template.load('websession') sre_invalid_nickname = sre.compile(""".*[,'@]+.*""") # pylint: disable-msg=C0301 def createGuestUser(): """Create a guest user , insert into user null values in all fields createGuestUser() -> GuestUserID """ if CFG_ACCESS_CONTROL_LEVEL_GUESTS == 0: try: return run_sql("insert into user (email, note) values ('', '1')") except OperationalError: return None elif CFG_ACCESS_CONTROL_LEVEL_GUESTS >= 1: try: return run_sql("insert into user (email, note) values ('', '0')") except OperationalError: return None def page_not_authorized(req, referer='', uid='', text='', navtrail='', ln=cdslang): """Show error message when account is not activated""" from invenio.webpage import page _ = gettext_set_language(ln) if not CFG_ACCESS_CONTROL_LEVEL_SITE: title = CFG_WEBACCESS_MSGS[5] if not uid: uid = getUid(req) try: res = run_sql("SELECT email FROM user WHERE id=%s" % uid) if res and res[0][0]: if text: body = text else: body = "%s %s" % (CFG_WEBACCESS_WARNING_MSGS[9] % res[0][0], ("%s %s" % (CFG_WEBACCESS_MSGS[0] % referer, CFG_WEBACCESS_MSGS[1]))) else: if text: body = text else: if CFG_ACCESS_CONTROL_LEVEL_GUESTS == 1: body = CFG_WEBACCESS_MSGS[3] else: body = CFG_WEBACCESS_WARNING_MSGS[4] + CFG_WEBACCESS_MSGS[2] except OperationalError, e: body = _("Database problem") + ': ' + str(e) elif CFG_ACCESS_CONTROL_LEVEL_SITE == 1: title = CFG_WEBACCESS_MSGS[8] body = "%s %s" % (CFG_WEBACCESS_MSGS[7], CFG_WEBACCESS_MSGS[2]) elif CFG_ACCESS_CONTROL_LEVEL_SITE == 2: title = CFG_WEBACCESS_MSGS[6] body = "%s %s" % (CFG_WEBACCESS_MSGS[4], CFG_WEBACCESS_MSGS[2]) return page(title=title, uid=getUid(req), body=body, navtrail=navtrail, req=req) def getUid (req): """Return user ID taking it from the cookie of the request. Includes control mechanism for the guest users, inserting in the database table when need be, raising the cookie back to the client. User ID is set to 0 when client refuses cookie or we are in the read-only site operation mode. User ID is set to -1 when we are in the permission denied site operation mode. getUid(req) -> userId """ if CFG_ACCESS_CONTROL_LEVEL_SITE == 1: return 0 if CFG_ACCESS_CONTROL_LEVEL_SITE == 2: return -1 guest = 0 sm = session.MPSessionManager(pSession, pSessionMapping()) try: s = sm.get_session(req) except SessionError: sm.revoke_session_cookie (req) s = sm.get_session(req) userId = s.getUid() if userId == -1: # first time, so create a guest user s.setUid(createGuestUser()) userId = s.getUid() guest = 1 sm.maintain_session(req, s) if guest == 0: guest = isGuestUser(userId) if guest: if CFG_ACCESS_CONTROL_LEVEL_GUESTS == 0: return userId elif CFG_ACCESS_CONTROL_LEVEL_GUESTS >= 1: return -1 else: res = run_sql("SELECT note FROM user WHERE id=%s" % userId) if CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS == 0: return userId elif CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS >= 1 and res and res[0][0] in [1, "1"]: return userId else: return -1 def setUid(req, uid): """It sets the userId into the session, and raise the cookie to the client. """ sm = session.MPSessionManager(pSession, pSessionMapping()) try: s = sm.get_session(req) except SessionError: sm.revoke_session_cookie(req) s = sm.get_session(req) s.setUid(uid) sm.maintain_session(req, s) return uid def get_user_info(uid, ln=cdslang): """Get infos for a given user. @param uid: user id (int) @return tuple: (uid, nickname, display_name) """ _ = gettext_set_language(ln) query = """SELECT id, nickname FROM user WHERE id=%i""" res = run_sql(query%uid) if res: if res[0]: user = list(res[0]) if user[1]: user.append(user[1]) else: user[1] = str(user[0]) user.append(_("user") + ' #' + str(user[0])) return tuple(user) return (uid, '', _("N/A")) def isGuestUser(uid): """It Checks if the userId corresponds to a guestUser or not isGuestUser(uid) -> boolean """ out = 1 try: res = run_sql("select email from user where id=%s", (uid,)) if res: if res[0][0]: out = 0 except OperationalError: pass return out def isUserSubmitter(uid): u_email = get_email(uid) res = run_sql("select * from sbmSUBMISSIONS where email=%s", (u_email,)) if len(res) > 0: return 1 else: return 0 def isUserReferee(uid): res = run_sql("select sdocname from sbmDOCTYPE") for row in res: doctype = row[0] categ = "*" (auth_code, auth_message) = acc_authorize_action(uid, "referee", doctype=doctype, categ=categ) if auth_code == 0: return 1 res2 = run_sql("select sname from sbmCATEGORIES where doctype=%s", (doctype,)) for row2 in res2: categ = row2[0] (auth_code, auth_message) = acc_authorize_action(uid, "referee", doctype=doctype, categ=categ) if auth_code == 0: return 1 return 0 def isUserAdmin(uid): "Return 1 if the user UID has some admin rights; 0 otherwise." out = 0 if acc_findUserRoleActions(uid): out = 1 return out def nickname_valid_p(nickname): """Check whether wanted NICKNAME supplied by the user is valid. At the moment we just check whether it is not empty, does not contain blanks or @, is not equal to `guest', etc. This check relies on sre_invalid_nickname regexp (see above) Return 1 if nickname is okay, return 0 if it is not. """ if nickname and \ not(nickname.startswith(' ') or nickname.endswith(' ')) and \ nickname.lower() != 'guest': if not sre_invalid_nickname.match(nickname): return 1 return 0 def email_valid_p(email): """Check whether wanted EMAIL address supplied by the user is valid. At the moment we just check whether it contains '@' and whether it doesn't contain blanks. We also check the email domain if CFG_ACCESS_CONTROL_LIMIT_REGISTRATION_TO_DOMAIN is set. Return 1 if email is okay, return 0 if it is not. """ if (string.find(email, "@") <= 0) or (string.find(email, " ") > 0): return 0 elif CFG_ACCESS_CONTROL_LIMIT_REGISTRATION_TO_DOMAIN: if not email.endswith(CFG_ACCESS_CONTROL_LIMIT_REGISTRATION_TO_DOMAIN): return 0 return 1 def registerUser(req, email, passw, nickname, register_without_nickname=False): """Register user with the desired values of NICKNAME, EMAIL and PASSW. If REGISTER_WITHOUT_NICKNAME is set to True, then ignore desired NICKNAME and do not set any. This is suitable for external authentications so that people can login without having to register an internal account first. Return 0 if the registration is successful, 1 if email is not valid, 2 if nickname is not valid, 3 if email is already in the database, 4 if nickname is already in the database, 5 when users cannot register themselves because of the site policy. """ # is email valid? if not email_valid_p(email): return 1 # is email already taken? res = run_sql("SELECT * FROM user WHERE email=%s", (email,)) if len(res) > 0: return 3 if register_without_nickname: # ignore desired nick and use default empty string one: nickname = "" else: # is nickname valid? if not nickname_valid_p(nickname): return 2 # is nickname already taken? res = run_sql("SELECT * FROM user WHERE nickname=%s", (nickname,)) if len(res) > 0: return 4 # okay, go on and register the user: if CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS == 0: activated = 1 elif CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS == 1: activated = 0 elif CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS >= 2: return 5 user_preference = get_default_user_preferences() setUid(req, run_sql("INSERT INTO user (nickname, email, password, note, settings) VALUES (%s,%s,%s,%s,%s)", (nickname, email, passw, activated, serialize_via_marshal(user_preference),))) if CFG_ACCESS_CONTROL_NOTIFY_USER_ABOUT_NEW_ACCOUNT: sendNewUserAccountWarning(email, email, passw) if CFG_ACCESS_CONTROL_NOTIFY_ADMIN_ABOUT_NEW_ACCOUNTS: sendNewAdminAccountWarning(email, adminemail) return 0 def updateDataUser(uid, email, nickname): """ Update user data. Used when a user changed his email or password or nickname. """ if email == 'guest': return 0 if CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS < 2: run_sql("update user set email=%s where id=%s", (email, uid)) if nickname and nickname != '': run_sql("update user set nickname=%s where id=%s", (nickname, uid)) return 1 def updatePasswordUser(uid, password): """Update the password of a user.""" if CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS < 3: run_sql("update user set password=%s where id=%s", (password, uid)) return 1 def loginUser(req, p_un, p_pw, login_method): """It is a first simple version for the authentication of user. It returns the id of the user, for checking afterwards if the login is correct """ # p_un passed may be an email or a nickname: p_email = get_email_from_username(p_un) # go on with the old stuff based on p_email: if not CFG_EXTERNAL_AUTHENTICATION.has_key(login_method): return ([], p_email, p_pw, 12) if CFG_EXTERNAL_AUTHENTICATION[login_method][0]: # External Authenthication try: + # auth_user can return either an email or a tuple(couple) of a email and + # a nickname p_email = CFG_EXTERNAL_AUTHENTICATION[login_method][0].auth_user(p_email, p_pw) except WebAccessExternalAuthError: return([], p_email, p_pw, 16) if p_email: # Authenthicated externally query_result = run_sql("SELECT id from user where email=%s", (p_email,)) - if not query_result: + if not query_result: # First time user import random p_pw_local = int(random.random() * 1000000) - if registerUser(req, p_email, p_pw_local, "", register_without_nickname=True) == 0: + p_nickname = '' + if CFG_EXTERNAL_AUTHENTICATION[login_method][0].enforce_external_nicknames: + try: # Let's discover the external nickname! + p_nickname = CFG_EXTERNAL_AUTHENTICATION[login_method][0].fetch_user_nickname(p_email, p_pw) + except (AttributeError, NotImplementedError): + pass + res = registerUser(req, p_email, p_pw_local, p_nickname, \ + register_without_nickname=p_nickname == '') + if res == 4 or res == 2: # The nickname was already taken + res = registerUser(req, p_email, p_pw_local, '', register_without_nickname=True) + if res == 0: # Everything was ok, with or without nickname. query_result = run_sql("SELECT id from user where email=%s", (p_email,)) else: return([], p_email, p_pw_local, 13) try: groups = CFG_EXTERNAL_AUTHENTICATION[login_method][0].fetch_user_groups_membership(p_email, p_pw) # groups is a dictionary {group_name : group_description,} new_groups = {} for key, value in groups.items(): new_groups[key + " [" + str(login_method) + "]"] = value groups = new_groups - except AttributeError: + except (AttributeError, NotImplementedError): pass except WebAccessExternalAuthError: return([], p_email, p_pw, 16) else: # Groups synchronization if groups != 0: userid = query_result[0][0] from invenio.webgroup import synchronize_external_groups synchronize_external_groups(userid, groups, login_method) user_prefs = get_user_preferences(query_result[0][0]) user_prefs["login_method"] = login_method for key in user_prefs.keys(): if key.startswith('EXTERNAL_'): del user_prefs[key] try: new_prefs = CFG_EXTERNAL_AUTHENTICATION[login_method][0].fetch_user_preferences(p_email, p_pw) for key, value in new_prefs.items(): user_prefs['EXTERNAL_' + key] = value - except AttributeError: + except (AttributeError, NotImplementedError): pass except WebAccessExternalAuthError: return([], p_email, p_pw, 16) set_user_preferences(query_result[0][0], user_prefs) else: return ([], p_un, p_pw, 10) else: # Internal Authenthication query_result = run_sql("SELECT id,email from user where email=%s and password=%s", (p_email, p_pw,)) if query_result: #FIXME drop external groups and settings preferred_login_method = get_user_preferences(query_result[0][0])['login_method'] p_email = query_result[0][1] if login_method != preferred_login_method: if CFG_EXTERNAL_AUTHENTICATION.has_key(preferred_login_method): return ([], p_email, p_pw, 11) else: return ([], p_email, p_pw, 14) # Login successful! Updating the last access time run_sql("UPDATE user SET last_login=NOW() WHERE email=%s", (p_email, )) return (query_result, p_email, p_pw, 0) def drop_external_settings(userId): """Drop the external (EXTERNAL_) settings of userid.""" prefs = get_user_preferences(userId) for key in prefs.keys(): if key.startswith('EXTERNAL_'): del prefs[key] set_user_preferences(userId, prefs) def logoutUser(req): """It logout the user of the system, creating a guest user. """ getUid(req) sm = session.MPSessionManager(pSession, pSessionMapping()) try: s = sm.get_session(req) except SessionError: sm.revoke_session_cookie(req) s = sm.get_session(req) id1 = createGuestUser() s.setUid(id1) sm.maintain_session(req, s) return id1 def username_exists_p(username): """Check if USERNAME exists in the system. Username may be either nickname or email. Return 1 if it does exist, 0 if it does not. """ if username == "": # return not exists if asked for guest users return 0 res = run_sql("SELECT email FROM user WHERE email=%s", (username,)) + \ run_sql("SELECT email FROM user WHERE nickname=%s", (username,)) if len(res) > 0: return 1 return 0 def emailUnique(p_email): """Check if the email address only exists once. If yes, return userid, if not, -1 """ query_result = run_sql("select id, email from user where email=%s", (p_email,)) if len(query_result) == 1: return query_result[0][0] elif len(query_result) == 0: return 0 return -1 def nicknameUnique(p_nickname): """Check if the nickname only exists once. If yes, return userid, if not, -1 """ query_result = run_sql("select id, nickname from user where nickname=%s", (p_nickname,)) if len(query_result) == 1: return query_result[0][0] elif len(query_result) == 0: return 0 return -1 def update_Uid(req, p_email): """It updates the userId of the session. It is used when a guest user is logged in succesfully in the system with a given email and password """ query_ID = int(run_sql("select id from user where email=%s", (p_email,))[0][0]) setUid(req, query_ID) return query_ID def givePassword(email): """ It checks in the database the password for a given email. It is used to send the password to the email of the user.It returns the password if the user exists, otherwise it returns -999 """ query_pass = run_sql("select password from user where email =%s", (email,)) if len(query_pass)>0: return query_pass[0][0] return -999 def sendNewAdminAccountWarning(newAccountEmail, sendTo, ln=cdslang): """Send an email to the address given by sendTo about the new account newAccountEmail.""" _ = gettext_set_language(ln) fromaddr = "From: %s" % supportemail toaddrs = "To: %s" % sendTo to = toaddrs + "\n" sub = "Subject: New account on '%s'" % cdsname if CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS == 1: sub += " - PLEASE ACTIVATE" sub += "\n\n" body = "A new account has been created on '%s'" % cdsname if CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS == 1: body += " and is awaiting activation" body += ":\n\n" body += " Username/Email: %s\n\n" % newAccountEmail body += "You can approve or reject this account request at: %s/admin/webaccess/webaccessadmin.py/manageaccounts\n" % weburl body += "\n---------------------------------" body += "\n%s" % cdsname body += "\nContact: %s" % supportemail msg = to + sub + body server = smtplib.SMTP('localhost') server.set_debuglevel(1) try: server.sendmail(fromaddr, toaddrs, msg) except smtplib.SMTPRecipientsRefused: return 0 server.quit() return 1 def sendNewUserAccountWarning(newAccountEmail, sendTo, password, ln=cdslang): """Send an email to the address given by sendTo about the new account newAccountEmail.""" _ = gettext_set_language(ln) fromaddr = "From: %s" % supportemail toaddrs = "To: %s" % sendTo to = toaddrs + "\n" sub = "Subject: Your account created on '%s'\n\n" % cdsname body = "You have created a new account on '%s':\n\n" % cdsname body += " Username/Email: %s\n" % newAccountEmail body += " Password: %s\n\n" % ("*" * len(password)) if CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS >= 1: body += "This account is awaiting approval by the site administrators and therefore cannot be used as of yet.\nYou will receive an email notification as soon as your account request has been processed.\n" body += "\n---------------------------------" body += "\n%s" % cdsname body += "\nContact: %s" % supportemail msg = to + sub + body server = smtplib.SMTP('localhost') server.set_debuglevel(1) try: server.sendmail(fromaddr, toaddrs, msg) except smtplib.SMTPRecipientsRefused: return 0 server.quit() return 1 def get_email(uid): """Return email address of the user uid. Return string 'guest' in case the user is not found.""" out = "guest" res = run_sql("SELECT email FROM user WHERE id=%s", (uid,), 1) if res and res[0][0]: out = res[0][0] return out def get_email_from_username(username): """Return email address of the user corresponding to USERNAME. The username may be either nickname or email. Return USERNAME untouched if not found in the database or if found several matching entries. """ out = username res = run_sql("SELECT email FROM user WHERE email=%s", (username,), 1) + \ run_sql("SELECT email FROM user WHERE nickname=%s", (username,), 1) if res and len(res) == 1: out = res[0][0] return out def get_password(uid): """Return password of the user uid. Return None in case the user is not found.""" out = None res = run_sql("SELECT password FROM user WHERE id=%s", (uid,), 1) if res and res[0][0] != None: out = res[0][0] return out def get_nickname(uid): """Return nickname of the user uid. Return None in case the user is not found.""" out = None res = run_sql("SELECT nickname FROM user WHERE id=%s", (uid,), 1) if res and res[0][0]: out = res[0][0] return out def get_nickname_or_email(uid): """Return nickname (preferred) or the email address of the user uid. Return string 'guest' in case the user is not found.""" out = "guest" res = run_sql("SELECT nickname, email FROM user WHERE id=%s", (uid,), 1) if res and res[0]: if res[0][0]: out = res[0][0] elif res[0][1]: out = res[0][1] return out def create_userinfobox_body(req, uid, language="en"): """Create user info box body for user UID in language LANGUAGE.""" if req: if req.subprocess_env.has_key('HTTPS') \ and req.subprocess_env['HTTPS'] == 'on': url_referer = sweburl + req.unparsed_uri else: url_referer = weburl + req.unparsed_uri else: url_referer = weburl try: return tmpl.tmpl_create_userinfobox(ln=language, url_referer=url_referer, guest = isGuestUser(uid), username = get_nickname_or_email(uid), submitter = isUserSubmitter(uid), referee = isUserReferee(uid), admin = isUserAdmin(uid), ) except OperationalError: return "" def list_registered_users(): """List all registered users.""" return run_sql("SELECT id,email FROM user where email!=''") def list_users_in_role(role): """List all users of a given role (see table accROLE) @param role: role of user (string) @return list of uids """ query = """SELECT uacc.id_user FROM user_accROLE uacc JOIN accROLE acc ON uacc.id_accROLE=acc.id WHERE acc.name='%s'""" res = run_sql(query% escape_string(role)) if res: return map(lambda x: int(x[0]), res) return [] def list_users_in_roles(role_list): """List all users of given roles (see table accROLE) @param role_list: list of roles [string] @return list of uids """ if not(type(role_list) is list or type(role_list) is tuple): role_list = [role_list] params = '' query = """SELECT distinct(uacc.id_user) FROM user_accROLE uacc JOIN accROLE acc ON uacc.id_accROLE=acc.id %s""" if len(role_list) > 0: params = 'WHERE ' for role in role_list[:-1]: params += "acc.name='%s' OR " % escape_string(role) params += "acc.name='%s'" % escape_string(role_list[-1]) res = run_sql(query% params) if res: return map(lambda x: int(x[0]), res) return [] ## --- follow some functions for Apache user/group authentication def auth_apache_user_p(user, password, apache_password_file=CFG_APACHE_PASSWORD_FILE): """Check whether user-supplied credentials correspond to valid Apache password data file. Return 0 in case of failure, 1 in case of success.""" try: if not apache_password_file.startswith("/"): apache_password_file = tmpdir + "/" + apache_password_file dummy, pipe_output = os.popen2(["grep", "^" + user + ":", apache_password_file], 'r') line = pipe_output.readlines()[0] password_apache = string.split(string.strip(line),":")[1] except: # no pw found, so return not-allowed status return 0 salt = password_apache[:2] if crypt.crypt(password, salt) == password_apache: return 1 else: return 0 def auth_apache_user_in_groups(user, apache_group_file=CFG_APACHE_GROUP_FILE): """Return list of Apache groups to which Apache user belong.""" out = [] try: if not apache_group_file.startswith("/"): apache_group_file = tmpdir + "/" + apache_group_file dummy, pipe_output = os.popen2(["grep", user, apache_group_file], 'r') for line in pipe_output.readlines(): out.append(string.split(string.strip(line),":")[0]) except: # no groups found, so return empty list pass return out def auth_apache_user_collection_p(user, password, coll): """Check whether user-supplied credentials correspond to valid Apache password data file, and whether this user is authorized to see the given collections. Return 0 in case of failure, 1 in case of success.""" from invenio.search_engine import coll_restricted_p, coll_restricted_group if not auth_apache_user_p(user, password): return 0 if not coll_restricted_p(coll): return 1 if coll_restricted_group(coll) in auth_apache_user_in_groups(user): return 1 else: return 0 def get_user_preferences(uid): pref = run_sql("SELECT id, settings FROM user WHERE id=%s", (uid,)) if pref: try: return deserialize_via_marshal(pref[0][1]) except: return get_default_user_preferences() return {} # empty dict mean no preferences def set_user_preferences(uid, pref): assert(type(pref) == type({})) run_sql("UPDATE user SET settings=%s WHERE id=%s", (serialize_via_marshal(pref), uid)) def get_default_user_preferences(): user_preference = { 'login_method': ''} for system in CFG_EXTERNAL_AUTHENTICATION.keys(): if CFG_EXTERNAL_AUTHENTICATION[system][1]: user_preference['login_method'] = system break return user_preference def serialize_via_marshal(obj): """Serialize Python object via marshal into a compressed string.""" return compress(dumps(obj)) def deserialize_via_marshal(string): """Decompress and deserialize string into a Python object via marshal.""" return loads(decompress(string))