Esempio n. 1
0
def create_login_page_box(referer='', ln=CFG_SITE_LANG):
    # List of referer regexep and message to print

    _ = gettext_set_language(ln)

    login_referrer2msg = (
        (re.compile(r"/search"), "<p>" + _("This collection is restricted.  If you think you have right to access it, please authenticate yourself.") + "</p>"),
        (re.compile(r"/%s/\d+/files/.+" % CFG_SITE_RECORD), "<p>" + _("This file is restricted.  If you think you have right to access it, please authenticate yourself.") + "</p>"),
    )

    msg = ""
    for regexp, txt in login_referrer2msg:
        if regexp.search(referer):
            msg = txt
            break

    internal = None
    for system in CFG_EXTERNAL_AUTHENTICATION.keys():
        if CFG_EXTERNAL_AUTHENTICATION[system] is None:
            internal = system
            break
    register_available = CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS <= 1 and internal
    ## Let's retrieve all the login method that are not dedicated to robots
    methods = [method[0] for method in CFG_EXTERNAL_AUTHENTICATION.iteritems() if not method[1] or not method[1].robot_login_method_p()]
    methods.sort()

    return websession_templates.tmpl_login_form(
             ln = ln,
             referer = referer,
             internal = internal,
             register_available = register_available,
             methods = methods,
             selected_method = CFG_EXTERNAL_AUTH_DEFAULT,
             msg = msg,
           )
Esempio n. 2
0
def create_login_page_box(referer='', ln=CFG_SITE_LANG):
    # List of referer regexep and message to print

    _ = gettext_set_language(ln)

    login_referrer2msg = (
        (re.compile(r"/search"), "<p>" +
         _("This collection is restricted.  If you think you have right to access it, please authenticate yourself."
           ) + "</p>"),
        (re.compile(r"/%s/\d+/files/.+" % CFG_SITE_RECORD), "<p>" +
         _("This file is restricted.  If you think you have right to access it, please authenticate yourself."
           ) + "</p>"),
        (re.compile(r"openid-invalid"),
         "<p>" + _("The OpenID identifier is invalid") + "</p>"),
        (re.compile(r"openid-python"), "<p>%s</p><p>%s</p>" %
         (_("python-openid package must be installed: run make install-openid-package or download manually from https://github.com/openid/python-openid/"
            ),
          _("Please inform the <a href='mailto%s'>administator</a>" %
            CFG_SITE_ADMIN_EMAIL))),
        (re.compile(r"oauth-rauth"), "<p>%s</p><p>%s</p>" %
         (_("rauth package must be installed: run make install-oauth-package or download manually from https://github.com/litl/rauth/"
            ),
          _("Please inform the <a href='mailto%s'>administator</a>" %
            CFG_SITE_ADMIN_EMAIL))),
        (re.compile(r"oauth-config"), "<p>%s</p><p>%s</p>" %
         (_("The configuration isn't set properly"),
          _("Please inform the <a href='mailto%s'>administator</a>" %
            CFG_SITE_ADMIN_EMAIL))),
        (re.compile(r"connection-error"), "<p>%s</p>" %
         (_("Cannot connect the provider. Please try again later."))),
    )

    msg = ""
    for regexp, txt in login_referrer2msg:
        if regexp.search(referer):
            msg = txt
            break

    internal = None
    for system in CFG_EXTERNAL_AUTHENTICATION.keys():
        if CFG_EXTERNAL_AUTHENTICATION[system] is None:
            internal = system
            break
    register_available = CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS <= 1 and internal
    ## Let's retrieve all the login method that are not dedicated to robots
    methods = [
        method[0] for method in CFG_EXTERNAL_AUTHENTICATION.iteritems()
        if not method[1] or not method[1].robot_login_method_p()
    ]
    methods.sort()

    return websession_templates.tmpl_login_form(
        ln=ln,
        referer=referer,
        internal=internal,
        register_available=register_available,
        methods=methods,
        selected_method=CFG_EXTERNAL_AUTH_DEFAULT,
        msg=msg,
    )
