Ejemplo n.º 1
0
def validate_pdf(file_key: str):
    """Validate the PDF file."""
    msg = []
    try:
        file = MinioService.get_file(file_key)
        open_pdf_file = io.BytesIO(file.data)
        pdf_reader = PyPDF2.PdfFileReader(open_pdf_file)
        pdf_size_units = pdf_reader.getPage(0).mediaBox

        if pdf_size_units.getWidth() != 612 or pdf_size_units.getHeight(
        ) != 792:
            msg.append({
                'error':
                babel(
                    'Document must be set to fit onto 8.5” x 11” letter-size paper.'
                )
            })

        file_info = MinioService.get_file_info(file_key)
        if file_info.size > 10000000:
            msg.append({'error': babel('File exceeds maximum size.')})

        if pdf_reader.isEncrypted:
            msg.append({'error': babel('File must be unencrypted.')})

    except Exception:
        msg.append({'error': babel('Invalid file.')})

    if msg:
        return msg

    return None
Ejemplo n.º 2
0
def test_delete_file(session, minio_server, tmpdir):  # pylint:disable=unused-argument
    """Assert that a file can be deleted."""
    key = _upload_file(tmpdir)
    MinioService.delete_file(key)

    try:
        MinioService.get_file_info(key)
    except S3Error as ex:
        assert ex.code == 'NoSuchKey'
Ejemplo n.º 3
0
def test_put_file(session, minio_server, tmpdir):  # pylint:disable=unused-argument
    """Assert that a file can be replaced."""
    key = _upload_file(tmpdir)

    pdf_file = _create_pdf_file()
    # Replace previous file with this pdf file
    MinioService.put_file(key, pdf_file, pdf_file.getbuffer().nbytes)

    try:
        file = MinioService.get_file(key)
        pdf_file.seek(0)
        assert file.data == pdf_file.read()
    except S3Error as ex:
        assert ex.code == 'NoSuchKey'
Ejemplo n.º 4
0
 def _get_static_report(self):
     document_type = ReportMeta.static_reports[
         self._report_key]['documentType']
     document: Document = self._filing.documents.filter(
         Document.type == document_type).first()
     response = MinioService.get_file(document.file_key)
     return response.data, response.status
Ejemplo n.º 5
0
def test_create_signed_get_url(session, minio_server, tmpdir):  # pylint:disable=unused-argument
    """Assert that a GET url can be pre-signed."""
    key = _upload_file(tmpdir)
    pre_signed_get = MinioService.create_signed_get_url(key)
    assert pre_signed_get
    get_response = requests.get(pre_signed_get)
    assert get_response
Ejemplo n.º 6
0
def _upload_file(page_size):
    signed_url = MinioService.create_signed_put_url('cooperative-test.pdf')
    key = signed_url.get('key')
    pre_signed_put = signed_url.get('preSignedUrl')

    requests.put(pre_signed_put, data=_create_pdf_file(page_size).read(),
                 headers={'Content-Type': 'application/octet-stream'})
    return key
