diff --git a/.dockerignore b/.dockerignore index c0724d6..283e9e8 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,4 @@ **/__pycache__ -**/env_voter +**/env_htb21reg instance/ +staging/ diff --git a/Dockerfile b/Dockerfile index 30daae8..179280b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM python:alpine3.7 WORKDIR /app -RUN apk add make +RUN apk add make alpine-sdk libffi-dev --no-cache RUN pip install gunicorn COPY ./requirements.txt ./requirements.txt RUN pip install -r requirements.txt diff --git a/app/hacker.py b/app/hacker.py index 8fb56e0..824d400 100644 --- a/app/hacker.py +++ b/app/hacker.py @@ -5,6 +5,12 @@ from json import dumps import arrow import time +from multiprocessing import Process +import requests +import tempfile +import boto3 +import shutil +import os bp = Blueprint('hacker', __name__, url_prefix='/hacker') @@ -115,26 +121,68 @@ def application(): ) -@bp.route('/application/submit', methods=['POST']) -@hacker_login_required -def submit_application(): +def s3_upload(filename,local_fn,tmpdir): + + s3 = boto3.client( + 's3', + region_name=os.environ['S3_REGION'], + endpoint_url=os.environ['S3_ENDPOINT'], + aws_access_key_id=os.environ['S3_ACCESS_KEY'], + aws_secret_access_key=os.environ['S3_ACCESS_SECRET'], + ) + + response = s3.upload_file(local_fn, os.environ['S3_BUCKET'], filename, ExtraArgs={'ContentType': "application/pdf", 'ACL': "public-read"}) + + shutil.rmtree(tmpdir) + + +def write_application(submit=False): db = get_db() c = db.cursor() - #appl, _ = resolve_application(session['email']) - #if appl['completed']: - # flasher('Can\'t re-submit, application already submitted!', color='warning') - # return redirect(url_for('hacker.application')) + appl_old, _ = resolve_application(session['email']) cfg = get_config(db) if (cfg['applications_dline'] <= time.time()): flasher('Application deadline has passed!', color='danger') return redirect(url_for('hacker.application')) + if request.files['resume'].filename != '': + + filename = f"htb21-cvs/{'_'.join(appl_old['user_id'].split(':'))}.pdf" + + # HAX - S3 upload is slow as fuck, so i'm doing it in the background + # and just hoping it works + print(filename) + + tmpdir = tempfile.mkdtemp() + local_fn = os.path.join(tmpdir, filename.split('/')[1]) + request.files['resume'].save(local_fn) + upload = Process(target=s3_upload, args=(filename,local_fn,tmpdir)) + + upload.daemon = True + upload.start() + + # oh jesus + resume = f"{os.environ['S3_SUBDOMAIN']}/{filename}" + # we're going to set this separately to avoid overriding existing values + c.execute(''' + UPDATE Applicants + SET resume=? + WHERE email=? + ''', (resume, session['email'])) + + #print(equest.files['resume']) + try: + + # checkboxes cb_gdpr = 'gdpr' in request.form and request.form['gdpr'] == 'on' + cb_gdpr_sponsor = 'gdpr_sponsor' in request.form and request.form['gdpr_sponsor'] == 'on' cb_mlh_coc = 'mlh_coc' in request.form and request.form['mlh_coc'] == 'on' + cb_mlh_admin = 'mlh_admin' in request.form and request.form['mlh_admin'] == 'on' + cb_mlh_email = 'mlh_email' in request.form and request.form['mlh_email'] == 'on' cb_adult = 'adult' in request.form and request.form['adult'] == 'on' cb_hackuk_admin = 'hackuk_admin' in request.form and request.form['hackuk_admin'] == 'on' cb_hackuk_email = 'hackuk_email' in request.form and request.form['hackuk_email'] == 'on' @@ -160,11 +208,14 @@ def submit_application(): description=?, essay=?, gdpr=?, + gdpr_sponsor=?, mlh_coc=?, + mlh_admin=?, + mlh_email=?, adult=?, hackuk_admin=?, hackuk_email=?, - completed=1, + completed=?, completed_time=? WHERE email=? @@ -185,16 +236,23 @@ def submit_application(): request.form['description'], request.form['essay'], cb_gdpr, + cb_gdpr_sponsor, cb_mlh_coc, + cb_mlh_admin, + cb_mlh_email, cb_adult, cb_hackuk_admin, cb_hackuk_email, - time.time(), + 1 if submit else 0, + (time.time()) if submit else None, session['email'] ]) c.connection.commit() - flasher('Submitted successfully!', color='success') + if submit: + flasher('Submitted successfully!', color='success') + else: + flasher('Saved successfully!', color='success') except Exception as e: raise e print(e) @@ -202,88 +260,17 @@ def submit_application(): return redirect(url_for('hacker.application')) + +@bp.route('/application/submit', methods=['POST']) +@hacker_login_required +def submit_application(): + write_application(submit=True) + return redirect(url_for('hacker.application')) + @bp.route('/application/save', methods=['POST']) @hacker_login_required def save_application(): - db = get_db() - c = db.cursor() - - appl, _ = resolve_application(session['email']) - if appl['completed']: - flasher('Can\'t save changes, application already submitted!', color='warning') - return redirect(url_for('hacker.application')) - - cfg = get_config(db) - if (cfg['applications_dline'] <= time.time()): - flasher('Application deadline has passed!', color='danger') - return redirect(url_for('hacker.application')) - - try: - # checkboxes - cb_gdpr = 'gdpr' in request.form and request.form['gdpr'] == 'on' - cb_mlh_coc = 'mlh_coc' in request.form and request.form['mlh_coc'] == 'on' - cb_adult = 'adult' in request.form and request.form['adult'] == 'on' - cb_hackuk_admin = 'hackuk_admin' in request.form and request.form['hackuk_admin'] == 'on' - cb_hackuk_email = 'hackuk_email' in request.form and request.form['hackuk_email'] == 'on' - - dd_gradYear = request.form['gradYear'] if 'gradYear' in request.form else None - dd_shirt_size = request.form['shirt_size'] if 'shirt_size' in request.form else None - - c.execute(''' - UPDATE Applicants - SET first_name=?, - last_name=?, - contact_email=?, - school=?, - gradYear=?, - shirt_size=?, - address_line_1=?, - address_line_2=?, - address_line_3=?, - address_city=?, - address_region=?, - address_country=?, - address_pcode=?, - description=?, - essay=?, - gdpr=?, - mlh_coc=?, - adult=?, - hackuk_admin=?, - hackuk_email=? - WHERE - email=? - ''',[ - request.form['first_name'], - request.form['last_name'], - request.form['contact_email'], - request.form['school'], - dd_gradYear, - dd_shirt_size, - request.form['address_line_1'], - request.form['address_line_2'], - request.form['address_line_3'], - request.form['address_city'], - request.form['address_region'], - request.form['address_country'], - request.form['address_pcode'], - request.form['description'], - request.form['essay'], - cb_gdpr, - cb_mlh_coc, - cb_adult, - cb_hackuk_admin, - cb_hackuk_email, - session['email'] - ]) - c.connection.commit() - - flasher('Saved successfully!', color='success') - except Exception as e: - raise - print(e) - flasher('Something went wrong! Please contact tech@hacktheburgh.com.', color='danger') - + write_application(submit=False) return redirect(url_for('hacker.application')) @@ -324,3 +311,62 @@ def invites(): invites=rows, login_type=capitalize_login_provider() ) + +@bp.route('/resume') +@hacker_login_required +def show_resume(): + # this exists solely for people who click the link too fast + # (before it has a chance to upload) + appl, _ = resolve_application(session['email']) + + if appl['resume'] is not None and appl['resume'] != '': + resp = requests.head(appl['resume']) + if resp.status_code != 403: + return redirect(appl['resume']) + else: + return 'Resume processing, please try again in a few seconds.' + else: + return "You haven't uploaded a resume!" + + +@bp.route('/resume/delete') +@hacker_login_required +def delete_resume(): + appl, _ = resolve_application(session['email']) + + db = get_db() + cfg = get_config(db) + if (cfg['applications_dline'] <= time.time()): + flasher('Application deadline has passed!', color='danger') + return redirect(url_for('hacker.application')) + + if appl['resume'] is not None and appl['resume'] != '': + filename = f"htb21-cvs/{'_'.join(appl['user_id'].split(':'))}.pdf" + + s3 = boto3.client( + 's3', + region_name=os.environ['S3_REGION'], + endpoint_url=os.environ['S3_ENDPOINT'], + aws_access_key_id=os.environ['S3_ACCESS_KEY'], + aws_secret_access_key=os.environ['S3_ACCESS_SECRET'], + ) + + s3.delete_object( + Bucket=os.environ['S3_BUCKET'], + Key=filename, + ) + + c = db.cursor() + c.execute(''' + UPDATE Applicants + SET resume=NULL + WHERE email=? + ''', [session['email']]) + c.connection.commit() + + flasher('Resume deleted successfully.', 'success') + + return redirect(url_for('hacker.application')) + else: + return "You haven't uploaded a resume!" + diff --git a/app/schema.sql b/app/schema.sql index f1c9204..68b1e1a 100644 --- a/app/schema.sql +++ b/app/schema.sql @@ -42,13 +42,17 @@ CREATE TABLE Applicants ( gender TEXT, description TEXT, essay TEXT, + resume TEXT, shirt_size TEXT, -- authorizations gdpr INTEGER, + gdpr_sponsor INTEGER, mlh_coc INTEGER, + mlh_admin INTEGER, + mlh_email INTEGER, hackuk_admin INTEGER, - hackuk_email INTEGER, + hackuk_email INTEGER, UNIQUE (user_id), UNIQUE (email) diff --git a/app/templates/hacker/form.html b/app/templates/hacker/form.html index e9c6972..0ec0179 100644 --- a/app/templates/hacker/form.html +++ b/app/templates/hacker/form.html @@ -5,7 +5,7 @@