Esempio n. 3
0
def create_login_page_box(referer="", apache_msg="", ln=CFG_SITE_LANG):
    # List of referer regexep and message to print

    _ = gettext_set_language(ln)

    login_referrer2msg = (
        (
            re.compile(r"/search"),
            "<p>"
            + _(
                "This collection is restricted.  If you think you have right to access it, please authenticate yourself."
            )
            + "</p>",
        ),
        (
            re.compile(r"/record/\d+/files/.+"),
            "<p>"
            + _("This file is restricted.  If you think you have right to access it, please authenticate yourself.")
            + "</p>",
        ),
    )

    msg = ""
    for regexp, txt in login_referrer2msg:
        if regexp.search(referer):
            msg = txt
            break

    # FIXME: Temporary Hack to help CDS current migration
    if CFG_CERN_SITE and apache_msg:
        return msg + apache_msg

    if apache_msg:
        msg += apache_msg + "<p>2) Otherwise please authenticate yourself" " in the following form:</p>"

    internal = None
    for system in CFG_EXTERNAL_AUTHENTICATION.keys():
        if not CFG_EXTERNAL_AUTHENTICATION[system][0]:
            internal = system
            break
    register_available = CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS <= 1 and internal
    methods = CFG_EXTERNAL_AUTHENTICATION.keys()
    methods.sort()
    selected = ""
    for method in methods:
        if CFG_EXTERNAL_AUTHENTICATION[method][1]:
            selected = method
            break

    return websession_templates.tmpl_login_form(
        ln=ln,
        referer=referer,
        internal=internal,
        register_available=register_available,
        methods=methods,
        selected_method=selected,
        msg=msg,
    )
    def test_create_example_url(self, email, login_method, robot, ip, assertion=None, timeout=None, referer=None, groups=None, nickname=None):
        """
        Create a test URL to test the robot login.

        @param email: email of the user we want to login as.
        @type email: string
        @param login_method: the login_method name as specified in CFG_EXTERNAL_AUTHENTICATION.
        @type login_method: string
        @param robot: the identifier of this robot.
        @type robot: string
        @param assertion: any further data we want to send to.
        @type: json serializable mapping
        @param ip: the IP of the user.
        @type: string
        @param timeout: timeout when the URL will expire (in seconds from the Epoch)
        @type timeout: float
        @param referer: the URL where to land after successful login.
        @type referer: string
        @param groups: the list of optional group of the user.
        @type groups: list of string
        @param nickname: the optional nickname of the user.
        @type nickname: string
        @return: the URL to login as the user.
        @rtype: string
        """
        from invenio.access_control_config import CFG_EXTERNAL_AUTHENTICATION
        from invenio.urlutils import create_url
        if assertion is None:
            assertion = {}
        assertion[self.email_attribute_name] = email
        if nickname:
            assertion[self.nickname_attribute_name] = nickname
        if groups:
            assertion[self.groups_attribute_name] = self.groups_separator.join(groups)
        if timeout is None:
            timeout = time.time() + CFG_ROBOT_URL_TIMEOUT
        assertion[self.timeout_attribute_name] = timeout
        if referer is None:
            referer = CFG_SITE_URL
        if login_method is None:
            for a_login_method, details in CFG_EXTERNAL_AUTHENTICATION.iteritems():
                if details[2]:
                    login_method = a_login_method
                    break
        robot_keys = load_robot_keys()
        assertion[self.userip_attribute_name] = ip
        assertion = json.dumps(assertion)
        if self.use_zlib:
            assertion = base64.urlsafe_b64encode(compress(assertion))
        shared_key = robot_keys[login_method][robot]
        digest = self.sign(shared_key, assertion)
        return create_url("%s%s" % (CFG_SITE_SECURE_URL, "/youraccount/robotlogin"), {
            'assertion': assertion,
            'robot': robot,
            'login_method': login_method,
            'digest': digest,
            'referer': referer})
    def test_create_example_url(self, email, login_method, robot, ip, assertion=None, timeout=None, referer=None, groups=None, nickname=None):
        """
        Create a test URL to test the robot login.

        @param email: email of the user we want to login as.
        @type email: string
        @param login_method: the login_method name as specified in CFG_EXTERNAL_AUTHENTICATION.
        @type login_method: string
        @param robot: the identifier of this robot.
        @type robot: string
        @param assertion: any further data we want to send to.
        @type: json serializable mapping
        @param ip: the IP of the user.
        @type: string
        @param timeout: timeout when the URL will expire (in seconds from the Epoch)
        @type timeout: float
        @param referer: the URL where to land after successful login.
        @type referer: string
        @param groups: the list of optional group of the user.
        @type groups: list of string
        @param nickname: the optional nickname of the user.
        @type nickname: string
        @return: the URL to login as the user.
        @rtype: string
        """
        from invenio.access_control_config import CFG_EXTERNAL_AUTHENTICATION
        from invenio.urlutils import create_url
        if assertion is None:
            assertion = {}
        assertion[self.email_attribute_name] = email
        if nickname:
            assertion[self.nickname_attribute_name] = nickname
        if groups:
            assertion[self.groups_attribute_name] = self.groups_separator.join(groups)
        if timeout is None:
            timeout = time.time() + CFG_ROBOT_URL_TIMEOUT
        assertion[self.timeout_attribute_name] = timeout
        if referer is None:
            referer = CFG_SITE_URL
        if login_method is None:
            for a_login_method, details in CFG_EXTERNAL_AUTHENTICATION.iteritems():
                if details[2]:
                    login_method = a_login_method
                    break
        robot_keys = load_robot_keys()
        assertion[self.userip_attribute_name] = ip
        assertion = json.dumps(assertion)
        if self.use_zlib:
            assertion = base64.urlsafe_b64encode(compress(assertion))
        shared_key = robot_keys[login_method][robot]
        digest = self.sign(shared_key, assertion)
        return create_url("%s%s" % (CFG_SITE_SECURE_URL, "/youraccount/robotlogin"), {
            'assertion': assertion,
            'robot': robot,
            'login_method': login_method,
            'digest': digest,
            'referer': referer})
