async def file_not_found(req_text):
     await logger.warning(f'Cant find {req_text}; {FileNotFoundError}')
     return web.HTTPBadRequest(reason=req_text)
Exemple #2
0
async def create_jobs(request, userdata):
    app = request.app
    db = app['db']
    log_store = app['log_store']

    worker_type = app['worker_type']
    worker_cores = app['worker_cores']

    batch_id = int(request.match_info['batch_id'])

    user = userdata['username']
    # restrict to what's necessary; in particular, drop the session
    # which is sensitive
    userdata = {
        'username': user,
        'bucket_name': userdata['bucket_name'],
        'gsa_key_secret_name': userdata['gsa_key_secret_name'],
        'tokens_secret_name': userdata['tokens_secret_name']
    }

    async with LoggingTimer(f'batch {batch_id} create jobs') as timer:
        async with timer.step('fetch batch'):
            record = await db.select_and_fetchone(
                '''
SELECT `state`, format_version FROM batches
WHERE user = %s AND id = %s AND NOT deleted;
''', (user, batch_id))

        if not record:
            raise web.HTTPNotFound()
        if record['state'] != 'open':
            raise web.HTTPBadRequest(reason=f'batch {batch_id} is not open')
        batch_format_version = BatchFormatVersion(record['format_version'])

        async with timer.step('get request json'):
            job_specs = await request.json()

        async with timer.step('validate job_specs'):
            try:
                validate_jobs(job_specs)
            except ValidationError as e:
                raise web.HTTPBadRequest(reason=e.reason)

        async with timer.step('build db args'):
            spec_writer = SpecWriter(log_store, batch_id)

            jobs_args = []
            job_parents_args = []
            job_attributes_args = []

            n_ready_jobs = 0
            ready_cores_mcpu = 0
            n_ready_cancellable_jobs = 0
            ready_cancellable_cores_mcpu = 0

            prev_job_idx = None
            start_job_id = None

            for spec in job_specs:
                job_id = spec['job_id']
                parent_ids = spec.pop('parent_ids', [])
                always_run = spec.pop('always_run', False)

                if batch_format_version.has_full_spec_in_gcs():
                    attributes = spec.pop('attributes', None)
                else:
                    attributes = spec.get('attributes')

                id = (batch_id, job_id)

                if start_job_id is None:
                    start_job_id = job_id

                if batch_format_version.has_full_spec_in_gcs(
                ) and prev_job_idx:
                    if job_id != prev_job_idx + 1:
                        raise web.HTTPBadRequest(
                            reason=
                            f'noncontiguous job ids found in the spec: {prev_job_idx} -> {job_id}'
                        )
                prev_job_idx = job_id

                resources = spec.get('resources')
                if not resources:
                    resources = {}
                    spec['resources'] = resources
                if 'cpu' not in resources:
                    resources['cpu'] = BATCH_JOB_DEFAULT_CPU
                if 'memory' not in resources:
                    resources['memory'] = BATCH_JOB_DEFAULT_MEMORY

                req_cores_mcpu = parse_cpu_in_mcpu(resources['cpu'])
                req_memory_bytes = parse_memory_in_bytes(resources['memory'])

                if req_cores_mcpu == 0:
                    raise web.HTTPBadRequest(
                        reason=f'bad resource request for job {id}: '
                        f'cpu cannot be 0')

                cores_mcpu = adjust_cores_for_memory_request(
                    req_cores_mcpu, req_memory_bytes, worker_type)

                if cores_mcpu > worker_cores * 1000:
                    total_memory_available = worker_memory_per_core_gb(
                        worker_type) * worker_cores
                    raise web.HTTPBadRequest(
                        reason=
                        f'resource requests for job {id} are unsatisfiable: '
                        f'requested: cpu={resources["cpu"]}, memory={resources["memory"]} '
                        f'maximum: cpu={worker_cores}, memory={total_memory_available}G'
                    )

                secrets = spec.get('secrets')
                if not secrets:
                    secrets = []
                    spec['secrets'] = secrets
                secrets.append({
                    'namespace': BATCH_PODS_NAMESPACE,
                    'name': userdata['gsa_key_secret_name'],
                    'mount_path': '/gsa-key',
                    'mount_in_copy': True
                })

                env = spec.get('env')
                if not env:
                    env = []
                    spec['env'] = env

                if len(parent_ids) == 0:
                    state = 'Ready'
                    n_ready_jobs += 1
                    ready_cores_mcpu += cores_mcpu
                    if not always_run:
                        n_ready_cancellable_jobs += 1
                        ready_cancellable_cores_mcpu += cores_mcpu
                else:
                    state = 'Pending'

                spec_writer.add(json.dumps(spec))
                db_spec = batch_format_version.db_spec(spec)

                jobs_args.append((batch_id, job_id, state, json.dumps(db_spec),
                                  always_run, cores_mcpu, len(parent_ids)))

                for parent_id in parent_ids:
                    job_parents_args.append((batch_id, job_id, parent_id))

                if attributes:
                    for k, v in attributes.items():
                        job_attributes_args.append((batch_id, job_id, k, v))

        if batch_format_version.has_full_spec_in_gcs():
            async with timer.step('write spec to gcs'):
                await spec_writer.write()

        rand_token = random.randint(0, app['n_tokens'] - 1)
        n_jobs = len(job_specs)

        async with timer.step('insert jobs'):

            @transaction(db)
            async def insert(tx):
                try:
                    await tx.execute_many(
                        '''
INSERT INTO jobs (batch_id, job_id, state, spec, always_run, cores_mcpu, n_pending_parents)
VALUES (%s, %s, %s, %s, %s, %s, %s);
''', jobs_args)
                except pymysql.err.IntegrityError as err:
                    # 1062 ER_DUP_ENTRY https://dev.mysql.com/doc/refman/5.7/en/server-error-reference.html#error_er_dup_entry
                    if err.args[0] == 1062:
                        log.info(
                            f'bunch containing job {(batch_id, jobs_args[0][1])} already inserted ({err})'
                        )
                        raise web.Response()
                    raise
                await tx.execute_many(
                    '''
INSERT INTO `job_parents` (batch_id, job_id, parent_id)
VALUES (%s, %s, %s);
''', job_parents_args)
                await tx.execute_many(
                    '''
INSERT INTO `job_attributes` (batch_id, job_id, `key`, `value`)
VALUES (%s, %s, %s, %s);
''', job_attributes_args)
                await tx.execute_update(
                    '''
INSERT INTO batches_staging (batch_id, token, n_jobs, n_ready_jobs, ready_cores_mcpu)
VALUES (%s, %s, %s, %s, %s)
ON DUPLICATE KEY UPDATE
  n_jobs = n_jobs + %s,
  n_ready_jobs = n_ready_jobs + %s,
  ready_cores_mcpu = ready_cores_mcpu + %s;
''', (batch_id, rand_token, n_jobs, n_ready_jobs, ready_cores_mcpu, n_jobs,
                n_ready_jobs, ready_cores_mcpu))
                await tx.execute_update(
                    '''
INSERT INTO batch_cancellable_resources (batch_id, token, n_ready_cancellable_jobs, ready_cancellable_cores_mcpu)
VALUES (%s, %s, %s, %s)
ON DUPLICATE KEY UPDATE
  n_ready_cancellable_jobs = n_ready_cancellable_jobs + %s,
  ready_cancellable_cores_mcpu = ready_cancellable_cores_mcpu + %s;
''', (batch_id, rand_token, n_ready_cancellable_jobs,
                ready_cancellable_cores_mcpu, n_ready_cancellable_jobs,
                ready_cancellable_cores_mcpu))

                if batch_format_version.has_full_spec_in_gcs():
                    await tx.execute_update(
                        '''
INSERT INTO batch_bunches (batch_id, token, start_job_id)
VALUES (%s, %s, %s);
''', (batch_id, spec_writer.token, start_job_id))

            await insert()  # pylint: disable=no-value-for-parameter
    return web.Response()
