from apollo_utils.service.schemas.base import RequestSchema from apollo_utils.service.schemas.fields.enum import EnumListField from apollo_utils.service.schemas.fields.list import SplitUniqueListField from apollo_utils.service.schemas.headers import SettingsHeader as BaseSettingsHeader from apollo_utils.service.schemas.mixins.pagination import PaginationResponseMixin from marshmallow import Schema, ValidationError, fields, post_load, validates_schema from server.constants.core import OS from server.constants.settings import Include as SettingsInclude from server.schemas.headers import AccountHeader from server.schemas.pagination import HighLimitPaginationMixin from server.schemas.utils import validate_app_version class SettingsHeader(BaseSettingsHeader, AccountHeader): client_type = fields.Str(data_key="Client-Type", required=False, missing=None) # temporary fix AG-9836 @post_load() def add_default_type(self, data, **kwargs): # TODO temporary fix AG-9836, should be removed after AG release if data.get("type") is None and data.get("client_type") == "mobile": data["type"] = "mobile" return data class SettingsCreateUpdateRequest(RequestSchema): data = fields.Dict(required=True) class SettingsBaseResponse(Schema): id = fields.Int() account_id = fields.Int() data = fields.Dict(required=False) class SettingsGet: class Request(HighLimitPaginationMixin, RequestSchema): is_inherited = fields.Boolean(required=False, missing=False) class Response(SettingsBaseResponse): default = fields.Dict(required=False) class SettingsGetBulk: class Request(HighLimitPaginationMixin, RequestSchema): user = SplitUniqueListField(fields.String(required=True), missing=None) type = SplitUniqueListField(fields.String(required=True), missing=None) version = SplitUniqueListField(fields.Integer(required=True), missing=None) class Response(PaginationResponseMixin, Schema): class Item(Schema): id = fields.Int() user_id = fields.Function(lambda x: x.account.user_id) account_id = fields.Int() data = fields.Dict(required=False) items = fields.List(fields.Nested(Item)) class AppVersion(Schema): min = fields.String(missing=None) max = fields.String(missing=None) eq = fields.String(missing=None) include_unset = fields.Boolean(missing=False) @validates_schema def validate(self, data, **kwargs): if any([data["min"], data["max"]]) and data["eq"]: raise ValidationError("Only one of ['min', 'max'] or 'eq' should be filled.") versions = [data[k] for k in ["min", "max", "eq"] if data[k]] for version in versions: validate_app_version(version) class Versions(Schema): min = fields.Integer(missing=None) max = fields.Integer(missing=None) eq = fields.Integer(missing=None) @validates_schema def validate_min_max_eq(self, data, **kwargs): if any([data["min"], data["max"]]) and data["eq"]: raise ValidationError("Only one of ['min', 'max'] or 'eq' should be filled.") class SettingsPostList: class Request(RequestSchema): class User(RequestSchema): id = fields.List(fields.String(), missing=None) class Account(RequestSchema): id = fields.List(fields.Integer(), missing=None) class Device(RequestSchema): is_active = fields.Boolean(missing=None) os = EnumListField(OS, missing=None) app_version = fields.Nested(AppVersion, missing=None) class Settings(RequestSchema): type = fields.String(missing=None) version = fields.Integer(missing=None) versions = fields.Nested(Versions, missing=None) user = fields.Nested(User, missing=None) account = fields.Nested(Account, missing=None) device = fields.Nested(Device, missing=None) settings = fields.Nested(Settings, missing=None) include = EnumListField(SettingsInclude, allow_all=True, missing=None) @validates_schema def validate_user_account(self, data, **kwargs): if data["user"] and data["account"]: raise ValidationError("Only one of 'user', 'account' should be filled.") class Response(Schema): class Item(Schema): class Device(Schema): id = fields.Integer() is_active = fields.Boolean(attribute="status") os = fields.String() expo_token = fields.String(attribute="token") class Settings(Schema): id = fields.Integer() type = fields.String() version = fields.String() data = fields.Dict() account_id = fields.Integer(attribute="id") user_id = fields.String() devices = fields.List(fields.Nested(Device)) settings = fields.Nested(Settings, attribute="settings_item") data = fields.List(fields.Nested(Item))