Esempio n. 6
0
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
Esempio n. 7
0
def create_login_page_box(referer='', ln=CFG_SITE_LANG):
    # List of referer regexep and message to print

    _ = gettext_set_language(ln)

    login_referrer2msg = (
        (re.compile(r"/search"), "<p>" + _("This collection is restricted.  If you think you have right to access it, please authenticate yourself.") + "</p>"),
        (re.compile(r"/%s/\d+/files/.+" % CFG_SITE_RECORD), "<p>" + _("This file is restricted.  If you think you have right to access it, please authenticate yourself.") + "</p>"),
        (re.compile(r"openid-invalid"), "<p>" + _("The OpenID identifier is invalid") + "</p>"),
        (re.compile(r"openid-python"), "<p>%s</p><p>%s</p>" % (_("python-openid package must be installed: run make install-openid-package or download manually from https://github.com/openid/python-openid/"), _("Please inform the <a href='mailto%s'>administator</a>" % CFG_SITE_ADMIN_EMAIL))),
        (re.compile(r"oauth-rauth"), "<p>%s</p><p>%s</p>" % (_("rauth package must be installed: run make install-oauth-package or download manually from https://github.com/litl/rauth/"), _("Please inform the <a href='mailto%s'>administator</a>" % CFG_SITE_ADMIN_EMAIL))),
        (re.compile(r"oauth-config"), "<p>%s</p><p>%s</p>" % (_("The configuration isn't set properly"), _("Please inform the <a href='mailto%s'>administator</a>" % CFG_SITE_ADMIN_EMAIL))),
        (re.compile(r"connection-error"), "<p>%s</p>" % (_("Cannot connect the provider. Please try again later."))),
    )

    msg = ""
    for regexp, txt in login_referrer2msg:
        if regexp.search(referer):
            msg = txt
            break

    internal = None
    for system in CFG_EXTERNAL_AUTHENTICATION.keys():
        if CFG_EXTERNAL_AUTHENTICATION[system] is None:
            internal = system
            break
    register_available = CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS <= 1 and internal
    ## Let's retrieve all the login method that are not dedicated to robots
    methods = [method[0] for method in CFG_EXTERNAL_AUTHENTICATION.iteritems() if not method[1] or not method[1].robot_login_method_p()]
    methods.sort()

    return websession_templates.tmpl_login_form(
             ln = ln,
             referer = referer,
             internal = internal,
             register_available = register_available,
             methods = methods,
             selected_method = CFG_EXTERNAL_AUTH_DEFAULT,
             msg = msg,
           )