async def presentation_exchange_send_proposal(request: web.BaseRequest):
    """
    Request handler for sending a presentation proposal.

    Args:
        request: aiohttp request object

    Returns:
        The presentation exchange details

    """
    r_time = get_timer()

    context: AdminRequestContext = request["context"]
    profile = context.profile
    outbound_handler = request["outbound_message_router"]

    body = await request.json()

    comment = body.get("comment")
    connection_id = body.get("connection_id")

    # Aries RFC 37 calls it a proposal in the proposal struct but it's of type preview
    presentation_preview = body.get("presentation_proposal")
    connection_record = None
    async with profile.session() as session:
        try:
            connection_record = await ConnRecord.retrieve_by_id(
                session, connection_id)
            presentation_proposal_message = PresentationProposal(
                comment=comment,
                presentation_proposal=IndyPresPreview.deserialize(
                    presentation_preview),
            )
        except (BaseModelError, StorageError) as err:
            # other party does not care about our false protocol start
            raise web.HTTPBadRequest(reason=err.roll_up)

    if not connection_record.is_ready:
        raise web.HTTPForbidden(reason=f"Connection {connection_id} not ready")

    trace_msg = body.get("trace")
    presentation_proposal_message.assign_trace_decorator(
        context.settings,
        trace_msg,
    )
    auto_present = body.get(
        "auto_present",
        context.settings.get("debug.auto_respond_presentation_request"))

    presentation_manager = PresentationManager(profile)
    pres_ex_record = None
    try:
        pres_ex_record = await presentation_manager.create_exchange_for_proposal(
            connection_id=connection_id,
            presentation_proposal_message=presentation_proposal_message,
            auto_present=auto_present,
        )
        result = pres_ex_record.serialize()
    except (BaseModelError, StorageError) as err:
        if pres_ex_record:
            async with profile.session() as session:
                await pres_ex_record.save_error_state(session,
                                                      reason=err.roll_up)
        # other party does not care about our false protocol start
        raise web.HTTPBadRequest(reason=err.roll_up)

    await outbound_handler(presentation_proposal_message,
                           connection_id=connection_id)

    trace_event(
        context.settings,
        presentation_proposal_message,
        outcome="presentation_exchange_propose.END",
        perf_counter=r_time,
    )

    return web.json_response(result)
def validate_output_dir(output_dir: str):
    """Checks that output_dir doesn't start with 'gs://' and strips trailing slashes."""
    if output_dir.startswith('gs://'):
        raise web.HTTPBadRequest(
            reason='Output directory cannot start with "gs://"')
    return output_dir.rstrip('/')  # Strip trailing slash.
Exemple #5
0
def route(request):

    session = yield from get_session(request)
    if 'uid' in session:
        uid = session['uid']
    else:
        return web.HTTPForbidden()

    query_parameters = request.rel_url.query
    try:
        fid = int(query_parameters["fid"])
        fid = str(fid).zfill(8)
    except:
        return web.HTTPBadRequest()

    if request.content_type != "multipart/form-data":
        return web.HTTPBadRequest()

    try:
        reader = yield from request.multipart()
    except Exception:
        return web.HTTPBadRequest()

    next = yield from reader.next()

    photo_dir = os.path.join(request.app["photo_dir"], fid)

    if os.path.exists(photo_dir) == 0:
        os.mkdir(photo_dir)

    size = 0
    suffix = ''
    hash_calc = hashlib.md5()

    while True:
        try:
            chunk = yield from next.read_chunk()  # 8192 bytes by default
        except Exception:
            return web.HTTPBadRequest()

        if not chunk:
            break

        if size == 0:

            if len(chunk) < 4:
                return web.HTTPBadRequest()

            top_eight_bytes = ''.join('{:02x}'.format(x)
                                      for x in chunk[0:4]).upper()

            if top_eight_bytes[0:6] == 'FFD8FF':
                suffix = "jpg"
            elif top_eight_bytes[0:8] == '89504E47':
                suffix = "png"
            elif top_eight_bytes[0:8] == '47494638':
                suffix = "gif"
            else:
                return web.HTTPBadRequest()

            while True:
                temp_name = str(int(time.time())) + str(random.randint(
                    0, 9999)).zfill(4)
                temp_file = os.path.join(photo_dir, temp_name)
                if not os.path.exists(temp_file):
                    break

            file = open(temp_file, 'wb')

        size = size + len(chunk)
        file.write(chunk)
        hash_calc.update(chunk)

        if size / 1048576 > 2:  # size limit 2MB
            file.close()
            os.remove(temp_file)
            return web.HTTPRequestEntityTooLarge()

    file.close()
    hash_value = hash_calc.hexdigest()
    formal_name = hash_value + "." + suffix
    formal_file = os.path.join(photo_dir, formal_name)

    if os.path.exists(formal_file) != 0:
        os.remove(temp_file)
    else:
        os.rename(temp_file, formal_file)

    # with (yield from request.app['pool']) as connect:

    #    cursor = yield from connect.cursor()

    #    try:
    #        yield from cursor.execute('''
    #            INSERT INTO photo VALUES(%s,%s,%s,%s)
    #        ''',(hash_value,fid,suffix,0))
    #        yield from connect.commit()
    #    except Exception as e:
    #        print(e)

    #    yield from cursor.close()
    #    connect.close()

    return web.Response(text=toolbox.jsonify({"filename": formal_name}),
                        # headers = {'Access-Control-Allow-Origin':'*'}
                        )
Exemple #6
0
async def credential_exchange_send(request: web.BaseRequest):
    """
    Request handler for sending credential from issuer to holder from attr values.

    If both issuer and holder are configured for automatic responses, the operation
    ultimately results in credential issue; otherwise, the result waits on the first
    response not automated; the credential exchange record retains state regardless.

    Args:
        request: aiohttp request object

    Returns:
        The credential exchange record

    """
    r_time = get_timer()

    context = request.app["request_context"]
    outbound_handler = request.app["outbound_message_router"]

    body = await request.json()

    comment = body.get("comment")
    connection_id = body.get("connection_id")
    preview_spec = body.get("credential_proposal")
    if not preview_spec:
        raise web.HTTPBadRequest(reason="credential_proposal must be provided")
    auto_remove = body.get("auto_remove")
    trace_msg = body.get("trace")

    connection_record = None
    cred_ex_record = None
    try:
        preview = CredentialPreview.deserialize(preview_spec)
        connection_record = await ConnectionRecord.retrieve_by_id(
            context, connection_id)
        if not connection_record.is_ready:
            raise web.HTTPForbidden(
                reason=f"Connection {connection_id} not ready")

        credential_proposal = CredentialProposal(
            comment=comment,
            credential_proposal=preview,
            **{t: body.get(t)
               for t in CRED_DEF_TAGS if body.get(t)},
        )
        credential_proposal.assign_trace_decorator(
            context.settings,
            trace_msg,
        )

        trace_event(
            context.settings,
            credential_proposal,
            outcome="credential_exchange_send.START",
        )

        credential_manager = CredentialManager(context)
        (
            cred_ex_record,
            credential_offer_message,
        ) = await credential_manager.prepare_send(
            connection_id,
            credential_proposal=credential_proposal,
            auto_remove=auto_remove,
        )
        result = cred_ex_record.serialize()
    except (StorageError, BaseModelError, CredentialManagerError) as err:
        await internal_error(
            err,
            web.HTTPBadRequest,
            cred_ex_record or connection_record,
            outbound_handler,
        )

    await outbound_handler(credential_offer_message,
                           connection_id=cred_ex_record.connection_id)

    trace_event(
        context.settings,
        credential_offer_message,
        outcome="credential_exchange_send.END",
        perf_counter=r_time,
    )

    return web.json_response(result)
