コード例 #1
0
def get_termination_by_employee_identifier(client, employee_identifier):
    zeep_client = Zeep("{0}{1}".format(client.base_url, endpoint))
    if 'EmployeeNumber' in employee_identifier:
        element = zeep_client.get_element('ns6:EmployeeNumberIdentifier')
        obj = element(**employee_identifier)
    elif 'EmailAddress' in employee_identifier:
        element = zeep_client.get_element('ns6:EmailAddressIdentifier')
        obj = element(**employee_identifier)

    response = zeep_client.service.GetTerminationByEmployeeIdentifier(
        _soapheaders=[client.session_header], employeeIdentifier=obj)

    return response['Results']
コード例 #2
0
def get_person_by_employee_identifier(client, employee_identifier):
    zeep_client = Zeep(f"{client.base_url}{endpoint}")
    if 'EmployeeNumber' in employee_identifier:
        element = zeep_client.get_element('ns6:EmployeeNumberIdentifier')
        obj = element(**employee_identifier)
    elif 'EmailAddress' in employee_identifier:
        element = zeep_client.get_element('ns6:EmailAddressIdentifier')
        obj = element(**employee_identifier)

    response = zeep_client.service.GetPersonByEmployeeIdentifier(
        _soapheaders=[client.session_header], employeeIdentifier=obj)

    return response['Results']
コード例 #3
0
def _call_federation(settings: CzNiaAppSettings, transport: Transport,
                     assertion: Element) -> Element:
    """Call FPSTS (Federation provider) service and return the assertion."""
    plugins = []
    history = None
    if settings.DEBUG:
        history = HistoryPlugin()
        plugins.append(history)
    client = Client(settings.FEDERATION_WSDL,
                    wsse=SAMLTokenSignature(assertion),
                    settings=SETTINGS,
                    transport=transport,
                    plugins=plugins)
    # prepare request
    request_type = client.get_element(
        QName(NiaNamespaces.WS_TRUST.value, 'RequestType'))
    request = AnyObject(request_type,
                        request_type(NiaNamespaces.WS_TRUST.value + '/Issue'))
    # Prepare WSA header
    applies = _get_wsa_header(client, settings.PUBLIC_ADDRESS)
    # Call the service
    service = client.bind('SecurityTokenService',
                          'WS2007FederationHttpBinding_IWSTrust13Sync')
    try:
        response = service.Trust13Issue(_value_1=[applies, request])
    except (Error, XmlsecError, RequestException) as err:
        _log_history(history, settings, 'FPSTS', success=False)
        raise NiaException(err)
    _log_history(history, settings, 'FPSTS')
    return response.RequestSecurityTokenResponse[0]['_value_1'][3]['_value_1']
コード例 #4
0
class TransmissaoSOAP(Transmissao):

    def __init__(self, certificado, session=Session(), cache=True,
                 disable_warnings=True, raw_response=True):
        """
        :param certificado: erpbrasil.assinatura.certificado
        :param cache: O cache torna as requisições mais rápidas entretanto,
        pode causar problemas em caso de troca de parametros dos webservices
        """
        if cache:
            self._cache = self.get_cache()
        self.certificado = certificado
        self.session = session
        self._disable_warnings = disable_warnings
        self.raw_response = raw_response

    @staticmethod
    def get_cache():
        temp_dir = tempfile.gettempdir()
        cache_file = os.path.join(temp_dir, 'erpbrasil_transmissao.db')
        return SqliteCache(path=cache_file, timeout=60)

    def desativar_avisos(self):
        if self._disable_warnings:
            requests.packages.urllib3.disable_warnings(
                InsecureRequestWarning
            )

    @contextmanager
    def cliente(self, url, verify=False, service_name=None, port_name=None):
        with ArquivoCertificado(self.certificado, 'w') as (key, cert):
            self.desativar_avisos()
            session = Session()
            session.cert = (key, cert)
            session.verify = verify
            transport = Transport(session=session, cache=self._cache)
            self._cliente = Client(
                url, transport=transport, service_name=service_name,
                port_name=port_name
            )
            yield self._cliente
            self._cliente = False

    def interpretar_mensagem(self, mensagem):
        if type(mensagem) == str:
            return etree.fromstring(mensagem, parser=etree.XMLParser(
                remove_blank_text=True
            ))
        return mensagem

    def set_header(self, elemento, **kwargs):
        header_element = self._cliente.get_element(elemento)
        header = header_element(**kwargs)
        self._cliente.set_default_soapheaders([header])

    def enviar(self, operacao, mensagem):
        with self._cliente.settings(raw_response=self.raw_response):
            return self._cliente.service[operacao](
                self.interpretar_mensagem(mensagem)
            )
コード例 #5
0
def test_parse_soap_wsdl():
    client = Client(
        'tests/wsdl_files/soap.wsdl',
        transport=Transport(),
    )

    response = """
        <?xml version="1.0"?>
        <soapenv:Envelope
            xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
            xmlns:stoc="http://example.com/stockquote.xsd">
           <soapenv:Header/>
           <soapenv:Body>
              <stoc:TradePrice>
                 <price>120.123</price>
              </stoc:TradePrice>
           </soapenv:Body>
        </soapenv:Envelope>
    """.strip()

    client.set_ns_prefix('stoc', 'http://example.com/stockquote.xsd')

    with requests_mock.mock() as m:
        m.post('http://example.com/stockquote', text=response)
        account_type = client.get_type('stoc:account')
        account = account_type(id=100)
        account.user = '******'
        country = client.get_element('stoc:country').type()
        country.name = 'The Netherlands'
        country.code = 'NL'

        result = client.service.GetLastTradePrice(tickerSymbol='foobar',
                                                  account=account,
                                                  country=country)
        assert result == 120.123

        request = m.request_history[0]

        # Compare request body
        expected = """
        <soap-env:Envelope
                xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
                xmlns:stoc="http://example.com/stockquote.xsd">
            <soap-env:Body>
              <stoc:TradePriceRequest>
                <tickerSymbol>foobar</tickerSymbol>
                <account>
                  <id>100</id>
                  <user>mvantellingen</user>
                </account>
                <stoc:country>
                  <name>The Netherlands</name>
                  <code>NL</code>
                </stoc:country>
              </stoc:TradePriceRequest>
           </soap-env:Body>
        </soap-env:Envelope>
        """
        assert_nodes_equal(expected, request.body)
コード例 #6
0
ファイル: test_wsdl.py プロジェクト: tobirl/python-zeep
def test_parse_soap_wsdl():
    client = Client('tests/wsdl_files/soap.wsdl', transport=Transport(),)

    response = """
        <?xml version="1.0"?>
        <soapenv:Envelope
            xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
            xmlns:stoc="http://example.com/stockquote.xsd">
           <soapenv:Header/>
           <soapenv:Body>
              <stoc:TradePrice>
                 <price>120.123</price>
              </stoc:TradePrice>
           </soapenv:Body>
        </soapenv:Envelope>
    """.strip()

    client.set_ns_prefix('stoc', 'http://example.com/stockquote.xsd')

    with requests_mock.mock() as m:
        m.post('http://example.com/stockquote', text=response)
        account_type = client.get_type('stoc:account')
        account = account_type(id=100)
        account.user = '******'
        country = client.get_element('stoc:country').type()
        country.name = 'The Netherlands'
        country.code = 'NL'

        result = client.service.GetLastTradePrice(
            tickerSymbol='foobar',
            account=account,
            country=country)
        assert result == 120.123

        request = m.request_history[0]

        # Compare request body
        expected = """
        <soap-env:Envelope
                xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
                xmlns:stoc="http://example.com/stockquote.xsd">
            <soap-env:Body>
              <stoc:TradePriceRequest>
                <tickerSymbol>foobar</tickerSymbol>
                <account>
                  <id>100</id>
                  <user>mvantellingen</user>
                </account>
                <stoc:country>
                  <name>The Netherlands</name>
                  <code>NL</code>
                </stoc:country>
              </stoc:TradePriceRequest>
           </soap-env:Body>
        </soap-env:Envelope>
        """
        assert_nodes_equal(expected, request.body)
コード例 #7
0
def execute_report(client, context, report_path, delimiter=','):
    session = requests.Session()
    session.headers.update({'US-DELIMITER': delimiter})
    transport = Transport(session=session)
    payload = {'ReportPath': report_path}
    zeep_client = ZeepClient(f"{client.base_url}{endpoint}",
                             transport=transport)
    element = zeep_client.get_element('ns5:ReportRequest')
    obj = element(**payload)
    r = zeep_client.service.ExecuteReport(request=obj, context=context)
    return r['ReportKey']