Ejemplo n.º 7
0
def test_dissolution_affidavit(session, minio_server, test_name, legal_type, dissolution_type, key, scenario,
                               identifier, expected_code, expected_msg):  # pylint: disable=too-many-arguments
    """Assert that an affidavit can be validated."""
    # setup
    business = Business(identifier=identifier)

    filing = copy.deepcopy(FILING_HEADER)
    filing['filing']['header']['name'] = 'dissolution'
    filing['filing']['business']['legalType'] = legal_type
    filing['filing']['dissolution'] = copy.deepcopy(DISSOLUTION)
    filing['filing']['dissolution']['dissolutionType'] = dissolution_type
    filing['filing']['dissolution']['parties'][1]['deliveryAddress'] = \
        filing['filing']['dissolution']['parties'][1]['mailingAddress']

    if scenario:
        if scenario == 'success':
            if legal_type == Business.LegalTypes.COOP.value:
                filing['filing']['dissolution']['affidavitFileKey'] = _upload_file(letter)
            else:
                del filing['filing']['dissolution']['affidavitFileKey']
                del filing['filing']['dissolution']['affidavitFileName']
        elif scenario == 'failAffidavit':
            filing['filing']['dissolution']['affidavitFileKey'] = 'invalid file key'
        elif scenario == 'invalidAffidavitPageSize':
            filing['filing']['dissolution']['affidavitFileKey'] = _upload_file(legal)
    else:
        # Assign key and value to test empty variables for failures
        key_value = ''
        filing['filing']['dissolution'][key] = key_value

    err = validate(business, filing)

    # validate outcomes
    if expected_code:
        assert err.code == expected_code
        assert lists_are_equal(err.msg, expected_msg)
    else:
        assert err is None

    # Cleanup
    if file_key := filing['filing']['dissolution'].get('affidavitFileKey', None):
        MinioService.delete_file(file_key)
Ejemplo n.º 8
0
def _upload_file(tmpdir):
    d = tmpdir.mkdir('subdir')
    fh = d.join('cooperative-test.pdf')
    fh.write('Test File')
    filename = os.path.join(fh.dirname, fh.basename)

    test_file = open(filename, 'rb')
    files = {'upload_file': test_file}
    file_name = fh.basename
    signed_url = MinioService.create_signed_put_url(file_name)
    key = signed_url.get('key')
    pre_signed_put = signed_url.get('preSignedUrl')
    requests.put(pre_signed_put, files=files)
    return key