Exemple #7
0
async def credential_exchange_send_free_offer(request: web.BaseRequest):
    """
    Request handler for sending free credential offer.

    An issuer initiates a such a credential offer, free from any
    holder-initiated corresponding credential proposal with preview.

    Args:
        request: aiohttp request object

    Returns:
        The credential exchange record

    """
    r_time = get_timer()

    context = request.app["request_context"]
    outbound_handler = request.app["outbound_message_router"]

    body = await request.json()

    connection_id = body.get("connection_id")
    cred_def_id = body.get("cred_def_id")
    if not cred_def_id:
        raise web.HTTPBadRequest(reason="cred_def_id is required")

    auto_issue = body.get(
        "auto_issue",
        context.settings.get("debug.auto_respond_credential_request"))

    auto_remove = body.get("auto_remove")
    comment = body.get("comment")
    preview_spec = body.get("credential_preview")
    if not preview_spec:
        raise web.HTTPBadRequest(reason=("Missing credential_preview"))
    trace_msg = body.get("trace")

    cred_ex_record = None
    connection_record = None
    try:
        connection_record = await ConnectionRecord.retrieve_by_id(
            context, connection_id)
        if not connection_record.is_ready:
            raise web.HTTPForbidden(
                reason=f"Connection {connection_id} not ready")

        (
            cred_ex_record,
            credential_offer_message,
        ) = await _create_free_offer(
            context,
            cred_def_id,
            connection_id,
            auto_issue,
            auto_remove,
            preview_spec,
            comment,
            trace_msg,
        )
        result = cred_ex_record.serialize()
    except (
            StorageNotFoundError,
            BaseModelError,
            CredentialManagerError,
            LedgerError,
    ) as err:
        await internal_error(
            err,
            web.HTTPBadRequest,
            cred_ex_record or connection_record,
            outbound_handler,
        )

    await outbound_handler(credential_offer_message,
                           connection_id=connection_id)

    trace_event(
        context.settings,
        credential_offer_message,
        outcome="credential_exchange_send_free_offer.END",
        perf_counter=r_time,
    )

    return web.json_response(result)
Exemple #8
0
async def present_proof_send_free_request(request: web.BaseRequest):
    """
    Request handler for sending a presentation request free from any proposal.

    Args:
        request: aiohttp request object

    Returns:
        The presentation exchange details

    """
    r_time = get_timer()

    context: AdminRequestContext = request["context"]
    outbound_handler = request["outbound_message_router"]

    body = await request.json()

    connection_id = body.get("connection_id")
    async with context.session() as session:
        try:
            conn_record = await ConnRecord.retrieve_by_id(session, connection_id)
        except StorageNotFoundError as err:
            raise web.HTTPBadRequest(reason=err.roll_up) from err

    if not conn_record.is_ready:
        raise web.HTTPForbidden(reason=f"Connection {connection_id} not ready")

    comment = body.get("comment")
    pres_request_spec = body.get("presentation_request")
    if pres_request_spec and V20PresFormat.Format.INDY.api in pres_request_spec:
        await _add_nonce(pres_request_spec[V20PresFormat.Format.INDY.api])
    pres_request_message = V20PresRequest(
        comment=comment,
        will_confirm=True,
        **_formats_attach(pres_request_spec, PRES_20_REQUEST, "request_presentations"),
    )
    trace_msg = body.get("trace")
    pres_request_message.assign_trace_decorator(
        context.settings,
        trace_msg,
    )

    pres_manager = V20PresManager(context.profile)
    pres_ex_record = None
    try:
        pres_ex_record = await pres_manager.create_exchange_for_request(
            connection_id=connection_id,
            pres_request_message=pres_request_message,
        )
        result = pres_ex_record.serialize()
    except (BaseModelError, StorageError) as err:
        if pres_ex_record:
            async with context.session() as session:
                await pres_ex_record.save_error_state(session, reason=err.roll_up)
        # other party does not care about our false protocol start
        raise web.HTTPBadRequest(reason=err.roll_up)

    await outbound_handler(pres_request_message, connection_id=connection_id)

    trace_event(
        context.settings,
        pres_request_message,
        outcome="presentation_exchange_send_request.END",
        perf_counter=r_time,
    )

    return web.json_response(result)
Exemple #9
0
async def present_proof_send_presentation(request: web.BaseRequest):
    """
    Request handler for sending a presentation.

    Args:
        request: aiohttp request object

    Returns:
        The presentation exchange details

    """
    r_time = get_timer()

    context: AdminRequestContext = request["context"]
    outbound_handler = request["outbound_message_router"]
    pres_ex_id = request.match_info["pres_ex_id"]
    body = await request.json()
    fmt = V20PresFormat.Format.get([f for f in body][0])  # "indy" xor "dif"

    pres_ex_record = None
    async with context.session() as session:
        try:
            pres_ex_record = await V20PresExRecord.retrieve_by_id(session, pres_ex_id)
        except StorageNotFoundError as err:
            raise web.HTTPNotFound(reason=err.roll_up) from err

        if pres_ex_record.state != (V20PresExRecord.STATE_REQUEST_RECEIVED):
            raise web.HTTPBadRequest(
                reason=(
                    f"Presentation exchange {pres_ex_id} "
                    f"in {pres_ex_record.state} state "
                    f"(must be {V20PresExRecord.STATE_REQUEST_RECEIVED})"
                )
            )

        connection_id = pres_ex_record.connection_id
        try:
            conn_record = await ConnRecord.retrieve_by_id(session, connection_id)
        except StorageNotFoundError as err:
            raise web.HTTPBadRequest(reason=err.roll_up) from err

    if not conn_record.is_ready:
        raise web.HTTPForbidden(reason=f"Connection {connection_id} not ready")

    pres_manager = V20PresManager(context.profile)
    try:
        indy_spec = body.get(V20PresFormat.Format.INDY.api)  # TODO: accommodate DIF
        pres_ex_record, pres_message = await pres_manager.create_pres(
            pres_ex_record,
            {
                "self_attested_attributes": indy_spec["self_attested_attributes"],
                "requested_attributes": indy_spec["requested_attributes"],
                "requested_predicates": indy_spec["requested_predicates"],
            },
            comment=body.get("comment"),
            format_=fmt,
        )
        result = pres_ex_record.serialize()
    except (
        BaseModelError,
        IndyHolderError,
        LedgerError,
        StorageError,
        WalletNotFoundError,
    ) as err:
        async with context.session() as session:
            await pres_ex_record.save_error_state(session, reason=err.roll_up)
        # other party cares that we cannot continue protocol
        await report_problem(
            err,
            ProblemReportReason.ABANDONED.value,
            web.HTTPBadRequest,
            pres_ex_record,
            outbound_handler,
        )
    trace_msg = body.get("trace")
    pres_message.assign_trace_decorator(
        context.settings,
        trace_msg,
    )
    await outbound_handler(pres_message, connection_id=connection_id)

    trace_event(
        context.settings,
        pres_message,
        outcome="presentation_exchange_send_request.END",
        perf_counter=r_time,
    )

    return web.json_response(result)
