139 lines
5.4 KiB
Python
139 lines
5.4 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Copyright (C) 2014-2017 Andrey Antukh <niwi@niwi.be>
|
|
# Copyright (C) 2014-2017 Jesús Espino <jespinog@gmail.com>
|
|
# Copyright (C) 2014-2017 David Barragán <bameda@dbarragan.com>
|
|
# Copyright (C) 2014-2017 Alejandro Alonso <alejandro.alonso@kaleidos.net>
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU Affero General Public License as
|
|
# published by the Free Software Foundation, either version 3 of the
|
|
# License, or (at your option) any later version.
|
|
#
|
|
# 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 Affero 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/>.
|
|
import logging
|
|
|
|
from django.apps import apps
|
|
from django.db.models import Q
|
|
from django.utils.translation import ugettext as _
|
|
|
|
from taiga.base import exceptions as exc
|
|
from taiga.base.filters import FilterBackend
|
|
from taiga.base.filters import get_filter_expression_can_view_projects
|
|
from taiga.base.utils.db import to_tsquery
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class DiscoverModeFilterBackend(FilterBackend):
|
|
def filter_queryset(self, request, queryset, view):
|
|
qs = queryset
|
|
|
|
if "discover_mode" in request.QUERY_PARAMS:
|
|
field_data = request.QUERY_PARAMS["discover_mode"]
|
|
discover_mode = self._special_values_dict.get(field_data, field_data)
|
|
|
|
if discover_mode:
|
|
# discover_mode enabled
|
|
qs = qs.filter(anon_permissions__contains=["view_project"],
|
|
blocked_code__isnull=True)
|
|
|
|
# random order for featured projects
|
|
if request.QUERY_PARAMS.get("is_featured", None) == 'true':
|
|
qs = qs.order_by("?")
|
|
|
|
return super().filter_queryset(request, qs, view)
|
|
|
|
|
|
class CanViewProjectObjFilterBackend(FilterBackend):
|
|
def filter_queryset(self, request, queryset, view):
|
|
project_id = None
|
|
|
|
# Filter by filter_fields
|
|
if (hasattr(view, "filter_fields") and "project" in view.filter_fields and
|
|
"project" in request.QUERY_PARAMS):
|
|
try:
|
|
project_id = int(request.QUERY_PARAMS["project"])
|
|
except:
|
|
logger.error("Filtering project diferent value than an integer: {}".format(
|
|
request.QUERY_PARAMS["project"]
|
|
))
|
|
raise exc.BadRequest(_("'project' must be an integer value."))
|
|
|
|
filter_expression = get_filter_expression_can_view_projects(
|
|
request.user,
|
|
project_id)
|
|
|
|
qs = queryset.filter(filter_expression)
|
|
|
|
return super().filter_queryset(request, qs, view)
|
|
|
|
|
|
class QFilterBackend(FilterBackend):
|
|
def filter_queryset(self, request, queryset, view):
|
|
# NOTE: See migtration 0033_text_search_indexes
|
|
q = request.QUERY_PARAMS.get('q', None)
|
|
if q:
|
|
tsquery = "to_tsquery('simple', %s)"
|
|
tsquery_params = [to_tsquery(q)]
|
|
tsvector = """
|
|
setweight(to_tsvector('simple',
|
|
coalesce(projects_project.name, '')), 'A') ||
|
|
setweight(to_tsvector('simple',
|
|
coalesce(inmutable_array_to_string(projects_project.tags), '')), 'B') ||
|
|
setweight(to_tsvector('simple',
|
|
coalesce(projects_project.description, '')), 'C')
|
|
"""
|
|
|
|
select = {
|
|
"rank": "ts_rank({tsvector},{tsquery})".format(tsquery=tsquery,
|
|
tsvector=tsvector),
|
|
}
|
|
select_params = tsquery_params
|
|
where = ["{tsvector} @@ {tsquery}".format(tsquery=tsquery,
|
|
tsvector=tsvector), ]
|
|
params = tsquery_params
|
|
order_by = ["-rank", ]
|
|
|
|
queryset = queryset.extra(select=select,
|
|
select_params=select_params,
|
|
where=where,
|
|
params=params,
|
|
order_by=order_by)
|
|
return queryset
|
|
|
|
|
|
class UserOrderFilterBackend(FilterBackend):
|
|
def filter_queryset(self, request, queryset, view):
|
|
if request.user.is_anonymous():
|
|
return queryset
|
|
|
|
raw_fieldname = request.QUERY_PARAMS.get(self.order_by_query_param, None)
|
|
if not raw_fieldname:
|
|
return queryset
|
|
|
|
if raw_fieldname.startswith("-"):
|
|
field_name = raw_fieldname[1:]
|
|
else:
|
|
field_name = raw_fieldname
|
|
|
|
if field_name != "user_order":
|
|
return queryset
|
|
|
|
model = queryset.model
|
|
sql = """SELECT projects_membership.user_order
|
|
FROM projects_membership
|
|
WHERE
|
|
projects_membership.project_id = {tbl}.id AND
|
|
projects_membership.user_id = {user_id}
|
|
"""
|
|
|
|
sql = sql.format(tbl=model._meta.db_table, user_id=request.user.id)
|
|
queryset = queryset.extra(select={"user_order": sql})
|
|
queryset = queryset.order_by(raw_fieldname)
|
|
return queryset
|