コード例 #8
0
def _call_identity(settings: CzNiaAppSettings,
                   transport: Transport) -> Element:
    """Call IPSTS (Identity provider) service and return the assertion."""
    plugins = []
    history = None
    if settings.DEBUG:
        history = HistoryPlugin()
        plugins.append(history)
    client = Client(settings.IDENTITY_WSDL,
                    wsse=BinarySignature(settings.KEY, settings.CERTIFICATE,
                                         settings.PASSWORD),
                    settings=SETTINGS,
                    transport=transport,
                    plugins=plugins)
    # Prepare token
    token_type = client.get_element(
        QName(NiaNamespaces.WS_TRUST.value, 'TokenType'))
    token = AnyObject(token_type, token_type(ASSERTION))
    # Prepare request
    request_type = client.get_element(
        QName(NiaNamespaces.WS_TRUST.value, 'RequestType'))
    request = AnyObject(request_type,
                        request_type(NiaNamespaces.WS_TRUST.value + '/Issue'))
    # Prepare key
    key_type = client.get_element(
        QName(NiaNamespaces.WS_TRUST.value, 'KeyType'))
    key = AnyObject(key_type,
                    key_type(NiaNamespaces.WS_TRUST.value + '/SymmetricKey'))
    # Prepare WSA header
    applies = _get_wsa_header(client, settings.FEDERATION_ADDRESS)
    # Call the service
    service = client.bind('SecurityTokenService',
                          'WS2007HttpBinding_IWSTrust13Sync2')
    try:
        response = service.Trust13Issue(
            _value_1=[token, request, key, applies])
    except (Error, XmlsecError, RequestException) as err:
        _log_history(history, settings, 'IPSTS', success=False)
        raise NiaException(err)
    _log_history(history, settings, 'IPSTS')
    return response.RequestSecurityTokenResponse[0]['_value_1'][3]['_value_1']
コード例 #9
0
def log_on_with_token(client):
    # print(inspect.getmembers(client))
    credentials = {
        'Token': client.token,
        'ClientAccessKey': client.client_access_key
    }

    # Log on to get ns5:DataContext object with auth
    zeep_client = ZeepClient(f"{client.base_url}{endpoint}")
    element = zeep_client.get_element('ns5:LogOnWithTokenRequest')
    obj = element(**credentials)
    # print(inspect.getmembers(obj))
    return zeep_client.service.LogOnWithToken(obj)
コード例 #10
0
ファイル: __init__.py プロジェクト: ideavateltd/tap-awin
def do_sync():
    LOGGER.info("Starting sync")

    client = Client(AWIN_PUBLISHER_API)
    UserAuthentication = client.get_element(
        "{http://api.affiliatewindow.com/}UserAuthentication")(
            iId=CONFIG['publisher_id'],
            sPassword=CONFIG['api_password'],
            sType=CONFIG['user_type'])
    client.set_default_soapheaders([UserAuthentication])

    sync_transactions(client)
    sync_advertisers(client)

    singer.write_state(STATE)

    LOGGER.info("Sync complete")
コード例 #11
0
ファイル: client.py プロジェクト: turnhq/tetrapod
    def build_zeep_client(self, alias='default'):
        config = self[alias]
        wsdl = config['wsdl']
        proxies = config.get('proxies', None)

        session = Session()
        session.verify = False
        transport = Transport(session=session)

        client = Zeep_client(wsdl, transport=transport)

        if proxies:
            client.transport.session.proxies = proxies

        auth = client.get_element(
            '{http://datalinkservices.org/}Authorization')
        client.set_default_soapheaders([
            auth(
                AcctID=config['account'],
                UserID=config['user'],
                Password=config['password'],
            )
        ])
        return client
コード例 #12
0
 def action_api_import_cron(self):
     #PREPROD
     #url_base = "http://213.60.254.109:85/Services/"
     #PROD
     url_base = "http://www.cegacol.com/Services/"
     url_api = url_base + "WsCatalogue.asmx?WSDL"
     client = Client(url_api)
     header = client.get_element("{" + url_base + "}AuthSoapHeader")
     end_date = datetime.strptime(fields.Date.today(), "%Y-%m-%d").\
         date()
     month_ago = datetime(end_date.year, end_date.month - 1,
                          end_date.day).date()
     milk_control_service = self.env.\
         ref('res_partner_farm_data.service_control_lechero')
     passwds = self.env['res.partner.passwd'].search([
         ('service', '=', milk_control_service.id)
     ])
     for passwd in passwds:
         stop_before = False
         if not passwd.passwd or not passwd.name:
             continue
         header_value = header(UserName=passwd.name,
                               Password=passwd.read(['passwd'
                                                     ])[0]['passwd'])
         client.set_default_soapheaders([header_value])
         last_sync_date = passwd.last_sync_date
         if last_sync_date:
             start_date = datetime.\
                 strptime(last_sync_date, "%Y-%m-%d").date() + \
                 timedelta(1)
             if start_date < month_ago:
                 start_date = month_ago
         else:
             start_date = month_ago
         delta = end_date - start_date
         for i in range(delta.days + 1):
             vals = {}
             filter_date = start_date + timedelta(days=i)
             try:
                 data = client.service.\
                     Controles(
                         dateInterval={'DateFrom': filter_date,
                                       'DateTo': filter_date},
                         idRangeQuery=0, status=0)
             except Exception, e:
                 self.create({
                     'date': filter_date.strftime("%Y-%m-%d"),
                     'exploitation_id': passwd.partner_id.id,
                     'state': 'incorrect',
                     'exception_txt': e.message
                 })
                 break
             if not data['ListResult']:
                 if data['MessageType']['Id'] != 30010:
                     self.create({
                         'date':
                         filter_date.strftime("%Y-%m-%d"),
                         'exploitation_id':
                         passwd.partner_id.id,
                         'state':
                         'incorrect',
                         'exception_txt':
                         data['MessageType']['Description']
                     })
                 else:
                     continue
             else:
                 milk_control = self.\
                     create({'date': filter_date.strftime("%Y-%m-%d"),
                             'exploitation_id': passwd.partner_id.id,
                             'state': 'correct'})
                 for cow_data in data['ListResult']['Control']:
                     if not cow_data['Grasa'] or cow_data[
                             'Grasa'] == Decimal('0.00'):
                         stop_before = True
                         break
                     vals = {
                         'control_id':
                         milk_control.id,
                         'cea':
                         cow_data['Cea'],
                         'cib':
                         cow_data['Cib'],
                         'name':
                         cow_data['Nombre'],
                         'date_birth':
                         cow_data['FechaParto'].date().strftime("%Y-%m-%d"),
                         'birth_number':
                         cow_data['NumeroParto'],
                         'control_number':
                         cow_data['NumeroControl'],
                         'days': (cow_data['FechaControl'] -
                                  cow_data['FechaParto']).days,
                         'milk_liters':
                         cow_data['LecheKilos'],
                         'fat':
                         cow_data['Grasa'],
                         'protein':
                         cow_data['Proteina'],
                         'rcs':
                         int(cow_data['RCS']),
                         'urea':
                         int(cow_data['Urea'])
                     }
                     vals['cumulative_milk'] = \
                         int(vals['milk_liters'] * vals['days'])
                     self.env['milk.control.line'].create(vals)
                 if stop_before:
                     milk_control.unlink()
                     passwd.last_sync_date = \
                         filter_date.strftime("%Y-%m-%d")
                     break
                 milk_control.create_report()
                 passwd.last_sync_date = filter_date.strftime("%Y-%m-%d")