Exemple #10
0
 async def _handler(self, request):
     # 当有请求时, 从`request`中获取必要的参数, 调用URL函数
     kw = None
     # 如果需要参数
     if self.has_var_kw_arg or self.has_name_kw_args:
         # 有 **kw 或 命名关键字参数
         if request.method == 'POST':
             if not request.content_type:
                 return web.HTTPBadRequest(text='No content_type.')
             content_type = request.content_type.lower()
             if content_type.startswith('application/json'):
                 params = await request.json()
                 if not isinstance(params, dict):
                     return web.HTTPBadRequest(text='Body must be json.')
                 kw = params
             elif content_type.startswith(
                     'application/x-www-form-urlencoded'
             ) or content_type.startswith('multipart/form-data'):
                 params = await request.post()
                 kw = dict(**params)
             else:
                 return web.HTTPBadRequest(
                     text='Unsupported Content-Type: {}.'.format(
                         request.content_type))
         if request.method == 'GET':
             query_string = request.query_string
             if query_string:
                 kw = dict()
                 for k, v in parse.parse_qs(query_string, True).items():
                     kw[k] = v[0]
     # 不需要参数 或 没有取到参数
     if kw is None:
         kw = dict(**request.match_info)
     else:
         # 取到参数 且没有 **kw
         if not self.has_var_kw_arg:
             copy = dict()
             # 只取出需要的参数
             for name in self.get_name_kw_args:
                 if name in kw:
                     copy[name] = kw[name]
             kw = copy
         # 把request的信息添加到kw
         for k, v in request.match_info.items():
             if k in kw:
                 logging.warning('Duplicate arg name {}:{} --> {}.'.format(
                     k, kw[k], v))
             kw[k] = v
     if self.has_request_arg:
         kw['request'] = request
     # 如果存在没有默认值的必需参数
     # if self.get_required_kw_args:
     for name in self.get_required_kw_args:
         if name not in kw:
             return web.HTTPBadRequest(
                 text='Missing argument: {}.'.format(name))
     logging.debug("[RequestHandler]:get response by: {}({})".format(
         self.func_name, str(kw)))
     try:
         rs = await self.func(**kw)
         return rs
     except APIError as e:
         logging.warning(
             '[APIError]: error_type:{}, error_kw:{}, message:{}'.format(
                 e.error_type, e.error_kw, e.message))
         return dict(error_type=e.error_type,
                     error_kw=e.error_kw,
                     message=e.message)
 async def __call__(self, request):
     kw = None
     if self._has_var_kw_arg or self._has_named_kw_args or self._required_kw_args:
         # 当传入的处理函数具有 关键字参数集 或 命名关键字参数 或 request参数
         if request.method == 'POST':
             # POST请求预处理
             if not request.content_type:
                 # 无正文类型信息时返回
                 return web.HTTPBadRequest('Missing Content-Type.')
             ct = request.content_type.lower()
             if ct.startswith('application/json'):
                 # 处理JSON类型的数据,传入参数字典中
                 params = await request.json()
                 if not isinstance(params, dict):
                     return web.HTTPBadRequest('JSON body must be object.')
                 kw = params
             elif ct.startswith('application/x-www-form-urlencoded') or ct.startswith('multipart/form-data'):
                 # 处理表单类型的数据,传入参数字典中
                 params = await request.post()
                 kw = dict(**params)
             else:
                 # 暂不支持处理其他正文类型的数据
                 return web.HTTPBadRequest('Unsupported Content-Type: %s' % request.content_type)
         if request.method == 'GET':
             # GET请求预处理
             qs = request.query_string
             # 获取URL中的请求参数,如 name=Justone, id=007
             if qs:
                 # 将请求参数传入参数字典中
                 kw = dict()
                 for k, v in parse.parse_qs(qs, True).items():
                     kw[k] = v[0]
     if kw is None:
         # 请求无请求参数时
         kw = dict(**request.match_info)
     else:
         # 参数字典收集请求参数
         if not self._has_var_kw_arg and self._named_kw_args:
             # remove all unamed kw:
             copy = dict()
             for name in self._named_kw_args:
                 if name in kw:
                     copy[name] = kw[name]
             kw = copy
         # check named arg:
         for k, v in request.match_info.items():
             if k in kw:
                 logging.warning('Duplicate arg name in named arg and kw args: %s' % k)
             kw[k] = v
     if self._has_request_arg:
         kw['request'] = request
     # check required kw:
     if self._required_kw_args:
         # 收集无默认值的关键字参数
         for name in self._required_kw_args:
             if not name in kw:
                 # 当存在关键字参数未被赋值时返回,例如 一般的账号注册时,没填入密码就提交注册申请时,提示密码未输入
                 return web.HTTPBadRequest('Missing argument: %s' % name)
     logging.info('call with args: %s' % str(kw))
     try:
         r = await self._func(**kw)
         # 最后调用处理函数,并传入请求参数,进行请求处理
         return r
     except APIError as e:
         return dict(error=e.error, data=e.data, message=e.message)
Exemple #12
0
async def objectsonline(request: web.Request) -> web.Response:
    """
    ---
    description: Takes several paraemeters (coordinates and a heading) and determines possible objects along that line
    tags:
        - Destination Prediction
    parameters:
        - in: query
          name: x
          type: number
          description: X Corrdinate
          required: true
        - in: query
          name: y
          type: number
          description: Y Coordinate
          required: true
        - in: query
          name: z
          type: number
          description: Z Corrdinate
          required: true
        - in: query
          name: yaw
          type: number
          description: Yaw angle
        - in: query
          name: pitch 
          type: number
          description: Pitch Angle
        - in: query
          name: speed
          description: Speed the object was travelling at
          type: number
          default: 16
        - in: query
          name: sdist
          description: Distance to use as the same object (for help with clusters)
          default: 50
          required: false
          type: number
        - in: query
          name: frame
          type: string
          description: Name of the empire for the frame the coordinates are in
          required: false
        - in: query
          name: output
          type: string
          default: csv
          description: Switched output from plaintext
        - in: query
          name: radius
          type: number
          description: Length of the virutal line used to determine matches default 1000
          required: false
          default: 1000
    produces:
        - text/plain
    responses:
        "200": 
            description: "Successfully was able to caculate objects, even if none were returned"
        "400":
            description: "An error in the query was detected"
    """
    frame = None
    x = float(request.query.get('x'))
    y = float(request.query.get('y'))
    z = float(request.query.get('z'))
    yaw = float(request.query.get('yaw'))
    pitch = float(request.query.get('pitch'))
    frame_slug = request.query.get('frame', None)
    speed = float(request.query.get('speed', 16))
    output = request.query.get('output', 'csv')
    sdist = float(request.query.get('sdist', 50))
    d = float(request.query.get('radius', 1000))
    if frame_slug and frame_slug not in request.app['atsborders']:
        for k in request.app['atsborders'].keys():
            if frame_slug.lower() in k.lower():
                frame = k
    elif frame_slug in request.app['atsborders']:
        frame = frame_slug
    elif not frame_slug:
        frame = None
    else:
        return web.HTTPBadRequest(
            body=
            "Frame {} is not a valid frame, these are the currently valid frames: {}"
            .format(frame_slug, request.app['atsborders'].keys()))
    if output.lower() == "json":
        l = objectprediction(output.lower(), request.app['atsborders'],
                             request.app['atsdb'], x, y, z, yaw, pitch, frame,
                             speed, d, sdist)
        return web.json_response(l)
    else:
        return web.Response(body=objectprediction(
            output.lower(), request.app['atsborders'], request.app['atsdb'], x,
            y, z, yaw, pitch, frame, speed, d))
Exemple #13
0
#!/usr/bin/env python3
Exemple #14
0
	async def __call__(self, request):
		' 分析请求,request handler,must be a coroutine that accepts a request instance as its only argument and returns a streamresponse derived instance '
		kw = None
		if self._has_var_kw_arg or self._has_named_kw_args or self._required_kw_args:
			# 当传入的处理函数具有 关键字参数集 或 命名关键字参数 或 request参数
			if request.method == 'POST':
				# POST请求预处理
				if not request.content_type:
					# 无正文类型信息时返回
					return web.HTTPBadRequest('Missing Content-Type.')
				ct = request.content_type.lower()
				if ct.startswith('application/json'):
					# 处理JSON类型的数据,传入参数字典中
					params = await request.json()
					if not isinstance(params, dict):
						return web.HTTPBadRequest('JSON body must be object.')
					kw = params
				elif ct.startswith('application/x-www-form-urlencoded') or ct.startswith('multipart/form-data'):
					# 处理表单类型的数据,传入参数字典中
					params = await request.post()
					kw = dict(**params)
				else:
					# 暂不支持处理其他正文类型的数据
					return web.HTTPBadRequest('Unsupported Content-Type: %s' % request.content_type)
			if request.method == 'GET':
				# GET请求预处理
				qs = request.query_string
				# 获取URL中的请求参数,如 name=Justone, id=007
				if qs:
					# 将请求参数传入参数字典中
					kw = dict()
					for k, v in parse.parse_qs(qs, True).items():
						# parse a query string, data are returned as a dict. the dict keys are the unique query variable names and the values are lists of values for each name
						# a True value indicates that blanks should be retained as blank strings
						kw[k] = v[0]
		if kw is None:
			# 请求无请求参数时
			kw = dict(**request.match_info)
			# Read-only property with AbstractMatchInfo instance for result of route resolving
		else:
			# 参数字典收集请求参数
			if not self._has_var_kw_arg and self._named_kw_args:
				copy = dict()
				for name in self._named_kw_args:
					if name in kw:
						copy[name] = kw[name]
				kw = copy
			for k, v in request.match_info.items():
				if k in kw:
					logging.warning('Duplicate arg name in named arg and kw args: %s' % k)
				kw[k] = v
		if self._has_request_arg:
			kw['request'] = request
		if self._required_kw_args:
			# 收集无默认值的关键字参数
			for name in self._required_kw_args:
				if not name in kw:
					# 当存在关键字参数未被赋值时返回,例如 一般的账号注册时,没填入密码就提交注册申请时,提示密码未输入
					return web.HTTPBadRequest('Missing arguments: %s' % name)
		logging.info('call with args: %s' % str(kw))
		try:
			r = await self._func(**kw)
			# 最后调用处理函数,并传入请求参数,进行请求处理
			return r
		except APIError as e:
			return dict(error=e.error, data=e.data, message=e.message)
