class OptionField(fields.Field): _options = { 'git': fields.Nested(GitInstallOptionsSchema, unknown=EXCLUDE), 'market': fields.Nested(MarketInstallOptionsSchema, unknown=EXCLUDE), } def _deserialize(self, value, attr, data): method = data.get('method') concrete_options = self._options.get(method) if not concrete_options: return {} return concrete_options._deserialize(value, attr, data)
class RoomSchema(Schema): uuid = fields.UUID(dump_only=True) tenant_uuid = fields.UUID(dump_only=True) name = fields.String(allow_none=True) users = fields.Nested('RoomUserSchema', many=True, missing=[])
class EmailPutSchema(BaseSchema): emails = fields.Nested(EmailSchema, required=True, many=True) @post_load def as_list(self, data): return data['emails'] @validates_schema def validate_only_one_main(self, data): emails = data.get('emails') if not emails: return main_emails_count = [email['main'] for email in emails].count(True) if main_emails_count > 1: raise ValidationError('Only one address should be main') if main_emails_count == 0: raise ValidationError('At least one address should be main') @validates_schema def validate_no_duplicates(self, data): emails = data.get('emails') if not emails: return addresses = list(email['address'] for email in emails if email.get('address')) if len(addresses) != len(set(addresses)): raise ValidationError('The same address can only be used once')
class ProfileSchema(BaseSchema): uuid = fields.UUID(dump_only=True) tenant_uuid = fields.UUID(dump_only=True) name = fields.String(validate=Length(min=1, max=512), required=True) display = fields.Nested(ResourceSchema) services = ServiceDictSchema(BaseSchema, required=True)
class SourceSchema(BaseSourceSchema): auth = fields.Nested( BaseAuthConfigSchema, missing=lambda: BaseAuthConfigSchema().load({}), ) endpoint = fields.String( missing='https://graph.microsoft.com/v1.0/me/contacts', validate=Length(min=1, max=255), )
class MessageSchema(Schema): uuid = fields.UUID(dump_only=True) content = fields.String(required=True) alias = fields.String(validate=validate.Length(max=256), allow_none=True) user_uuid = fields.UUID(dump_only=True) tenant_uuid = fields.UUID(dump_only=True) wazo_uuid = fields.UUID(dump_only=True) created_at = fields.DateTime(dump_only=True) room = fields.Nested('RoomSchema', dump_only=True, only=['uuid'])
class DisplaySchema(BaseSchema): uuid = fields.UUID(dump_only=True) tenant_uuid = fields.UUID(dump_only=True) name = fields.String(validate=Length(min=1, max=512), required=True) columns = fields.Nested( DisplayColumnSchema, many=True, required=True, validate=Length(min=1), )
class UserPresenceSchema(Schema): uuid = fields.UUID(dump_only=True) tenant_uuid = fields.UUID(dump_only=True) state = fields.String( required=True, validate=OneOf(['available', 'unavailable', 'invisible', 'away'])) status = fields.String(allow_none=True) last_activity = fields.DateTime(dump_only=True) line_state = fields.String(dump_only=True) mobile = fields.Boolean(dump_only=True) do_not_disturb = fields.Boolean(dump_only=True) connected = fields.Boolean(dump_only=True) lines = fields.Nested('LinePresenceSchema', many=True, dump_only=True) @post_dump def _set_line_state(self, user, **kwargs): line_states = [line['state'] for line in user['lines']] if 'ringing' in line_states: merged_state = 'ringing' elif 'progressing' in line_states: merged_state = 'progressing' elif 'holding' in line_states: merged_state = 'holding' elif 'talking' in line_states: merged_state = 'talking' elif 'available' in line_states: merged_state = 'available' else: merged_state = 'unavailable' user['line_state'] = merged_state return user @post_dump(pass_original=True) def _set_mobile(self, user, raw_user, **kwargs): for token in raw_user.refresh_tokens: if token.mobile is True: user['mobile'] = True return user for session in raw_user.sessions: if session.mobile is True: user['mobile'] = True return user user['mobile'] = False return user @post_dump(pass_original=True) def _set_connected(self, user, raw_user, **kwargs): user['connected'] = True if raw_user.sessions else False return user
class ContactSchema(BaseSchema): id = fields.Integer() name = fields.String() extensions = fields.Nested(ExtensionSchema, many=True) incalls = fields.Nested(ExtensionSchema, many=True) @pre_dump def unpack_extensions(self, data, **kwargs): extension_schema = ExtensionSchema(many=True) incalls = [] extensions = extension_schema.dump(data['extensions']) for incall in data['incalls']: incalls += extension_schema.dump(incall['extensions']) data['extensions'] = extensions data['incalls'] = incalls return data
class ContactSchema(BaseSchema): id = fields.Integer() name = fields.String() extensions = fields.Nested(ExtensionSchema, many=True) incalls = fields.Nested(ExtensionSchema, many=True) @pre_dump(pass_many=True) def unpack_extensions(self, data, many): extension_schema = ExtensionSchema(many=True) for contact in data: incalls = [] extensions = extension_schema.dump(contact['extensions']).data for incall in contact['incalls']: incalls += extension_schema.dump(incall['extensions']).data contact['extensions'] = extensions contact['incalls'] = incalls return data
class CDRSchema(Schema): id = fields.Integer() tenant_uuid = fields.UUID() start = fields.DateTime(attribute='date') end = fields.DateTime(attribute='date_end') answered = fields.Boolean(attribute='marshmallow_answered') answer = fields.DateTime(attribute='date_answer') duration = fields.TimeDelta(default=None, attribute='marshmallow_duration') call_direction = fields.String(attribute='direction') destination_extension = fields.String(attribute='destination_exten') destination_internal_context = fields.String() destination_internal_extension = fields.String( attribute='destination_internal_exten' ) destination_line_id = fields.Integer() destination_name = fields.String() destination_user_uuid = fields.UUID() requested_name = fields.String() requested_context = fields.String() requested_extension = fields.String(attribute='requested_exten') requested_internal_context = fields.String() requested_internal_extension = fields.String(attribute='requested_internal_exten') source_extension = fields.String(attribute='source_exten') source_internal_context = fields.String() source_internal_name = fields.String() source_internal_extension = fields.String(attribute='source_internal_exten') source_line_id = fields.Integer() source_name = fields.String() source_user_uuid = fields.UUID() tags = fields.List(fields.String(), attribute='marshmallow_tags') recordings = fields.Nested('RecordingSchema', many=True, default=[]) @pre_dump def _compute_fields(self, data, **kwargs): data.marshmallow_answered = True if data.date_answer else False if data.date_answer and data.date_end: data.marshmallow_duration = data.date_end - data.date_answer return data @post_dump def fix_negative_duration(self, data, **kwargs): if data['duration'] is not None: data['duration'] = max(data['duration'], 0) return data @pre_dump def _populate_tags_field(self, data, **kwargs): data.marshmallow_tags = set() for participant in data.participants: data.marshmallow_tags.update(participant.tags) return data
class MarketListResultSchema(Schema): homepage = fields.String() color = fields.String() display_name = fields.String() name = fields.String(validate=Regexp(_PLUGIN_NAME_REGEXP), required=True) namespace = fields.String(validate=Regexp(_PLUGIN_NAMESPACE_REGEXP), required=True) tags = fields.List(fields.String) author = fields.String() versions = fields.Nested(MarketVersionResultSchema, many=True, required=True, unknown=EXCLUDE) screenshots = fields.List(fields.String) icon = fields.String() description = fields.String() short_description = fields.String() license = fields.String() installed_version = fields.String(missing=None)
class TenantFullSchema(BaseSchema): uuid = fields.UUID(missing=None) parent_uuid = fields.UUID(dump_only=True) name = fields.String( validate=validate.Length(min=1, max=128), default=None, missing=None ) slug = fields.String( validate=[validate.Length(min=1, max=10), validate.Regexp(r'^[a-zA-Z0-9_]+$')], missing=None, ) contact_uuid = fields.UUID(data_key='contact', missing=None, default=None) phone = fields.String( validate=validate.Length(min=1, max=32), default=None, missing=None ) domain_names = fields.List( fields.String( validate=validate.Regexp( r'^(?=.{1,253}\.?$)(?:(?!(-|_)|[^.]+_)[A-Za-z0-9-_]{1,}(?<!-)(?:\.|$)){2,63}$' ), ), missing=[], default=[], allow_none=False, ) address = fields.Nested( TenantAddress, missing=empty_tenant_address, default=empty_tenant_address, allow_none=False, ) @post_dump def add_empty_address(self, data, **kwargs): data['address'] = data['address'] or empty_tenant_address return data @post_load def ensure_domain_names_are_unique(self, data, **kwargs): data['domain_names'] = sorted(list(set(data['domain_names']))) return data
class PluginMetadataSchema(Schema): version_fields = ['version', 'max_wazo_version', 'min_wazo_version'] current_version = None name = fields.String(validate=Regexp(_PLUGIN_NAME_REGEXP), required=True) namespace = fields.String(validate=Regexp(_PLUGIN_NAMESPACE_REGEXP), required=True) version = fields.String(required=True) plugin_format_version = fields.Integer( validate=Range(min=0, max=_MAX_PLUGIN_FORMAT_VERSION), missing=_DEFAULT_PLUGIN_FORMAT_VERSION) max_wazo_version = fields.String() min_wazo_version = fields.String() depends = fields.Nested(MarketInstallOptionsSchema, many=True, unknown=EXCLUDE) @pre_load def ensure_string_versions(self, data): for field in self.version_fields: if field not in data: continue value = data[field] if not isinstance(value, (float, int)): continue data[field] = str(value) return data def on_bind_field(self, field_name, field_obj): if field_name == 'max_wazo_version': self._set_max_wazo_version_parameters(field_obj) elif field_name == 'min_wazo_version': self._set_min_wazo_version_parameters(field_obj) def _set_max_wazo_version_parameters(self, field_obj): field_obj.validators = [Range(min=self.current_version)] def _set_min_wazo_version_parameters(self, field_obj): field_obj.validators = [Range(max=self.current_version)]
class TenantSchema(BaseSchema): uuid = xfields.UUID(missing=None) parent_uuid = xfields.UUID(dump_only=True) name = xfields.String(validate=validate.Length(min=1, max=128), default=None, missing=None) contact_uuid = xfields.UUID(data_key='contact', missing=None, default=None) phone = xfields.String(validate=validate.Length(min=1, max=32), default=None, missing=None) address = xfields.Nested( TenantAddress, missing=empty_tenant_address, default=empty_tenant_address, allow_none=False, ) @post_dump def add_empty_address(self, data): data['address'] = data['address'] or empty_tenant_address return data
class ConfigField(fields.Field): _default_options = fields.Dict(validate=validate_string_dict, allow_none=False, required=True) _options = { 'http': fields.Nested(HTTPSubscriptionConfigSchema, required=True) } def _deserialize(self, value, attr, data, **kwargs): service = data.get('service') try: concrete_options = self._options.get(service, self._default_options) except TypeError: raise ValidationError({ 'message': 'Invalid destination', 'constraint_id': 'destination-type', 'constraint': { 'type': 'string' }, }) return concrete_options.deserialize(value, attr, data, **kwargs)
class TenantSchema(BaseSchema): uuid = xfields.UUID(missing=None) parent_uuid = xfields.UUID(dump_only=True) name = xfields.String(validate=validate.Length(min=1, max=128), default=None, missing=None) contact_uuid = xfields.UUID(load_from='contact', dump_to='contact', missing=None, default=None) phone = xfields.String(validate=validate.Length(min=1, max=32), default=None, missing=None) address = xfields.Nested(TenantAddress, missing=dict, default=dict, allow_none=False) @post_dump def add_empty_address(self, data): data['address'] = data['address'] or TenantAddress().dump( data['address']).data return data
class AdminEmailPutSchema(_EmailPutSchema): emails = fields.Nested(_AdminEmailSchema, required=True, many=True)
class CDRSchemaList(Schema): items = fields.Nested(CDRSchema, many=True) total = fields.Integer() filtered = fields.Integer()
class SourceSchema(BaseSourceSchema): auth = fields.Nested(AuthConfigSchema, missing=lambda: AuthConfigSchema().load({})) confd = fields.Nested( ConfdConfigSchema, missing=lambda: ConfdConfigSchema().load({}) )
class SourceSchema(BaseSourceSchema): auth = fields.Nested(_AuthConfigSchema, missing={})
class QueueStatisticsQoSSchemaList(Schema): items = fields.Nested(QueueStatisticsQoSSchema, many=True) total = fields.Integer()
class AgentStatisticsSchemaList(Schema): items = fields.Nested(AgentStatisticsSchema, many=True) total = fields.Integer()
class QueueStatisticsQoSSchema(_StatisticsPeriodSchema): queue_id = fields.Integer(default=None) queue_name = fields.String(default=None) quality_of_service = fields.List(fields.Nested(_QoSSchema))
class ServiceSchema(BaseSchema): sources = fields.Nested(SourceSchema, many=True)
class SourceSchema(BaseSourceSchema): auth = fields.Nested( BaseAuthConfigSchema, missing=lambda: BaseAuthConfigSchema().load({}), )
class ServiceConfigSchema(BaseSchema): sources = fields.Nested(ResourceSchema, many=True, missing=[]) options = fields.Dict(missing={})
class ProfileSchema(BaseSchema): uuid = fields.UUID(dump_only=True) tenant_uuid = fields.UUID(dump_only=True) name = fields.String() display = fields.Nested(DisplaySchema) services = ServiceDictSchema(BaseSchema, required=True)
class UserEmailPutSchema(_EmailPutSchema): emails = fields.Nested(_UserEmailSchema, required=True, many=True)