From d1d5e5f11460f50f9d8e1ae4bc80ff327014e685 Mon Sep 17 00:00:00 2001
From: Stephan Porada <sporada@uni-bielefeld.de>
Date: Mon, 8 Jul 2019 14:06:35 +0200
Subject: [PATCH] Add registration form, view, template

---
 app/auth/forms.py                   |  20 +++++++-
 app/templates/auth/login.html.j2    |   6 +--
 app/templates/auth/register.html.j2 |  68 +++++++++++++++++-----------
 app/templates/base.html.j2          |   1 +
 data_dev.sqlite                     | Bin 32768 -> 32768 bytes
 5 files changed, 64 insertions(+), 31 deletions(-)

diff --git a/app/auth/forms.py b/app/auth/forms.py
index 43a64679..3a71b095 100644
--- a/app/auth/forms.py
+++ b/app/auth/forms.py
@@ -14,7 +14,25 @@ class LoginForm(FlaskForm):
 
 
 class RegistrationForm(FlaskForm):
-    email = StringField('Email', validators=[DataRequired(), Length(1, 64), Email()])
+    email = StringField('Email', validators=[DataRequired(), Length(1, 64),
+                                             Email()])
+    username = StringField('Username', validators=[
+        DataRequired(), Length(1, 64),
+        Regexp('^[A-Za-z][A-Za-z0-9_.]*$', 0,
+               'Usernames must have only letters, numbers, dots or '
+               'underscores')])
+    password = PasswordField('Password', validators=[
+        DataRequired(), EqualTo('password2', message='Passwords must match.')])
+    password2 = PasswordField('Confirm password', validators=[DataRequired()])
+    submit = SubmitField('Register')
+
+    def validate_email(self, field):
+        if User.query.filter_by(email=field.data.lower()).first():
+            raise ValidationError('Email already registered.')
+
+    def validate_username(self, field):
+        if User.query.filter_by(username=field.data).first():
+            raise ValidationError('Username already in use.')
 
 
 class PasswordResetRequestForm(FlaskForm):
diff --git a/app/templates/auth/login.html.j2 b/app/templates/auth/login.html.j2
index 325e99c4..3c9fdf4a 100644
--- a/app/templates/auth/login.html.j2
+++ b/app/templates/auth/login.html.j2
@@ -10,9 +10,9 @@
     <div class="card-content">
       <p>Sign in into an exisiting account or register a new one!</p>
       <br>
-    <div class="card-action">
-      <a class="btn" href="{{url_for('auth.register')}}">Register</a>
-    </div>
+      <div class="card-action">
+        <a class="btn" href="{{url_for('auth.register')}}">Register</a>
+      </div>
     </div>
   </div>
 </div>
diff --git a/app/templates/auth/register.html.j2 b/app/templates/auth/register.html.j2
index 6a85c9a9..52070a1a 100644
--- a/app/templates/auth/register.html.j2
+++ b/app/templates/auth/register.html.j2
@@ -2,33 +2,47 @@
 
 {% block page_content %}
 <div class="col s12">
-  <div class="row">
-    <div class="card medium">
-      <div class="card-content">
-        <span class="card-title">Register</span>
-        <form>
-          <div class="input-field col s6">
-            <input id="first-name" type="text" class="validate">
-            <label for="first-name">First Name</label>
-          </div>
-          <div class="input-field col s6">
-            <input id="last-name" type="text" class="validate">
-            <label for="last-name">Last Name</label>
-          </div>
-          <div class="row">
-            <div class="input-field col s12">
-              <input id="password" type="password" class="validate">
-              <label for="password">Password</label>
-            </div>
-          </div>
-          <div class="row">
-            <div class="input-field col s12">
-              <input id="email" type="email" class="validate">
-              <label for="email">Email</label>
-            </div>
-          </div>
-        </form>
-      </div>
+  <div class="card large">
+    <div class="card-content">
+      <span class="card-title">Register</span>
+      <form method="POST">
+        {{ form.hidden_tag() }}
+        <div class="input-field">
+          <i class="material-icons prefix">account_circle</i>
+          {{ form.username(class='validate') }}
+          {{ form.username.label }}
+          {% for error in form.username.errors %}
+            <span class="helper-text" style="color:red;">{{ error }}</span>
+          {% endfor %}
+        </div>
+        <div class="input-field">
+          <i class="material-icons prefix">vpn_key</i>
+          {{ form.password(class='validate') }}
+          {{ form.password.label }}
+          {% for error in form.password.errors %}
+            <span class="helper-text" style="color:red;">{{ error }}</span>
+          {% endfor %}
+        </div>
+        <div class="input-field">
+          <i class="material-icons prefix">vpn_key</i>
+          {{ form.password2(class='validate') }}
+          {{ form.password2.label }}
+          {% for error in form.password2.errors %}
+            <span class="helper-text" style="color:red;">{{ error }}</span>
+          {% endfor %}
+        </div>
+        <div class="input-field ">
+          <i class="material-icons prefix">email</i>
+          {{ form.email(class='validate', type='email') }}
+          {{ form.email.label }}
+          {% for error in form.email.errors %}
+            <span class="helper-text" style="color:red;">{{ error }}</span>
+          {% endfor %}
+        </div>
+        <div class="card-action">
+          {{ form.submit(class='btn right') }}
+        </div>
+      </form>
     </div>
   </div>
 </div>