Exemple #15
0
=======
        raise web.HTTPForbidden(
            reason="Configuration does not include introduction service"
        )
>>>>>>> work in progress

    try:
        await service.start_introduction(
            init_connection_id, target_connection_id, message, outbound_handler
        )
<<<<<<< HEAD
    except IntroductionError as err:
=======
    except (IntroductionError, StorageError) as err:
>>>>>>> work in progress
        raise web.HTTPBadRequest(reason=err.roll_up) from err

    return web.json_response({})


async def register(app: web.Application):
    """Register routes."""

    app.add_routes(
        [web.post("/connections/{conn_id}/start-introduction", introduction_start)]
    )


def post_process_routes(app: web.Application):
    """Amend swagger API."""
Exemple #16
0
async def present_proof_verify_presentation(request: web.BaseRequest):
    """
    Request handler for verifying a presentation request.

    Args:
        request: aiohttp request object

    Returns:
        The presentation exchange details

    """
    r_time = get_timer()

    context: AdminRequestContext = request["context"]
    outbound_handler = request["outbound_message_router"]

    pres_ex_id = request.match_info["pres_ex_id"]

    pres_ex_record = None
    async with context.session() as session:
        try:
            pres_ex_record = await V20PresExRecord.retrieve_by_id(session, pres_ex_id)
        except StorageNotFoundError as err:
            raise web.HTTPNotFound(reason=err.roll_up) from err

        if pres_ex_record.state != (V20PresExRecord.STATE_PRESENTATION_RECEIVED):
            raise web.HTTPBadRequest(
                reason=(
                    f"Presentation exchange {pres_ex_id} "
                    f"in {pres_ex_record.state} state "
                    f"(must be {V20PresExRecord.STATE_PRESENTATION_RECEIVED})"
                )
            )

        connection_id = pres_ex_record.connection_id

        try:
            conn_record = await ConnRecord.retrieve_by_id(session, connection_id)
        except StorageError as err:
            raise web.HTTPBadRequest(reason=err.roll_up) from err

    if not conn_record.is_ready:
        raise web.HTTPForbidden(reason=f"Connection {connection_id} not ready")

    pres_manager = V20PresManager(context.profile)
    try:
        pres_ex_record = await pres_manager.verify_pres(pres_ex_record)
        result = pres_ex_record.serialize()
    except (BaseModelError, LedgerError, StorageError) as err:
        if pres_ex_record:
            async with context.session() as session:
                await pres_ex_record.save_error_state(session, reason=err.roll_up)
        # other party cares that we cannot continue protocol
        await report_problem(
            err,
            ProblemReportReason.ABANDONED.value,
            web.HTTPBadRequest,
            pres_ex_record,
            outbound_handler,
        )

    trace_event(
        context.settings,
        pres_ex_record,
        outcome="presentation_exchange_verify.END",
        perf_counter=r_time,
    )

    return web.json_response(result)
Exemple #17
0
async def credential_exchange_create(request: web.BaseRequest):
    """
    Request handler for creating a credential from attr values.

    The internal credential record will be created without the credential
    being sent to any connection. This can be used in conjunction with
    the `oob` protocols to bind messages to an out of band message.

    Args:
        request: aiohttp request object

    Returns:
        The credential exchange record

    """
    r_time = get_timer()

    context = request.app["request_context"]

    body = await request.json()

    comment = body.get("comment")
    preview_spec = body.get("credential_proposal")
    if not preview_spec:
        raise web.HTTPBadRequest(reason="credential_proposal must be provided")
    auto_remove = body.get("auto_remove")
    trace_msg = body.get("trace")

    try:
        preview = CredentialPreview.deserialize(preview_spec)

        credential_proposal = CredentialProposal(
            comment=comment,
            credential_proposal=preview,
            **{t: body.get(t)
               for t in CRED_DEF_TAGS if body.get(t)},
        )
        credential_proposal.assign_trace_decorator(
            context.settings,
            trace_msg,
        )

        trace_event(
            context.settings,
            credential_proposal,
            outcome="credential_exchange_create.START",
        )

        credential_manager = CredentialManager(context)

        (
            credential_exchange_record,
            credential_offer_message,
        ) = await credential_manager.prepare_send(
            None,
            credential_proposal=credential_proposal,
            auto_remove=auto_remove,
        )
    except (StorageError, BaseModelError) as err:
        raise web.HTTPBadRequest(reason=err.roll_up) from err

    trace_event(
        context.settings,
        credential_offer_message,
        outcome="credential_exchange_create.END",
        perf_counter=r_time,
    )

    return web.json_response(credential_exchange_record.serialize())
Exemple #18
0
    async def callback(self, req: Request) -> Response:
        """Include correct tokens in cookies as a callback after login.

        Sets session information such as access_token and user_info.
        Sets encrypted cookie to identify clients.

        :raises: HTTPBadRequest in case login failed
        :raises: HTTPForbidden in case of bad session
        :param req: A HTTP request instance with callback parameters
        :returns: HTTPSeeOther redirect to home page
        """
        # Response from AAI must have the query params `state` and `code`
        if "state" in req.query and "code" in req.query:
            LOG.debug("AAI response contained the correct params.")
            params = {"state": req.query["state"], "code": req.query["code"]}
        else:
            reason = f"AAI response is missing mandatory params, received: {req.query}"
            LOG.error(reason)
            raise web.HTTPBadRequest(reason=reason)

        # Verify, that states match
        state = await self._get_from_session(req, "oidc_state")
        if not secrets.compare_digest(str(state), str(params["state"])):
            raise web.HTTPForbidden(reason="Bad user session.")

        auth = BasicAuth(login=self.client_id, password=self.client_secret)
        data = {
            "grant_type": "authorization_code",
            "code": params["code"],
            "redirect_uri": self.callback_url
        }

        # Set up client authentication for request
        async with ClientSession(auth=auth) as sess:
            # Send request to AAI
            async with sess.post(f"{self.token_url}", data=data) as resp:
                LOG.debug(f"AAI response status: {resp.status}.")
                # Validate response from AAI
                if resp.status == 200:
                    result = await resp.json()
                    if all(x in result for x in ["id_token", "access_token"]):
                        LOG.debug("Both ID and Access tokens received.")
                        access_token = result["access_token"]
                        id_token = result["id_token"]
                        await self._validate_jwt(id_token)
                    else:
                        reason = "AAI response did not contain access and id tokens."
                        LOG.error(reason)
                        raise web.HTTPBadRequest(reason=reason)
                else:
                    reason = f"Token request to AAI failed: {resp}"
                    LOG.error(reason)
                    raise web.HTTPBadRequest(reason=reason)

        await self._save_to_session(req,
                                    key="access_token",
                                    value=access_token)
        await self._set_user(req, access_token)

        response = web.HTTPSeeOther(f"{self.redirect}/home")

        cookie, _ = generate_cookie(req)

        cookie["referer"] = req.url.host
        cookie["signature"] = (hashlib.sha256(
            (cookie["id"] + cookie["referer"] +
             req.app["Salt"]).encode("utf-8"))).hexdigest()

        session = cookie["id"]

        cookie_crypted = req.app["Crypt"].encrypt(
            json.dumps(cookie).encode("utf-8")).decode("utf-8")

        response.headers[
            "Cache-Control"] = "no-cache, no-store, must-revalidate"
        response.headers["Pragma"] = "no-Cache"
        response.headers["Expires"] = "0"

        trust = False if self.domain.startswith(
            "http://localhost:5430") else True

        response.set_cookie(
            name="MTD_SESSION",
            value=cookie_crypted,
            max_age=3600,
            secure=trust,  # type: ignore
            httponly=trust,  # type: ignore
        )

        req.app["Cookies"].add(session)

        # done like this otherwise it will not redirect properly
        response.headers[
            "Location"] = "/home" if self.redirect == self.domain else f"{self.redirect}/home"

        LOG.debug(f"cookie MTD_SESSION set {cookie_crypted}")
        return response
