예제 #1
0
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)
예제 #2
0
class WizardDiscoverSchema(BaseSchema):
    hostname = fields.String()
    nameservers = fields.List(fields.String())
    domain = fields.String()
    timezone = fields.String()
    interfaces = fields.List(Nested(WizardDiscoverInterfaceSchema))
    gateways = fields.List(Nested(WizardDiscoverGatewaySchema))
예제 #3
0
class AgentSchema(BaseSchema):
    id = fields.Integer(dump_only=True)
    tenant_uuid = fields.String(dump_only=True)
    number = fields.String(validate=Regexp(NUMBER_REGEX), required=True)
    firstname = fields.String(validate=Length(max=128), allow_none=True)
    lastname = fields.String(validate=Length(max=128), allow_none=True)
    password = fields.String(validate=Length(max=128),
                             allow_none=True,
                             attribute='passwd')
    language = fields.String(validate=Length(max=20), allow_none=True)
    preprocess_subroutine = fields.String(validate=Length(max=39),
                                          allow_none=True)
    description = fields.String(allow_none=True)
    links = ListLink(Link('agents'))

    queues = Nested(
        'AgentQueuesMemberSchema',
        attribute='queue_queue_members',
        many=True,
        dump_only=True,
    )
    skills = Nested('AgentSkillsSchema',
                    attribute='agent_queue_skills',
                    many=True,
                    dump_only=True)
    users = Nested(
        'UserSchema',
        only=['uuid', 'firstname', 'lastname', 'links'],
        many=True,
        dump_only=True,
    )
예제 #4
0
class SwitchboardSchema(BaseSchema):
    uuid = fields.UUID(dump_only=True)
    tenant_uuid = fields.String(dump_only=True)
    name = fields.String(validate=Length(max=128), required=True)
    timeout = fields.Integer(validate=Range(min=1), allow_none=True)
    queue_music_on_hold = fields.String(validate=Length(max=128), allow_none=True)
    waiting_room_music_on_hold = fields.String(
        validate=Length(max=128), allow_none=True
    )
    links = ListLink(Link('switchboards', field='uuid'))
    extensions = Nested(
        'ExtensionSchema',
        only=['id', 'exten', 'context', 'links'],
        many=True,
        dump_only=True,
    )
    incalls = Nested(
        'IncallSchema', only=['id', 'extensions', 'links'], many=True, dump_only=True
    )

    user_members = Nested(
        'UserSchema',
        only=['uuid', 'firstname', 'lastname', 'links'],
        many=True,
        dump_only=True,
    )
    fallbacks = Nested('SwitchboardFallbackSchema', dump_only=True)

    @post_dump
    def wrap_users(self, data, **kwargs):
        user_members = data.pop('user_members', [])
        if not self.only or 'members' in self.only:
            data['members'] = {'users': user_members}
        return data
예제 #5
0
class ConferenceSchema(BaseSchema):
    id = fields.Integer(dump_only=True)
    tenant_uuid = fields.String(dump_only=True)
    name = fields.String(allow_none=True, validate=Length(max=128))
    preprocess_subroutine = fields.String(allow_none=True,
                                          validate=Length(max=39))
    max_users = fields.Integer(validate=Range(min=0))
    record = fields.Boolean()
    pin = fields.String(allow_none=True,
                        validate=(Length(max=80), Predicate('isdigit')))
    admin_pin = fields.String(allow_none=True,
                              validate=(Length(max=80), Predicate('isdigit')))
    quiet_join_leave = fields.Boolean()
    announce_join_leave = fields.Boolean()
    announce_user_count = fields.Boolean()
    announce_only_user = fields.Boolean()
    music_on_hold = fields.String(allow_none=True, validate=Length(max=128))
    links = ListLink(Link('conferences'))

    extensions = Nested(
        'ExtensionSchema',
        only=['id', 'exten', 'context', 'links'],
        many=True,
        dump_only=True,
    )
    incalls = Nested('IncallSchema',
                     only=['id', 'extensions', 'links'],
                     many=True,
                     dump_only=True)
예제 #6
0
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,
    )
예제 #7
0
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,
    )