Esempio n. 8
0
def synchronize_groups_with_login_method():
    """For each login_method, if possible, synchronize groups in a bulk fashion
    (i.e. when fetch_all_users_groups_membership is implemented in the
    external_authentication class). Otherwise, for each user that belong to at
    least one external group for a given login_method, ask, if possible, for
    his group memberships and merge them.
    """
    from invenio.access_control_config import CFG_EXTERNAL_AUTHENTICATION
    for login_method, authorizer in CFG_EXTERNAL_AUTHENTICATION.items():
        if authorizer:
            try:
                usersgroups = authorizer.fetch_all_users_groups_membership()
                synchronize_all_external_groups(usersgroups, login_method)
            except (NotImplementedError, NameError):
                users = db.get_all_users_with_groups_with_login_method(
                    login_method)
                for email, uid in users.items():
                    try:
                        groups = authorizer.fetch_user_groups_membership(email)
                        synchronize_external_groups(uid, groups, login_method)
                    except (NotImplementedError, NameError):
                        pass
Esempio n. 9
0
def synchronize_groups_with_login_method():
    """For each login_method, if possible, synchronize groups in a bulk fashion
    (i.e. when fetch_all_users_groups_membership is implemented in the
    external_authentication class). Otherwise, for each user that belong to at
    least one external group for a given login_method, ask, if possible, for
    his group memberships and merge them.
    """
    from invenio.access_control_config import CFG_EXTERNAL_AUTHENTICATION

    for login_method, authorizer in CFG_EXTERNAL_AUTHENTICATION.items():
        if authorizer:
            try:
                usersgroups = authorizer.fetch_all_users_groups_membership()
                synchronize_all_external_groups(usersgroups, login_method)
            except (NotImplementedError, NameError):
                users = db.get_all_users_with_groups_with_login_method(login_method)
                for email, uid in users.items():
                    try:
                        groups = authorizer.fetch_user_groups_membership(email)
                        synchronize_external_groups(uid, groups, login_method)
                    except (NotImplementedError, NameError):
                        pass
Esempio n. 10
0
def perform_set(email, ln, can_config_bibcatalog=False,
                can_config_profiling=False, verbose=0, csrf_token=''):
    """Perform_set(email,password): edit your account parameters, email and
    password.
    If can_config_bibcatalog is True, show the bibcatalog dialog (if configured).
    """

    try:
        res = run_sql("SELECT id, nickname FROM user WHERE email=%s", (email,))
        uid = res[0][0]
        nickname = res[0][1]
    except IndexError:
        uid = 0
        nickname = ""

    CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS_LOCAL = CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS
    prefs = get_user_preferences(uid)
    if prefs['login_method'] in CFG_EXTERNAL_AUTHENTICATION and CFG_EXTERNAL_AUTHENTICATION[prefs['login_method']] is not None:
        CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS_LOCAL = 3

    out = websession_templates.tmpl_user_preferences(
             ln = ln,
             email = email,
             email_disabled = (CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS_LOCAL >= 2),
             password_disabled = (CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS_LOCAL >= 3),
             nickname = nickname,
             csrf_token = csrf_token
           )
    if len(CFG_EXTERNAL_AUTHENTICATION) > 1:
        try:
            uid = run_sql("SELECT id FROM user where email=%s", (email,))
            uid = uid[0][0]
        except IndexError:
            uid = 0
        current_login_method = prefs['login_method']
        methods = CFG_EXTERNAL_AUTHENTICATION.keys()

        # Filtering out methods that don't provide user_exists to check if
        # a user exists in the external auth method before letting him/her
        # to switch.

        for method in methods:
            if CFG_EXTERNAL_AUTHENTICATION[method] is not None:
                try:
                    if not CFG_EXTERNAL_AUTHENTICATION[method].user_exists(email):
                        methods.remove(method)
                except (AttributeError, InvenioWebAccessExternalAuthError, NotImplementedError):
                    methods.remove(method)
        methods.sort()

        if len(methods) > 1:
            out += websession_templates.tmpl_user_external_auth(
                    ln = ln,
                    methods = methods,
                    current = current_login_method,
                    method_disabled = (CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS >= 4),
                    csrf_token = csrf_token,
                )

    current_group_records = prefs.get('websearch_group_records', 10)
    show_latestbox = prefs.get('websearch_latestbox', True)
    show_helpbox = prefs.get('websearch_helpbox', True)
    out += websession_templates.tmpl_user_websearch_edit(
                ln = ln,
                current = current_group_records,
                show_latestbox = show_latestbox,
                show_helpbox = show_helpbox,
                csrf_token = csrf_token,
                )

    preferred_lang = prefs.get('language', ln)
    out += websession_templates.tmpl_user_lang_edit(
                ln = ln,
                preferred_lang = preferred_lang,
                csrf_token = csrf_token,
                )

    keys_info = web_api_key.show_web_api_keys(uid=uid)
    out+=websession_templates.tmpl_user_api_key(
                ln = ln,
                keys_info = keys_info,
                csrf_token = csrf_token,
                )

    #show this dialog only if the system has been configured to use a ticket system
    from invenio.config import CFG_BIBCATALOG_SYSTEM
    if CFG_BIBCATALOG_SYSTEM and can_config_bibcatalog:
        bibcatalog_username = prefs.get('bibcatalog_username', "")
        bibcatalog_password = prefs.get('bibcatalog_password', "")
        out += websession_templates.tmpl_user_bibcatalog_auth(bibcatalog_username,
                                                              bibcatalog_password, ln=ln,
                                                              csrf_token=csrf_token)

    if can_config_profiling:
        out += websession_templates.tmpl_user_profiling_settings(ln=ln,
                                                                 enable_profiling=prefs.get('enable_profiling'),
                                                                 csrf_token=csrf_token)

    if verbose >= 9:
        for key, value in prefs.items():
            out += "<b>%s</b>:%s<br />" % (key, value)
    out += perform_display_external_user_settings(prefs, ln)
    return out