Exemple #19
0
async def credential_exchange_create_free_offer(request: web.BaseRequest):
    """
    Request handler for creating free credential offer.

    Unlike with `send-offer`, this credential exchange is not tied to a specific
    connection. It must be dispatched out-of-band by the controller.

    Args:
        request: aiohttp request object

    Returns:
        The credential exchange record

    """
    r_time = get_timer()

    context = request.app["request_context"]
    outbound_handler = request.app["outbound_message_router"]

    body = await request.json()

    cred_def_id = body.get("cred_def_id")
    if not cred_def_id:
        raise web.HTTPBadRequest(reason="cred_def_id is required")

    auto_issue = body.get(
        "auto_issue",
        context.settings.get("debug.auto_respond_credential_request"))
    auto_remove = body.get("auto_remove")
    comment = body.get("comment")
    preview_spec = body.get("credential_preview")
    if not preview_spec:
        raise web.HTTPBadRequest(reason=("Missing credential_preview"))

    connection_id = body.get("connection_id")
    trace_msg = body.get("trace")

    wallet: BaseWallet = await context.inject(BaseWallet)
    if connection_id:
        try:
            connection_record = await ConnectionRecord.retrieve_by_id(
                context, connection_id)
            conn_did = await wallet.get_local_did(connection_record.my_did)
        except (WalletError, StorageError) as err:
            raise web.HTTPBadRequest(reason=err.roll_up) from err
    else:
        conn_did = await wallet.get_public_did()
        if not conn_did:
            raise web.HTTPBadRequest(
                reason=f"Wallet '{wallet.name}' has no public DID")
        connection_id = None

    did_info = await wallet.get_public_did()
    endpoint = did_info.metadata.get("endpoint",
                                     context.settings.get("default_endpoint"))
    if not endpoint:
        raise web.HTTPBadRequest(
            reason="An endpoint for the public DID is required")

    cred_ex_record = None
    try:
        (
            cred_ex_record,
            credential_offer_message,
        ) = await _create_free_offer(
            context,
            cred_def_id,
            connection_id,
            auto_issue,
            auto_remove,
            preview_spec,
            comment,
            trace_msg,
        )

        trace_event(
            context.settings,
            credential_offer_message,
            outcome="credential_exchange_create_free_offer.END",
            perf_counter=r_time,
        )

        oob_url = serialize_outofband(credential_offer_message, conn_did,
                                      endpoint)
        result = cred_ex_record.serialize()
    except (BaseModelError, CredentialManagerError, LedgerError) as err:
        await internal_error(
            err,
            web.HTTPBadRequest,
            cred_ex_record or connection_record,
            outbound_handler,
        )

    response = {"record": result, "oob_url": oob_url}
    return web.json_response(response)
 def handler(request):
     try:
         yield from request.post()
     except ValueError:
         return web.HTTPOk()
     return web.HTTPBadRequest()
Exemple #21
0
    async def __call__(self, request):
        kw = None
        if self._has_var_kw_arg or self._has_named_kw_args or self._required_kw_args:
            if request.method == 'POST':
                if not request.content_type:
                    return web.HTTPBadRequest('Missing Content-Type.')

                ct = request.content_type.lower()

                if ct.startswith('application/json'):
                    params = await request.json()
                    if not isinstance(params, dict):
                        return web.HTTPBadRequest('JSON body must be object.')
                    kw = params
                elif ct.startswith('application/x-www-form-rulencoded'
                                   ) or ct.startswith('multipart/form-data'):
                    params = await request.post()
                    kw = dict(**params)
                else:
                    return web.HTTPBadRequest('Unsupported Content-Type: %s' %
                                              request.content_type)

            if request.method == 'GET':
                qs = request.query_string
                if qs:
                    kw = dict()
                    for k, v in parse.parse_qs(qs, True).items():
                        kw[k] = v[0]
        if kw is None:
            kw = dict(**request.match_info)
            #print('\nkw:\n', kw, '\nrequest.match_info:\n', request.match_info)
            #kw{'id':'001514861142476bd95fab85f7542178dba245d02470c57000'},
            #match_info<MatchInfo {'id': '001514861142476bd95fab85f7542178dba245d02470c57000'}: <ResourceRoute [GET] <DynamicResource  /blog/{id} -> <function AbstractRoute.__init__.<locals>.handler_wrapper at 0x7fc186c39f28>>
            #request请求就是/blog/001514861142476bd95fab85f7542178dba245d02470c57000啊
            #由注册的路径后面的定义的{id}转换成id名,id变量,则是函数内部变量。。。
            #应该是web.Application匹配注册的方法的/blog/{id}路径,再看这个/blog/001514861142476bd95fab85f7542178dba245d02470c57000路径,匹配上去的吧。试个/blog/{cd}?
            #还别说,还真成{'cd': '001514861142476bd95fab85f7542178dba245d02470c57000'}了
            #<MatchInfo {'cd': '001514861142476bd95fab85f7542178dba245d02470c57000'}: <ResourceRoute [GET] <DynamicResource  /blog/{cd} -> <function AbstractRoute.__init__.<locals>.handler_wrapper at 0x7f39d0a18f28>>
            #看来,后注册的同样路径,能覆盖之前注册的
        else:
            if not self._has_var_kw_arg and self._named_kw_args:
                #remove all unamed kw:
                copy = dict()
                for name in self._named_kw_args:
                    if name in kw:
                        copy[name] = kw[name]
                kw = copy

            #check named arg:
            for k, v in request.match_info.items():
                if k in kw:
                    logging.warning(
                        'Duplicate arg name in named arg and kw args: %s' % k)
                kw[k] = v
        if self._has_request_arg:
            kw['request'] = request
        #check required kw:
        if self._required_kw_args:
            for name in self._required_kw_args:
                if not name in kw:
                    return web.HTTPBadRequest('Missing argument: %s' % name)
        logging.info('call with args: %s' % str(kw))
        try:
            #print('kw',kw)
            r = await self._func(**kw)  #这里还没有调用哦,只是生成了这个对象
            #然后,把这种方法注册到app上,调用这方法时要加request参数哦
            #然后,app把request和id的值给它的吧
            return r
        except APIError as e:
            return dict(error=e.error, data=e.data, message=e.message)
Exemple #22
0
    async def cancel_handler(self, request):
        if request.method == 'OPTIONS':
            return web.Response(status=200,
                                headers=self.get_cors_headers(request))

        return web.HTTPBadRequest(headers=self.get_cors_headers(request))