예제 #8
0
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)
예제 #9
0
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({}))
예제 #10
0
class ApplicationSchema(BaseSchema):
    uuid = fields.String(dump_only=True)
    tenant_uuid = fields.String(dump_only=True)
    name = fields.String(validate=Length(max=128), allow_none=True)
    destination = fields.String(
        validate=OneOf(ApplicationDestinationOptionsField._options.keys()),
        allow_none=True,
        default=None,
    )
    destination_options = ApplicationDestinationOptionsField(default={})
    links = ListLink(
        Link('applications', field='uuid', target='application_uuid'))

    lines = Nested('LineSchema',
                   only=['id', 'name', 'links'],
                   many=True,
                   dump_only=True)

    @pre_dump
    def map_destination(self, obj, **kwargs):
        if obj.dest_node:
            obj.destination = 'node'
            obj.destination_options = obj.dest_node
        return obj

    @post_load
    def create_objects(self, data, **kwargs):
        dest = data.pop('destination', None)
        dest_options = data.pop('destination_options', {})
        data['dest_node'] = None
        if dest == 'node':
            data['dest_node'] = ApplicationDestNode(**dest_options)
        return data
예제 #11
0
class ParkingLotSchema(BaseSchema):
    id = fields.Integer(dump_only=True)
    tenant_uuid = fields.String(dump_only=True)
    name = fields.String(allow_none=True, validate=Length(max=128))
    slots_start = fields.String(validate=(Length(max=40),
                                          Predicate('isdigit')),
                                required=True)
    slots_end = fields.String(validate=(Length(max=40), Predicate('isdigit')),
                              required=True)
    timeout = fields.Integer(validate=Range(min=0),
                             allow_none=True,
                             missing=45)
    music_on_hold = fields.String(validate=Length(max=128),
                                  allow_none=True,
                                  missing='default')
    links = ListLink(Link('parkinglots'))

    extensions = Nested(
        'ExtensionSchema',
        only=['id', 'exten', 'context', 'links'],
        many=True,
        dump_only=True,
    )

    @validates_schema
    def validate_slots_range(self, data, **kwargs):
        # validates_schema is executed before fields validator, so the required
        # fields is not yet checked
        if not data.get('slots_start') or not data.get('slots_end'):
            return

        if int(data['slots_start']) > int(data['slots_end']):
            raise ValidationError('It is not a valid range')
예제 #12
0
class MohSchema(BaseSchema):
    uuid = fields.UUID(dump_only=True)
    tenant_uuid = fields.String(dump_only=True)
    name = fields.String(dump_only=True)
    label = fields.String(validate=Length(max=128), required=True)
    mode = fields.String(validate=OneOf(['custom', 'files', 'mp3']),
                         required=True)
    application = fields.String(validate=Length(max=256), allow_none=True)
    sort = fields.String(validate=OneOf(
        ['alphabetical', 'random', 'random_start']),
                         allow_none=True)
    files = Nested(MohFileSchema, many=True, dump_only=True)

    links = ListLink(Link('moh', field='uuid'))

    # DEPRECATED 21.15
    @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 moh is deprecated. use "label" instead')
            data['label'] = data['name']
        return data
예제 #13
0
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 = Nested('VoicemailSchema', only=['name'], dump_only=True)

    @pre_dump
    def separate_action(self, data, **kwargs):
        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, **kwargs):
        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, **kwargs):
        if data.get('voicemail'):
            data['voicemail_name'] = data['voicemail']['name']

        data.pop('voicemail', None)
        return data
예제 #14
0
class FeaturesConfigurationSchema(BaseSchema):
    options = Nested(AsteriskOptionSchema, many=True, required=True)

    @pre_load
    def convert_options_to_collection(self, data, **kwargs):
        options = data.get('options')
        if isinstance(options, dict):
            data['options'] = [{
                'key': key,
                'value': value
            } for key, value in options.items()]
        return data

    @post_dump
    def convert_options_to_dict(self, data, **kwargs):
        data['options'] = {
            option['key']: option['value']
            for option in data['options']
        }
        return data

    @pre_dump
    def add_envelope(self, data, **kwargs):
        return {'options': data}

    @post_load
    def remove_envelope(self, data, **kwargs):
        return data['options']
예제 #15
0
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,
    )