コード例 #13
0
ファイル: connection.py プロジェクト: weezheng/olap
class XMLAConnection(object):
    @classmethod
    def addMethod(cls, funcname, func):
        return setattr(cls, funcname, func)

    @classmethod
    def setupMembers(cls):
        def getFunc(schemaName):
            return lambda this, *args, **kw: cls.Discover(
                this, schemaName, *args, **kw)

        for schemaName in xmla1_1_rowsets:
            mname = schemaNameToMethodName(schemaName)
            cls.addMethod(mname, getFunc(schemaName))

    def __init__(self, url, location, sslverify, **kwargs):

        if "session" in kwargs:
            session = kwargs["session"]
            del kwargs["session"]
            transport = Transport(session=session)
        else:
            transport = Transport()

        if "auth" in kwargs:
            transport.session.auth = kwargs["auth"]
            del kwargs["auth"]

        transport.session.verify = sslverify
        self.sessionplugin = SessionPlugin(self)
        plugins = [self.sessionplugin]

        if "log" in kwargs:
            log = kwargs.get("log")
            if isinstance(log, Plugin):
                plugins.append(log)
            elif log == True:
                plugins.append(LogRequest())
            del kwargs["log"]

        self.client = Client(
            url,
            transport=transport,
            # cache=None, unwrap=False,
            plugins=plugins)

        self.service = self.client.create_service(
            ns_name(schema_xmla, "MsXmlAnalysisSoap"), location)
        self.client.set_ns_prefix(None, schema_xmla)
        # optional, call might fail
        self.getMDSchemaLevels = lambda *args, **kw: self.Discover(
            "MDSCHEMA_LEVELS", *args, **kw)
        self.setListenOnSessionId(False)
        self.setSessionId(None)
        self._soapheaders = None

    def getListenOnSessionId(self):
        return self.listenOnSessionId

    def setListenOnSessionId(self, trueOrFalse):
        self.listenOnSessionId = trueOrFalse

    def setSessionId(self, sessionId):
        self.sessionId = sessionId

    def Discover(self, what, restrictions=None, properties=None):
        rl = as_etree(restrictions, "RestrictionList")
        pl = as_etree(properties, "PropertyList")
        try:
            #import pdb; pdb.set_trace()
            doc = self.service.Discover(RequestType=what,
                                        Restrictions=rl,
                                        Properties=pl,
                                        _soapheaders=self._soapheaders)
            root = fromETree(doc.body["return"]["_value_1"],
                             ns=schema_xmla_rowset)
            res = getattr(root, "row", [])
            if res:
                res = aslist(res)
        except Fault as fault:
            raise XMLAException(fault.message,
                                dictify(fromETree(fault.detail, ns=None)))
        #logger.debug( res )
        return res

    def Execute(self,
                command,
                dimformat="Multidimensional",
                axisFormat="TupleFormat",
                **kwargs):
        if isinstance(command, stringtypes):
            command = as_etree({"Statement": command})
        props = {"Format": dimformat, "AxisFormat": axisFormat}
        props.update(kwargs)

        plist = as_etree({"PropertyList": props})
        try:

            res = self.service.Execute(Command=command,
                                       Properties=plist,
                                       _soapheaders=self._soapheaders)
            root = res.body["return"]["_value_1"]
            return TupleFormatReader(fromETree(root, ns=schema_xmla_mddataset))
        except Fault as fault:
            raise XMLAException(fault.message,
                                dictify(fromETree(fault.detail, ns=None)))

    def BeginSession(self):
        bs = self.client.get_element(ns_name(schema_xmla,
                                             "BeginSession"))(mustUnderstand=1)
        self.setListenOnSessionId(True)
        cmd = as_etree("Statement")

        self.service.Execute(Command=cmd, _soapheaders={"BeginSession": bs})
        self.setListenOnSessionId(False)

        sess = self.client.get_element(ns_name(schema_xmla, "Session"))(
            SessionId=self.sessionId, mustUnderstand=1)
        self._soapheaders = {"Session": sess}

    def EndSession(self):
        if self.sessionId is not None:
            es = self.client.get_element(ns_name(schema_xmla, "EndSession"))(
                SessionId=self.sessionId, mustUnderstand=1)
            cmd = as_etree("Statement")
            self.service.Execute(Command=cmd, _soapheaders={"EndSession": es})
            self.setSessionId(None)
            self._soapheaders = None
コード例 #14
0
def _get_wsa_header(client: Client, address: str) -> AnyObject:
    """Get WSA header from the client."""
    applies_type = client.get_element(QName(WSP, 'AppliesTo'))
    reference_type = client.get_element(QName(WSA, 'EndpointReference'))
    reference = AnyObject(reference_type, reference_type(Address=address))
    return AnyObject(applies_type, applies_type(_value_1=reference))
