##// END OF EJS Templates
goto-switcher: optimized performance and query capabilities....
goto-switcher: optimized performance and query capabilities. - Previous implementation had on significant bug. The use of LIMIT 20 was limiting results BEFORE auth checks. In case of large ammount of similarly named repositories user didn't had access too, the result goto search was empty. This was becuase first 20 items fetched didn't pass permission checks and final auth list was empty. To fix this we now use proper filtering for auth using SQL. It means we first check user allowed repositories, and add this as a filter so end result from database is already to only the accessible repositories.

File last commit:

r1789:13d7e2ce default
r2038:2bdf9d4d default
Show More
integration.py
215 lines | 7.5 KiB | text/x-python | PythonLexer
dan
integrations: add integration support...
r411 # -*- coding: utf-8 -*-
license: updated copyright year to 2017
r1271 # Copyright (C) 2011-2017 RhodeCode GmbH
dan
integrations: add integration support...
r411 #
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License, version 3
# (only), as published by the Free Software Foundation.
#
# This program 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 Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# This program is dual-licensed. If you wish to learn more about the
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
"""
Model for integrations
"""
import logging
dan
integrations: refactor/cleanup + features, fixes #4181...
r731 from sqlalchemy import or_, and_
dan
integrations: add integration support...
r411
import rhodecode
from rhodecode import events
from rhodecode.lib.caching_query import FromCache
from rhodecode.model import BaseModel
integrations: remove usage of template context from integrations models
r1320 from rhodecode.model.db import Integration, Repository, RepoGroup
dan
integrations: add integration support...
r411 from rhodecode.integrations import integration_type_registry
log = logging.getLogger(__name__)
class IntegrationModel(BaseModel):
cls = Integration
def __get_integration(self, integration):
if isinstance(integration, Integration):
return integration
elif isinstance(integration, (int, long)):
return self.sa.query(Integration).get(integration)
else:
if integration:
raise Exception('integration must be int, long or Instance'
' of Integration got %s' % type(integration))
dan
integrations: add recursive repo group scope to allow integrations...
r793 def create(self, IntegrationType, name, enabled, repo, repo_group,
child_repos_only, settings):
dan
integrations: fix bug where deleting a repo did not delete integrations
r427 """ Create an IntegrationType integration """
integrations-db: don't use default contructor to be consisten with other modules...
r448 integration = Integration()
integration.integration_type = IntegrationType.key
dan
integrations: fix bug where deleting a repo did not delete integrations
r427 self.sa.add(integration)
dan
integrations: add recursive repo group scope to allow integrations...
r793 self.update_integration(integration, name, enabled, repo, repo_group,
child_repos_only, settings)
dan
integrations: fix bug where deleting a repo did not delete integrations
r427 self.sa.commit()
return integration
dan
integrations: add recursive repo group scope to allow integrations...
r793 def update_integration(self, integration, name, enabled, repo, repo_group,
child_repos_only, settings):
dan
integrations: refactor/cleanup + features, fixes #4181...
r731 integration = self.__get_integration(integration)
dan
integrations: add recursive repo group scope to allow integrations...
r793 integration.repo = repo
integration.repo_group = repo_group
integration.child_repos_only = child_repos_only
dan
integrations: refactor/cleanup + features, fixes #4181...
r731 integration.name = name
integration.enabled = enabled
integration.settings = settings
return integration
dan
integrations: add integration support...
r411 def delete(self, integration):
dan
integrations: refactor/cleanup + features, fixes #4181...
r731 integration = self.__get_integration(integration)
if integration:
self.sa.delete(integration)
return True
dan
integrations: add integration support...
r411 return False
def get_integration_handler(self, integration):
TypeClass = integration_type_registry.get(integration.integration_type)
if not TypeClass:
log.error('No class could be found for integration type: {}'.format(
integration.integration_type))
return None
return TypeClass(integration.settings)
def send_event(self, integration, event):
""" Send an event to an integration """
handler = self.get_integration_handler(integration)
if handler:
events: re-organizate events handling....
r1789 log.debug(
'events: sending event %s on integration %s using handler %s',
event, integration, handler)
dan
integrations: add integration support...
r411 handler.send_event(event)
dan
integrations: refactor/cleanup + features, fixes #4181...
r731 def get_integrations(self, scope, IntegrationType=None):
"""
Return integrations for a scope, which must be one of:
'all' - every integration, global/repogroup/repo
'global' - global integrations only
<Repository> instance - integrations for this repo only
<RepoGroup> instance - integrations for this repogroup only
"""
dan
integrations: add integration support...
r411
dan
integrations: refactor/cleanup + features, fixes #4181...
r731 if isinstance(scope, Repository):
query = self.sa.query(Integration).filter(
Integration.repo==scope)
elif isinstance(scope, RepoGroup):
query = self.sa.query(Integration).filter(
Integration.repo_group==scope)
elif scope == 'global':
# global integrations
query = self.sa.query(Integration).filter(
and_(Integration.repo_id==None, Integration.repo_group_id==None)
)
dan
integrations: add recursive repo group scope to allow integrations...
r793 elif scope == 'root-repos':
dan
integrations: refactor/cleanup + features, fixes #4181...
r731 query = self.sa.query(Integration).filter(
and_(Integration.repo_id==None,
Integration.repo_group_id==None,
Integration.child_repos_only==True)
)
elif scope == 'all':
query = self.sa.query(Integration)
else:
raise Exception(
"invalid `scope`, must be one of: "
"['global', 'all', <Repository>, <RepoGroup>]")
if IntegrationType is not None:
query = query.filter(
Integration.integration_type==IntegrationType.key)
result = []
for integration in query.all():
IntType = integration_type_registry.get(integration.integration_type)
result.append((IntType, integration))
return result
dan
integrations: add integration support...
r411
def get_for_event(self, event, cache=False):
"""
Get integrations that match an event
"""
dan
integrations: refactor/cleanup + features, fixes #4181...
r731 query = self.sa.query(
Integration
).filter(
Integration.enabled==True
)
global_integrations_filter = and_(
Integration.repo_id==None,
Integration.repo_group_id==None,
Integration.child_repos_only==False,
)
if isinstance(event, events.RepoEvent):
root_repos_integrations_filter = and_(
Integration.repo_id==None,
Integration.repo_group_id==None,
Integration.child_repos_only==True,
)
clauses = [
global_integrations_filter,
]
dan
integrations: add integration support...
r411
dan
integrations: refactor/cleanup + features, fixes #4181...
r731 # repo integrations
if event.repo.repo_id: # pre create events dont have a repo_id yet
clauses.append(
Integration.repo_id==event.repo.repo_id
)
if event.repo.group:
clauses.append(
dan
integrations: add recursive repo group scope to allow integrations...
r793 and_(
Integration.repo_group_id==event.repo.group.group_id,
Integration.child_repos_only==True
)
dan
integrations: refactor/cleanup + features, fixes #4181...
r731 )
dan
integrations: add recursive repo group scope to allow integrations...
r793 # repo group cascade to kids
clauses.append(
and_(
Integration.repo_group_id.in_(
[group.group_id for group in
event.repo.groups_with_parents]
),
Integration.child_repos_only==False
)
)
dan
integrations: refactor/cleanup + features, fixes #4181...
r731
if not event.repo.group: # root repo
clauses.append(root_repos_integrations_filter)
query = query.filter(or_(*clauses))
dan
integrations: add integration support...
r411 if cache:
caches: ensure we don't use non-ascii characters in cache keys....
r1749 cache_key = "get_enabled_repo_integrations_%i" % event.repo.repo_id
query = query.options(
FromCache("sql_cache_short", cache_key))
dan
integrations: add integration support...
r411 else: # only global integrations
dan
integrations: refactor/cleanup + features, fixes #4181...
r731 query = query.filter(global_integrations_filter)
dan
integrations: add integration support...
r411 if cache:
caches: ensure we don't use non-ascii characters in cache keys....
r1749 query = query.options(
FromCache("sql_cache_short", "get_enabled_global_integrations"))
dan
integrations: add integration support...
r411
dan
integrations: refactor/cleanup + features, fixes #4181...
r731 result = query.all()
return result