Esempio n. 11
0
def perform_set(email, ln, can_config_bibcatalog = False, verbose = 0):
    """Perform_set(email,password): edit your account parameters, email and
    password.
    If can_config_bibcatalog is True, show the bibcatalog dialog (if configured).
    """

    try:
        res = run_sql("SELECT id, nickname FROM user WHERE email=%s", (email,))
        uid = res[0][0]
        nickname = res[0][1]
    except:
        uid = 0
        nickname = ""

    CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS_LOCAL = CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS
    prefs = get_user_preferences(uid)
    if CFG_EXTERNAL_AUTHENTICATION.has_key(prefs['login_method']) and CFG_EXTERNAL_AUTHENTICATION[prefs['login_method']] is not None:
        CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS_LOCAL = 3

    out = websession_templates.tmpl_user_preferences(
             ln = ln,
             email = email,
             email_disabled = (CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS_LOCAL >= 2),
             password_disabled = (CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS_LOCAL >= 3),
             nickname = nickname,
           )
    if len(CFG_EXTERNAL_AUTHENTICATION) > 1:
        try:
            uid = run_sql("SELECT id FROM user where email=%s", (email,))
            uid = uid[0][0]
        except:
            uid = 0
        current_login_method = prefs['login_method']
        methods = CFG_EXTERNAL_AUTHENTICATION.keys()

        # Filtering out methods that don't provide user_exists to check if
        # a user exists in the external auth method before letting him/her
        # to switch.

        for method in methods:
            if CFG_EXTERNAL_AUTHENTICATION[method] is not None:
                try:
                    if not CFG_EXTERNAL_AUTHENTICATION[method].user_exists(email):
                        methods.remove(method)
                except (AttributeError, InvenioWebAccessExternalAuthError, NotImplementedError):
                    methods.remove(method)
        methods.sort()

        if len(methods) > 1:
            out += websession_templates.tmpl_user_external_auth(
                    ln = ln,
                    methods = methods,
                    current = current_login_method,
                    method_disabled = (CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS >= 4)
                )

    current_group_records = prefs.get('websearch_group_records', 10)
    show_latestbox = prefs.get('websearch_latestbox', True)
    show_helpbox = prefs.get('websearch_helpbox', True)
    out += websession_templates.tmpl_user_websearch_edit(
                ln = ln,
                current = current_group_records,
                show_latestbox = show_latestbox,
                show_helpbox = show_helpbox,
                )

    preferred_lang = prefs.get('language', ln)
    out += websession_templates.tmpl_user_lang_edit(
                ln = ln,
                preferred_lang = preferred_lang
                )
    #show this dialog only if the system has been configured to use a ticket system
    from invenio.config import CFG_BIBCATALOG_SYSTEM
    if CFG_BIBCATALOG_SYSTEM and can_config_bibcatalog:
        bibcatalog_username = prefs.get('bibcatalog_username', "")
        bibcatalog_password = prefs.get('bibcatalog_password', "")
        out += websession_templates.tmpl_user_bibcatalog_auth(bibcatalog_username, \
                                                          bibcatalog_password, ln=ln)

    if verbose >= 9:
        for key, value in prefs.items():
            out += "<b>%s</b>:%s<br />" % (key, value)
    out += perform_display_external_user_settings(prefs, ln)
    return out