Exemple #23
0
async def run_code(req: web.Request) -> web.Response:
    start_time = time.time()

    language = validate_language(req.match_info["language_name"])

    body = await req.read()
    if not body:
        data: Dict[str, Any] = {}
    else:
        try:
            data = json.loads(body)
        except JSONDecodeError:
            raise web.HTTPBadRequest(reason="Bad json in body: unable to decode")

        if not isinstance(data, dict):
            raise web.HTTPBadRequest(reason="Bad json in body: root object is not map")

    payload = {
        "code": data.pop("code", language.example),
        "input": data.pop("input", ""),
    }

    if language.compiled:
        payload["compilers"] = data.pop("compilers", language.compilers)
        payload["compile_args"] = data.pop("compile_args", language.compile_args)

        if len(payload["compilers"]) != len(payload["compile_args"]):
            raise web.HTTPBadRequest(reason="Mismatch of compilers and compile_args")

    payload["merge_output"] = get_query_bool_flag(req, "merge", False)

    backend_run_url = (
        f"{req.config_dict['config']['app']['run-lb-ip']}/run/{language.name}"
    )

    log.debug("sending request to %s", backend_run_url)

    async with ClientSession() as cs:
        async with cs.post(backend_run_url, json=payload) as resp:
            if resp.status == 503:
                log.warn("status 503, no free servers")

                raise web.HTTPServiceUnavailable(
                    reason="Service is too busy. Try again later"
                )

            elif resp.status != 200:
                log.error("bad response status: %d: %s", resp.status, resp.reason)

                raise web.HTTPInternalServerError(
                    reason=f"Backend response error: {resp.reason}"
                )

            try:
                response_json = await resp.json()
            except JSONDecodeError:
                log.error("bad json returned by backend: %s", await req.text())
                raise web.HTTPInternalServerError(
                    reason="Backend response decoding error"
                )

    return web.json_response(
        {"processing_time": time.time() - start_time, **response_json}
    )
Exemple #24
0
 async def handler(request):
     try:
         await request.post()
     except ValueError:
         return web.Response()
     raise web.HTTPBadRequest()
Exemple #25
0
async def user(request):
    lega_instance = request.match_info['lega']
    users_dir = request.match_info['users_dir']
    identifier = request.match_info['identifier']

    if 'idType' in request.rel_url.query and request.rel_url.query[
            'idType'] == 'username':
        id_type = request.rel_url.query['idType']
        LOG.info(
            f'User ID request: {lega_instance}, in {users_dir}, with request of id type {id_type} and name {identifier}.'
        )
        try:
            with open(f'{users_dir}/{identifier}.yml', 'r') as stream:
                data = dict()
                data['header'] = fixed_header
                d = yaml.load(stream)
                # We are mocking this so we only need the result to be right
                data['response'] = {
                    "numTotalResults":
                    1,
                    "resultType":
                    "eu.crg.ega.microservice.dto.lega.v1.users.LocalEgaUser",
                    "result": [{
                        'username': d.get("username", None),
                        'passwordHash': d.get("password_hash", None),
                        'sshPublicKey': d.get("pubkey", None),
                        'uid': int(d.get("uid", None)),
                        'gecos': d.get("gecos", "EGA User"),
                        "enabled": None
                    }]
                }
                return web.json_response(data)
        except OSError:
            raise web.HTTPBadRequest(
                text=
                f'No info for user {identifier} in LocalEGA {lega_instance}... yet\n'
            )
    elif 'idType' in request.rel_url.query and request.rel_url.query[
            'idType'] == 'uid':
        id_type = request.rel_url.query['idType']
        LOG.info(
            f'User ID request: {lega_instance}, in {users_dir}, with request of id type {id_type} and UID {identifier}.'
        )
        try:
            with open(f'{users_dir}_ids/{identifier}.yml', 'r') as stream:
                data = dict()
                data['header'] = fixed_header
                d = yaml.load(stream)
                # We are mocking this so we only need the result to be right
                data['response'] = {
                    "numTotalResults":
                    1,
                    "resultType":
                    "eu.crg.ega.microservice.dto.lega.v1.users.LocalEgaUser",
                    "result": [{
                        'username': d.get("username", None),
                        'passwordHash': d.get("password_hash", None),
                        'sshPublicKey': d.get("pubkey", None),
                        'uid': int(d.get("uid", None)),
                        'gecos': d.get("gecos", "EGA User"),
                        "enabled": None
                    }]
                }
                return web.json_response(data)
        except OSError:
            raise web.HTTPBadRequest(
                text=
                f'No info for user id {identifier} in LocalEGA {lega_instance}... yet\n'
            )
    else:
        raise web.HTTPBadRequest(text='Missing or wrong idType')
Exemple #26
0
async def add_service(request):
    """
    Create a new service to run a specific plugin

    :Example:
             curl -X POST http://localhost:8081/foglamp/service -d '{"name": "DHT 11", "plugin": "dht11", "type": "south", "enabled": true}'
             curl -sX POST http://localhost:8081/foglamp/service -d '{"name": "Sine", "plugin": "sinusoid", "type": "south", "enabled": true, "config": {"dataPointsPerSec": {"value": "10"}}}' | jq
             curl -X POST http://localhost:8081/foglamp/service -d '{"name": "NotificationServer", "type": "notification", "enabled": true}' | jq
    """

    try:
        data = await request.json()
        if not isinstance(data, dict):
            raise ValueError('Data payload must be a valid JSON')

        name = data.get('name', None)
        plugin = data.get('plugin', None)
        service_type = data.get('type', None)
        enabled = data.get('enabled', None)
        config = data.get('config', None)

        if name is None:
            raise web.HTTPBadRequest(reason='Missing name property in payload.')
        if utils.check_reserved(name) is False:
            raise web.HTTPBadRequest(reason='Invalid name property in payload.')

        if service_type is None:
            raise web.HTTPBadRequest(reason='Missing type property in payload.')
        service_type = str(service_type).lower()
        if service_type == 'north':
            raise web.HTTPNotAcceptable(reason='north type is not supported for the time being.')
        if service_type not in ['south', 'notification']:
            raise web.HTTPBadRequest(reason='Only south and notification type are supported.')

        if plugin is None and service_type == 'south':
            raise web.HTTPBadRequest(reason='Missing plugin property for type south in payload.')
        if plugin and utils.check_reserved(plugin) is False:
            raise web.HTTPBadRequest(reason='Invalid plugin property in payload.')

        if enabled is not None:
            if enabled not in ['true', 'false', True, False]:
                raise web.HTTPBadRequest(reason='Only "true", "false", true, false'
                                                ' are allowed for value of enabled.')
        is_enabled = True if ((type(enabled) is str and enabled.lower() in ['true']) or (
            (type(enabled) is bool and enabled is True))) else False

        # Check if a valid plugin has been provided
        plugin_module_path, plugin_config, process_name, script = "", {}, "", ""
        if service_type == 'south':
            # "plugin_module_path" is fixed by design. It is MANDATORY to keep the plugin in the exactly similar named
            # folder, within the plugin_module_path.
            # if multiple plugin with same name are found, then python plugin import will be tried first
            plugin_module_path = "foglamp.plugins.south"
            try:
                plugin_info = load_python_plugin(plugin_module_path, plugin, service_type)
                plugin_config = plugin_info['config']
                if not plugin_config:
                    _logger.exception("Plugin %s import problem from path %s", plugin, plugin_module_path)
                    raise web.HTTPNotFound(reason='Plugin "{}" import problem from path "{}".'.format(plugin, plugin_module_path))
                process_name = 'south_c'
                script = '["services/south_c"]'
            except ImportError as ex:
                # Checking for C-type plugins
                plugin_config = load_c_plugin(plugin, service_type)
                if not plugin_config:
                    _logger.exception("Plugin %s import problem from path %s. %s", plugin, plugin_module_path, str(ex))
                    raise web.HTTPNotFound(reason='Plugin "{}" import problem from path "{}".'.format(plugin, plugin_module_path))

                process_name = 'south_c'
                script = '["services/south_c"]'
            except TypeError as ex:
                _logger.exception(str(ex))
                raise web.HTTPBadRequest(reason=str(ex))
            except Exception as ex:
                _logger.exception("Failed to fetch plugin configuration. %s", str(ex))
                raise web.HTTPInternalServerError(reason='Failed to fetch plugin configuration')
        elif service_type == 'notification':
            process_name = 'notification_c'
            script = '["services/notification_c"]'

        storage = connect.get_storage_async()
        config_mgr = ConfigurationManager(storage)

        # Check  whether category name already exists
        category_info = await config_mgr.get_category_all_items(category_name=name)
        if category_info is not None:
            raise web.HTTPBadRequest(reason="The '{}' category already exists".format(name))

        # Check that the schedule name is not already registered
        count = await check_schedules(storage, name)
        if count != 0:
            raise web.HTTPBadRequest(reason='A service with this name already exists.')

        # Check that the process name is not already registered
        count = await check_scheduled_processes(storage, process_name)
        if count == 0:
            # Now first create the scheduled process entry for the new service
            payload = PayloadBuilder().INSERT(name=process_name, script=script).payload()
            try:
                res = await storage.insert_into_tbl("scheduled_processes", payload)
            except StorageServerError as ex:
                _logger.exception("Failed to create scheduled process. %s", ex.error)
                raise web.HTTPInternalServerError(reason='Failed to create service.')
            except Exception as ex:
                _logger.exception("Failed to create scheduled process. %s", str(ex))
                raise web.HTTPInternalServerError(reason='Failed to create service.')

        # check that notification service is not already registered, right now notification service LIMIT to 1
        if service_type == 'notification':
            res = await check_notification_schedule(storage)
            for ps in res['rows']:
                if 'notification_c' in ps['process_name']:
                    raise web.HTTPBadRequest(reason='A Notification service schedule already exists.')
        elif service_type == 'south':
            try:
                # Create a configuration category from the configuration defined in the plugin
                category_desc = plugin_config['plugin']['description']
                await config_mgr.create_category(category_name=name,
                                                 category_description=category_desc,
                                                 category_value=plugin_config,
                                                 keep_original_items=True)
                # Create the parent category for all South services
                await config_mgr.create_category("South", {}, "South microservices", True)
                await config_mgr.create_child_category("South", [name])

                # If config is in POST data, then update the value for each config item
                if config is not None:
                    if not isinstance(config, dict):
                        raise ValueError('Config must be a JSON object')
                    for k, v in config.items():
                        await config_mgr.set_category_item_value_entry(name, k, v['value'])

            except Exception as ex:
                await config_mgr.delete_category_and_children_recursively(name)
                _logger.exception("Failed to create plugin configuration. %s", str(ex))
                raise web.HTTPInternalServerError(reason='Failed to create plugin configuration.')

        # If all successful then lastly add a schedule to run the new service at startup
        try:
            schedule = StartUpSchedule()
            schedule.name = name
            schedule.process_name = process_name
            schedule.repeat = datetime.timedelta(0)
            schedule.exclusive = True
            #  if "enabled" is supplied, it gets activated in save_schedule() via is_enabled flag
            schedule.enabled = False

            # Save schedule
            await server.Server.scheduler.save_schedule(schedule, is_enabled)
            schedule = await server.Server.scheduler.get_schedule_by_name(name)
        except StorageServerError as ex:
            await config_mgr.delete_category_and_children_recursively(name)
            _logger.exception("Failed to create schedule. %s", ex.error)
            raise web.HTTPInternalServerError(reason='Failed to create service.')
        except Exception as ex:
            await config_mgr.delete_category_and_children_recursively(name)
            _logger.exception("Failed to create service. %s", str(ex))
            raise web.HTTPInternalServerError(reason='Failed to create service.')

    except ValueError as e:
        raise web.HTTPBadRequest(reason=str(e))
    else:
        return web.json_response({'name': name, 'id': str(schedule.schedule_id)})
