From a13a88a5b357d5ce4091c99247484845da5be53e Mon Sep 17 00:00:00 2001 From: Allie Bopp <aebopp@umich.edu> Date: Thu, 18 Jun 2020 00:52:03 -0400 Subject: [PATCH] points submission --- .../templates/confirmSubmission.html | 11 +++ servicePoints/templates/delete.html | 7 +- servicePoints/templates/index.html | 2 +- servicePoints/templates/submitPoints.html | 31 ++++++ .../views/__pycache__/accounts.cpython-36.pyc | Bin 7123 -> 9432 bytes servicePoints/views/accounts.py | 88 +++++++++++++++++- sql/schema.sql | 9 ++ ...b68456865edbbdaa67c99783de324711384437.jpg | Bin 0 -> 7810 bytes ...c8996fb92427ae41e4649b934ca495991b7852b855 | 0 var/servicePoints.sqlite3 | Bin 20480 -> 24576 bytes 10 files changed, 137 insertions(+), 11 deletions(-) create mode 100644 servicePoints/templates/confirmSubmission.html create mode 100644 servicePoints/templates/submitPoints.html create mode 100644 var/images/c0cf17efda2368530bb66b4e2fb68456865edbbdaa67c99783de324711384437.jpg create mode 100644 var/images/e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 diff --git a/servicePoints/templates/confirmSubmission.html b/servicePoints/templates/confirmSubmission.html new file mode 100644 index 0000000..5d8a185 --- /dev/null +++ b/servicePoints/templates/confirmSubmission.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html> + <body> + <p> + Your submission has been sent to {{leader}} + </p> + <form action="/accounts/confirmSubmission/" method="post" enctype="multipart/form-data"> + <input type="submit" name="return" value="Return to Homepage"/> + </form> + </body> +</html> \ No newline at end of file diff --git a/servicePoints/templates/delete.html b/servicePoints/templates/delete.html index 9a5db10..8ef2fd1 100644 --- a/servicePoints/templates/delete.html +++ b/servicePoints/templates/delete.html @@ -7,14 +7,9 @@ <body> <h1> - <a href="/">/ </a> - | - <a href="/u/{{username}}/">{{username}}</a> + <a href="/">Back to Homepage</a> </h1> <p>{{username}}</p> - <p> - {{username}} - </p> <form action="/accounts/delete/" method="post" enctype="multipart/form-data"> <input type="submit" name="delete" value="confirm delete account"/> </form> diff --git a/servicePoints/templates/index.html b/servicePoints/templates/index.html index 38f8151..3810b90 100644 --- a/servicePoints/templates/index.html +++ b/servicePoints/templates/index.html @@ -21,7 +21,7 @@ <a href="/accounts/mask/"> <img src=/images/tutor.png alt="mask"> </a> - <a href="/accounts/mask/"> + <a href="/accounts/submitPoints/"> <img src=/images/submit.png alt="mask"> </a> diff --git a/servicePoints/templates/submitPoints.html b/servicePoints/templates/submitPoints.html new file mode 100644 index 0000000..cd49ae0 --- /dev/null +++ b/servicePoints/templates/submitPoints.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html> + <head> + <link rel="stylesheet" type="text/css" href="/css/style.css"> + <h1 style="text-align:center">Submit Points</h1> + <p>{{username}}</p> + <p>{{org}}</p> + <p>Hours: {{hours}}</p> + <a href="/accounts/index/">Back to Homepage</a> + </head> + + <form action="/accounts/submitPoints/" method="post" enctype="multipart/form-data"> + <p> + <label for="service">Select the type of service:</label> + + <select name="service" id="service"> + <option value="mask">Mask-Making</option> + <option value="blood">Donating Blood</option> + <option value="tutor">Tutoring</option> + <option value="food">Donating Food</option> + </select> + </p> + <p> + Photo for proof of service + <input type="file" name="file"> + </p> + <p> + <input type="submit" name="update" value="submit" /> + </p> + </form> +</html> \ No newline at end of file diff --git a/servicePoints/views/__pycache__/accounts.cpython-36.pyc b/servicePoints/views/__pycache__/accounts.cpython-36.pyc index 865419fc28b3340d4bb6e9312e8ea0508d78d314..eb1ed6e4f1999df8fe3ef75147131ce55ee8d14b 100644 GIT binary patch delta 2988 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 UCMxMlqGDGJ{O2{0rz++D0&gqKo&W#< delta 1029 zcmYk5-D?zA7{<>#J0E9fKW29`o6Sxpeq=W>-&#dtMa+t#q+mj^Mp%q#%sY{+yIDJl zcL}*jKxi>l-U}~mq0qb54`eU;7xY39BK1bL^dfC9YEcv{UW(_86S{La&&)i(=bU-Z z;mq^#XQPEfiG=y}&o3^$>}TvR)^e%hxg`41gWHAPHKiJ<sbv)yGK8vD*1SkX_l$KY zbBuUeB|2kDt;A484fQJu8aEZ>7~NnZ6AziW4j99D;3YyY(UMQ16|iK;Qafx-OqRw> z0Id+V?Lfh7%myrl?U>tO<#d?oXvyT!2{M_Gb+#}Uy8_l0vRy4~H}2V3ldG^pxVHs% zV<8xr4Oy{;^<Zzn+C#Rlh4o>7z;YoQ5IZx7LxI;3dc*(cQ#gYA1DHoR$NCR6dX*;; zh|^o`cNm~8{V04#KPUsRN$+DLG-q5(uS76$Rq>xMvq}<^>j1RLov4*(!T_}B5kEJ$ z^Og!-HP2RbOwa49#<E^9Dtw)-@)cf*V}|xeyQ20=bW?slOXs8ayP9m_7BJT2^Vh4@ z#o3zI)V$j4Le&>0BiEXvZ_HU;o4s83m+6i9rT&RLP9>U(b*m}|v#}Ao5U~#mvzc62 zoU7NaRlQ~JbltDf-^u%Mg6^85^w_esW~AyZ(x28vm}!iqegZf}|E71t88R~`p-dB* z0-UD3*_`ehVzN7pZ!@0)+-p2;;{X%%o4p9X(1~m(Owx3Aizad<?SRPrN?*1A0iV-k z?j$@V$~~lFzK4dKPHkA0L^nFVC&THX@w@}ug!v!g3*ydLt|aI`qAzhFOo>AZIQS*H z<eY``bkFIvUP~(fAEv0_PtmsXuJ1qTeH>we3O4xD!s&N>SKR#1gfx}<l5f$gLQ$+K zQ#@RpltfnQn^I&|{+N`Klqo6G^ic0O#*fwNc)jW!mm9w{AcTvOWQ&V#M!4ecvJH2{ SJ>q70%uTv6*K`fpZ0!S~aPltz diff --git a/servicePoints/views/accounts.py b/servicePoints/views/accounts.py index e42976a..a35f8bc 100644 --- a/servicePoints/views/accounts.py +++ b/servicePoints/views/accounts.py @@ -2,6 +2,8 @@ import hashlib import uuid import os import flask +import shutil +import tempfile from flask import render_template import servicePoints APP = flask.Flask(__name__) @@ -68,10 +70,14 @@ def create(): if cursor.fetchone() is None: return flask.redirect(flask.url_for('orgNotFound')) - # If a user tries to create an account with an empty string as the - # password, abort(400) - if password == '': - flask.abort(400) + if len(str(flask.request.form['password'])) is 0 or len(str(flask.request.form['fullname'])) is 0: + return flask.redirect(flask.url_for('incompleteForm', prev="create")) + + if len(str(flask.request.form['orgName'])) is 0 or len(str(flask.request.form['email'])) is 0: + return flask.redirect(flask.url_for('incompleteForm', prev="create")) + + if len(str(flask.request.form['username'])) is 0: + return flask.redirect(flask.url_for('incompleteForm', prev="create")) flask.session['username'] = flask.request.form['username'] flask.session['fullname'] = flask.request.form['fullname'] @@ -247,3 +253,77 @@ def images(filename): return flask.send_from_directory( servicePoints.app.config['IMAGES_FOLDER'], filename, as_attachment=True) return flask.redirect(flask.url_for('login')) + +@servicePoints.app.route('/accounts/submitPoints/', methods=['GET', 'POST']) +def submitPoints(): + if flask.request.method == 'POST': + dummy, temp_filename = tempfile.mkstemp() + file = flask.request.files["file"] + serviceType = flask.request.form["service"] + file.save(temp_filename) + + # Compute filename + hash_txt = sha256sum(temp_filename) + dummy, suffix = os.path.splitext(file.filename) + hash_filename_basename = hash_txt + suffix + hash_filename = os.path.join( + servicePoints.app.config["IMAGES_FOLDER"], + hash_filename_basename + ) + + # Move temp file to permanent location + shutil.move(temp_filename, hash_filename) + cursor = servicePoints.model.get_db() + username = flask.session["username"] + studentOrgCur = cursor.execute('SELECT orgName FROM users WHERE ' + 'username =:who', + {"who": username}) + results = studentOrgCur.fetchone() + orgName = results["orgName"] + studentOrgLeader = cursor.execute('SELECT username FROM orgs WHERE ' + 'orgName =:who', + {"who": orgName}) + results = studentOrgLeader.fetchone() + leader = results["username"] + cursor.execute('INSERT INTO requests(member, leader, service, filename) VALUES ' + '(:one,:two,:three,:four)', {"one": username, "two": leader, "three": serviceType, "four": hash_filename_basename}) + return flask.redirect(flask.url_for('confirmSubmission')) + username = flask.session["username"] + cursor = servicePoints.model.get_db() + studentOrgCur = cursor.execute('SELECT orgName, hours FROM users WHERE ' + 'username =:who', + {"who": username}) + results = studentOrgCur.fetchone() + context = {'username': username, 'org': results["orgName"], 'hours': results["hours"]} + return render_template('submitPoints.html', **context) + +@servicePoints.app.route('/accounts/confirmSubmission/', methods=['GET', 'POST']) +def confirmSubmission(): + if flask.request.method == 'POST': + return flask.redirect(flask.url_for('index')) + username = flask.session["username"] + cursor = servicePoints.model.get_db() + studentOrgCur = cursor.execute('SELECT orgName FROM users WHERE ' + 'username =:who', + {"who": username}) + results = studentOrgCur.fetchone() + orgName = results["orgName"] + studentOrgLeader = cursor.execute('SELECT username FROM orgs WHERE ' + 'orgName =:who', + {"who": orgName}) + results = studentOrgLeader.fetchone() + leader = results["username"] + studentOrgLeaderFull = cursor.execute('SELECT fullname FROM users WHERE ' + 'username =:who', + {"who": leader}) + results = studentOrgLeaderFull.fetchone() + context = {"leader": results["fullname"]} + return render_template('confirmSubmission.html', **context) + + + +def sha256sum(filename): + """Return sha256 hash of file content, similar to UNIX sha256sum.""" + content = open(filename, 'rb').read() + sha256_obj = hashlib.sha256(content) + return sha256_obj.hexdigest() \ No newline at end of file diff --git a/sql/schema.sql b/sql/schema.sql index cf8c4be..5779cd8 100644 --- a/sql/schema.sql +++ b/sql/schema.sql @@ -14,4 +14,13 @@ CREATE TABLE orgs( username VARCHAR(20) NOT NULL, orgName VARCHAR(40) NOT NULL, PRIMARY KEY(orgName) +); + +CREATE TABLE requests( + postid INTEGER NOT NULL, + member VARCHAR(20) NOT NULL, + leader VARCHAR(40) NOT NULL, + service VARCHAR(40) NOT NULL, + filename VARCHAR(64) NOT NULL, + PRIMARY KEY(postid) ); \ No newline at end of file diff --git a/var/images/c0cf17efda2368530bb66b4e2fb68456865edbbdaa67c99783de324711384437.jpg b/var/images/c0cf17efda2368530bb66b4e2fb68456865edbbdaa67c99783de324711384437.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b7f849e6e752e3a8331fe22bb1261a55ce6965e8 GIT binary patch literal 7810 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 ak{mLsi3@Rso(-Jk|Bf&J{}I6Fx&H-B7inJr literal 0 HcmV?d00001 diff --git a/var/images/e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 b/var/images/e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 new file mode 100644 index 0000000..e69de29 diff --git a/var/servicePoints.sqlite3 b/var/servicePoints.sqlite3 index 12b075764feae87c8ab17d440739fe167aa7a16e..d8f2f0286c34dc7b57ddc6ecf5e2c42001235257 100644 GIT binary patch delta 462 zcmZozz}Rqrae}lU2Ll5G8xX?)^F$qEaSjGOnGL-BKNwhfRT=mW^PlAt=9|T<y0LLR zPfTMrE4#R?EMv1~Nn%n?YEf!oX=-svF^pz&4svx2aa9O$bn<akfQf2waVjVj<QJD@ zrYLy&g}A!A1}XUYhbZ`k`uOO8<Z@GUlTwQ&|KXEj%Sla40W#(IB{&omic^cqGLt9E z@=IDOD5PcPq~;~&rYeLv2042;25Fd?XrdYu5aj9W7!;}C?HZ{8u}+gqbF(ntM@BXV z0R{$s)6Iekdi;#1CpI4E;sSXYB=~)^pu-*hi4#PGIKiR73nZENpEK}(<9`m6y3Mc3 z%fu`$o?e!bm7SIjBsdtE1%-1{{fp8;W-#%;XW;+I{~lsW0J}6Nvp6GI9TOX~FegwI z$UsK^^$h&$fz~hO5A<hbXAl$=ZR7>|IyE=3I6Kui$spOp#K_VjE!i;H(8Mw^Eh)_; u*}~G&EG@~>$i&DzG1bH{)x^xiGRe}|BstN<($vz@Fv;A))F{cq)D!@0o_NLp delta 1001 zcmZ8gON-n^5dY6(mo@B6J1!zi0;@0}f=EBAtGbW5>0!+$@KDuVy;+SWOq5|yll2oM z*Ie`?1oj>T&z?Ma)R2piLjr>0#U9tq!GgYY*X#G_2S1D+d_Q`4eX%<X!%ja}F@E%6 zczbvF=*E+o`E!`g4~F@V=BN3={PD%&&F^Lx2lJPs{ptRz!F)V_ID5MPs$c)Mzd8S8 zy0^G~c=YXO=2(yQ<_VvEb$a)k)3cM~vs<f^Px(u|f19K8OU=cTZG{^r07y(yeN8Nk zrRD0D7|17SDpFES1m0P#lqn}lm?<(T*cP(y?;fR9X}k#xl#8^eHlPQJt`SM|P<`~F zSX)(sP-1H%L7x=`w7;lgA6jFy6&poc5+-|oYqEFv&U;%htaA6>y_<LLoT{$s*X`u& z_UB*xA5xM{h7xka1O%CC78Zpf)z+dMX_-R->jfoMR_d35L@H)%kq`q~mwoK}6^`t^ z*VHIQPUH%*vZX*!JVq{RU2KUIgQH$qDmABBH$J&qQX$C<;xvZlT&hqoMrqKhJ&)r( z)1zZrtyb&*#E8D-2%V@33cYJ;*o!QA74o*WC8I@Ke9{t}DAr0P#T?ZIN<qmHhbHJY zi0FHo>oN#nV3#uoTfu><unW%nj<<8se6-m4t_`e!qZ$&`SnGB$Nu(U8R7lW4mskSz z#Yb0*uX|iAo<p_B&5KRY^%rR^p>$G+nEKEqq9EW_k>+ck?IWpJ>g;>fBr!VH5Gims zB5o5RX4d2Yx+tZ~qEK^iDIwXw0i3n!i9ECb90E6&`}X9Zo6Ih=<<@++YIaV9Yp26r z>wju$o(<-i`Q7|s{=Qhe`?L9Acd{5A>-5^>aCB*|$<D-#R^#c!ys@73lCgO{n7_>P tp8kt@|E=-l@aQt}we5CB6JyrvZU3=(F_;(s_Wsoz%qB;p*IAbx{{g^e5ElRd -- GitLab