Ejemplo n.º 9
0
class ListFilingResource(Resource):
    """Business Filings service."""
    @staticmethod
    @cors.crossdomain(origin='*')
    @jwt.requires_auth
    def get(identifier, filing_id=None):  # pylint: disable=too-many-return-statements,too-many-branches;
        # fix this while refactoring this whole module
        """Return a JSON object with meta information about the Service."""
        original_filing = str(request.args.get('original',
                                               None)).lower() == 'true'
        if identifier.startswith('T'):
            rv = CoreFiling.get(identifier, filing_id)

            if not rv.storage:
                return jsonify({'message': f'{identifier} no filings found'
                                }), HTTPStatus.NOT_FOUND
            if str(request.accept_mimetypes
                   ) == 'application/pdf' and filing_id:
                if rv.filing_type == 'incorporationApplication':
                    return legal_api.reports.get_pdf(rv.storage, None)

            if original_filing:
                filing_json = rv.raw
            else:
                filing_json = rv.json
                filing_json['filing']['documents'] = DocumentMetaService(
                ).get_documents(filing_json)

            if filing_json['filing']['header'][
                    'status'] == Filing.Status.PENDING.value:
                try:
                    headers = {
                        'Authorization':
                        f'Bearer {jwt.get_token_auth_header()}',
                        'Content-Type': 'application/json'
                    }
                    payment_svc_url = current_app.config.get('PAYMENT_SVC_URL')
                    pay_response = requests.get(
                        url=
                        f'{payment_svc_url}/{filing_json["filing"]["header"]["paymentToken"]}',
                        headers=headers)
                    pay_details = {
                        'isPaymentActionRequired':
                        pay_response.json().get('isPaymentActionRequired',
                                                False),
                        'paymentMethod':
                        pay_response.json().get('paymentMethod', '')
                    }
                    filing_json['filing']['header'].update(pay_details)

                except (exceptions.ConnectionError, exceptions.Timeout) as err:
                    current_app.logger.error(
                        f'Payment connection failure for getting {identifier} filing payment details. ',
                        err)

            return jsonify(filing_json)

        business = Business.find_by_identifier(identifier)

        if not business:
            return jsonify(filings=[]), HTTPStatus.NOT_FOUND

        if filing_id:
            rv = CoreFiling.get(identifier, filing_id)
            if not rv:
                return jsonify({'message': f'{identifier} no filings found'
                                }), HTTPStatus.NOT_FOUND

            if str(request.accept_mimetypes) == 'application/pdf':
                report_type = request.args.get('type', None)

                if rv.filing_type == CoreFiling.FilingTypes.CORRECTION.value:
                    # This is required until #5302 ticket implements
                    rv.storage._filing_json['filing']['correction'][
                        'diff'] = rv.json['filing']['correction']['diff']  # pylint: disable=protected-access; # noqa: E501;

                return legal_api.reports.get_pdf(rv.storage, report_type)
            return jsonify(rv.raw if original_filing else rv.json)

        # Does it make sense to get a PDF of all filings?
        if str(request.accept_mimetypes) == 'application/pdf':
            return jsonify({'message': _('Cannot return a single PDF of multiple filing submissions.')}),\
                HTTPStatus.NOT_ACCEPTABLE

        rv = []
        filings = CoreFiling.get_filings_by_status(
            business.id,
            [Filing.Status.COMPLETED.value, Filing.Status.PAID.value])
        for filing in filings:
            filing_json = filing.raw
            filing_json['filing']['documents'] = DocumentMetaService(
            ).get_documents(filing_json)
            rv.append(filing_json)

        return jsonify(filings=rv)

    @staticmethod
    @cors.crossdomain(origin='*')
    @jwt.requires_auth
    def post(identifier, filing_id=None):
        """Create a new filing for the business."""
        return ListFilingResource.put(identifier, filing_id)

    @staticmethod
    @cors.crossdomain(origin='*')
    @jwt.requires_auth
    def put(identifier, filing_id):  # pylint: disable=too-many-return-statements,too-many-locals
        """Modify an incomplete filing for the business."""
        # basic checks
        err_msg, err_code = ListFilingResource._put_basic_checks(
            identifier, filing_id, request)
        if err_msg:
            return jsonify({'errors': [
                err_msg,
            ]}), err_code
        json_input = request.get_json()

        # check authorization
        response, response_code = ListFilingResource._check_authorization(
            identifier, json_input)
        if response:
            return response, response_code

        # get query params
        draft = (request.args.get('draft', None).lower() == 'true') \
            if request.args.get('draft', None) else False
        only_validate = (request.args.get('only_validate', None).lower() == 'true') \
            if request.args.get('only_validate', None) else False

        # get header params
        payment_account_id = request.headers.get('accountId', None)

        if not draft \
                and not ListFilingResource._is_historical_colin_filing(json_input) \
                and not ListFilingResource._is_before_epoch_filing(json_input, Business.find_by_identifier(identifier)):
            if identifier.startswith('T'):
                business_validate = RegistrationBootstrap.find_by_identifier(
                    identifier)
            else:
                business_validate = Business.find_by_identifier(identifier)
            err = validate(business_validate, json_input)
            # err_msg, err_code = ListFilingResource._validate_filing_json(request)
            if err or only_validate:
                if err:
                    json_input['errors'] = err.msg
                    return jsonify(json_input), err.code
                return jsonify(json_input), HTTPStatus.OK

        # save filing, if it's draft only then bail
        user = User.get_or_create_user_by_jwt(g.jwt_oidc_token_info)
        try:
            business, filing, err_msg, err_code = ListFilingResource._save_filing(
                request, identifier, user, filing_id)
            if err_msg or draft:
                reply = filing.json if filing else json_input
                reply['errors'] = [
                    err_msg,
                ]
                return jsonify(reply), err_code or \
                    (HTTPStatus.CREATED if (request.method == 'POST') else HTTPStatus.ACCEPTED)
        except Exception as err:
            print(err)

        # complete filing
        response, response_code = ListFilingResource.complete_filing(
            business, filing, draft, payment_account_id)
        if response and (response_code != HTTPStatus.CREATED
                         or filing.source == Filing.Source.COLIN.value):
            return response, response_code

        # all done
        filing_json = filing.json
        if response:
            filing_json['filing']['header'].update(response)
        return jsonify(filing_json),\
            (HTTPStatus.CREATED if (request.method == 'POST') else HTTPStatus.ACCEPTED)

    @staticmethod
    @cors.crossdomain(origin='*')
    @jwt.requires_auth
    def delete(identifier, filing_id=None):  # pylint: disable=too-many-branches
        """Delete a filing from the business."""
        if not filing_id:
            return ({
                'message': _('No filing id provided for:') + identifier
            }, HTTPStatus.BAD_REQUEST)

        # check authorization
        if not authorized(identifier, jwt, action=['edit']):
            return jsonify({'message':
                            _('You are not authorized to delete a filing for:') + identifier}),\
                HTTPStatus.UNAUTHORIZED

        if identifier.startswith('T'):
            filing = Filing.get_temp_reg_filing(identifier, filing_id)
        else:
            filing = Business.get_filing_by_id(identifier, filing_id)

        if not filing:
            return jsonify({'message':
                            _('Filing Not Found.')}), HTTPStatus.NOT_FOUND

        if filing.deletion_locked:  # should not be deleted
            return ListFilingResource._create_deletion_locked_response(
                identifier, filing)

        try:
            ListFilingResource._delete_from_minio(filing)
            filing.delete()
        except BusinessException as err:
            return jsonify({'errors': [
                {
                    'error': err.error
                },
            ]}), err.status_code

        if identifier.startswith('T'):
            bootstrap = RegistrationBootstrap.find_by_identifier(identifier)
            if bootstrap:
                deregister_status = RegistrationBootstrapService.deregister_bootstrap(
                    bootstrap)
                delete_status = RegistrationBootstrapService.delete_bootstrap(
                    bootstrap)
                if deregister_status != HTTPStatus.OK or delete_status != HTTPStatus.OK:
                    current_app.logger.error(
                        'Unable to deregister and delete temp reg:',
                        identifier)

        return jsonify({'message': _('Filing deleted.')}), HTTPStatus.OK

    @staticmethod
    def _delete_from_minio(filing):
        if cooperative := filing. \
                filing_json.get('filing', {}).get('incorporationApplication', {}).get('cooperative', None):
            if rules_file_key := cooperative.get('rulesFileKey', None):
                MinioService.delete_file(rules_file_key)
            if memorandum_file_key := cooperative.get('memorandumFileKey',
                                                      None):
                MinioService.delete_file(memorandum_file_key)