Exemple #27
0
def fetch_string(data):
    if data and "data" in data and len(data["data"]) > 0:
        return base64.b64decode(data["data"]).decode("utf-8")
    else:
        raise web.HTTPBadRequest("arithmetic string is not valid")
Exemple #28
0
async def auth_middleware(request, handler):
    """
    Проверяем токен в каждом запросе
    :param request:
    :param handler:
    :return:
    """
    metrics = request.app.get('metrics')
    await metrics.inc('requests')
    # в каждый реквест будем добавлять поле auth

    request.auth = None
    if check_request(
            request,
            WHITE_LIST_ROUTES):  # если белый роут, пропускаем без токена
        return await handler(request)
    if request.method == 'OPTIONS':
        return await handler(request)

    # дергаем из заголовка авторизацию
    if 'Authorization' not in request.headers:
        raise web.HTTPForbidden(reason='Please login first', )

    try:
        scheme, jwt_token = request.headers.get('Authorization').strip().split(
            ' ')
    except ValueError:
        raise web.HTTPForbidden(reason='Please login first', )

    if not jwt_token:
        msg = 'Please login!'
        return web.HTTPUnauthorized(reason=msg, body=msg)

    try:
        jwt_token = jwt_token.strip('"').strip("'")
        # так как подделать payload не могут, вся инфа у нас уже будет внутри, в БД за данными юзера ходить не надо
        request.auth = jwt.decode(jwt_token,
                                  JWT_SECRET,
                                  algorithms=[JWT_ALGORITHM])
        # проверим, что токен выдан нами :)
        cache = request.app.get('cache')
        token_from_redis = await cache.get_cache(
            'uid_token_' + str(request.auth.get('id'))) or []

        if jwt_token not in token_from_redis:
            # если в редисе нет нашего токена, значит надо обновить юзеру профиль
            #TODO: на будущее - обновление токена автоматом
            #main_handler = Main()
            #return await main_handler.refresh(request)
            msg = 'Session expired! Please, login'
            return web.HTTPUnauthorized(reason=msg, body=msg)

    except jwt.DecodeError:
        msg = 'Security problem. Please, relogin!'
        return web.HTTPUnauthorized(reason=msg, body=msg)

    except jwt.ExpiredSignatureError:
        msg = 'Security problem. Your session has expired. Please login!'
        return web.HTTPUnauthorized(reason=msg, body=msg)
    except Exception as e:
        return web.HTTPBadRequest(reason=str(e), body=str(e))
    return await handler(request)
async def presentation_exchange_send_free_request(request: web.BaseRequest):
    """
    Request handler for sending a presentation request free from any proposal.

    Args:
        request: aiohttp request object

    Returns:
        The presentation exchange details

    """
    r_time = get_timer()

    context: AdminRequestContext = request["context"]
    profile = context.profile
    outbound_handler = request["outbound_message_router"]

    body = await request.json()

    connection_id = body.get("connection_id")
    async with profile.session() as session:
        try:
            connection_record = await ConnRecord.retrieve_by_id(
                session, connection_id)
        except StorageNotFoundError as err:
            raise web.HTTPBadRequest(reason=err.roll_up) from err

    if not connection_record.is_ready:
        raise web.HTTPForbidden(reason=f"Connection {connection_id} not ready")

    comment = body.get("comment")
    indy_proof_request = body.get("proof_request")
    if not indy_proof_request.get("nonce"):
        indy_proof_request["nonce"] = await generate_pr_nonce()

    presentation_request_message = PresentationRequest(
        comment=comment,
        request_presentations_attach=[
            AttachDecorator.data_base64(
                mapping=indy_proof_request,
                ident=ATTACH_DECO_IDS[PRESENTATION_REQUEST],
            )
        ],
    )
    trace_msg = body.get("trace")
    presentation_request_message.assign_trace_decorator(
        context.settings,
        trace_msg,
    )
    auto_verify = body.get(
        "auto_verify", context.settings.get("debug.auto_verify_presentation"))

    pres_ex_record = None
    try:
        presentation_manager = PresentationManager(profile)
        pres_ex_record = await presentation_manager.create_exchange_for_request(
            connection_id=connection_id,
            presentation_request_message=presentation_request_message,
            auto_verify=auto_verify,
        )
        result = pres_ex_record.serialize()
    except (BaseModelError, StorageError) as err:
        if pres_ex_record:
            async with profile.session() as session:
                await pres_ex_record.save_error_state(session,
                                                      reason=err.roll_up)
        # other party does not care about our false protocol start
        raise web.HTTPBadRequest(reason=err.roll_up)

    await outbound_handler(presentation_request_message,
                           connection_id=connection_id)

    trace_event(
        context.settings,
        presentation_request_message,
        outcome="presentation_exchange_send_request.END",
        perf_counter=r_time,
    )

    return web.json_response(result)
 async def bad_request(req_text):
     await logger.warning(f'Failed due to {req_text}')
     return web.HTTPBadRequest(reason=req_text)  # 400