コード例 #15
0
class Adapter:
    xml_template = '<ds:Signature ' \
                   'xmlns:ds="http://www.w3.org/2000/09/xmldsig#">' \
                   '<ds:SignedInfo>' \
                   '<ds:CanonicalizationMethod ' \
                   'Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>' \
                   '<ds:SignatureMethod ' \
                   'Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411"/>' \
                   '<ds:Reference URI="#SIGNED_BY_CALLER"><ds:Transforms>' \
                   '<ds:Transform ' \
                   'Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>' \
                   '<ds:Transform ' \
                   'Algorithm="urn://smev-gov-ru/xmldsig/transform"/>' \
                   '</ds:Transforms>' \
                   '<ds:DigestMethod ' \
                   'Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr3411"/>' \
                   '<ds:DigestValue></ds:DigestValue></ds:Reference>' \
                   '</ds:SignedInfo><ds:SignatureValue></ds:SignatureValue>' \
                   '<ds:KeyInfo><ds:X509Data><ds:X509Certificate>' \
                   '</ds:X509Certificate></ds:X509Data></ds:KeyInfo>' \
                   '</ds:Signature>'

    def __init__(
            self,
            wsdl="http://smev3-d.test.gosuslugi.ru:7500/smev/v1.2/ws?wsdl",
            ftp_addr="ftp://smev3-d.test.gosuslugi.ru/",
            history=False,
            method='sharp',
            serial=None,
            container=None,
            crt_name=None):
        self.log = logging.getLogger('smev.adapter')
        self.log.setLevel(logging.root.level)
        self.ftp_addr = ftp_addr
        self.crypto = Crypto()
        self.crypto.serial = serial
        self.crypto.crt_name = crt_name
        self.crypto.container = container
        self.method = method

        if history:
            self.history = HistoryPlugin()
            self.proxy = Client(wsdl, plugins=[self.history])
        else:
            self.proxy = Client(wsdl)

    def dump(self):
        res = "Prefixes:\n"
        for prefix, namespace in self.proxy.wsdl.types.prefix_map.items():
            res += ' ' * 4 + '%s: %s\n' % (prefix, namespace)

        res += "\nGlobal elements:\n"
        for elm_obj in sorted(self.proxy.wsdl.types.elements,
                              key=lambda k: k.qname):
            value = elm_obj.signature(schema=self.proxy.wsdl.types)
            res += ' ' * 4 + value + '\n'

        res += "\nGlobal types:\n"
        for type_obj in sorted(self.proxy.wsdl.types.types,
                               key=lambda k: k.qname or ''):
            value = type_obj.signature(schema=self.proxy.wsdl.types)
            res += ' ' * 4 + value + '\n'

        res += "\nBindings:\n"
        for binding_obj in sorted(self.proxy.wsdl.bindings.values(),
                                  key=lambda k: six.text_type(k)):
            res += ' ' * 4 + six.text_type(binding_obj) + '\n'

        res += '\n'
        for service in self.proxy.wsdl.services.values():
            res += six.text_type(service) + '\n'
            for port in service.ports.values():
                res += ' ' * 4 + six.text_type(port) + '\n'
                res += ' ' * 8 + 'Operations:\n'

                operations = sorted(port.binding._operations.values(),
                                    key=operator.attrgetter('name'))

                for operation in operations:
                    res += '%s%s\n' % (' ' * 12, six.text_type(operation))
                res += '\n'
        return res

    # def get_request(self, uri='urn://augo/smev/uslugi/1.0.0',
    #                 local_name='directum'):
    def get_request(self,
                    uri=None,
                    local_name=None,
                    node_id=None,
                    gen_xml_only=False):
        # if (uri and not local_name) or (not uri and local_name):
        #     raise Exception(
        #         'uri и local_name необходимо указывать одновременно')

        operation = 'GetRequest'
        timestamp = datetime.now()
        node = self.proxy.create_message(
            self.proxy.service,
            operation, {
                'NamespaceURI': uri,
                'RootElementLocalName': local_name,
                'Timestamp': timestamp,
                'NodeID': node_id
            },
            CallerInformationSystemSignature=etree.Element('Signature'))
        node[0][0][0].set('Id', 'SIGNED_BY_CALLER')
        node_str = etree.tostring(node)
        self.log.debug(node_str)

        res = self.__call_sign(
            self.__xml_part(node_str, b'ns1:MessageTypeSelector'))
        # COM variant
        # res = self.crypto.sign_com(
        #     self.__xml_part(node_str, b'ns1:MessageTypeSelector').decode())
        # res = self.__xml_part(res, 'Signature')
        # res = res.replace('URI=""', 'URI="#SIGNED_BY_CALLER"')

        # CSP variant
        # self.crypto.container = "049fc71a-1ff0-4e06-8714-03303ae34afd"
        # res = self.crypto.sign_csp(
        #     self.__xml_part(node_str, b'ns1:MessageTypeSelector'))

        # Sharp variant
        # self.crypto.serial = '008E BDC8 291F 0003 81E7 11E1 AF7A 5ED3 27'
        # res = self.crypto.sign_sharp(
        #     self.__xml_part(node_str, b'ns1:MessageTypeSelector'))

        res = node_str.decode().replace('<Signature/>', res)
        if gen_xml_only:
            return res

        res = self.__send(operation, res)
        self.log.debug(type(res))
        self.log.debug(res)

        declar, uuid, reply_to, files = None, None, None, {}

        if 'MessagePrimaryContent' in res:
            xml = etree.fromstring(res)

            declar = Declar.parsexml(
                etree.tostring(
                    xml.find('.//{urn://augo/smev/uslugi/1.0.0}declar')))

            if 'RefAttachmentHeaderList' in res:
                files = {}
                attach_head_list = objectify.fromstring(
                    self.__xml_part(res, b'RefAttachmentHeaderList'))
                for head in attach_head_list.getchildren():
                    files[head.uuid] = {'MimeType': head.MimeType}
                attach_list = objectify.fromstring(
                    self.__xml_part(res, b'FSAttachmentsList'))
                for attach in attach_list.getchildren():
                    files[attach.uuid]['UserName'] = str(attach.UserName)
                    files[attach.uuid]['Password'] = str(attach.Password)
                    files[attach.uuid]['FileName'] = str(attach.FileName)
                for uuid, file in files.items():
                    file_name = file['FileName']
                    fn, ext = path.splitext(file_name)
                    res = self.__load_file(uuid, file['UserName'],
                                           file['Password'], file['FileName'])
                    if isinstance(res, (str, bytes)):
                        new_ext = guess_extension(file_name).lower()
                        ext = ext.lower()
                        if ext != new_ext:
                            file_name = fn + new_ext
                    else:
                        res, e = res
                        file_name = fn + '.txt'
                    declar.files.append({res: file_name})

            uuid = xml.find('.//{*}MessageID').text
            reply_to = xml.find('.//{*}ReplyTo')
            if reply_to:
                reply_to = reply_to.text

        if hasattr(res, 'Request') \
                and hasattr(res.Request, 'SenderProvidedRequestData') \
                and hasattr(res.Request.SenderProvidedRequestData,
                            'MessagePrimaryContent') \
                and res.Request.SenderProvidedRequestData.MessagePrimaryContent:
            # declar = Declar.parsexml(
            #     etree.tostring(
            #         res.Request.SenderProvidedRequestData.MessagePrimaryContent.find(
            #             './/{urn://augo/smev/uslugi/1.0.0}declar')))
            declar = Declar.parsexml(
                etree.tostring(res.Request.SenderProvidedRequestData.
                               MessagePrimaryContent._value_1))
            if hasattr(res.Request, 'FSAttachmentsList') \
                    and res.Request.FSAttachmentsList:
                attach_head_list = res.Request.SenderProvidedRequestData.RefAttachmentHeaderList
                for head in attach_head_list:
                    files[head.uuid] = {'MimeType': head.MimeType}
                attach_list = res.Request.FSAttachmentsList
                for attach in attach_list:
                    files[attach.uuid]['UserName'] = str(attach.UserName)
                    files[attach.uuid]['Password'] = str(attach.Password)
                    files[attach.uuid]['FileName'] = str(attach.FileName)
                for uuid, file in files.items():
                    file_name = file['FileName']
                    fn, ext = path.splitext(file_name)
                    res = self.__load_file(uuid, file['UserName'],
                                           file['Password'], file['FileName'])
                    if isinstance(res, (str, bytes)):
                        new_ext = guess_extension(file_name).lower()
                        ext = ext.lower()
                        if ext != new_ext:
                            file_name = fn + new_ext
                    else:
                        res, e = res
                        file_name = fn + '.txt'
                    # declar.files.append({res: file_name})
                    files[file_name] = res

            uuid = res.Request.SenderProvidedRequestData.MessageID
            reply_to = res.Request.ReplyTo

        if uuid:
            operation = 'Ack'
            tm = etree.Element('AckTargetMessage',
                               Id='SIGNED_BY_CALLER',
                               accepted='true')
            tm.text = uuid
            node = self.proxy.create_message(
                self.proxy.service,
                operation,
                tm,
                CallerInformationSystemSignature=etree.Element('Signature'))
            res = node.find('.//{*}AckTargetMessage')
            res.set('Id', 'SIGNED_BY_CALLER')
            res.set('accepted', 'true')
            res.text = uuid
            node_str = etree.tostring(node)
            self.log.debug(node_str)
            res = self.__xml_part(node_str, b'ns1:AckTargetMessage')
            res = self.__call_sign(res)
            res = node_str.decode().replace('<Signature/>', res)
            res = self.__send(operation, res)
            self.log.debug(res)

        return declar, uuid, reply_to, files

    def get_response(self,
                     uri="",
                     local_name="",
                     node_id=None,
                     gen_xml_only=False):
        operation = 'GetResponse'
        timestamp = datetime.now()
        node = self.proxy.create_message(
            self.proxy.service,
            operation, {
                'NamespaceURI': uri,
                'RootElementLocalName': local_name,
                'Timestamp': timestamp,
                'NodeID': node_id
            },
            CallerInformationSystemSignature=etree.Element('Signature'))
        node[0][0][0].set('Id', 'SIGNED_BY_CALLER')
        node_str = etree.tostring(node)
        self.log.debug(node_str)

        res = self.__call_sign(
            self.__xml_part(node_str, b'ns1:MessageTypeSelector'))

        res = node_str.decode().replace('<Signature/>', res)
        if gen_xml_only:
            return res

        res = self.__send(operation, res)
        self.log.debug(type(res))
        self.log.debug(res)

        request, uuid, reply_to, files = None, None, None, {}

        if hasattr(res, 'Response') \
                and hasattr(res.Response, 'SenderProvidedResponseData'):
            request = res.Response.SenderProvidedResponseData
            if hasattr(res.Response.SenderProvidedResponseData,
                            'MessagePrimaryContent') \
                and res.Response.SenderProvidedResponseData.MessagePrimaryContent:
                # request = RequestResponse.parsexml(
                #     etree.tostring(
                #         res.Response.SenderProvidedResponseData.MessagePrimaryContent._value_1))
                res1 = RequestResponse.parsexml(
                    etree.tostring(res.Response.SenderProvidedResponseData.
                                   MessagePrimaryContent._value_1))
                request.MessagePrimaryContent._value_1 = str(res1)
            if hasattr(res.Response, 'FSAttachmentsList') \
                    and res.Response.FSAttachmentsList:
                attach_head_list = res.Response.SenderProvidedResponseData.RefAttachmentHeaderList
                for head in attach_head_list:
                    files[head.uuid] = {'MimeType': head.MimeType}
                attach_list = res.Response.FSAttachmentsList
                for attach in attach_list:
                    files[attach.uuid]['UserName'] = str(attach.UserName)
                    files[attach.uuid]['Password'] = str(attach.Password)
                    files[attach.uuid]['FileName'] = str(attach.FileName)
                for uuid, file in files.items():
                    file_name = file['FileName']
                    fn, ext = path.splitext(file_name)
                    res = self.__load_file(uuid, file['UserName'],
                                           file['Password'], file['FileName'])
                    if isinstance(res, (str, bytes)):
                        new_ext = guess_extension(file_name).lower()
                        ext = ext.lower()
                        if ext != new_ext:
                            file_name = fn + new_ext
                    else:
                        res, e = res
                        file_name = fn + '.txt'
                    files[file_name] = res

            uuid = res.Response.SenderProvidedResponseData.MessageID
            reply_to = res.Response.SenderProvidedResponseData.To

        if uuid:
            operation = 'Ack'
            tm = etree.Element('AckTargetMessage',
                               Id='SIGNED_BY_CALLER',
                               accepted='true')
            tm.text = uuid
            node = self.proxy.create_message(
                self.proxy.service,
                operation,
                tm,
                CallerInformationSystemSignature=etree.Element('Signature'))
            res = node.find('.//{*}AckTargetMessage')
            res.set('Id', 'SIGNED_BY_CALLER')
            res.set('accepted', 'true')
            res.text = uuid
            node_str = etree.tostring(node)
            self.log.debug(node_str)
            res = self.__xml_part(node_str, b'ns1:AckTargetMessage')
            res = self.__call_sign(res)
            res = node_str.decode().replace('<Signature/>', res)
            res = self.__send(operation, res)
            self.log.debug(res)

        return request, uuid, reply_to, files

    def __add_element(self, parent, ns, elem, data, file_names=list()):
        if not data:
            return
        se = etree.SubElement(parent, '{%s}%s' % (ns, elem))
        if elem == 'AppliedDocument':
            if isinstance(data, list):
                for itm in data:
                    for item in ('title', 'number', 'date', 'valid_until',
                                 'file_name', 'url', 'url_valid_until'):
                        if item in itm and itm[item]:
                            if item == 'file_name':
                                fn = itm[item]
                                file_names.append(fn)
                                self.__add_element(se, ns, item,
                                                   path.basename(fn),
                                                   file_names)
                            else:
                                self.__add_element(se, ns, item, itm[item],
                                                   file_names)
                    if data.index(itm) < len(data) - 1:
                        se = etree.SubElement(parent, '{%s}%s' % (ns, elem))
            else:
                for item in ('title', 'number', 'date', 'valid_until',
                             'file_name', 'url', 'url_valid_until'):
                    if item in data and data[item]:
                        if item == 'file_name':
                            file_names.append(item)
                        self.__add_element(se, ns, item, data[item],
                                           file_names)
        elif elem == 'legal_entity':
            if isinstance(data, list):
                for itm in data:
                    for item in ('name', 'full_name', 'inn', 'kpp', 'address',
                                 'ogrn', 'taxRegDoc', 'govRegDoc',
                                 'govRegDate', 'phone', 'email', 'bossFio',
                                 'buhFio', 'bank', 'bankAccount',
                                 'lastCtrlDate', 'opf', 'govRegOgv', 'person'):
                        if item in itm and itm[item]:
                            self.__add_element(se, ns, item, itm[item],
                                               file_names)
                    if data.index(itm) < len(data) - 1:
                        se = etree.SubElement(parent, '{%s}%s' % (ns, elem))
            else:
                for item in ('name', 'full_name', 'inn', 'kpp', 'address',
                             'ogrn', 'taxRegDoc', 'govRegDoc', 'govRegDate',
                             'phone', 'email', 'bossFio', 'buhFio', 'bank',
                             'bankAccount', 'lastCtrlDate', 'opf', 'govRegOgv',
                             'person'):
                    if item in data and data[item]:
                        self.__add_element(se, ns, item, data[item],
                                           file_names)
        elif 'address' in elem:
            for item in ('Postal_Code', 'Region', 'District', 'City',
                         'Urban_District', 'Soviet_Village', 'Locality',
                         'Street', 'House', 'Reference_point', 'Housing',
                         'Building', 'Apartment'):
                if item in data and data[item]:
                    self.__add_element(se, ns, item, data[item], file_names)
        elif elem in ('person', 'confidant'):
            if isinstance(data, list):
                for itm in data:
                    for item in ('surname', 'first_name', 'patronymic',
                                 'address', 'fact_address', 'email',
                                 'birthdate', 'passport_serial',
                                 'passport_number', 'passport_agency',
                                 'passport_date', 'phone', 'inn', 'sex',
                                 'snils'):
                        if item in itm and itm[item]:
                            self.__add_element(se, ns, item, itm[item],
                                               file_names)
                    if data.index(itm) < len(data) - 1:
                        se = etree.SubElement(parent, '{%s}%s' % (ns, elem))
            else:
                for item in ('surname', 'first_name', 'patronymic', 'address',
                             'fact_address', 'email', 'birthdate',
                             'passport_serial', 'passport_number',
                             'passport_agency', 'passport_date', 'phone',
                             'inn', 'sex', 'snils'):
                    if item in data and data[item]:
                        self.__add_element(se, ns, item, data[item],
                                           file_names)
        else:
            if isinstance(data, (date, datetime)):
                se.text = data.strftime('%Y-%m-%d')
            else:
                se.text = data
        # if isinstance(data, dict):
        #     se = etree.SubElement(parent, '{%s}%s' % (ns, elem))
        #     for k, v in data.items():
        #         if not v:
        #             continue
        #         self.__add_element(se, ns, k, v)
        # elif isinstance(data, (list, tuple)):
        #     for v in data:
        #         if not isinstance(v, (dict, list, tuple)):
        #             etree.SubElement(parent, '{%s}%s' % (ns, elem)).text = v
        #         else:
        #             se = etree.SubElement(parent, '{%s}%s' % (ns, elem))
        #             self.__add_element(se, ns, elem, v)
        # elif isinstance(data, (date, datetime)):
        #     etree.SubElement(parent, '{%s}%s' % (ns, elem)).text = \
        #         data.strftime('%Y-%m-%d')
        # else:
        #     etree.SubElement(parent, '{%s}%s' % (ns, elem)).text = data

    def send_request(self, declar):
        operation = 'SendRequest'
        file_names = []

        element = self.proxy.get_element('ns1:MessagePrimaryContent')
        rr = etree.Element('{urn://augo/smev/uslugi/1.0.0}declar',
                           nsmap={'ns1': 'urn://augo/smev/uslugi/1.0.0'})
        self.log.debug(declar)
        for item in ('declar_number', 'service', 'register_date', 'end_date',
                     'object_address', 'AppliedDocument', 'legal_entity',
                     'person', 'confidant', 'Param'):
            if item in declar and declar[item]:
                self.__add_element(rr, 'urn://augo/smev/uslugi/1.0.0', item,
                                   declar[item], file_names)
        # for k, v in declar.items():
        #     if isinstance(v, list):
        #         for val in v:
        #             se = etree.SubElement(
        #                 rr, '{urn://augo/smev/uslugi/1.0.0}%s' % k)
        #             for n, m in val.items():
        #                 if not m:
        #                     continue
        #                 if n == 'file_name':
        #                     file_names.append(m)
        #                 else:
        #                     self.__add_element(
        #                         se, 'urn://augo/smev/uslugi/1.0.0', n, m)
        #     elif isinstance(v, dict):
        #         se = etree.SubElement(
        #             rr, '{urn://augo/smev/uslugi/1.0.0}%s' % k)
        #         for n, m in v.items():
        #             if not m:
        #                 continue
        #             self.__add_element(
        #                 se, 'urn://augo/smev/uslugi/1.0.0', n, m)
        #     else:
        #         if not v:
        #             continue
        #         self.__add_element(
        #             rr, 'urn://augo/smev/uslugi/1.0.0', k, v)
        mpc = element(rr)

        node = self.proxy.create_message(
            self.proxy.service,
            operation, {
                'MessageID': uuid1(),
                'MessagePrimaryContent': mpc
            },
            CallerInformationSystemSignature=etree.Element('Signature'))
        res = node.find('.//{*}SenderProvidedRequestData')
        res.set('Id', 'SIGNED_BY_CALLER')

        if file_names:
            ns = etree.QName(
                node.find('.//{*}MessagePrimaryContent')).namespace
            rahl = etree.SubElement(res, '{%s}RefAttachmentHeaderList' % ns)
            for file_name in file_names:
                rah = etree.SubElement(rahl, '{%s}RefAttachmentHeader' % ns)
                etree.SubElement(rah,
                                 '{%s}uuid' % ns).text = self.__upload_file(
                                     file_name, translate(basename(file_name)))
                f_hash = self.crypto.get_file_hash(file_name)
                etree.SubElement(rah, '{%s}Hash' % ns).text = f_hash
                etree.SubElement(rah, '{%s}MimeType' %
                                 ns).text = guess_type(file_name)[0]
                # etree.SubElement(
                #     rah,
                #     '{%s}SignaturePKCS7' % ns).text = self.crypto.get_file_sign(
                #     file_name)

        # Mark request as test request
        ns = etree.QName(
            node.find('.//{*}SenderProvidedRequestData')).namespace
        etree.SubElement(res, '{%s}TestMessage' % ns)

        node_str = etree.tostring(node)
        res = etree.QName(res)
        node_str = node_str.replace(
            b'<ns0:SenderProvidedRequestData',
            b'<ns0:SenderProvidedRequestData xmlns:ns0="' +
            res.namespace.encode() + b'"')
        self.log.debug(node_str)
        res = self.__xml_part(node_str, b'ns0:SenderProvidedRequestData')
        res = self.__call_sign(res)
        res = node_str.decode().replace('<Signature/>', res)
        self.log.debug(res)
        res = self.__send(operation, res.encode('utf-8'))
        self.log.debug(res)
        return res

    def send_response(self,
                      reply_to,
                      declar_number,
                      register_date,
                      result='FINAL',
                      text='',
                      applied_documents=list(),
                      ftp_user='',
                      ftp_pass=''):
        files = []
        for doc in applied_documents:
            if isinstance(doc, (bytes, str)):
                file_name = os.path.split(doc)[1]
                uuid = self.__upload_file(doc, file_name, ftp_user, ftp_pass)
                files.append({
                    uuid: {
                        'name': file_name,
                        'type': guess_type(doc)[0],
                        'full_name': doc
                    }
                })
            if doc.file:
                uuid = self.__upload_file(doc.file, doc.file_name, ftp_user,
                                          ftp_pass)
                files.append({
                    uuid: {
                        'name': doc.file_name,
                        'type': guess_type(doc.file)[0],
                        'full_name': doc.file
                    }
                })

        operation = 'SendResponse'
        element = self.proxy.get_element('ns1:MessagePrimaryContent')
        rr = etree.Element('{urn://augo/smev/uslugi/1.0.0}requestResponse',
                           nsmap={'ns1': 'urn://augo/smev/uslugi/1.0.0'})
        etree.SubElement(
            rr,
            '{urn://augo/smev/uslugi/1.0.0}declar_number').text = declar_number
        etree.SubElement(
            rr,
            '{urn://augo/smev/uslugi/1.0.0}register_date').text = \
            register_date.strftime('%Y-%m-%d') if isinstance(
                register_date, (date, datetime)) else register_date
        etree.SubElement(rr,
                         '{urn://augo/smev/uslugi/1.0.0}result').text = result
        if text:
            etree.SubElement(rr,
                             '{urn://augo/smev/uslugi/1.0.0}text').text = text
        if files:
            for doc in applied_documents:
                ad = etree.SubElement(
                    rr, '{urn://augo/smev/uslugi/1.0.0}AppliedDocument')
                etree.SubElement(
                    ad,
                    '{urn://augo/smev/uslugi/1.0.0}title').text = \
                    doc.title
                etree.SubElement(
                    ad,
                    '{urn://augo/smev/uslugi/1.0.0}number').text = \
                    doc.number
                etree.SubElement(
                    ad,
                    '{urn://augo/smev/uslugi/1.0.0}date').text = \
                    doc.date
                etree.SubElement(
                    ad,
                    '{urn://augo/smev/uslugi/1.0.0}valid_until').text = \
                    doc.valid_until
                etree.SubElement(
                    ad,
                    '{urn://augo/smev/uslugi/1.0.0}file_name').text = \
                    doc.file_name
                etree.SubElement(
                    ad, '{urn://augo/smev/uslugi/1.0.0}url').text = doc.url
                etree.SubElement(
                    ad,
                    '{urn://augo/smev/uslugi/1.0.0}url_valid_until').text = \
                    doc.url_valid_until

        mpc = element(rr)
        node = self.proxy.create_message(
            self.proxy.service,
            operation, {
                'MessageID': uuid1(),
                'To': reply_to,
                'MessagePrimaryContent': mpc
            },
            CallerInformationSystemSignature=etree.Element('Signature'))
        res = node.find('.//{*}SenderProvidedResponseData')
        res.set('Id', 'SIGNED_BY_CALLER')

        if files:
            ns = etree.QName(
                node.find('.//{*}MessagePrimaryContent')).namespace
            rahl = etree.SubElement(res, '{%s}RefAttachmentHeaderList' % ns)
            for uuid, file in files:
                rah = etree.SubElement(rahl, '{%s}RefAttachmentHeader' % ns)
                etree.SubElement(rah, '{%s}uuid' % ns).text = uuid
                etree.SubElement(rah, '{%s}Hash' %
                                 ns).text = self.crypto.get_file_hash(
                                     file['full_name'])
                etree.SubElement(rah, '{%s}MimeType' % ns).text = file['type']
                # etree.SubElement(
                #     rah,
                #     '{%s}SignaturePKCS7' % ns).text = self.crypto.get_file_sign(
                #     file['full_name'])

        node_str = etree.tostring(node)
        res = etree.QName(res)
        node_str = node_str.replace(
            b'<ns0:SenderProvidedResponseData',
            b'<ns0:SenderProvidedResponseData xmlns:ns0="' +
            res.namespace.encode() + b'"')
        self.log.debug(node_str)
        res = self.__xml_part(node_str, b'ns0:SenderProvidedResponseData')
        res = self.__call_sign(res)
        res = node_str.decode().replace('<Signature/>', res)
        res = self.__send(operation, res.encode('utf-8'))
        self.log.debug(res)
        return res

    def __call_sign(self, xml):
        method_name = 'sign_' + self.method
        self.log.debug('Calling Crypto.%s' % method_name)
        method = getattr(self.crypto, method_name)
        return method(xml)

    def __upload_file(self,
                      file,
                      file_name,
                      ftp_user='******',
                      ftp_pass='******'):
        self.log.debug(file_name)
        addr = urlparse(self.ftp_addr).netloc
        with ftplib.FTP(addr, ftp_user, ftp_pass) as con:
            uuid = str(uuid1())
            res = con.mkd(uuid)
            self.log.debug(res)
            con.cwd(uuid)
            with open(file, 'rb') as f:
                res = con.storbinary('STOR ' + file_name, f)
            self.log.debug(res)
        return uuid

    def __load_file(self, uuid, user, passwd, file_name):
        addr = urlparse(self.ftp_addr).netloc
        f, file_path = tempfile.mkstemp()
        try:
            with ftplib.FTP(addr, user, passwd) as con:
                con.cwd(uuid)
                if file_name[0] == '/':
                    file_name = file_name[1:]
                close(f)
                with open(file_path, 'wb') as f:
                    con.retrbinary('RETR ' + file_name, f.write)
        except ftplib.all_errors as e:
            self.log.error(str(e))
            write(f, str(e).encode('cp1251'))
            close(f)
            return file_path, e
        return file_path

    def __send(self, operation, msg):
        kw = {'_soapheaders': self.proxy.service._client._default_soapheaders}
        response = self.proxy.transport.post(
            self.proxy.service._binding_options['address'], msg, kw)
        res = self.proxy.service._binding.process_reply(
            self.proxy.service._client,
            self.proxy.service._binding.get(operation), response)
        # if not res and b'--uuid:' in response.content:
        #     res = response.content[
        #               response.content.index(b'Content-Type:'):]
        #     res = res[:res.index(b'--uuid:')]
        #     self.log.debug(res)
        return res

    def __xml_part(self, xml_as_str, tag_name):
        """
        Cuts the XML part from `xml_as_str` bounded by tag `tag_name`

        :param xml_as_str: String with source XML

        :param tag_name: XML tag name bounds target XML part
        """
        b_idx = xml_as_str.index(tag_name) - 1
        try:
            if isinstance(tag_name, str):
                tgn = tag_name + '>'
            else:
                tgn = tag_name + b'>'
            e_idx = xml_as_str.index(tgn,
                                     b_idx + len(tag_name)) + len(tag_name) + 1
        except ValueError:
            if isinstance(tag_name, str):
                tgn = tag_name + ' '
            else:
                tgn = tag_name + b' '
            e_idx = xml_as_str.index(tgn,
                                     b_idx + len(tag_name)) + len(tag_name) + 1
        return xml_as_str[b_idx:e_idx]
