web/views/authentication.py
branchstable
changeset 4910 f40fddaa79ad
parent 4856 c8f887a5b2fa
child 4916 4b8cdda342ae
equal deleted inserted replaced
4909:a13c1d1ecc5b 4910:f40fddaa79ad
    37 
    37 
    38 class LoginPasswordRetreiver(WebAuthInfoRetreiver):
    38 class LoginPasswordRetreiver(WebAuthInfoRetreiver):
    39     __regid__ = 'loginpwdauth'
    39     __regid__ = 'loginpwdauth'
    40     order = 10
    40     order = 10
    41 
    41 
    42     def __init__(self, vreg):
       
    43         self.anoninfo = vreg.config.anonymous_user()
       
    44 
       
    45     def authentication_information(self, req):
    42     def authentication_information(self, req):
    46         """retreive authentication information from the given request, raise
    43         """retreive authentication information from the given request, raise
    47         NoAuthInfo if expected information is not found.
    44         NoAuthInfo if expected information is not found.
    48         """
    45         """
    49         login, password = req.get_authorization()
    46         login, password = req.get_authorization()
    50         if not login:
    47         if not login:
    51             # No session and no login -> try anonymous
    48             raise NoAuthInfo()
    52             login, password = self.anoninfo
       
    53             if not login: # anonymous not authorized
       
    54                 raise NoAuthInfo()
       
    55         return login, {'password': password}
    49         return login, {'password': password}
    56 
    50 
    57 
    51 
    58 class RepositoryAuthenticationManager(AbstractAuthenticationManager):
    52 class RepositoryAuthenticationManager(AbstractAuthenticationManager):
    59     """authenticate user associated to a request and check session validity"""
    53     """authenticate user associated to a request and check session validity"""
    63         self.repo = vreg.config.repository(vreg)
    57         self.repo = vreg.config.repository(vreg)
    64         self.log_queries = vreg.config['query-log-file']
    58         self.log_queries = vreg.config['query-log-file']
    65         self.authinforetreivers = sorted(vreg['webauth'].possible_objects(vreg),
    59         self.authinforetreivers = sorted(vreg['webauth'].possible_objects(vreg),
    66                                     key=lambda x: x.order)
    60                                     key=lambda x: x.order)
    67         assert self.authinforetreivers
    61         assert self.authinforetreivers
       
    62         self.anoninfo = vreg.config.anonymous_user()
    68 
    63 
    69     def validate_session(self, req, session):
    64     def validate_session(self, req, session):
    70         """check session validity, and return eventually hijacked session
    65         """check session validity, and return eventually hijacked session
    71 
    66 
    72         :raise InvalidSession:
    67         :raise InvalidSession:
   114                 login, authinfo = retreiver.authentication_information(req)
   109                 login, authinfo = retreiver.authentication_information(req)
   115             except NoAuthInfo:
   110             except NoAuthInfo:
   116                 continue
   111                 continue
   117             try:
   112             try:
   118                 cnx = self._authenticate(req, login, authinfo)
   113                 cnx = self._authenticate(req, login, authinfo)
   119                 break
       
   120             except ExplicitLogin:
   114             except ExplicitLogin:
   121                 continue # the next one may succeed
   115                 continue # the next one may succeed
       
   116             for retreiver_ in self.authinforetreivers:
       
   117                 retreiver_.authenticated(req, cnx, retreiver)
       
   118             break
   122         else:
   119         else:
   123             raise ExplicitLogin()
   120             # false if no authentication info found, eg this is not an
   124         for retreiver_ in self.authinforetreivers:
   121             # authentication failure
   125             retreiver_.authenticated(req, cnx, retreiver)
   122             if 'login' in locals():
       
   123                 req.set_message(req._('authentication failure'))
       
   124             cnx = self._open_anonymous_connection(req)
   126         return cnx
   125         return cnx
   127 
   126 
   128     def _authenticate(self, req, login, authinfo):
   127     def _authenticate(self, req, login, authinfo):
   129         # remove possibly cached cursor coming from closed connection
       
   130         cnxprops = ConnectionProperties(self.vreg.config.repo_method,
   128         cnxprops = ConnectionProperties(self.vreg.config.repo_method,
   131                                         close=False, log=self.log_queries)
   129                                         close=False, log=self.log_queries)
   132         try:
   130         try:
   133             cnx = repo_connect(self.repo, login, cnxprops=cnxprops, **authinfo)
   131             cnx = repo_connect(self.repo, login, cnxprops=cnxprops, **authinfo)
   134         except AuthenticationError:
   132         except AuthenticationError:
   135             req.set_message(req._('authentication failure'))
   133             raise ExplicitLogin()
   136             # restore an anonymous connection if possible
   134         self._init_cnx(cnx, login, authinfo)
   137             anonlogin, anonpassword = self.vreg.config.anonymous_user()
       
   138             if anonlogin and anonlogin != login:
       
   139                 cnx = repo_connect(self.repo, anonlogin, password=anonpassword,
       
   140                                    cnxprops=cnxprops)
       
   141                 self._init_cnx(cnx, anonlogin, {'password': anonpassword})
       
   142             else:
       
   143                 raise ExplicitLogin()
       
   144         else:
       
   145             self._init_cnx(cnx, login, authinfo)
       
   146         # associate the connection to the current request
   135         # associate the connection to the current request
   147         req.set_connection(cnx)
   136         req.set_connection(cnx)
   148         return cnx
   137         return cnx
       
   138 
       
   139     def _open_anonymous_connection(self, req):
       
   140         # restore an anonymous connection if possible
       
   141         login, password = self.anoninfo
       
   142         if login:
       
   143             return self._authenticate(req, login, {'password': password})
       
   144         raise ExplicitLogin()
   149 
   145 
   150     def _init_cnx(self, cnx, login, authinfo):
   146     def _init_cnx(self, cnx, login, authinfo):
   151         # decorate connection
   147         # decorate connection
   152         if login == self.vreg.config.anonymous_user()[0]:
   148         if login == self.vreg.config.anonymous_user()[0]:
   153             cnx.anonymous_connection = True
   149             cnx.anonymous_connection = True