class OutcallSchema(BaseSchema): id = fields.Integer(dump_only=True) tenant_uuid = fields.String(dump_only=True) name = fields.String(validate=Length(max=128), required=True) internal_caller_id = StrictBoolean() preprocess_subroutine = fields.String(validate=Length(max=39), allow_none=True) ring_time = fields.Integer(validate=Range(min=0), allow_none=True) description = fields.String(allow_none=True) enabled = StrictBoolean() links = ListLink(Link('outcalls')) trunks = Nested( 'TrunkSchema', only=['tenant_uuid', 'id', 'endpoint_sip', 'endpoint_custom', 'links'], many=True, dump_only=True, ) extensions = Nested('DialPatternSchema', attribute='dialpatterns', many=True, dump_only=True) schedules = Nested( 'ScheduleSchema', only=['tenant_uuid', 'id', 'name', 'links'], many=True, dump_only=True, ) call_permissions = Nested( 'CallPermissionSchema', only=['tenant_uuid', 'id', 'name', 'links'], many=True, dump_only=True, )
class VoicemailSchema(BaseSchema): id = fields.Integer(dump_only=True) tenant_uuid = fields.String(dump_only=True) name = fields.String(validate=Length(max=80), required=True) number = fields.String(validate=Regexp(NUMBER_REGEX), required=True) context = fields.String(required=True) password = fields.String(validate=Regexp(PASSWORD_REGEX), allow_none=True) email = fields.String(validate=Length(max=80), allow_none=True) language = fields.String(validate=Regexp(LANGUAGE_REGEX), allow_none=True) timezone = fields.String(allow_none=True) pager = fields.String(validate=Length(max=80), allow_none=True) max_messages = fields.Integer(validate=Range(min=0), allow_none=True) attach_audio = StrictBoolean(allow_none=True) delete_messages = StrictBoolean() ask_password = StrictBoolean() enabled = StrictBoolean() options = fields.List( fields.List(fields.String(), validate=Length(equal=2))) links = ListLink(Link('voicemails')) users = Nested( 'UserSchema', only=['uuid', 'firstname', 'lastname', 'links'], many=True, dump_only=True, )
class TrunkSchema(BaseSchema): id = fields.Integer(dump_only=True) tenant_uuid = fields.String(dump_only=True) context = fields.String(allow_none=True) twilio_incoming = StrictBoolean(allow_none=True) links = ListLink(Link('trunks')) endpoint_sip = fields.Nested('SipSchema', only=['id', 'username', 'links'], dump_only=True) endpoint_custom = fields.Nested('CustomSchema', only=['id', 'interface', 'links'], dump_only=True) endpoint_iax = fields.Nested('IAXSchema', only=['id', 'name', 'links'], dump_only=True) outcalls = fields.Nested('OutcallSchema', only=['id', 'name', 'links'], many=True, dump_only=True) register_iax = fields.Nested('RegisterIAXSchema', only=['id', 'links'], dump_only=True) register_sip = fields.Nested('RegisterSIPSchema', only=['id', 'links'], dump_only=True)
class TrunkSchema(BaseSchema): id = fields.Integer(dump_only=True) tenant_uuid = fields.String(dump_only=True) context = fields.String(allow_none=True) twilio_incoming = StrictBoolean(allow_none=True) links = ListLink(Link('trunks')) endpoint_sip = Nested( 'EndpointSIPSchema', only=[ 'uuid', 'label', 'name', 'auth_section_options.username', 'registration_section_options.client_uri', 'links', ], dump_only=True, ) endpoint_custom = Nested( 'CustomSchema', only=['id', 'interface', 'links'], dump_only=True ) endpoint_iax = Nested('IAXSchema', only=['id', 'name', 'links'], dump_only=True) outcalls = Nested( 'OutcallSchema', only=['id', 'name', 'links'], many=True, dump_only=True ) register_iax = Nested('RegisterIAXSchema', only=['id', 'links'], dump_only=True)
class VoicemailDestinationSchema(BaseDestinationSchema): voicemail_id = fields.Integer(attribute='actionarg1', required=True) skip_instructions = StrictBoolean() greeting = fields.String(validate=OneOf(['busy', 'unavailable']), allow_none=True) voicemail = fields.Nested('VoicemailSchema', only=['name'], dump_only=True) @pre_dump def separate_action(self, data): options = data.actionarg2 if data.actionarg2 else '' data.skip_instructions = True if 's' in options else False data.greeting = ('busy' if 'b' in options else 'unavailable' if 'u' in options else None) return data @post_load def merge_action(self, data): greeting = data.pop('greeting', None) data['actionarg2'] = '{}{}'.format( 'b' if greeting == 'busy' else 'u' if greeting == 'unavailable' else '', 's' if data.pop('skip_instructions', False) else '', ) return data @post_dump def make_voicemail_fields_flat(self, data): if data.get('voicemail'): data['voicemail_name'] = data['voicemail']['name'] data.pop('voicemail', None) return data
class CallPermissionSchema(BaseSchema): id = fields.Integer(dump_only=True) tenant_uuid = fields.String(dump_only=True) name = fields.String(validate=Length(min=1, max=128), required=True) password = fields.String(validate=Regexp(PASSWORD_REGEX), allow_none=True) mode = fields.String(validate=OneOf(['allow', 'deny'])) extensions = fields.List(fields.String(validate=Regexp(EXTENSION_REGEX))) enabled = StrictBoolean() description = fields.String(allow_none=True) links = ListLink(Link('callpermissions')) outcalls = Nested('OutcallSchema', only=['id', 'name', 'links'], many=True, dump_only=True) groups = Nested('GroupSchema', only=['uuid', 'id', 'name', 'links'], many=True, dump_only=True) users = Nested( 'UserSchema', only=['uuid', 'firstname', 'lastname', 'links'], many=True, dump_only=True, )
class ForwardUnconditionalSchema(BaseSchema): enabled = StrictBoolean(attribute='unconditional_enabled') destination = fields.String(attribute='unconditional_destination', validate=Length(max=128), allow_none=True) types = ['unconditional']
class ForwardNoAnswerSchema(BaseSchema): enabled = StrictBoolean(attribute='noanswer_enabled') destination = fields.String(attribute='noanswer_destination', validate=Length(max=128), allow_none=True) types = ['noanswer']
class ForwardBusySchema(BaseSchema): enabled = StrictBoolean(attribute='busy_enabled') destination = fields.String(attribute='busy_destination', validate=Length(max=128), allow_none=True) types = ['busy']
class CustomSchema(BaseSchema): id = fields.Integer(dump_only=True) tenant_uuid = fields.String(dump_only=True) interface = fields.String(validate=Regexp(INTERFACE_REGEX), required=True) interface_suffix = fields.String(validate=Length(max=32), allow_none=True) enabled = StrictBoolean() links = ListLink(Link('endpoint_custom')) trunk = Nested('TrunkSchema', only=['id', 'links'], dump_only=True) line = Nested('LineSchema', only=['id', 'links'], dump_only=True)
class WizardSchema(BaseSchema): xivo_uuid = fields.UUID(dump_only=True) admin_username = fields.Constant(constant='root', dump_only=True) admin_password = fields.String(validate=Regexp(ADMIN_PASSWORD_REGEX), required=True) license = StrictBoolean(validate=Equal(True), required=True) language = fields.String(validate=OneOf(['en_US', 'fr_FR']), missing='en_US') timezone = fields.String(validate=Length(max=128), required=True) network = Nested(WizardNetworkSchema, required=True) steps = Nested(WizardStepsSchema, missing=WizardStepsSchema().load({}))
class UserSummarySchema(BaseSchema): id = fields.Integer() uuid = fields.String() firstname = fields.String() lastname = fields.String() email = fields.String() extension = fields.String() context = fields.String() provisioning_code = fields.String() protocol = fields.String() enabled = StrictBoolean()
class ContextSchema(BaseSchema): id = fields.Integer(dump_only=True) name = fields.String( validate=( Regexp(CONTEXT_REGEX), Length(min=1, max=39), NoneOf( [ 'authentication', 'general', 'global', 'globals', 'parkedcalls', 'xivo-features', 'zonemessages', ] ), ), required=True, ) label = fields.String(validate=Length(max=128), allow_none=True) type = fields.String( validate=OneOf(['internal', 'incall', 'outcall', 'services', 'others']) ) user_ranges = Nested(RangeSchema, many=True) group_ranges = Nested(RangeSchema, many=True) queue_ranges = Nested(RangeSchema, many=True) conference_room_ranges = Nested(RangeSchema, many=True) incall_ranges = Nested(IncallRangeSchema, many=True) description = fields.String(allow_none=True) tenant_uuid = fields.String(dump_only=True) enabled = StrictBoolean() links = ListLink(Link('contexts')) contexts = Nested( 'ContextSchema', only=['id', 'name', 'label', 'links'], many=True, dump_only=True, ) @post_load def create_objects(self, data, **kwargs): for key in [ 'user_ranges', 'group_ranges', 'queue_ranges', 'conference_room_ranges', 'incall_ranges', ]: if data.get(key): data[key] = [ContextNumbers(**d) for d in data[key]] return data
class SoundDestinationSchema(BaseDestinationSchema): filename = fields.String(validate=Length(max=255), attribute='actionarg1', required=True) skip = StrictBoolean() no_answer = StrictBoolean() @pre_dump def separate_action(self, data): options = data.actionarg2 if data.actionarg2 else '' data.skip = True if 'skip' in options else False data.no_answer = True if 'noanswer' in options else False return data @post_load def merge_action(self, data): data['actionarg2'] = '{skip}{noanswer}'.format( skip='skip' if data.pop('skip', False) else '', noanswer='noanswer' if data.pop('no_answer', False) else '', ) return data
class DeviceSchema(BaseSchema): id = fields.String(dump_only=True) status = fields.String(dump_only=True) tenant_uuid = fields.String(dump_only=True) is_new = StrictBoolean(dump_only=True) ip = fields.String(validate=Regexp(IP_REGEX), allow_none=True) mac = fields.String(validate=Regexp(MAC_REGEX), allow_none=True) sn = fields.String(allow_none=True) plugin = fields.String(allow_none=True) vendor = fields.String(allow_none=True) model = fields.String(allow_none=True) version = fields.String(allow_none=True) description = fields.String(allow_none=True) template_id = fields.String(allow_none=True) options = Nested(DeviceOptionsSchema, allow_none=True) links = ListLink(Link('devices'))
class CallFilterSchema(BaseSchema): id = fields.Integer(dump_only=True) tenant_uuid = fields.String(dump_only=True) name = fields.String(validate=Length(max=128), required=True) strategy = fields.String( validate=OneOf([ 'all-recipients-then-linear-surrogates', 'all-recipients-then-all-surrogates', 'all-surrogates-then-all-recipients', 'linear-surrogates-then-all-recipients', 'all', ]), required=True, ) source = fields.String( validate=OneOf(['internal', 'external', 'all']), attribute='callfrom', required=True, ) caller_id_mode = fields.String(validate=OneOf( ['prepend', 'overwrite', 'append']), allow_none=True) caller_id_name = fields.String(validate=Length(max=80), allow_none=True) surrogates_timeout = fields.Integer(validate=Range(min=0), allow_none=True) description = fields.String(allow_none=True) enabled = StrictBoolean() links = ListLink(Link('callfilters')) recipients = fields.Nested('CallFilterRecipientsSchema', many=True, dump_only=True) surrogates = fields.Nested('CallFilterSurrogatesSchema', many=True, dump_only=True) fallbacks = fields.Nested('CallFilterFallbackSchema', dump_only=True) @post_dump def wrap_users(self, data): recipient_users = data.pop('recipients', []) surrogate_users = data.pop('surrogates', []) if not self.only or 'recipients' in self.only: data['recipients'] = {'users': recipient_users} if not self.only or 'surrogates' in self.only: data['surrogates'] = {'users': surrogate_users} return data
class CallPickupSchema(BaseSchema): id = fields.Integer(dump_only=True) tenant_uuid = fields.String(dump_only=True) name = fields.String(validate=Length(max=128), required=True) description = fields.String(allow_none=True) enabled = StrictBoolean() links = ListLink(Link('callpickups')) group_interceptors = Nested('GroupSchema', only=['id', 'name'], many=True, dump_only=True) group_targets = Nested('GroupSchema', only=['id', 'name'], many=True, dump_only=True) user_interceptors = Nested('UserSchema', only=['uuid', 'firstname', 'lastname'], many=True, dump_only=True) user_targets = Nested('UserSchema', only=['uuid', 'firstname', 'lastname'], many=True, dump_only=True) @post_dump def wrap_users(self, data, **kwargs): interceptor_groups = data.pop('group_interceptors', []) interceptor_users = data.pop('user_interceptors', []) target_groups = data.pop('group_targets', []) target_users = data.pop('user_targets', []) if not self.only or 'interceptors' in self.only: data['interceptors'] = { 'groups': interceptor_groups, 'users': interceptor_users, } if not self.only or 'targets' in self.only: data['targets'] = {'groups': target_groups, 'users': target_users} return data
class GroupSchema(BaseSchema): id = fields.Integer(dump_only=True) uuid = fields.String(dump_only=True) tenant_uuid = fields.String(dump_only=True) name = fields.String(dump_only=True) label = fields.String(validate=[Length(max=128), Regexp(LABEL_REGEX)], required=True) preprocess_subroutine = fields.String(validate=Length(max=39), allow_none=True) ring_strategy = fields.String(validate=OneOf([ 'all', 'random', 'least_recent', 'linear', # Issue when editing to this value: ASTERISK-17049 'fewest_calls', 'memorized_round_robin', 'weight_random', ])) caller_id_mode = fields.String(validate=OneOf( ['prepend', 'overwrite', 'append']), allow_none=True) caller_id_name = fields.String(validate=Length(max=80), allow_none=True) timeout = fields.Integer(validate=Range(min=0), allow_none=True) user_timeout = fields.Integer(validate=Range(min=0), allow_none=True) retry_delay = fields.Integer(validate=Range(min=0), allow_none=True) music_on_hold = fields.String(validate=Length(max=128), allow_none=True) ring_in_use = StrictBoolean() mark_answered_elsewhere = StrictBoolean( attribute='mark_answered_elsewhere_bool') enabled = StrictBoolean() links = ListLink(Link('groups', field='uuid')) extensions = Nested( 'ExtensionSchema', only=['id', 'exten', 'context', 'links'], many=True, dump_only=True, ) fallbacks = Nested('GroupFallbackSchema', dump_only=True) incalls = Nested('IncallSchema', only=['id', 'extensions', 'links'], many=True, dump_only=True) user_queue_members = Nested('GroupUsersMemberSchema', many=True, dump_only=True) extension_queue_members = Nested('GroupExtensionsMemberSchema', many=True, dump_only=True) schedules = Nested('ScheduleSchema', only=['id', 'name', 'links'], many=True, dump_only=True) call_permissions = Nested('CallPermissionSchema', only=['id', 'name', 'links'], many=True, dump_only=True) # DEPRECATED 21.04 @pre_load def copy_name_to_label(self, data, **kwargs): if 'label' in data: return data if 'name' in data: logger.warning( 'the "name" field of groups is deprecated. use "label" instead' ) data['label'] = data['name'] return data @post_dump def convert_ring_strategy_to_user(self, data, **kwargs): ring_strategy = data.get('ring_strategy', None) if ring_strategy == 'ringall': data['ring_strategy'] = 'all' elif ring_strategy == 'leastrecent': data['ring_strategy'] = 'least_recent' elif ring_strategy == 'fewestcalls': data['ring_strategy'] = 'fewest_calls' elif ring_strategy == 'rrmemory': data['ring_strategy'] = 'memorized_round_robin' elif ring_strategy == 'wrandom': data['ring_strategy'] = 'weight_random' return data @post_dump def wrap_users_member(self, data, **kwargs): users_member = data.pop('user_queue_members', []) extensions_member = data.pop('extension_queue_members', []) if not self.only or 'members' in self.only: data['members'] = { 'users': users_member, 'extensions': extensions_member } return data @post_load def convert_ring_strategy_to_database(self, data, **kwargs): ring_strategy = data.get('ring_strategy', None) if ring_strategy == 'all': data['ring_strategy'] = 'ringall' elif ring_strategy == 'least_recent': data['ring_strategy'] = 'leastrecent' elif ring_strategy == 'fewest_calls': data['ring_strategy'] = 'fewestcalls' elif ring_strategy == 'memorized_round_robin': data['ring_strategy'] = 'rrmemory' elif ring_strategy == 'weight_random': data['ring_strategy'] = 'wrandom' return data
class GroupSchema(BaseSchema): id = fields.Integer(dump_only=True) tenant_uuid = fields.String(dump_only=True) name = fields.String( validate=(Regexp(NAME_REGEX), NoneOf(['general']), Length(max=128)), required=True, ) preprocess_subroutine = fields.String(validate=Length(max=39), allow_none=True) ring_strategy = fields.String(validate=OneOf([ 'all', 'random', 'least_recent', 'linear', # Issue when editing to this value: ASTERISK-17049 'fewest_calls', 'memorized_round_robin', 'weight_random', ])) caller_id_mode = fields.String(validate=OneOf( ['prepend', 'overwrite', 'append']), allow_none=True) caller_id_name = fields.String(validate=Length(max=80), allow_none=True) timeout = fields.Integer(validate=Range(min=0), allow_none=True) user_timeout = fields.Integer(validate=Range(min=0), allow_none=True) retry_delay = fields.Integer(validate=Range(min=0), allow_none=True) music_on_hold = fields.String(validate=Length(max=128), allow_none=True) ring_in_use = StrictBoolean() enabled = StrictBoolean() links = ListLink(Link('groups')) extensions = fields.Nested( 'ExtensionSchema', only=['id', 'exten', 'context', 'links'], many=True, dump_only=True, ) fallbacks = fields.Nested('GroupFallbackSchema', dump_only=True) incalls = fields.Nested('IncallSchema', only=['id', 'extensions', 'links'], many=True, dump_only=True) user_queue_members = fields.Nested('GroupUsersMemberSchema', many=True, dump_only=True) extension_queue_members = fields.Nested('GroupExtensionsMemberSchema', many=True, dump_only=True) schedules = fields.Nested('ScheduleSchema', only=['id', 'name', 'links'], many=True, dump_only=True) call_permissions = fields.Nested('CallPermissionSchema', only=['id', 'name', 'links'], many=True, dump_only=True) @post_dump def convert_ring_strategy_to_user(self, data): ring_strategy = data.get('ring_strategy', None) if ring_strategy == 'ringall': data['ring_strategy'] = 'all' elif ring_strategy == 'leastrecent': data['ring_strategy'] = 'least_recent' elif ring_strategy == 'fewestcalls': data['ring_strategy'] = 'fewest_calls' elif ring_strategy == 'rrmemory': data['ring_strategy'] = 'memorized_round_robin' elif ring_strategy == 'wrandom': data['ring_strategy'] = 'weight_random' return data @post_dump def wrap_users_member(self, data): users_member = data.pop('user_queue_members', []) extensions_member = data.pop('extension_queue_members', []) if not self.only or 'members' in self.only: data['members'] = { 'users': users_member, 'extensions': extensions_member } return data @post_load def convert_ring_strategy_to_database(self, data): ring_strategy = data.get('ring_strategy', None) if ring_strategy == 'all': data['ring_strategy'] = 'ringall' elif ring_strategy == 'least_recent': data['ring_strategy'] = 'leastrecent' elif ring_strategy == 'fewest_calls': data['ring_strategy'] = 'fewestcalls' elif ring_strategy == 'memorized_round_robin': data['ring_strategy'] = 'rrmemory' elif ring_strategy == 'weight_random': data['ring_strategy'] = 'wrandom' return data
class ServiceIncallFilterSchema(BaseSchema): enabled = StrictBoolean(attribute='incallfilter_enabled', required=True) types = ['incallfilter']
class ServiceDNDSchema(BaseSchema): enabled = StrictBoolean(attribute='dnd_enabled', required=True) types = ['dnd']
class UserSchema(BaseSchema): id = fields.Integer(dump_only=True) uuid = fields.String(dump_only=True) firstname = fields.String(validate=Length(max=128), required=True) lastname = fields.String(validate=Length(max=128), allow_none=True) email = fields.Email(validate=Length(max=254), allow_none=True) timezone = fields.String(validate=Length(max=128), allow_none=True) language = fields.String(validate=Regexp(LANGUAGE_REGEX), allow_none=True) description = fields.String(allow_none=True) caller_id = fields.String(validate=(Regexp(CALLER_ID_REGEX), Length(max=160))) outgoing_caller_id = fields.String(validate=Length(max=80), allow_none=True) mobile_phone_number = fields.String( validate=(Regexp(MOBILE_PHONE_NUMBER_REGEX), Length(max=80)), allow_none=True) username = fields.String(validate=Regexp(USERNAME_REGEX), allow_none=True) password = fields.String(validate=Regexp(PASSWORD_REGEX), allow_none=True) music_on_hold = fields.String(validate=Length(max=128), allow_none=True) preprocess_subroutine = fields.String(validate=Length(max=39), allow_none=True) userfield = fields.String(validate=Length(max=128), allow_none=True) call_transfer_enabled = StrictBoolean() dtmf_hangup_enabled = StrictBoolean() call_record_enabled = StrictBoolean() call_record_outgoing_external_enabled = StrictBoolean() call_record_outgoing_internal_enabled = StrictBoolean() call_record_incoming_internal_enabled = StrictBoolean() call_record_incoming_external_enabled = StrictBoolean() online_call_record_enabled = StrictBoolean() supervision_enabled = StrictBoolean() ring_seconds = fields.Integer(validate=Range(min=0, max=10800)) simultaneous_calls = fields.Integer(validate=Range(min=1, max=20)) call_permission_password = fields.String( validate=Regexp(CALL_PERMISSION_PASSWORD_REGEX), allow_none=True) subscription_type = fields.Integer(validate=Range(min=0, max=10)) created_at = fields.DateTime(dump_only=True) enabled = StrictBoolean() tenant_uuid = fields.String(dump_only=True) links = ListLink(Link('users')) agent = Nested('AgentSchema', only=['id', 'number', 'links'], dump_only=True) call_permissions = Nested('CallPermissionSchema', only=['id', 'name', 'links'], many=True, dump_only=True) call_pickup_user_targets_flat = Nested( 'UserSchema', only=['uuid', 'firstname', 'lastname', 'links'], many=True, dump_only=True, ) fallbacks = Nested('UserFallbackSchema', dump_only=True) groups = Nested('GroupSchema', only=['uuid', 'id', 'name', 'links'], many=True, dump_only=True) incalls = Nested('IncallSchema', only=['id', 'extensions', 'links'], many=True, dump_only=True) lines = Nested( 'LineSchema', only=[ 'id', 'name', 'endpoint_sip', 'endpoint_sccp', 'endpoint_custom', 'extensions', 'links', ], many=True, dump_only=True, ) forwards = Nested('ForwardsSchema', dump_only=True) schedules = Nested('ScheduleSchema', only=['id', 'name', 'links'], many=True, dump_only=True) services = Nested('ServicesSchema', dump_only=True) switchboards = Nested('SwitchboardSchema', only=['uuid', 'name', 'links'], many=True, dump_only=True) voicemail = Nested('VoicemailSchema', only=['id', 'name', 'links'], dump_only=True) queues = Nested('QueueSchema', only=['id', 'name', 'label', 'links'], many=True, dump_only=True) @pre_dump def flatten_call_pickup_targets(self, data, **kwargs): if self.only and 'call_pickup_target_users' not in self.only: return data all_ = [ list(data.users_from_call_pickup_group_interceptors_user_targets), list(data.users_from_call_pickup_group_interceptors_group_targets), list(data.users_from_call_pickup_user_targets), list(data.users_from_call_pickup_group_targets), ] data.call_pickup_user_targets_flat = list(set(self._flatten(all_))) return data @post_dump def format_call_pickup_targets(self, data, **kwargs): if not self.only or 'call_pickup_target_users' in self.only: call_pickup_user_targets = data.pop( 'call_pickup_user_targets_flat', []) data['call_pickup_target_users'] = call_pickup_user_targets return data @classmethod def _flatten(cls, iterable_of_iterable): for item in iterable_of_iterable: try: itercheck = iter(item) yield from cls._flatten(itercheck) except TypeError: yield item # DEPRECATED 20.01 @validates_schema def validate_schema(self, data, **kwargs): call_record_any_enabled = any(( data.get('call_record_outgoing_external_enabled') is not None, data.get('call_record_outgoing_internal_enabled') is not None, data.get('call_record_incoming_external_enabled') is not None, data.get('call_record_incoming_internal_enabled') is not None, )) deprecated_call_record_enabled = data.get( 'call_record_enabled') is not None if deprecated_call_record_enabled and call_record_any_enabled: raise ValidationError( "'call_record_enabled' is deprecated and incompatible with 'call_record_*_enabled' options" ) # DEPRECATED 20.01 @post_dump def dump_call_record_enable_deprecated(self, data, **kwargs): if self.only and 'call_record_enabled' not in self.only: return data call_record_all_enabled = all(( data.get('call_record_outgoing_external_enabled'), data.get('call_record_outgoing_internal_enabled'), data.get('call_record_incoming_external_enabled'), data.get('call_record_incoming_internal_enabled'), )) data['call_record_enabled'] = call_record_all_enabled return data # DEPRECATED 20.01 @post_load def load_call_record_enable_deprecated(self, data, **kwargs): call_record_enabled = data.pop('call_record_enabled', None) if call_record_enabled is None: return data if call_record_enabled: data['call_record_outgoing_external_enabled'] = True data['call_record_outgoing_internal_enabled'] = True data['call_record_incoming_external_enabled'] = True data['call_record_incoming_internal_enabled'] = True else: data['call_record_outgoing_external_enabled'] = False data['call_record_outgoing_internal_enabled'] = False data['call_record_incoming_external_enabled'] = False data['call_record_incoming_internal_enabled'] = False return data
class UserSchema(BaseSchema): id = fields.Integer(dump_only=True) uuid = fields.String(dump_only=True) firstname = fields.String(validate=Length(max=128), required=True) lastname = fields.String(validate=Length(max=128), allow_none=True) email = fields.Email(validate=Length(max=254), allow_none=True) timezone = fields.String(validate=Length(max=128), allow_none=True) language = fields.String(validate=Regexp(LANGUAGE_REGEX), allow_none=True) description = fields.String(allow_none=True) caller_id = fields.String(validate=(Regexp(CALLER_ID_REGEX), Length(max=160))) outgoing_caller_id = fields.String(validate=Length(max=80), allow_none=True) mobile_phone_number = fields.String( validate=(Regexp(MOBILE_PHONE_NUMBER_REGEX), Length(max=80)), allow_none=True) username = fields.String(validate=Regexp(USERNAME_REGEX), allow_none=True) password = fields.String(validate=Regexp(PASSWORD_REGEX), allow_none=True) music_on_hold = fields.String(validate=Length(max=128), allow_none=True) preprocess_subroutine = fields.String(validate=Length(max=39), allow_none=True) userfield = fields.String(validate=Length(max=128), allow_none=True) call_transfer_enabled = StrictBoolean() dtmf_hangup_enabled = StrictBoolean() call_record_enabled = StrictBoolean() online_call_record_enabled = StrictBoolean() supervision_enabled = StrictBoolean() ring_seconds = fields.Integer(validate=Range(min=0, max=60)) simultaneous_calls = fields.Integer(validate=Range(min=1, max=20)) call_permission_password = fields.String( validate=Regexp(CALL_PERMISSION_PASSWORD_REGEX), allow_none=True) subscription_type = fields.Integer(validate=Range(min=0, max=10)) created_at = fields.DateTime(dump_only=True) enabled = StrictBoolean() tenant_uuid = fields.String(dump_only=True) links = ListLink(Link('users')) agent = fields.Nested('AgentSchema', only=['id', 'number', 'links'], dump_only=True) call_permissions = fields.Nested('CallPermissionSchema', only=['id', 'name', 'links'], many=True, dump_only=True) fallbacks = fields.Nested('UserFallbackSchema', dump_only=True) groups = fields.Nested('GroupSchema', only=['id', 'name', 'links'], many=True, dump_only=True) incalls = fields.Nested('IncallSchema', only=['id', 'extensions', 'links'], many=True, dump_only=True) lines = fields.Nested( 'LineSchema', only=[ 'id', 'name', 'endpoint_sip', 'endpoint_sccp', 'endpoint_custom', 'extensions', 'links', ], many=True, dump_only=True, ) forwards = fields.Nested('ForwardsSchema', dump_only=True) schedules = fields.Nested('ScheduleSchema', only=['id', 'name', 'links'], many=True, dump_only=True) services = fields.Nested('ServicesSchema', dump_only=True) switchboards = fields.Nested('SwitchboardSchema', only=['uuid', 'name', 'links'], many=True, dump_only=True) voicemail = fields.Nested('VoicemailSchema', only=['id', 'name', 'links'], dump_only=True) queues = fields.Nested('QueueSchema', only=['id', 'name', 'label', 'links'], many=True, dump_only=True)
class FuncKeySchema(BaseSchema): id = fields.Integer(dump_only=True) inherited = fields.Boolean(dump_only=True) blf = StrictBoolean() label = fields.String(allow_none=True) destination = FuncKeyDestinationField(BaseDestinationSchema, required=True)
class QueueSchema(BaseSchema): id = fields.Integer(dump_only=True) tenant_uuid = fields.String(dump_only=True) name = fields.String( validate=(Regexp(NAME_REGEX), NoneOf(['general']), Length(max=128)), required=True, ) label = fields.String(validate=Length(max=128), missing=None) data_quality = StrictBoolean(attribute='data_quality_bool') dtmf_hangup_callee_enabled = StrictBoolean() dtmf_hangup_caller_enabled = StrictBoolean() dtmf_transfer_callee_enabled = StrictBoolean() dtmf_transfer_caller_enabled = StrictBoolean() dtmf_record_callee_enabled = StrictBoolean() dtmf_record_caller_enabled = StrictBoolean() retry_on_timeout = StrictBoolean() ring_on_hold = StrictBoolean() timeout = fields.Integer(validate=Range(min=0), allow_none=True) announce_hold_time_on_entry = StrictBoolean() ignore_forward = StrictBoolean(attribute='ignore_forward_bool') preprocess_subroutine = fields.String(validate=Length(max=39), allow_none=True) music_on_hold = fields.String(validate=Length(max=128), allow_none=True) wait_time_threshold = fields.Integer(validate=Range(min=0), allow_none=True) wait_time_destination = DestinationField(allow_none=True) wait_ratio_threshold = fields.Float(validate=Range(min=0), allow_none=True) wait_ratio_destination = DestinationField(allow_none=True) caller_id_mode = fields.String(validate=OneOf( ['prepend', 'overwrite', 'append']), allow_none=True) caller_id_name = fields.String(validate=Length(max=80), allow_none=True) enabled = StrictBoolean() options = fields.List( fields.List(fields.String(), validate=Length(equal=2))) links = ListLink(Link('queues')) extensions = fields.Nested( 'ExtensionSchema', only=['id', 'exten', 'context', 'links'], many=True, dump_only=True, ) schedules = fields.Nested('ScheduleSchema', only=['id', 'name', 'links'], many=True, dump_only=True) agent_queue_members = fields.Nested('QueueAgentQueueMembersSchema', many=True, dump_only=True) user_queue_members = fields.Nested('QueueUserQueueMembersSchema', many=True, dump_only=True) @post_load def create_objects(self, data): for key in ('wait_time_destination', 'wait_ratio_destination'): if data.get(key): data[key] = Dialaction(**data[key]) return data @post_dump def wrap_members(self, data): if not self.only or 'members' in self.only: data['members'] = { 'agents': data.pop('agent_queue_members', []), 'users': data.pop('user_queue_members', []), } return data
class LiveReloadSchema(BaseSchema): enabled = StrictBoolean(required=True)
class DeviceOptionsSchema(BaseSchema): switchboard = StrictBoolean()
class RegisterIAXSchema(BaseSchema): id = fields.Integer(dump_only=True) auth_username = fields.String(validate=Regexp(INVALID_CHAR), allow_none=True) auth_password = fields.String(validate=Regexp(INVALID_CHAR), allow_none=True) remote_host = fields.String(validate=Regexp(INVALID_REMOTE_HOST), required=True) remote_port = fields.Integer(validate=Range(min=0, max=65535), allow_none=True) callback_extension = fields.String( validate=Regexp(INVALID_CALLBACK_EXTENSION), allow_none=True) callback_context = fields.String(allow_none=True) enabled = StrictBoolean(missing=True) links = ListLink(Link('register_iax')) trunk = fields.Nested('TrunkSchema', only=['id', 'links'], dump_only=True) @validates_schema def validate_auth_username(self, data): if data.get('auth_username') and not data.get('auth_password'): raise ValidationError( 'Cannot set field "auth_username" if the field "auth_password" is not set', 'auth_username', ) @validates_schema def validate_callback_context(self, data): if data.get('callback_context') and not data.get('callback_extension'): raise ValidationError( 'Cannot set field "callback_context" if the field "callback_extension" is not set', 'callback_context', ) @validates_schema def validate_total_length(self, data): if len(self.convert_to_chaniax(data)['var_val']) > 255: raise ValidationError( 'The sum of all fields is longer than maximum length 255') @post_load def convert_to_chaniax(self, data): chaniax_fmt = ( '{auth_username}{auth_password}{separator}' '{remote_host}{remote_port}{callback_extension}{callback_context}') data['var_val'] = chaniax_fmt.format( auth_username=data.get('auth_username') if data.get('auth_username') else '', auth_password='******'.format(data.get('auth_password')) if data.get('auth_password') else '', separator='@' if data.get('auth_username') or data.get('auth_password') else '', remote_host=data.get('remote_host'), remote_port=':{}'.format(data.get('remote_port')) if data.get('remote_port') else '', callback_extension='/{}'.format(data.get('callback_extension')) if data.get('callback_extension') else '', callback_context='?{}'.format(data.get('callback_context')) if data.get('callback_context') else '', ) return data @pre_dump def convert_from_chaniax(self, data): register = REGISTER_REGEX.match(data.var_val) result = register.groupdict() result['id'] = data.id result['enabled'] = data.enabled result['trunk'] = data.trunk return result