コード例 #16
0
ファイル: connection.py プロジェクト: may-day/olap
class XMLAConnection(object):
    
    @classmethod
    def addMethod(cls, funcname, func):
        return setattr(cls, funcname, func)

        
    @classmethod
    def setupMembers(cls):
        def getFunc(schemaName):
            return lambda this, *args, **kw: cls.Discover(this, 
                                                          schemaName, 
                                                          *args, **kw)
        
        for schemaName in xmla1_1_rowsets:
            mname = schemaNameToMethodName(schemaName)
            cls.addMethod( mname, getFunc(schemaName) )

    def __init__(self, url, location, sslverify, **kwargs):

        if "session" in kwargs:
            session = kwargs["session"]
            del kwargs["session"]
            transport = Transport(session=session)
        else:
            transport = Transport()
            
        if "auth" in kwargs:
            transport.session.auth = kwargs["auth"]
            del kwargs["auth"]

        transport.session.verify = sslverify
        self.sessionplugin=SessionPlugin(self)
        plugins=[self.sessionplugin]

        if "log" in kwargs:
            log = kwargs.get("log")
            if isinstance(log, Plugin):
                plugins.append(log)
            elif log == True:
                plugins.append(LogRequest())
            del kwargs["log"]
            
        self.client = Client(url, 
                             transport=transport, 
                             # cache=None, unwrap=False,
                             plugins=plugins)

        self.service = self.client.create_service(ns_name(schema_xmla,"MsXmlAnalysisSoap"), location)
        self.client.set_ns_prefix(None, schema_xmla)
        # optional, call might fail
        self.getMDSchemaLevels = lambda *args, **kw: self.Discover("MDSCHEMA_LEVELS", 
                                                                   *args, **kw)
        self.setListenOnSessionId(False)
        self.setSessionId(None)
        self._soapheaders=None
             

    def getListenOnSessionId(self):
        return self.listenOnSessionId

    def setListenOnSessionId(self, trueOrFalse):
        self.listenOnSessionId = trueOrFalse

    def setSessionId(self, sessionId):
        self.sessionId = sessionId
        
    def Discover(self, what, restrictions=None, properties=None):
        rl = as_etree(restrictions, "RestrictionList")
        pl = as_etree(properties, "PropertyList")
        try:
            #import pdb; pdb.set_trace()
            doc=self.service.Discover(RequestType=what, Restrictions=rl, Properties=pl, _soapheaders=self._soapheaders)
            root = fromETree(doc.body["return"]["_value_1"], ns=schema_xmla_rowset)
            res = getattr(root, "row", [])
            if res:
                res = aslist(res)
        except Fault as fault:
            raise XMLAException(fault.message, dictify(fromETree(fault.detail, ns=None)))
        #logger.debug( res )
        return res


    def Execute(self, command, dimformat="Multidimensional", 
                axisFormat="TupleFormat", **kwargs):
        if isinstance(command, stringtypes):
            command=as_etree({"Statement": command})
        props = {"Format":dimformat, "AxisFormat":axisFormat}
        props.update(kwargs)

        plist = as_etree({"PropertyList":props})
        try:
            
            res = self.service.Execute(Command=command, Properties=plist, _soapheaders=self._soapheaders)
            root = res.body["return"]["_value_1"]
            return TupleFormatReader(fromETree(root, ns=schema_xmla_mddataset))
        except Fault as fault:
            raise XMLAException(fault.message, dictify(fromETree(fault.detail, ns=None)))
        
        
    def BeginSession(self):
        bs= self.client.get_element(ns_name(schema_xmla,"BeginSession"))(mustUnderstand=1)
        self.setListenOnSessionId(True)
        cmd = as_etree("Statement")

        self.service.Execute(Command=cmd,_soapheaders={"BeginSession":bs})
        self.setListenOnSessionId(False)

        sess= self.client.get_element(ns_name(schema_xmla,"Session"))(SessionId=self.sessionId, mustUnderstand = 1)
        self._soapheaders={"Session":sess}
        
    def EndSession(self):
        if self.sessionId is not None:
            es= self.client.get_element(ns_name(schema_xmla,"EndSession"))(SessionId=self.sessionId, mustUnderstand = 1)
            cmd = as_etree("Statement")
            self.service.Execute(Command=cmd, _soapheaders={"EndSession":es})
            self.setSessionId(None)
            self._soapheaders=None