diff --git a/app/templates/base.html.j2 b/app/templates/base.html.j2
index 46aa1d10..40601f13 100644
--- a/app/templates/base.html.j2
+++ b/app/templates/base.html.j2
@@ -25,6 +25,7 @@
         <li><a href="{{ url_for('auth.logout') }}"><i class="material-icons">chevron_left</i>Log out</a></li>
         {% else %}
         <li><a href="{{ url_for('auth.login') }}"><i class="material-icons">chevron_right</i>Log in</a></li>
+        <li><a href="{{ url_for('auth.register') }}"><i class="material-icons">chevron_right</i>Register</a></li>
         {% endif %}
       </ul>
       <div id="nav-settings-dropdown" class="dropdown-content grey-text text-darken-4">
diff --git a/data_dev.sqlite b/data_dev.sqlite
index 531008fb53485717ae2e3a339dedeebc9fc1eb8d..75d6c1549dd45cb57958eab66cc0bea1a30ac0cc 100644
GIT binary patch
delta 860
zcmZva%}Z2K7{;%2XU2vc&xnXn&Thn=ob#S<+Za(1WP+PW5ILWWi81Nu*lMOt;3g`e
zO`HCKAn6Zi<vLontZm!&b?%s=Fn4n<&;9tl@AEu^L1{23y}3Cy@pkS`Wg=Ug`+VX*
zt~RRmW`+(X|4zP|MD_Re=9j5Pt={id$Fqgm?B#=Q*y}FunB6V2=)+2JcI>u~u(a1U
zz{L{bI9;u9FRa6Ed#y#aBV0*C4Gk7Y#y#d5V`l+O)WY&8!4MIF1@5q7nsKg8dL6t0
zD{QY)fcxj<0?!h8c#b4*uRat{9=CZ5J1nfnQfr2}uvS^mtXC>p=B30oa)ymnK2Wey
z>gZJrPDLV|4xDJQUryxdGjPAVToCDS=fjcQVDO{oFTl5gqlp_LGm%ot!I(g`ln`hd
z!EqT0xJV&JYy!5<Dj^&gPPwwe5X^e{WvdG;EcVYfhLL36y9?_(_eG0gDKz#*I!<W{
zA}WF@VC#(y)^aY0<6cN+xR!x~N<$DYBO@#Y#2DQ#jc4;Sm#zNqbZ28!##?K8i}{t%
zQWTq%BFJbZPbO2Mlmag~kul)3CQIg8OJ!<;3qlJaXatYb;vOt@#|N9Q8&!0ap<n0-
zeMeu>C-fopZXaz-<qKnl1s9d8UMRx~qyZ~elp><?6$O%#H}d(j{}f*(q14Q8*Nz99
zH{Ny134NNOQ}hG<LBG*Y^ev%J(5+fNJ2otMwYVG7D&zTd(hke#3gp-Fnc=h2^}Jc@
LJPpsfd#?Qtuv_!j

delta 88
zcmZo@U}|V!njp={K2gS*m7PJ)z-nX40)I9}{xSysvdw}5IsB8$;`@O7M-2RrfczW$
pEV9gwoRb^kr6v`y0L8yB@PFAXXz+@khnrcJvmh%qucSCR0{|x*7~=o{

-- 
GitLab