'Update pe_id, roles and realms for the current user'

def s3_set_roles(self):

    session = current.session
    s3 = current.response.s3
    if ('restricted_tables' in s3):
        del s3['restricted_tables']
    permission = self.permission
    permission.clear_cache()
    system_roles = self.get_system_roles()
    ANONYMOUS = system_roles.ANONYMOUS
    if ANONYMOUS:
        session.s3.roles = [ANONYMOUS]
    else:
        session.s3.roles = []
    if self.user:
        db = current.db
        s3db = current.s3db
        user_id = self.user.id
        ltable = s3db.table('pr_person_user')
        if (ltable is not None):
            query = (ltable.user_id == user_id)
            row = db(query).select(ltable.pe_id, limitby=(0, 1), cache=s3db.cache).first()
            if row:
                self.user['pe_id'] = row.pe_id
        else:
            self.user['pe_id'] = None
        mtable = self.settings.table_membership
        query = (((mtable.deleted != True) & (mtable.user_id == user_id)) & (mtable.group_id != None))
        rows = db(query).select(mtable.group_id, mtable.pe_id, cacheable=True)
        session.s3.roles.extend(list(set([row.group_id for row in rows])))
        if (not permission.entity_realm):
            self.user['realms'] = Storage([(row.group_id, None) for row in rows])
            self.user['delegations'] = Storage()
        else:
            realms = {}
            delegations = {}
            unrestrictable = (system_roles.ADMIN, system_roles.ANONYMOUS, system_roles.AUTHENTICATED)
            default_realm = s3db.pr_realm(self.user['pe_id'])
            for row in rows:
                group_id = row.group_id
                if ((group_id in realms) and (realms[group_id] is None)):
                    continue
                if (group_id in unrestrictable):
                    realms[group_id] = None
                    continue
                if (group_id not in realms):
                    realms[group_id] = []
                realm = realms[group_id]
                pe_id = row.pe_id
                if (pe_id is None):
                    if default_realm:
                        realm.extend([e for e in default_realm if (e not in realm)])
                    if (not realm):
                        del realms[group_id]
                elif (pe_id == 0):
                    realms[group_id] = None
                elif (pe_id not in realm):
                    realms[group_id].append(pe_id)
            if permission.entity_hierarchy:
                all_entities = []
                append = all_entities.append
                for realm in realms.values():
                    if (realm is not None):
                        for entity in realm:
                            if (entity not in all_entities):
                                append(entity)
                if (permission.delegations and self.user.pe_id):
                    ancestors = s3db.pr_get_ancestors(self.user.pe_id)
                    dtable = s3db.pr_delegation
                    rtable = s3db.pr_role
                    atable = s3db.pr_affiliation
                    dn = dtable._tablename
                    rn = rtable._tablename
                    an = atable._tablename
                    query = ((((dtable.deleted != True) & (atable.role_id == dtable.role_id)) & atable.pe_id.belongs(ancestors)) & (rtable.id == dtable.role_id))
                    rows = db(query).select(rtable.pe_id, dtable.group_id, atable.pe_id, cacheable=True)
                    extensions = []
                    partners = []
                    for row in rows:
                        extensions.append(row[rn].pe_id)
                        partners.append(row[an].pe_id)
                else:
                    rows = []
                    extensions = []
                    partners = []
                entities = ((all_entities + extensions) + partners)
                descendants = s3db.pr_descendants(entities)
                pmap = {}
                for p in partners:
                    if (p in all_entities):
                        pmap[p] = [p]
                    elif (p in descendants):
                        d = descendants[p]
                        pmap[p] = ([e for e in all_entities if (e in d)] or [p])
                for group_id in realms:
                    realm = realms[group_id]
                    if (realm is None):
                        continue
                    append = realm.append
                    for entity in list(realm):
                        if (entity in descendants):
                            for subsidiary in descendants[entity]:
                                if (subsidiary not in realm):
                                    append(subsidiary)
                if permission.delegations:
                    for row in rows:
                        owner = row[rn].pe_id
                        partner = row[an].pe_id
                        group_id = row[dn].group_id
                        if ((group_id in delegations) and (owner in delegations[group_id])):
                            continue
                        if (partner not in pmap):
                            continue
                        if (group_id not in delegations):
                            delegations[group_id] = Storage()
                        groups = delegations[group_id]
                        r = [owner]
                        if (owner in descendants):
                            r.extend(descendants[owner])
                        for p in pmap[partner]:
                            if (p not in groups):
                                groups[p] = []
                            realm = groups[p]
                            realm.extend(r)
            self.user['realms'] = realms
            self.user['delegations'] = delegations
        if ANONYMOUS:
            self.user['realms'][ANONYMOUS] = None