コード例 #17
0
def webhook():
    chatresponse = {}
    try:
        #get the fulfilnment request
        fulfilmentrequest = request.data
        fulfilmentrequest = json.loads(fulfilmentrequest.decode('UTF-8'))
        intentname = fulfilmentrequest['result']['metadata']['intentName']
        if intentname == 'warranty_check':
            client = Client(
                'https://apiaiwebhookpassthough.herokuapp.com/static/content/EntitlementService.xml'
            )
            requesttype = client.get_element('ns2:EntitlementRequest')
            entitlementrequest = requesttype(
                BusinessOrgID=1,
                ProductTypeCode='P',
                RequestedByUserID='26may2017',
                SerialNumber=fulfilmentrequest['result']['parameters']['slno'],
                SymptomIDList='0707')
            response = client.service.Entitle(request=entitlementrequest)

            warrantyexpirydate = response['Entitlement']['WarrantyExpiryDate']
            if datetime.now() < warrantyexpirydate:
                chatresponse['displayText'] = "The phone is under warranty"
                chatresponse['speech'] = "Your phone is under warranty"
            else:
                chatresponse['displayText'] = "The phone is not under warranty"
                chatresponse['speech'] = "Your phone is not under warranty"
        elif intentname == 'warranty_expiry_date':
            client = Client(
                'https://apiaiwebhookpassthough.herokuapp.com/static/content/EntitlementService.xml'
            )
            requesttype = client.get_element('ns2:EntitlementRequest')
            entitlementrequest = requesttype(
                BusinessOrgID=1,
                ProductTypeCode='P',
                RequestedByUserID='26may2017',
                SerialNumber=fulfilmentrequest['result']['parameters']['slno'],
                SymptomIDList='0707')
            response = client.service.Entitle(request=entitlementrequest)

            warrantyexpirydate = response['Entitlement']['WarrantyExpiryDate']
            if datetime.now() < warrantyexpirydate:
                chatresponse[
                    'displayText'] = "The warranty is valid till {}".format(
                        warrantyexpirydate)
                chatresponse[
                    'speech'] = "Your phone is under warranty till {}".format(
                        warrantyexpirydate)
            else:
                chatresponse['displayText'] = "The phone is not under warranty"
                chatresponse['speech'] = "Your phone is not under warranty"

        elif intentname == 'warranty_valid_duration':
            client = Client(
                'https://apiaiwebhookpassthough.herokuapp.com/static/content/EntitlementService.xml'
            )
            requesttype = client.get_element('ns2:EntitlementRequest')
            entitlementrequest = requesttype(
                BusinessOrgID=1,
                ProductTypeCode='P',
                RequestedByUserID='26may2017',
                SerialNumber=fulfilmentrequest['result']['parameters']['slno'],
                SymptomIDList='0707')
            response = client.service.Entitle(request=entitlementrequest)

            warrantyexpirydate = response['Entitlement']['WarrantyExpiryDate']
            if datetime.now() < warrantyexpirydate:
                warrantyvaliddays = (warrantyexpirydate -
                                     datetime.today()).days
                chatresponse[
                    'displayText'] = "The warranty is valid for next {} days".format(
                        warrantyvaliddays)
                chatresponse[
                    'speech'] = "Your phone is under warranty for {} days".format(
                        warrantyvaliddays)
            else:
                chatresponse['displayText'] = "The phone is not under warranty"
                chatresponse['speech'] = "Your phone is not under warranty"

    except Exception as e:
        chatresponse[
            'displayText'] = "Unable to find warranty details!  Please check the serial number and try again"
        chatresponse['speech'] = "Check the serial number and try again"

    return json.dumps(chatresponse)