Esempio n. 12
0
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:
            p_email = CFG_EXTERNAL_AUTHENTICATION[login_method][0].auth_user(p_email, p_pw, req) or CFG_EXTERNAL_AUTHENTICATION[login_method][0].auth_user(p_un, p_pw, req) ## We try to login with either the email of the nickname
            if p_email:
                p_email = p_email.lower()
            else:
                return([], p_email, p_pw, 15)
        except InvenioWebAccessExternalAuthError:
            register_exception(alert_admin=True)
            raise
        if p_email: # Authenthicated externally
            query_result = run_sql("SELECT id from user where email=%s", (p_email,))
            if not query_result: # First time user
                p_pw_local = int(random.random() * 1000000)
                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, req)
                    except (AttributeError, NotImplementedError):
                        pass
                    except:
                        register_exception(alert_admin=True)
                        raise
                res = registerUser(req, p_email, p_pw_local, p_nickname,
                        register_without_nickname=p_nickname == '',
                        login_method=login_method)
                if res == 4 or res == 2: # The nickname was already taken
                    res = registerUser(req, p_email, p_pw_local, '',
                    register_without_nickname=True,
                    login_method=login_method)
                elif res == 0: # Everything was ok, with or without nickname.
                    query_result = run_sql("SELECT id from user where email=%s", (p_email,))
                elif res == 6: # error in contacting the user via email
                    return([], p_email, p_pw_local, 19)
                else:
                    return([], p_email, p_pw_local, 13)
            try:
                groups = CFG_EXTERNAL_AUTHENTICATION[login_method][0].fetch_user_groups_membership(p_email, p_pw, req)
                # 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, NotImplementedError):
                pass
            except:
                register_exception(alert_admin=True)
                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])
            if CFG_ACCESS_CONTROL_LEVEL_ACCOUNTS >= 4:
                # Let's prevent the user to switch login_method
                if user_prefs.has_key("login_method") and \
                           user_prefs["login_method"] != login_method:
                    return([], p_email, p_pw, 11)
            user_prefs["login_method"] = login_method

            # Cleaning external settings
            for key in user_prefs.keys():
                if key.startswith('EXTERNAL_'):
                    del user_prefs[key]
            try:
                # Importing external settings
                new_prefs = CFG_EXTERNAL_AUTHENTICATION[login_method][0].fetch_user_preferences(p_email, p_pw, req)
                for key, value in new_prefs.items():
                    user_prefs['EXTERNAL_' + key] = value
            except (AttributeError, NotImplementedError):
                pass
            except InvenioWebAccessExternalAuthError:
                register_exception(alert_admin=True)
                return([], p_email, p_pw, 16)
            # Storing settings
            set_user_preferences(query_result[0][0], user_prefs)
        else:
            return ([], p_un, p_pw, 10)
    else: # Internal Authenthication
        if not p_pw:
            p_pw = ''
        query_result = run_sql("SELECT id,email,note from user where email=%s and password=AES_ENCRYPT(email,%s)", (p_email, p_pw,))
        if query_result:
            #FIXME drop external groups and settings
            note = query_result[0][2]
            if note == '1': # Good account
                preferred_login_method = get_user_preferences(query_result[0][0])['login_method']
                p_email = query_result[0][1].lower()
                if login_method != preferred_login_method:
                    if CFG_EXTERNAL_AUTHENTICATION.has_key(preferred_login_method):
                        return ([], p_email, p_pw, 11)
            elif note == '2': # Email address need to be confirmed by user
                return ([], p_email, p_pw, 17)
            elif note == '0': # Account need to be confirmed by administrator
                return ([], p_email, p_pw, 18)
        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)