예제 #16
0
class EmailConfigSchema(BaseSchema):
    domain_name = fields.String(attribute='mydomain',
                                validate=Length(max=255),
                                missing='')
    from_ = fields.String(attribute='origin',
                          data_key='from',
                          validate=Length(max=255),
                          missing='')
    address_rewriting_rules = fields.List(
        Nested(_RewriteRule, missing=None),
        attribute='canonical_lines',
        missing=[],
    )
    smtp_host = fields.String(attribute='relayhost',
                              validate=Length(max=255),
                              missing='')
    fallback_smtp_host = fields.String(attribute='fallback_relayhost',
                                       validate=Length(max=255),
                                       missing='')

    @pre_dump
    def split_canonical(self, data, **kwargs):
        data.canonical_lines = [
            line for line in data.canonical.split('\\n') if line
        ]
        return data

    @post_load
    def join_canonical(self, data, **kwargs):
        data['canonical'] = '\\n'.join(data.get('canonical_lines', []))
        return data
예제 #17
0
class FuncKeyUnifiedTemplateSchema(BaseSchema):
    id = fields.Integer(dump_only=True)
    name = fields.String(validate=Length(max=128))
    keys = FuncKeyPositionField(
        fields.Integer(validate=Range(min=1)),
        Nested(FuncKeySchema, required=True),
    )
예제 #18
0
class SccpSchema(BaseSchema):
    id = fields.Integer(dump_only=True)
    tenant_uuid = fields.String(dump_only=True)
    options = fields.List(fields.List(fields.String(), validate=Length(equal=2)))
    links = ListLink(Link('endpoint_sccp'))

    line = Nested('LineSchema', only=['id', 'links'], dump_only=True)
예제 #19
0
class UserDestinationSchema(BaseDestinationSchema):
    user_id = fields.Integer(required=True)

    user = Nested(
        'UserSchema',
        attribute='userfeatures',
        only=['firstname', 'lastname'],
        dump_only=True,
    )

    endpoint_list = 'users_list'

    @post_dump
    def generate_href(self, output, **kwargs):
        user_id = output['user_id']
        output['href'] = url_for('users', id=user_id, _external=True)
        return output

    @post_dump
    def make_user_fields_flat(self, data, **kwargs):
        if data.get('user'):
            data['user_firstname'] = data['user']['firstname']
            data['user_lastname'] = data['user']['lastname']

        data.pop('user', None)
        return data
예제 #20
0
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 = Nested('CallFilterRecipientsSchema',
                        many=True,
                        dump_only=True)
    surrogates = Nested('CallFilterSurrogatesSchema',
                        many=True,
                        dump_only=True)
    fallbacks = Nested('CallFilterFallbackSchema', dump_only=True)

    @post_dump
    def wrap_users(self, data, **kwargs):
        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
예제 #21
0
class GroupExtensionsSchema(BaseSchema):
    extensions = Nested(GroupExtensionSchema, many=True, required=True)

    @post_load
    def set_default_priority(self, data, **kwargs):
        for priority, extension in enumerate(data['extensions']):
            extension['priority'] = extension.get('priority', priority)
        return data
예제 #22
0
class ServicesSchema(BaseSchema):
    dnd = Nested(ServiceDNDSchema)
    incallfilter = Nested(ServiceIncallFilterSchema)

    types = ['dnd', 'incallfilter']

    @pre_dump()
    def add_envelope(self, data, **kwargs):
        return {type_: data for type_ in self.types}

    @post_load
    def remove_envelope(self, data, **kwargs):
        result = {}
        for service in data.values():
            for key, value in service.items():
                result[key] = value
        return result
예제 #23
0
    def _serialize(self, nested_obj, attr, obj):
        base = super()._serialize(nested_obj, attr, obj)
        if not base:
            return base
        schema = self.destination_schemas[base['type']]

        if base['type'] == 'application':
            base = Nested(schema,
                          **self.kwargs)._serialize(nested_obj, attr, obj)
            schema = self.application_schemas[base['application']]

        if base['type'] == 'hangup':
            base = Nested(schema,
                          **self.kwargs)._serialize(nested_obj, attr, obj)
            schema = self.hangup_schemas[base['cause']]

        return Nested(schema, **self.kwargs)._serialize(nested_obj, attr, obj)
예제 #24
0
class GroupUsersSchema(BaseSchema):
    users = Nested(GroupUserSchema, many=True, required=True)

    @post_load
    def set_default_priority(self, data, **kwargs):
        for priority, user in enumerate(data['users']):
            user['priority'] = user.get('priority', priority)
        return data
