Commit a010e2ef authored by Romain Loth's avatar Romain Loth

static to server transformation: cgi-bin became server

parent 504391b1
Memo for chown
--------------
To ensure correct access rights to the DB,
the entire folder data/ should should be owned
by www-data or a user member of www-data group.
Exemple:
```
sudo chown -R romain:www-data data/
```
"""
Flask server used to test the registration page for comex app
Flask server used for the registration page for comex app
Context:
- templates-based input form validated fields and checked if all were present
(base_form.html + static/js/comex_reg_form_controllers.js)
(in production this script is not used anymore
=> the registration page will be a static form
with js and cgi-bin answers management )
- Doors recorded the email + password combination
- POSSIBLE Doors validated the email was new ??
=> TODO more generic use the server to generate the form and validation
"""
__author__ = "CNRS"
__copyright__ = "Copyright 2016 ISCPIF-CNRS"
__version__ = "1"
__email__ = "romain.loth@iscpif.fr"
__status__ = "Test"
__status__ = "Dev"
from flask import Flask, render_template, request
from ctypes import c_int
from time import sleep
from flask import Flask, render_template, request
from ctypes import c_int32
# from time import sleep
from jinja2 import Template, Environment, FileSystemLoader
from sqlite3 import connect
from re import sub
# ============= app creation =============
app = Flask(__name__)
app.config['DEBUG'] = True
# templating setup
templating_env = Environment(loader = FileSystemLoader('templates'),
autoescape = False)
########### PARAMS ###########
# all columns as they are declared in form & DB as tuple:
# NAME, NOT NULL, N or MAXCHARS (if applicable)
COLS = [ ("doors_uid", True, 36),
("last_modified_date", True, 24), # ex 2016-11-16T17:47:07.308Z
("email", True, 255),
("initials", True, 7),
("country", True, 60),
("first_name", True, 30),
("middle_name", False, 30),
("last_name", True, 50),
("jobtitle", True, 30),
("keywords", True, 350),
("institution", True, 120),
("institution_type", True, 50),
("team_lab", False, 50),
("institution_city", False, 50),
("interests_text", False, 1200),
("community_hashtags", False, 350),
("gender", False, 1), # M|F
("pic_file", False, None)]
# ============= views =============
# ------------------------------------------------------------------
# /!\ All routes will be prefixed by comexsomething/reg in prod /!\
# ------------------------------------------------------------------
@app.route("/", methods=['GET','POST'])
def one_big_form():
if request.method == 'GET':
return render_template("base_layout.html")
return render_template("base_form.html")
elif request.method == 'POST':
# ex: request.form = ImmutableMultiDict([('initials', 'R.L.'), ('email', 'romain.loth@iscpif.fr'), ('last_name', 'Loth'), ('country', 'France'), ('first_name', 'Romain'), ('my-captchaHash', '-773776109'), ('my-captcha', 'TSZVIN')])
# print("GOT ANSWERS <<========<<", request.form)
# 1 - testing the captcha answer
userinput = request.form['my-captcha']
userhash = re_hash(userinput)
captchash = int(request.form['my-captchaHash'])
if userhash != captchash:
captcha_userinput = request.form['my-captcha']
captcha_userhash = re_hash(captcha_userinput)
captcha_verifhash = int(request.form['my-captchaHash'])
# dbg
# print(str(captcha_verifhash))
if captcha_userhash != captcha_verifhash:
print("captcha rejected")
sleep(3)
return render_template("thank_you.html", form_accepted = False)
# normal case
else:
print("OK accepted")
from_reception_to_save(request.form) #£TODO debug this
return render_template("thank_you.html", form_accepted = True)
# TODO combine with:
# show received values in template
# ================================
print_to_buffer(
template_thanks.render(
form_accepted = captcha_accepted,
# for debug
records = clean_records,
message = ""
)
)
# def re_hash(userinput, salt="#salt"):
def re_hash(userinput, salt=""):
########### SUBS ###########
def re_hash(userinput, salt="verylonverylongverylonverylongverylonverylong"):
"""
my rewrite of keith-wood.name/realPerson.html python's version
Build the captcha's verification hash server side
(my rewrite of keith-wood.name/realPerson.html python's version)
NB the number of iterations is prop to salt length
<< 5 pads binary repr by 5 zeros on the right (including possible change of sign)
NB in all languages except python it truncates on the left
=> here we need to emulate the same mechanism
=> using c_int32() works well
"""
hashk = 5381
value = userinput.upper() + salt
# debug
# print("evaluated value:"+value)
for i, char in enumerate(value):
hashk = c_int32(hashk << 5).value + hashk + ord(char)
# debug iterations
# print(str(i) + ": " + str(hashk))
hashk = c_int( ((hashk << 5) + hashk + ord(char)) & 0xFFFFFFFF ).value
# bitwise masks 0xFFFFFFFF to go back to int32 each time
# c_int( previous ).value to go from unsigned ints to c signed ints each time
print(i, hashk)
return hashk
def get_template(filename):
"""
Retrieve a jinja2 template from templates
£TODO: check if necessary in server context ?
"""
return templating_env.get_template(filename)
def sanitize(value):
"""
simple and radical: leaves only alphanum and '.' '-' ':' ',' '(', ')', ' '
TODO better
"""
vtype = type(value)
str_val = str(value)
clean_val = sub(r'^\s+', '', str_val)
clean_val = sub(r'\s+$', '', clean_val)
san_val = sub(r'[^\w@\.-:,() ]', '_', clean_val)
if vtype not in [int, str]:
raise ValueError("Value has an incorrect type %s" % str(vtype))
else:
# cast back to orginal type
san_typed_val = vtype(san_val)
return san_typed_val
def save_to_db(safe_recs_arr):
"""
see COLS and table_specifications.md
"""
# expected number of vals (for instance 3 vals ===> "(?,?,?)" )
db_mask = '('+ ','.join(['?' for i in range(len(COLS))]) + ')'
# £TODO check if email exists first
# yes =>propose login via doors + overwrite ?)
# no => proceed
reg_db = connect('data/registered.db')
reg_db_c = reg_db.cursor()
reg_db_c.execute('INSERT INTO comex_registrations VALUES' + db_mask , safe_recs_arr)
reg_db.commit()
reg_db.close()
def from_reception_to_save(incoming_data):
"""
WIP: function to relate between one_big_form POST reception and previous cgi-bin post-treatment
TODO: integrate partly into one_big_form and maybe into save_to_db
"""
# init var
clean_records = {}
# read in + sanitize values
# =========================
# NB password values have already been sent by ajax to Doors
# we should have all the mandatory fields (checked in client-side js)
for field_info in COLS:
field = field_info[0]
if field in incoming_data:
if field not in ["doors_uid", "last_modified_date", "pic_file"]:
clean_records[field] = sanitize(incoming_data[field])
# these 3 fields were already validated actually :)
else:
clean_records[field] = incoming_data[field]
# debug cleaned data keys
# print(str(clean_records))
# save to DB
# ===========
save_to_db([clean_records.get(k[0], None) for k in COLS])
########### MAIN ###########
if __name__ == "__main__":
app.run()
......@@ -580,10 +580,10 @@ var passwords = [pass1, pass2]
// £DEBUG autofill ----------->8------
// email.value= makeRandomString(10)+"@om.fr"
// pass1.value="123456+789"
// pass2.value="123456+789"
// initialsInput.value="JPP"
email.value= makeRandomString(10)+"@om.fr"
pass1.value="123456+789"
pass2.value="123456+789"
initialsInput.value="JPP"
// --------------------------->8------
......
......@@ -74,20 +74,9 @@
</div>
<!-- ########################### ( debg ) ########################## -->
<!-- test cgi user from submit point of view -->
<!-- <form id="test_user_form" enctype="multipart/form-data"
method="post"
action="cgi-bin/test_cgi_user.py.cgi">
<input type="submit" class="btn btn-lg btn-success" style="float:right"
id="testsubmit" value="Test user submit" />
</form> -->
<!-- ########################### ( FORM ) ########################## -->
<form id="comex_reg_form" enctype="multipart/form-data"
method="post" onsubmit="validateSubmit(event, 'from form', 'register')"
action="cgi-bin/comex_merci_pour_les_infos.py.cgi">
method="post" onsubmit="validateSubmit(event, 'from form', 'register')">
<!-- todo onsubmit also save to cache -->
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment