def view_signed_agreement(supplier_id, framework_slug): # not properly validating this - all we do is pass it through next_status = request.args.get("next_status") supplier = data_api_client.get_supplier(supplier_id)['suppliers'] framework = data_api_client.get_framework(framework_slug)['frameworks'] if not framework.get('frameworkAgreementVersion'): abort(404) supplier_framework = data_api_client.get_supplier_framework_info( supplier_id, framework_slug)['frameworkInterest'] if not supplier_framework.get('agreementReturned'): abort(404) lot_names = [] if framework["status"] in ("live", "expired"): # If the framework is live or expired we don't need to filter drafts, we only care about successful services service_iterator = data_api_client.find_services_iter( supplier_id=supplier_id, framework=framework_slug) for service in service_iterator: if service['lotName'] not in lot_names: lot_names.append(service['lotName']) else: # If the framework has not yet become live we need to filter out unsuccessful services service_iterator = data_api_client.find_draft_services_iter( supplier_id=supplier_id, framework=framework_slug) for service in service_iterator: if service["status"] == "submitted" and service[ 'lotName'] not in lot_names: lot_names.append(service['lotName']) agreements_bucket = s3.S3(current_app.config['DM_AGREEMENTS_BUCKET']) if framework_slug in OLD_COUNTERSIGNING_FLOW_FRAMEWORKS: is_e_signature_flow = False # Fetch path to supplier's signature page path = supplier_framework['agreementPath'] template = "suppliers/view_signed_agreement.html" else: is_e_signature_flow = True # Fetch path to combined countersigned agreement, if available path = supplier_framework.get('countersignedPath') template = "suppliers/view_esignature_agreement.html" url = get_signed_url(agreements_bucket, path, current_app.config['DM_ASSETS_URL']) if path else "" agreement_ext = get_extension(path) if path else "" if not url: current_app.logger.info(f'No agreement file found for {path}') return render_template( template, company_details=get_company_details_from_supplier(supplier), supplier=supplier, framework=framework, supplier_framework=supplier_framework, lot_names=list(sorted(lot_names)), agreement_url=url, agreement_ext=agreement_ext, next_status=next_status, is_e_signature_flow=is_e_signature_flow)
def signature_upload(framework_slug): framework = get_framework(data_api_client, framework_slug) return_supplier_framework_info_if_on_framework_or_abort( data_api_client, framework_slug) agreements_bucket = s3.S3(current_app.config['DM_AGREEMENTS_BUCKET']) signature_page = get_most_recently_uploaded_agreement_file_or_none( agreements_bucket, framework_slug) upload_error = None if request.method == 'POST': # No file chosen for upload and file already exists on s3 so can use existing and progress if not request.files['signature_page'].filename and signature_page: return redirect( url_for(".contract_review", framework_slug=framework_slug)) if not file_is_image( request.files['signature_page']) and not file_is_pdf( request.files['signature_page']): upload_error = "The file must be a PDF, JPG or PNG" elif not file_is_less_than_5mb(request.files['signature_page']): upload_error = "The file must be less than 5MB" elif file_is_empty(request.files['signature_page']): upload_error = "The file must not be empty" if not upload_error: upload_path = get_agreement_document_path( framework_slug, current_user.supplier_code, '{}{}'.format( SIGNED_AGREEMENT_PREFIX, get_extension(request.files['signature_page'].filename))) agreements_bucket.save(upload_path, request.files['signature_page'], acl='private') session['signature_page'] = request.files[ 'signature_page'].filename data_api_client.create_audit_event( audit_type=AuditTypes.upload_signed_agreement, user=current_user.email_address, object_type="suppliers", object_id=current_user.supplier_code, data={ "upload_signed_agreement": request.files['signature_page'].filename, "upload_path": upload_path }) return redirect( url_for(".contract_review", framework_slug=framework_slug)) status_code = 400 if upload_error else 200 return render_template_with_csrf( "frameworks/signature_upload.html", status_code=status_code, framework=framework, signature_page=signature_page, upload_error=upload_error, )
def test_get_extension(self): assert get_extension('what.jpg') == '.jpg' assert get_extension('what the.jpg') == '.jpg' assert get_extension('what.the.jpg') == '.jpg' assert get_extension('what.the..jpg') == '.jpg' assert get_extension('what.the.🐈.jpg') == '.jpg' assert get_extension('what.the.🐈jpg') == '.🐈jpg' assert get_extension('ಠ▃ಠ.jpg') == '.jpg'
def signature_upload(framework_slug): framework = get_framework(data_api_client, framework_slug) return_supplier_framework_info_if_on_framework_or_abort(data_api_client, framework_slug) agreements_bucket = s3.S3(current_app.config['DM_AGREEMENTS_BUCKET']) signature_page = get_most_recently_uploaded_agreement_file_or_none(agreements_bucket, framework_slug) upload_error = None if request.method == 'POST': # No file chosen for upload and file already exists on s3 so can use existing and progress if not request.files['signature_page'].filename and signature_page: return redirect(url_for(".contract_review", framework_slug=framework_slug)) if not file_is_image(request.files['signature_page']) and not file_is_pdf(request.files['signature_page']): upload_error = "The file must be a PDF, JPG or PNG" elif not file_is_less_than_5mb(request.files['signature_page']): upload_error = "The file must be less than 5MB" elif file_is_empty(request.files['signature_page']): upload_error = "The file must not be empty" if not upload_error: upload_path = get_agreement_document_path( framework_slug, current_user.supplier_code, '{}{}'.format(SIGNED_AGREEMENT_PREFIX, get_extension(request.files['signature_page'].filename)) ) agreements_bucket.save( upload_path, request.files['signature_page'], acl='private' ) session['signature_page'] = request.files['signature_page'].filename data_api_client.create_audit_event( audit_type=AuditTypes.upload_signed_agreement, user=current_user.email_address, object_type="suppliers", object_id=current_user.supplier_code, data={ "upload_signed_agreement": request.files['signature_page'].filename, "upload_path": upload_path }) return redirect(url_for(".contract_review", framework_slug=framework_slug)) status_code = 400 if upload_error else 200 return render_template_with_csrf( "frameworks/signature_upload.html", status_code=status_code, framework=framework, signature_page=signature_page, upload_error=upload_error, )
def upload_framework_agreement(framework_slug): framework = get_framework(data_api_client, framework_slug, allowed_statuses=['standstill', 'live']) supplier_framework = return_supplier_framework_info_if_on_framework_or_abort(data_api_client, framework_slug) upload_error = None if not file_is_less_than_5mb(request.files['agreement']): upload_error = "Document must be less than 5MB" elif file_is_empty(request.files['agreement']): upload_error = "Document must not be empty" if upload_error is not None: return render_template_with_csrf( "frameworks/agreement.html", status_code=400, framework=framework, supplier_framework=supplier_framework, upload_error=upload_error, agreement_filename=AGREEMENT_FILENAME ) agreements_bucket = s3.S3(current_app.config['DM_AGREEMENTS_BUCKET']) extension = get_extension(request.files['agreement'].filename) path = get_agreement_document_path( framework_slug, current_user.supplier_code, '{}{}'.format(SIGNED_AGREEMENT_PREFIX, extension) ) agreements_bucket.save( path, request.files['agreement'], acl='private', download_filename='{}-{}-{}{}'.format( sanitise_supplier_name(current_user.supplier_name), current_user.supplier_code, SIGNED_AGREEMENT_PREFIX, extension ) ) data_api_client.register_framework_agreement_returned( current_user.supplier_code, framework_slug, current_user.email_address) try: email_body = render_template( 'emails/framework_agreement_uploaded.html', framework_name=framework['name'], supplier_name=current_user.supplier_name, supplier_code=current_user.supplier_code, user_name=current_user.name ) send_email( current_app.config['DM_FRAMEWORK_AGREEMENTS_EMAIL'], email_body, '{} framework agreement'.format(framework['name']), current_app.config["DM_GENERIC_NOREPLY_EMAIL"], '{} Supplier'.format(framework['name']), ['{}-framework-agreement'.format(framework_slug)], reply_to=current_user.email_address, ) except EmailError as e: rollbar.report_exc_info() current_app.logger.error( "Framework agreement email failed to send. " "error {error} supplier_code {supplier_code} email_hash {email_hash}", extra={'error': six.text_type(e), 'supplier_code': current_user.supplier_code, 'email_hash': hash_email(current_user.email_address)}) abort(503, "Framework agreement email failed to send") return redirect(url_for('.framework_agreement', framework_slug=framework_slug))
def signature_upload(framework_slug, agreement_id): framework = get_framework(data_api_client, framework_slug, allowed_statuses=['standstill', 'live']) # if there's no frameworkAgreementVersion key it means we're pre-G-Cloud 8 and shouldn't be using this route if not framework.get('frameworkAgreementVersion'): abort(404) supplier_framework = return_supplier_framework_info_if_on_framework_or_abort( data_api_client, framework_slug) agreement = data_api_client.get_framework_agreement( agreement_id)['agreement'] check_agreement_is_related_to_supplier_framework_or_abort( agreement, supplier_framework) agreements_bucket = s3.S3(current_app.config['DM_AGREEMENTS_BUCKET']) signature_page = agreements_bucket.get_key( agreement.get('signedAgreementPath')) upload_error = None if request.method == 'POST': # No file chosen for upload and file already exists on s3 so can use existing and progress if not request.files['signature_page'].filename and signature_page: return redirect( url_for(".contract_review", framework_slug=framework_slug, agreement_id=agreement_id)) if not file_is_image( request.files['signature_page']) and not file_is_pdf( request.files['signature_page']): upload_error = "The file must be a PDF, JPG or PNG" elif not file_is_less_than_5mb(request.files['signature_page']): upload_error = "The file must be less than 5MB" elif file_is_empty(request.files['signature_page']): upload_error = "The file must not be empty" if not upload_error: extension = get_extension(request.files['signature_page'].filename) upload_path = generate_timestamped_document_upload_path( framework_slug, current_user.supplier_id, 'agreements', '{}{}'.format(SIGNED_AGREEMENT_PREFIX, extension)) agreements_bucket.save( upload_path, request.files['signature_page'], acl='private', download_filename='{}-{}-{}{}'.format( sanitise_supplier_name(current_user.supplier_name), current_user.supplier_id, SIGNED_SIGNATURE_PAGE_PREFIX, extension), disposition_type= 'inline' # Embeddeding PDFs in admin pages requires 'inline' and not 'attachment' ) data_api_client.update_framework_agreement( agreement_id, {"signedAgreementPath": upload_path}, current_user.email_address) session['signature_page'] = request.files[ 'signature_page'].filename return redirect( url_for(".contract_review", framework_slug=framework_slug, agreement_id=agreement_id)) return render_template( "frameworks/signature_upload.html", agreement=agreement, framework=framework, signature_page=signature_page, upload_error=upload_error, ), 400 if upload_error else 200
def upload_framework_agreement(framework_slug): """ This is the route used to upload agreements for pre-G-Cloud 8 frameworks """ framework = get_framework(data_api_client, framework_slug, allowed_statuses=['standstill', 'live']) # if there's a frameworkAgreementVersion key it means we're on G-Cloud 8 or higher and shouldn't be using this route if framework.get('frameworkAgreementVersion'): abort(404) supplier_framework = return_supplier_framework_info_if_on_framework_or_abort( data_api_client, framework_slug) upload_error = None if not file_is_less_than_5mb(request.files['agreement']): upload_error = "Document must be less than 5MB" elif file_is_empty(request.files['agreement']): upload_error = "Document must not be empty" if upload_error is not None: return render_template( "frameworks/agreement.html", framework=framework, supplier_framework=supplier_framework, upload_error=upload_error, agreement_filename=AGREEMENT_FILENAME, ), 400 agreements_bucket = s3.S3(current_app.config['DM_AGREEMENTS_BUCKET']) extension = get_extension(request.files['agreement'].filename) path = generate_timestamped_document_upload_path( framework_slug, current_user.supplier_id, 'agreements', '{}{}'.format(SIGNED_AGREEMENT_PREFIX, extension)) agreements_bucket.save( path, request.files['agreement'], acl='private', download_filename='{}-{}-{}{}'.format( sanitise_supplier_name(current_user.supplier_name), current_user.supplier_id, SIGNED_AGREEMENT_PREFIX, extension)) agreement_id = data_api_client.create_framework_agreement( current_user.supplier_id, framework_slug, current_user.email_address)['agreement']['id'] data_api_client.update_framework_agreement(agreement_id, {"signedAgreementPath": path}, current_user.email_address) data_api_client.sign_framework_agreement( agreement_id, current_user.email_address, {"uploaderUserId": current_user.id}) try: email_body = render_template( 'emails/framework_agreement_uploaded.html', framework_name=framework['name'], supplier_name=current_user.supplier_name, supplier_id=current_user.supplier_id, user_name=current_user.name) send_email( current_app.config['DM_FRAMEWORK_AGREEMENTS_EMAIL'], email_body, current_app.config['DM_MANDRILL_API_KEY'], '{} framework agreement'.format(framework['name']), current_app.config["DM_GENERIC_NOREPLY_EMAIL"], '{} Supplier'.format(framework['name']), ['{}-framework-agreement'.format(framework_slug)], reply_to=current_user.email_address, ) except MandrillException as e: current_app.logger.error( "Framework agreement email failed to send. " "error {error} supplier_id {supplier_id} email_hash {email_hash}", extra={ 'error': six.text_type(e), 'supplier_id': current_user.supplier_id, 'email_hash': hash_email(current_user.email_address) }) abort(503, "Framework agreement email failed to send") return redirect( url_for('.framework_agreement', framework_slug=framework_slug))
def upload_framework_agreement(framework_slug): framework = get_framework(data_api_client, framework_slug, allowed_statuses=['standstill', 'live']) supplier_framework = return_supplier_framework_info_if_on_framework_or_abort( data_api_client, framework_slug) upload_error = None if not file_is_less_than_5mb(request.files['agreement']): upload_error = "Document must be less than 5MB" elif file_is_empty(request.files['agreement']): upload_error = "Document must not be empty" if upload_error is not None: return render_template_with_csrf("frameworks/agreement.html", status_code=400, framework=framework, supplier_framework=supplier_framework, upload_error=upload_error, agreement_filename=AGREEMENT_FILENAME) agreements_bucket = s3.S3(current_app.config['DM_AGREEMENTS_BUCKET']) extension = get_extension(request.files['agreement'].filename) path = get_agreement_document_path( framework_slug, current_user.supplier_code, '{}{}'.format(SIGNED_AGREEMENT_PREFIX, extension)) agreements_bucket.save( path, request.files['agreement'], acl='private', download_filename='{}-{}-{}{}'.format( sanitise_supplier_name(current_user.supplier_name), current_user.supplier_code, SIGNED_AGREEMENT_PREFIX, extension)) data_api_client.register_framework_agreement_returned( current_user.supplier_code, framework_slug, current_user.email_address) try: email_body = render_template( 'emails/framework_agreement_uploaded.html', framework_name=framework['name'], supplier_name=current_user.supplier_name, supplier_code=current_user.supplier_code, user_name=current_user.name) send_email( current_app.config['DM_FRAMEWORK_AGREEMENTS_EMAIL'], email_body, '{} framework agreement'.format(framework['name']), current_app.config["DM_GENERIC_NOREPLY_EMAIL"], '{} Supplier'.format(framework['name']), ['{}-framework-agreement'.format(framework_slug)], reply_to=current_user.email_address, ) except EmailError as e: rollbar.report_exc_info() current_app.logger.error( "Framework agreement email failed to send. " "error {error} supplier_code {supplier_code} email_hash {email_hash}", extra={ 'error': six.text_type(e), 'supplier_code': current_user.supplier_code, 'email_hash': hash_email(current_user.email_address) }) abort(503, "Framework agreement email failed to send") return redirect( url_for('.framework_agreement', framework_slug=framework_slug))