show only devices wb via api

This commit is contained in:
Cayo Puigdefabregas 2022-07-18 17:56:54 +02:00
parent a6c84ae588
commit 31abdf55e2
1 changed files with 72 additions and 41 deletions

View File

@ -3,28 +3,33 @@ import uuid
from itertools import filterfalse
import marshmallow
from flask import g, current_app as app, render_template, request, Response
from flask import Response
from flask import current_app as app
from flask import g, render_template, request
from flask.json import jsonify
from flask_sqlalchemy import Pagination
from marshmallow import Schema as MarshmallowSchema
from marshmallow import fields
from marshmallow import fields as f
from marshmallow import validate as v
from sqlalchemy.util import OrderedSet
from marshmallow import fields, fields as f, validate as v, Schema as MarshmallowSchema
from teal import query
from teal.db import ResourceNotFound
from teal.cache import cache
from teal.resource import View
from teal.db import ResourceNotFound
from teal.marshmallow import ValidationError
from teal.resource import View
from ereuse_devicehub import auth
from ereuse_devicehub.db import db
from ereuse_devicehub.query import SearchQueryParser, things_response
from ereuse_devicehub.resources import search
from ereuse_devicehub.resources.action import models as actions
from ereuse_devicehub.resources.action.models import Trade
from ereuse_devicehub.resources.device import states
from ereuse_devicehub.resources.device.models import Device, Manufacturer, Computer
from ereuse_devicehub.resources.device.models import Computer, Device, Manufacturer
from ereuse_devicehub.resources.device.search import DeviceSearch
from ereuse_devicehub.resources.enums import SnapshotSoftware
from ereuse_devicehub.resources.lot.models import LotDeviceDescendants
from ereuse_devicehub.resources.action.models import Trade
from ereuse_devicehub.resources.tag.model import Tag
@ -61,15 +66,16 @@ class Filters(query.Query):
manufacturer = query.ILike(Device.manufacturer)
serialNumber = query.ILike(Device.serial_number)
# todo test query for rating (and possibly other filters)
rating = query.Join((Device.id == actions.ActionWithOneDevice.device_id)
rating = query.Join(
(Device.id == actions.ActionWithOneDevice.device_id)
& (actions.ActionWithOneDevice.id == actions.Rate.id),
RateQ)
RateQ,
)
tag = query.Join(Device.id == Tag.device_id, TagQ)
# todo This part of the query is really slow
# And forces usage of distinct, as it returns many rows
# due to having multiple paths to the same
lot = query.Join((Device.id == LotDeviceDescendants.device_id),
LotQ)
lot = query.Join((Device.id == LotDeviceDescendants.device_id), LotQ)
class Sorting(query.Sort):
@ -104,12 +110,15 @@ class DeviceView(View):
return super().get(id)
def patch(self, id):
dev = Device.query.filter_by(id=id, owner_id=g.user.id, active=True).one()
dev = Device.query.filter_by(
id=id, owner_id=g.user.id, active=True, placeholder=None
).one()
if isinstance(dev, Computer):
resource_def = app.resources['Computer']
# TODO check how to handle the 'actions_one'
patch_schema = resource_def.SCHEMA(
only=['transfer_state', 'actions_one'], partial=True)
only=['transfer_state', 'actions_one'], partial=True
)
json = request.get_json(schema=patch_schema)
# TODO check how to handle the 'actions_one'
json.pop('actions_one')
@ -129,12 +138,16 @@ class DeviceView(View):
return self.one_private(id)
def one_public(self, id: int):
device = Device.query.filter_by(devicehub_id=id, active=True).one()
device = Device.query.filter_by(
devicehub_id=id, active=True, placeholder=None
).one()
return render_template('devices/layout.html', device=device, states=states)
@auth.Auth.requires_auth
def one_private(self, id: str):
device = Device.query.filter_by(devicehub_id=id, owner_id=g.user.id, active=True).first()
device = Device.query.filter_by(
devicehub_id=id, owner_id=g.user.id, active=True, placeholder=None
).first()
if not device:
return self.one_public(id)
return self.schema.jsonify(device)
@ -148,7 +161,11 @@ class DeviceView(View):
devices = query.paginate(page=args['page'], per_page=30) # type: Pagination
return things_response(
self.schema.dump(devices.items, many=True, nested=1),
devices.page, devices.per_page, devices.total, devices.prev_num, devices.next_num
devices.page,
devices.per_page,
devices.total,
devices.prev_num,
devices.next_num,
)
def query(self, args):
@ -158,9 +175,11 @@ class DeviceView(View):
trades_dev_ids = {d.id for t in trades for d in t.devices}
query = Device.query.filter(Device.active == True).filter(
(Device.owner_id == g.user.id) | (Device.id.in_(trades_dev_ids))
).distinct()
query = (
Device.query.filter(Device.active == True, Device.placeholder == None)
.filter((Device.owner_id == g.user.id) | (Device.id.in_(trades_dev_ids)))
.distinct()
)
unassign = args.get('unassign', None)
search_p = args.get('search', None)
@ -168,14 +187,18 @@ class DeviceView(View):
properties = DeviceSearch.properties
tags = DeviceSearch.tags
devicehub_ids = DeviceSearch.devicehub_ids
query = query.join(DeviceSearch).filter(
search.Search.match(properties, search_p) |
search.Search.match(tags, search_p) |
search.Search.match(devicehub_ids, search_p)
).order_by(
search.Search.rank(properties, search_p) +
search.Search.rank(tags, search_p) +
search.Search.rank(devicehub_ids, search_p)
query = (
query.join(DeviceSearch)
.filter(
search.Search.match(properties, search_p)
| search.Search.match(tags, search_p)
| search.Search.match(devicehub_ids, search_p)
)
.order_by(
search.Search.rank(properties, search_p)
+ search.Search.rank(tags, search_p)
+ search.Search.rank(devicehub_ids, search_p)
)
)
if unassign:
subquery = LotDeviceDescendants.query.with_entities(
@ -221,10 +244,16 @@ class DeviceMergeView(View):
raise ValidationError('The devices is not the same type.')
# Adding actions of self.with_device
with_actions_one = [a for a in self.with_device.actions
if isinstance(a, actions.ActionWithOneDevice)]
with_actions_multiple = [a for a in self.with_device.actions
if isinstance(a, actions.ActionWithMultipleDevices)]
with_actions_one = [
a
for a in self.with_device.actions
if isinstance(a, actions.ActionWithOneDevice)
]
with_actions_multiple = [
a
for a in self.with_device.actions
if isinstance(a, actions.ActionWithMultipleDevices)
]
# Moving the tags from `with_device` to `base_device`
# Union of tags the device had plus the (potentially) new ones
@ -269,20 +298,22 @@ class DeviceMergeView(View):
class ManufacturerView(View):
class FindArgs(marshmallow.Schema):
search = marshmallow.fields.Str(required=True,
search = marshmallow.fields.Str(
required=True,
# Disallow like operators
validate=lambda x: '%' not in x and '_' not in x)
validate=lambda x: '%' not in x and '_' not in x,
)
@cache(datetime.timedelta(days=1))
def find(self, args: dict):
search = args['search']
manufacturers = Manufacturer.query \
.filter(Manufacturer.name.ilike(search + '%')) \
.paginate(page=1, per_page=6) # type: Pagination
manufacturers = Manufacturer.query.filter(
Manufacturer.name.ilike(search + '%')
).paginate(
page=1, per_page=6
) # type: Pagination
return jsonify(
items=app.resources[Manufacturer.t].schema.dump(
manufacturers.items,
many=True,
nested=1
manufacturers.items, many=True, nested=1
)
)