예제 #25
0
class IAXGeneralSchema(BaseSchema):
    options = Nested(IAXGeneralOption, many=True, required=True)

    ordered_options = fields.List(Nested(IAXGeneralOrderedOption),
                                  required=True)

    @pre_load
    def convert_options_to_collection(self, data, **kwargs):
        options = data.get('options')
        if isinstance(options, dict):
            data['options'] = [{
                'key': key,
                'value': value
            } for key, value in options.items()]
        return data

    @post_load
    def merge_options_and_ordered_options(self, data, **kwargs):
        self._add_metric(data)
        result = []
        result.extend(data['options'])
        result.extend(data['ordered_options'])
        return result

    def _add_metric(self, data):
        for metric, ordered_option in enumerate(data['ordered_options']):
            ordered_option['metric'] = metric
        for option in data['options']:
            option['metric'] = None

    @pre_dump
    def separate_options_and_ordered_options(self, data, **kwargs):
        return {
            'options': [option for option in data if option.metric is None],
            'ordered_options':
            [option for option in data if option.metric is not None],
        }

    @post_dump
    def convert_options_to_dict(self, data, **kwargs):
        data['options'] = {
            option['key']: option['value']
            for option in data['options']
        }
        return data
예제 #26
0
class ExtensionSchema(BaseSchema):
    id = fields.Integer(dump_only=True)
    tenant_uuid = fields.String(dump_only=True)
    exten = fields.String(validate=Length(max=40), required=True)
    context = fields.String(required=True)
    commented = fields.Boolean(attribute='legacy_commented')
    enabled = fields.Boolean()
    links = ListLink(Link('extensions'))

    conference = Nested('ConferenceSchema',
                        only=['id', 'name', 'links'],
                        dump_only=True)
    parking_lot = Nested('ParkingLotSchema',
                         only=['id', 'name', 'links'],
                         dump_only=True)
    group = Nested('GroupSchema',
                   only=['uuid', 'id', 'name', 'links'],
                   dump_only=True)
    incall = Nested('IncallSchema', only=['id', 'links'], dump_only=True)
    lines = Nested('LineSchema',
                   only=['id', 'name', 'links'],
                   many=True,
                   dump_only=True)
    outcall = Nested('OutcallSchema',
                     only=['id', 'name', 'links'],
                     dump_only=True)
    queue = Nested('QueueSchema',
                   only=['id', 'name', 'label', 'links'],
                   dump_only=True)
예제 #27
0
class ForwardsSchema(BaseSchema):
    busy = Nested(ForwardBusySchema)
    noanswer = Nested(ForwardNoAnswerSchema)
    unconditional = Nested(ForwardUnconditionalSchema)

    types = ['busy', 'noanswer', 'unconditional']

    @pre_dump
    def add_envelope(self, data, **kwargs):
        return {type_: data for type_ in self.types}

    @post_load
    def remove_envelope(self, data, **kwargs):
        result = {}
        for forward in data.values():
            for key, value in forward.items():
                result[key] = value
        return result
예제 #28
0
class FuncKeyTemplateSchema(BaseSchema):
    id = fields.Integer(dump_only=True)
    tenant_uuid = fields.String(dump_only=True)
    name = fields.String(validate=Length(max=128))
    keys = FuncKeyPositionField(
        fields.Integer(validate=Range(min=1)),
        Nested(FuncKeySchema, required=True),
    )
    links = ListLink(Link('func_keys_templates'))
예제 #29
0
class VoicemailZoneMessagesSchema(BaseSchema):
    items = Nested(VoicemailZoneMessagesOption, many=True, required=True)

    @post_load
    def remove_envelope(self, data, **kwargs):
        return data['items']

    @pre_dump
    def add_envelope(self, data, **kwargs):
        return {'items': [option for option in data]}
예제 #30
0
class IAXCallNumberLimitsCollectionSchema(BaseSchema):
    items = Nested(IAXCallNumberLimitsSchema, many=True, required=True)

    @post_load
    def remove_envelope(self, data, **kwargs):
        return data['items']

    @pre_dump
    def add_envelope(self, data, **kwargs):
        return {'items': [option for option in data]}