コード例 #18
0
class SfdcMetadataApi:
    # pylint: disable=too-many-instance-attributes
    """ Class to work with Salesforce Metadata API """
    _METADATA_API_BASE_URI = "/services/Soap/m/{version}"
    _XML_NAMESPACES = {
        'soapenv': 'http://schemas.xmlsoap.org/soap/envelope/',
        'mt': 'http://soap.sforce.com/2006/04/metadata'
    }

    # pylint: disable=R0913
    def __init__(self, session, session_id, instance, metadata_url, headers,
                 api_version):
        """ Initialize and check session """
        self.session = session
        self._session_id = session_id
        self._instance = instance
        self.metadata_url = metadata_url
        self.headers = headers
        self._api_version = api_version
        self._deploy_zip = None
        wsdl_path = os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                 'metadata.wsdl')
        self._client = Client(
            os.path.join('simple_salesforce', wsdl_path),
            settings=Settings(strict=False, xsd_ignore_sequence_order=True))
        self._service = self._client.create_service(
            "{http://soap.sforce.com/2006/04/metadata}MetadataBinding",
            self.metadata_url)
        self._session_header = self._client.get_element('ns0:SessionHeader')(
            sessionId=self._session_id)

    def __getattr__(self, item):
        return MetadataType(item, self._service,
                            self._client.get_type('ns0:' + item),
                            self._session_header)

    def describe_metadata(self):
        """
        Performs a describeMetadata call

        :returns: An object of zeep.objects.DescribeMetadataResult
        """
        return self._service.describeMetadata(
            self._api_version, _soapheaders=[self._session_header])

    def list_metadata(self, queries):
        """
        Performs a listMetadata call

        :param queries: A list of zeep.objects.ListMetadataQuery that specify
        which components you are interested in.
                        Limit: 3
        :type queries: list
        :returns: List of zeep.objects.FileProperties objects
        :rtype: list
        """
        return self._service.listMetadata(queries,
                                          self._api_version,
                                          _soapheaders=[self._session_header])

    # pylint: disable=R0914
    # pylint: disable-msg=C0103
    def deploy(self, zipfile, sandbox, **kwargs):
        """ Kicks off async deployment, returns deployment id
        :param zipfile:
        :type zipfile:
        :param kwargs:
        :type kwargs:
        :return:
        :rtype:
        """
        client = kwargs.get('client', 'simple_salesforce_metahelper')
        checkOnly = kwargs.get('checkOnly', False)
        testLevel = kwargs.get('testLevel')
        tests = kwargs.get('tests')
        ignoreWarnings = kwargs.get('ignoreWarnings', False)
        allowMissingFiles = kwargs.get('allowMissingFiles', False)
        autoUpdatePackage = kwargs.get('autoUpdatePackage', False)
        performRetrieve = kwargs.get('performRetrieve', False)
        purgeOnDelete = kwargs.get('purgeOnDelete', False)
        rollbackOnError = kwargs.get('rollbackOnError', False)
        singlePackage = True

        attributes = {
            'client': client,
            'checkOnly': checkOnly,
            'sessionId': self._session_id,
            'ZipFile': self._read_deploy_zip(zipfile),
            'testLevel': testLevel,
            'tests': tests,
            'ignoreWarnings': ignoreWarnings,
            'allowMissingFiles': allowMissingFiles,
            'autoUpdatePackage': autoUpdatePackage,
            'performRetrieve': performRetrieve,
            'purgeOnDelete': purgeOnDelete,
            'rollbackOnError': rollbackOnError,
            'singlePackage': singlePackage,
        }

        if not sandbox:
            attributes['allowMissingFiles'] = False
            attributes['rollbackOnError'] = True

        if testLevel:
            test_level = "<met:testLevel>%s</met:testLevel>" % testLevel
            attributes['testLevel'] = test_level

        tests_tag = ''
        if tests and \
                str(testLevel).lower() == 'runspecifiedtests':
            for test in tests:
                tests_tag += '<met:runTests>%s</met:runTests>\n' % test
            attributes['tests'] = tests_tag

        request = DEPLOY_MSG.format(**attributes)

        headers = {'Content-Type': 'text/xml', 'SOAPAction': 'deploy'}
        result = call_salesforce(url=self.metadata_url + 'deployRequest',
                                 method='POST',
                                 session=self.session,
                                 headers=self.headers,
                                 additional_headers=headers,
                                 data=request)

        async_process_id = ET.fromstring(result.text).find(
            'soapenv:Body/mt:deployResponse/mt:result/mt:id',
            self._XML_NAMESPACES).text
        state = ET.fromstring(result.text).find(
            'soapenv:Body/mt:deployResponse/mt:result/mt:state',
            self._XML_NAMESPACES).text

        return async_process_id, state

    @staticmethod
    # pylint: disable=R1732
    def _read_deploy_zip(zipfile):
        """
        :param zipfile:
        :type zipfile:
        :return:
        :rtype:
        """
        if hasattr(zipfile, 'read'):
            file = zipfile
            file.seek(0)
            should_close = False
        else:
            file = open(zipfile, 'rb')
            should_close = True
        raw = file.read()
        if should_close:
            file.close()
        return b64encode(raw).decode("utf-8")

    def _retrieve_deploy_result(self, async_process_id, **kwargs):
        """ Retrieves status for specified deployment id
        :param async_process_id:
        :type async_process_id:
        :param kwargs:
        :type kwargs:
        :return:
        :rtype:
        """
        client = kwargs.get('client', 'simple_salesforce_metahelper')

        attributes = {
            'client': client,
            'sessionId': self._session_id,
            'asyncProcessId': async_process_id,
            'includeDetails': 'true'
        }
        mt_request = CHECK_DEPLOY_STATUS_MSG.format(**attributes)
        headers = {
            'Content-type': 'text/xml',
            'SOAPAction': 'checkDeployStatus'
        }

        res = call_salesforce(url=self.metadata_url + 'deployRequest/' +
                              async_process_id,
                              method='POST',
                              session=self.session,
                              headers=self.headers,
                              additional_headers=headers,
                              data=mt_request)

        root = ET.fromstring(res.text)
        result = root.find(
            'soapenv:Body/mt:checkDeployStatusResponse/mt:result',
            self._XML_NAMESPACES)
        if result is None:
            raise Exception("Result node could not be found: %s" % res.text)

        return result

    @staticmethod
    def get_component_error_count(value):
        """Get component error counts"""
        try:
            return int(value)
        except ValueError:
            return 0

    def check_deploy_status(self, async_process_id, **kwargs):
        """
        Checks whether deployment succeeded
        :param async_process_id:
        :type async_process_id:
        :param kwargs:
        :type kwargs:
        :return:
        :rtype:
        """
        result = self._retrieve_deploy_result(async_process_id, **kwargs)

        state = result.find('mt:status', self._XML_NAMESPACES).text
        state_detail = result.find('mt:stateDetail', self._XML_NAMESPACES)
        if state_detail is not None:
            state_detail = state_detail.text

        unit_test_errors = []
        deployment_errors = []
        failed_count = self.get_component_error_count(
            result.find('mt:numberComponentErrors', self._XML_NAMESPACES).text)
        if state == 'Failed' or failed_count > 0:
            # Deployment failures
            failures = result.findall('mt:details/mt:componentFailures',
                                      self._XML_NAMESPACES)
            for failure in failures:
                deployment_errors.append({
                    'type':
                    failure.find('mt:componentType',
                                 self._XML_NAMESPACES).text,
                    'file':
                    failure.find('mt:fileName', self._XML_NAMESPACES).text,
                    'status':
                    failure.find('mt:problemType', self._XML_NAMESPACES).text,
                    'message':
                    failure.find('mt:problem', self._XML_NAMESPACES).text
                })
            # Unit test failures
            failures = result.findall(
                'mt:details/mt:runTestResult/mt:failures',
                self._XML_NAMESPACES)
            for failure in failures:
                unit_test_errors.append({
                    'class':
                    failure.find('mt:name', self._XML_NAMESPACES).text,
                    'method':
                    failure.find('mt:methodName', self._XML_NAMESPACES).text,
                    'message':
                    failure.find('mt:message', self._XML_NAMESPACES).text,
                    'stack_trace':
                    failure.find('mt:stackTrace', self._XML_NAMESPACES).text
                })

        deployment_detail = {
            'total_count':
            result.find('mt:numberComponentsTotal', self._XML_NAMESPACES).text,
            'failed_count':
            result.find('mt:numberComponentErrors', self._XML_NAMESPACES).text,
            'deployed_count':
            result.find('mt:numberComponentsDeployed',
                        self._XML_NAMESPACES).text,
            'errors':
            deployment_errors
        }
        unit_test_detail = {
            'total_count':
            result.find('mt:numberTestsTotal', self._XML_NAMESPACES).text,
            'failed_count':
            result.find('mt:numberTestErrors', self._XML_NAMESPACES).text,
            'completed_count':
            result.find('mt:numberTestsCompleted', self._XML_NAMESPACES).text,
            'errors':
            unit_test_errors
        }

        return state, state_detail, deployment_detail, unit_test_detail

    def download_unit_test_logs(self, async_process_id):
        """ Downloads Apex logs for unit tests executed during specified
        deployment """
        result = self._retrieve_deploy_result(async_process_id)
        print("response: %s" %
              ET.tostring(result, encoding="us-ascii", method="xml"))

    def retrieve(self, async_process_id, **kwargs):
        """ Submits retrieve request """
        # Compose unpackaged XML
        client = kwargs.get('client', 'simple_salesforce_metahelper')
        single_package = kwargs.get('single_package', True)

        if not isinstance(single_package, bool):
            raise TypeError('single_package must be bool')

        unpackaged = ''
        if kwargs.get('unpackaged'):
            for metadata_type in kwargs.get('unpackaged'):
                if isinstance(kwargs.get('unpackaged'), dict):
                    members = kwargs.get('unpackaged')[metadata_type]
                    unpackaged += '<types>'
                    for member in members:
                        unpackaged += '<members>{member}</members>'.format(
                            member=member)
                    unpackaged += '<name>{metadata_type}</name></types>'.format(
                        metadata_type=metadata_type)
                else:
                    raise TypeError('unpackaged metadata types must be a dict')

        # Compose retrieve request XML
        attributes = {
            'client': client,
            'sessionId': self._session_id,
            'apiVersion': self._api_version,
            'singlePackage': single_package,
            'unpackaged': unpackaged
        }
        request = RETRIEVE_MSG.format(**attributes)
        # Submit request
        headers = {'Content-type': 'text/xml', 'SOAPAction': 'retrieve'}

        res = call_salesforce(url=self.metadata_url + 'deployRequest/' +
                              async_process_id,
                              method='POST',
                              session=self.session,
                              headers=self.headers,
                              additional_headers=headers,
                              data=request)

        # Parse response to get async Id and status
        async_process_id = ET.fromstring(res.text).find(
            'soapenv:Body/mt:retrieveResponse/mt:result/mt:id',
            self._XML_NAMESPACES).text
        state = ET.fromstring(res.text).find(
            'soapenv:Body/mt:retrieveResponse/mt:result/mt:state',
            self._XML_NAMESPACES).text

        return async_process_id, state

    def retrieve_retrieve_result(self, async_process_id, include_zip,
                                 **kwargs):
        """ Retrieves status for specified retrieval id """
        client = kwargs.get('client', 'simple_salesforce_metahelper')
        attributes = {
            'client': client,
            'sessionId': self._session_id,
            'asyncProcessId': async_process_id,
            'includeZip': include_zip
        }
        mt_request = CHECK_RETRIEVE_STATUS_MSG.format(**attributes)
        headers = {
            'Content-type': 'text/xml',
            'SOAPAction': 'checkRetrieveStatus'
        }
        res = call_salesforce(url=self.metadata_url + 'deployRequest/' +
                              async_process_id,
                              method='POST',
                              session=self.session,
                              headers=self.headers,
                              additional_headers=headers,
                              data=mt_request)

        root = ET.fromstring(res.text)
        result = root.find(
            'soapenv:Body/mt:checkRetrieveStatusResponse/mt:result',
            self._XML_NAMESPACES)
        if result is None:
            raise Exception("Result node could not be found: %s" % res.text)

        return result

    def retrieve_zip(self, async_process_id, **kwargs):
        """ Retrieves ZIP file """
        result = self.retrieve_retrieve_result(async_process_id, 'true',
                                               **kwargs)
        state = result.find('mt:status', self._XML_NAMESPACES).text
        error_message = result.find('mt:errorMessage', self._XML_NAMESPACES)
        if error_message is not None:
            error_message = error_message.text

        # Check if there are any messages
        messages = []
        message_list = result.findall('mt:details/mt:messages',
                                      self._XML_NAMESPACES)
        for message in message_list:
            messages.append({
                'file':
                message.find('mt:fileName', self._XML_NAMESPACES).text,
                'message':
                message.find('mt:problem', self._XML_NAMESPACES).text
            })

        # Retrieve base64 encoded ZIP file
        zipfile_base64 = result.find('mt:zipFile', self._XML_NAMESPACES).text
        zipfile = b64decode(zipfile_base64)

        return state, error_message, messages, zipfile

    def check_retrieve_status(self, async_process_id, **kwargs):
        """ Checks whether retrieval succeeded """
        result = self.retrieve_retrieve_result(async_process_id, 'false',
                                               **kwargs)
        state = result.find('mt:status', self._XML_NAMESPACES).text
        error_message = result.find('mt:errorMessage', self._XML_NAMESPACES)
        if error_message is not None:
            error_message = error_message.text

        # Check if there are any messages
        messages = []
        message_list = result.findall('mt:details/mt:messages',
                                      self._XML_NAMESPACES)
        for message in message_list:
            messages.append({
                'file':
                message.find('mt:fileName', self._XML_NAMESPACES).text,
                'message':
                message.find('mt:problem', self._XML_NAMESPACES).text
            })

        return state, error_message, messages