Ejemplo n.º 10
0
 def _delete_from_minio(filing):
     if cooperative := filing. \
             filing_json.get('filing', {}).get('incorporationApplication', {}).get('cooperative', None):
         if rules_file_key := cooperative.get('rulesFileKey', None):
             MinioService.delete_file(rules_file_key)
Ejemplo n.º 11
0
def get_signatures(file_name: str):
    """Return a pre-signed URL for the new document."""
    return MinioService.create_signed_put_url(file_name), HTTPStatus.OK
Ejemplo n.º 12
0
def test_get_file(session, minio_server, tmpdir):  # pylint:disable=unused-argument
    """Assert that we can retrieve a file."""
    key = _upload_file(tmpdir)
    get_response = MinioService.get_file(key)
    assert get_response
Ejemplo n.º 13
0
def test_get_file_info(session, minio_server, tmpdir):  # pylint:disable=unused-argument
    """Assert that we can retrieve a file info."""
    key = _upload_file(tmpdir)
    file_info = MinioService.get_file_info(key)
    assert file_info
Ejemplo n.º 14
0
def test_create_signed_put_url(session, minio_server):  # pylint:disable=unused-argument
    """Assert that the a PUT url can be pre-signed."""
    file_name = 'cooperative-test.pdf'
    signed_url = MinioService.create_signed_put_url(file_name)
    assert signed_url
    assert signed_url.get('key').endswith('.pdf')