Revision 24589c11
Suppression d'une requête IN coûteuse (#772)
Suppression d'une requête IN coûteuse dans VigiGraph.
Il n'en reste plus que 3...
Change-Id: I67bf1c21798cf0bb0cd0312fce7587ad64a7ab50
Refs: #772.
Reviewed-on: https://vigilo-dev.si.c-s.fr/review/271
Tested-by: Build system <qa@vigilo-dev.si.c-s.fr>
Reviewed-by: Aurelien BOMPARD <aurelien.bompard@c-s.fr>
vigigraph/controllers/rpc.py | ||
---|---|---|
24 | 24 |
from formencode import validators, schema |
25 | 25 |
from sqlalchemy import or_ |
26 | 26 |
from sqlalchemy.sql.expression import literal_column |
27 |
from sqlalchemy.orm import aliased, lazyload |
|
27 | 28 |
|
28 | 29 |
from vigilo.turbogears.controllers import BaseController |
29 | 30 |
from vigilo.turbogears.helpers import get_current_user |
30 |
from vigilo.turbogears.controllers.proxy import get_through_proxy
|
|
31 |
from vigilo.turbogears.controllers.proxy import get_through_proxy |
|
31 | 32 |
|
32 | 33 |
from vigilo.models.session import DBSession |
33 |
from vigilo.models.tables import Host |
|
34 |
from vigilo.models.tables import SupItemGroup
|
|
35 |
from vigilo.models.tables import PerfDataSource
|
|
36 |
from vigilo.models.tables import Graph, GraphGroup
|
|
34 |
from vigilo.models.tables import Host, SupItemGroup, PerfDataSource
|
|
35 |
from vigilo.models.tables import Graph, GraphGroup, Change, UserGroup
|
|
36 |
from vigilo.models.tables import DataPermission
|
|
37 |
from vigilo.models.tables.group import Group
|
|
37 | 38 |
from vigilo.models.tables.grouphierarchy import GroupHierarchy |
38 |
from vigilo.models.tables import Change |
|
39 | 39 |
|
40 | 40 |
from vigilo.models.tables.secondary_tables import SUPITEM_GROUP_TABLE |
41 | 41 |
from vigilo.models.tables.secondary_tables import GRAPH_GROUP_TABLE |
42 | 42 |
from vigilo.models.tables.secondary_tables import GRAPH_PERFDATASOURCE_TABLE |
43 |
from vigilo.models.tables.secondary_tables import USER_GROUP_TABLE |
|
43 | 44 |
from vigilo.models.functions import sql_escape_like |
44 | 45 |
|
45 | 46 |
LOGGER = logging.getLogger(__name__) |
... | ... | |
118 | 119 |
# correspondant au motif, quel que soit l'hôte. |
119 | 120 |
if search_form_graph: |
120 | 121 |
if not search_form_host: |
121 |
search_form_host = '*' |
|
122 |
search_form_host = u'*'
|
|
122 | 123 |
|
123 | 124 |
search_form_host = sql_escape_like(search_form_host) |
124 | 125 |
search_form_graph = sql_escape_like(search_form_graph) |
... | ... | |
358 | 359 |
if len(set(hostgroups).intersection(set(supitemgroups))) < 1: |
359 | 360 |
message = _('Access denied to host "%s"') % host |
360 | 361 |
LOGGER.warning(message) |
361 |
raise http_exc.HTTPForbidden(message)
|
|
362 |
raise http_exc.HTTPForbidden(message) |
|
362 | 363 |
|
363 | 364 |
# Récupération de la liste des noms des graphes associés à l'hôte. |
364 | 365 |
graphs = DBSession.query( |
... | ... | |
407 | 408 |
).join( |
408 | 409 |
(SUPITEM_GROUP_TABLE, SUPITEM_GROUP_TABLE.c.idsupitem == \ |
409 | 410 |
Host.idhost), |
410 |
).filter(Host.name.like(query + '%') |
|
411 |
).filter(Host.name.like(query + u'%')
|
|
411 | 412 |
).order_by( |
412 | 413 |
Host.name.asc(), |
413 | 414 |
) |
... | ... | |
462 | 463 |
if not is_manager: |
463 | 464 |
direct_access = False |
464 | 465 |
user = get_current_user() |
465 |
user_groups = dict(user.supitemgroups()) |
|
466 |
# On regarde d'abord si le groupe fait partie de ceux |
|
467 |
# auquels l'utilisateur a explicitement accès, ou s'il |
|
468 |
# est un parent des groupes auxquels l'utilisateur a accès |
|
469 |
if parent_id in user_groups.keys(): |
|
470 |
direct_access = user_groups[parent_id] |
|
471 |
# Dans le cas contraire, on vérifie si le groupe est un |
|
472 |
# sous-groupe des groupes auxquels l'utilisateur a accès |
|
473 |
else: |
|
474 |
id_list = [ug for ug in user_groups.keys() if user_groups[ug]] |
|
475 |
child_groups = DBSession.query(SupItemGroup.idgroup |
|
476 |
).distinct( |
|
466 |
|
|
467 |
# On calcule la distance de ce groupe par rapport aux groupes |
|
468 |
# sur lesquels l'utilisateur a explicitement les permissions. |
|
469 |
# |
|
470 |
# La distance est définie ainsi : |
|
471 |
# 0 : l'utilisateur a des droits explicites sur ce groupe. |
|
472 |
# > 0 : l'utilisateur a accès implicitement au groupe. |
|
473 |
# < 0 : l'utilisateur n'a pas d'accès (il peut juste parcourir |
|
474 |
# ce groupe) |
|
475 |
# |
|
476 |
# Il faut 2 étapes pour trouver la distance. La 1ère essaye |
|
477 |
# de trouver une distance >= 0, la 2ème une distance <= 0. |
|
478 |
|
|
479 |
# Distance positive. |
|
480 |
distance = DBSession.query( |
|
481 |
GroupHierarchy.hops |
|
482 |
).join( |
|
483 |
(Group, Group.idgroup == GroupHierarchy.idparent), |
|
484 |
(DataPermission, DataPermission.idgroup == Group.idgroup), |
|
485 |
(UserGroup, UserGroup.idgroup == DataPermission.idusergroup), |
|
486 |
(USER_GROUP_TABLE, USER_GROUP_TABLE.c.idgroup == \ |
|
487 |
UserGroup.idgroup), |
|
488 |
).filter(USER_GROUP_TABLE.c.username == user.user_name |
|
489 |
).filter(Group._grouptype == u'supitemgroup' |
|
490 |
).filter(GroupHierarchy.idchild == parent_id |
|
491 |
).order_by(GroupHierarchy.hops.desc()).scalar() |
|
492 |
|
|
493 |
if distance is None: |
|
494 |
# Distance négative. |
|
495 |
distance = DBSession.query( |
|
496 |
GroupHierarchy.hops |
|
477 | 497 |
).join( |
478 |
(GroupHierarchy, |
|
479 |
GroupHierarchy.idchild == SupItemGroup.idgroup), |
|
480 |
).filter(GroupHierarchy.idparent.in_(id_list) |
|
481 |
).filter(GroupHierarchy.hops > 0 |
|
482 |
).all() |
|
483 |
for ucg in child_groups: |
|
484 |
if ucg.idgroup == parent_id: |
|
485 |
direct_access = True |
|
486 |
break |
|
487 |
# Sinon, l'utilisateur n'a pas accès à ce groupe |
|
488 |
else: |
|
489 |
return dict(groups = [], items = []) |
|
498 |
(Group, Group.idgroup == GroupHierarchy.idchild), |
|
499 |
(DataPermission, DataPermission.idgroup == Group.idgroup), |
|
500 |
(UserGroup, UserGroup.idgroup == DataPermission.idusergroup), |
|
501 |
(USER_GROUP_TABLE, USER_GROUP_TABLE.c.idgroup == \ |
|
502 |
UserGroup.idgroup), |
|
503 |
).filter(USER_GROUP_TABLE.c.username == user.user_name |
|
504 |
).filter(Group._grouptype == u'supitemgroup' |
|
505 |
).filter(GroupHierarchy.idparent == parent_id |
|
506 |
).order_by(GroupHierarchy.hops.desc()).scalar() |
|
507 |
if distance is not None: |
|
508 |
distance = -distance |
|
509 |
|
|
510 |
if distance is None: |
|
511 |
# Pas d'accès à ce groupe. |
|
512 |
return dict(groups = [], items = []) |
|
513 |
|
|
514 |
direct_access = distance >= 0 |
|
490 | 515 |
|
491 | 516 |
limit = int(config.get("max_menu_entries", 20)) |
492 | 517 |
result = {"groups": [], "items": []} |
... | ... | |
494 | 519 |
if not onlytype or onlytype == "group": |
495 | 520 |
# On récupère la liste des groupes dont |
496 | 521 |
# l'identifiant du parent est passé en paramètre |
522 |
gh1 = aliased(GroupHierarchy, name='gh1') |
|
523 |
gh2 = aliased(GroupHierarchy, name='gh2') |
|
524 |
|
|
497 | 525 |
db_groups = DBSession.query( |
498 | 526 |
SupItemGroup |
527 |
).options(lazyload('_path_obj') |
|
528 |
).distinct( |
|
499 | 529 |
).join( |
500 |
(GroupHierarchy, GroupHierarchy.idchild == \ |
|
501 |
SupItemGroup.idgroup), |
|
502 |
).filter(GroupHierarchy.hops == 1 |
|
503 |
).filter(GroupHierarchy.idparent == parent_id |
|
530 |
(gh1, gh1.idchild == SupItemGroup.idgroup), |
|
531 |
).filter(gh1.hops == 1 |
|
532 |
).filter(gh1.idparent == parent_id |
|
504 | 533 |
).order_by(SupItemGroup.name.asc()) |
534 |
|
|
505 | 535 |
if not is_manager and not direct_access: |
506 |
id_list = [ug for ug in user_groups.keys()] |
|
536 |
# On ne doit afficher que les fils du groupe <parent_id> |
|
537 |
# tels que l'utilisateur a accès explicitement à l'un |
|
538 |
# des fils de l'un de ces groupes. |
|
539 |
db_groups = db_groups.join( |
|
540 |
(gh2, gh2.idparent == gh1.idchild), |
|
541 |
(DataPermission, DataPermission.idgroup == gh2.idchild), |
|
542 |
(UserGroup, UserGroup.idgroup == DataPermission.idusergroup), |
|
543 |
(USER_GROUP_TABLE, USER_GROUP_TABLE.c.idgroup == UserGroup.idgroup), |
|
544 |
).filter(USER_GROUP_TABLE.c.username == user.user_name) |
|
507 | 545 |
|
508 |
db_groups = db_groups.filter( |
|
509 |
SupItemGroup.idgroup.in_(id_list)) |
|
510 | 546 |
num_children_left = db_groups.count() - offset |
511 | 547 |
if offset: |
512 | 548 |
result["continued_from"] = offset |
... | ... | |
770 | 806 |
@expose('json') |
771 | 807 |
def external_links(self): |
772 | 808 |
return dict(links=config['external_links']) |
773 |
|
Also available in: Unified diff